def archive_kernel_dump(path: str) -> None: """ Packages the dump together with its vmlinux and modules in a gzipped archive in the working directory. """ # pylint: disable=too-many-locals # # We import drgn and libkdumpfile specifically here and # not in the top-level to allow users that don't have # it installed to still be able to use savedump for # userland core files. # import kdumpfile # pylint: disable=import-outside-toplevel kdump_info = kdumpfile.kdumpfile(path) dumpname = os.path.basename(path) nodename = kdump_info.attr['linux.uts.nodename'] osrelease = kdump_info.attr['linux.uts.release'] vmlinux_path = f"/usr/lib/debug/boot/vmlinux-{osrelease}" if not os.path.exists(vmlinux_path): sys.exit(f"error: cannot find vmlinux at: {vmlinux_path}") print(f"vmlinux found: {vmlinux_path}") mod_paths = get_module_paths(osrelease, path) archive_dir = f"{nodename}.archive-{dumpname}" pathlib.Path(archive_dir).mkdir(parents=True, exist_ok=True) shutil.copy(path, archive_dir) shutil.copy(vmlinux_path, archive_dir) for mod_path in mod_paths: archive_mod_path = f"{archive_dir}{mod_path}" os.makedirs(os.path.dirname(archive_mod_path), exist_ok=True) shutil.copy(mod_path, archive_mod_path) # # Generate run-sdb.sh. # run_sdb_path = f"{archive_dir}/run-sdb.sh" with open(run_sdb_path, "w") as sdb_script: print(RUN_CRASH_SDB_CONTENTS.format(os.path.basename(vmlinux_path), dumpname), file=sdb_script) os.chmod(run_sdb_path, 0o755) # # Generate run-pycrash.sh. # run_pycrash_path = f"{archive_dir}/run-pycrash.sh" with open(run_pycrash_path, "w") as pycrash_script: print(RUN_PYCRASH_CONTENTS.format(os.path.basename(vmlinux_path), dumpname), file=pycrash_script) os.chmod(run_pycrash_path, 0o755) msg = compress_archive(archive_dir) shutil.rmtree(archive_dir) if msg: sys.exit(f"error: {msg}")
def __init__(self, fil): if isinstance(fil, str): fil = file(fil) self.fil = fil print "kdump (%s)" % fil self.kdump = kdumpfile(fil) self.kdump.symbol_func = symbol_func self.kdump.vtop_init() super(Target, self).__init__() gdb.execute('set print thread-events 0') self.setup_tasks()
def attach_vmcore(self, vmcore_filename, debug=False): self.vmcore_filename = vmcore_filename self.vmcore = kdumpfile(vmcore_filename) self.target = crash.kdump.target.Target(self.vmcore, debug) self.base_offset = 0 try: KERNELOFFSET = "linux.vmcoreinfo.lines.KERNELOFFSET" attr = self.vmcore.attr.get(KERNELOFFSET, "0") self.base_offset = long(attr, base=16) except Exception as e: print(e)
def open(self, args: str, from_tty: bool) -> None: argv = shlex.split(args) if len(argv) < 2: raise gdb.GdbError("kdumpfile target requires kernel image and vmcore") vmlinux = argv[0] filename = argv[1] try: self.kdump = kdumpfile(file=filename) except Exception as e: raise gdb.GdbError("Failed to open `{}': {}" .format(filename, str(e))) # pylint: disable=unsupported-assignment-operation self.kdump.attr['addrxlat.ostype'] = 'linux' KERNELOFFSET = "linux.vmcoreinfo.lines.KERNELOFFSET" try: attr = self.kdump.attr.get(KERNELOFFSET, "0") # pylint: disable=no-member self.base_offset = int(attr, base=16) except (TypeError, ValueError): pass # Load the kernel at the relocated address # Unfortunately, the percpu section has an offset of 0 and # ends up getting placed at the offset base. This is easy # enough to handle in the percpu code. result = gdb.execute("symbol-file {} -o {:#x}" .format(vmlinux, self.base_offset), to_string=True) if self.debug: print(result) # We don't have an exec-file so we need to set the architecture # explicitly. arch = gdb.objfiles()[0].architecture.name() result = gdb.execute("set architecture {}".format(arch), to_string=True) if self.debug: print(result)
def __init__(self, filename, debug=False): self.filename = filename self.arch = None self.debug = debug try: self.kdump = kdumpfile(filename) except OSErrorException as e: raise RuntimeError(str(e)) ctx = self.kdump.get_addrxlat_ctx() ctx.cb_sym = SymbolCallback(ctx) self.kdump.attr['addrxlat.ostype'] = 'linux' gdb.execute('set print thread-events 0') self.setup_arch() # So far we've read from the kernel image, now that we've setup # the architecture, we're ready to plumb into the target # infrastructure. super(Target, self).__init__() # Now we're reading from the dump file self.setup_tasks()
def open(self, filename: str, from_tty: bool) -> None: objfiles = gdb.objfiles() if not objfiles: raise gdb.GdbError( "kdumpfile target requires kernel to be already loaded for symbol resolution" ) try: self.kdump = kdumpfile(file=filename) except Exception as e: raise gdb.GdbError("Failed to open `{}': {}".format( filename, str(e))) # pylint: disable=unsupported-assignment-operation self.kdump.attr['addrxlat.ostype'] = 'linux' KERNELOFFSET = "linux.vmcoreinfo.lines.KERNELOFFSET" try: attr = self.kdump.attr.get(KERNELOFFSET, "0") # pylint: disable=no-member self.base_offset = int(attr, base=16) except (TypeError, ValueError): pass vmlinux = gdb.objfiles()[0].filename # Load the kernel at the relocated address # Unfortunately, the percpu section has an offset of 0 and # ends up getting placed at the offset base. This is easy # enough to handle in the percpu code. result = gdb.execute("add-symbol-file {} -o {:#x}".format( vmlinux, self.base_offset), to_string=True) if self.debug: print(result) # Clear out the old symbol cache gdb.execute("file {}".format(vmlinux))
def __init__(self, kernel_exec=None, vmcore=None, kernelpath=None, searchpath=None, debug=False): print("crash-python initializing...") if searchpath is None: searchpath = [] autoload_submodules('crash.cache') autoload_submodules('crash.subsystem') autoload_submodules('crash.commands') self.searchpath = searchpath if not kernel_exec: return try: kdump = kdumpfile(vmcore) except OSErrorException as e: raise RuntimeError(str(e)) kaslr_off = long( kdump.attr.get("linux.vmcoreinfo.lines.KERNELOFFSET", "0"), base=16) error = gdb.execute("exec-file {}".format(kernel_exec), to_string=True) tinfo = gdb.execute("info target", to_string=True) args="" textaddr = 0 in_exec = False for line in tinfo.splitlines(): if line.startswith((" ", "\t")): if not in_exec: continue try: (addrs, sect) = line.strip().split(" is ") except ValueError: continue (start, end) = addrs.split(" - ") sect = sect.split(' ')[0] startaddr = long(start, base=0) + kaslr_off if sect == ".text": textaddr = startaddr args += " 0x{:x}".format(startaddr) elif startaddr >= textaddr: args += " -s {} 0x{:x}".format(sect, startaddr) elif line.startswith("Local exec file:"): in_exec = True elif not line.startswith("warning: "): in_exec = False error = gdb.execute("add-symbol-file {}{}".format(kernel_exec, args), to_string=True) try: list_type = gdb.lookup_type('struct list_head') except gdb.error as e: load_debuginfo(searchpath, gdb.objfiles()[0], kernelpath) try: list_type = gdb.lookup_type('struct list_head') except gdb.error as e: raise RuntimeError("Couldn't locate debuginfo for {}".format(kernel_exec)) self.target = crash.kdump.target.Target(kdump, debug) load_modules(self.searchpath)
addr.addr += step.idx[step.remain - 1] * step.elemsz else: addr = step.base remark = note.note(addr, ' ({})') print('{:>4}: {:16x}{}'.format(tbl, addr.addr, remark), end='') try: step.step() if step.remain and step.raw is not None: print(' => {:x}'.format(step.raw)) except addrxlat.NotPresentError: print(' => {:x} NOT PRESENT'.format(step.raw)) return print() if len(argv) != 3: print('Usage: {} <dumpfile> <virtual address>'.format(argv[0])) exit(1) kdf = kdumpfile.kdumpfile(argv[1]) kdf.addrxlat_convert = addrxlat.convert kdf.attr['addrxlat.ostype'] = 'linux' sys = kdf.get_addrxlat_sys() ctx = kdf.get_addrxlat_ctx() addr = int(argv[2], base=0) try: vtop(addr, ctx, sys) except addrxlat.BaseException as e: print('Translation failed: {}'.format(e.message))
else: addr = step.base remark = note.note(addr, ' ({})') print('{:>4}: {:16x}{}'.format(tbl, addr.addr, remark), end='') try: step.step() if step.remain and step.raw is not None: print(' => {:x}'.format(step.raw)) except addrxlat.NotPresentError: print(' => {:x} NOT PRESENT'.format(step.raw)) return print() if len(argv) != 3: print('Usage: {} <dumpfile> <virtual address>'.format(argv[0])) exit(1) kdf = kdumpfile.kdumpfile(argv[1]) kdf.addrxlat_convert = addrxlat.convert kdf.attr['addrxlat.ostype'] = 'linux' sys = kdf.get_addrxlat_sys() ctx = kdf.get_addrxlat_ctx() addr = int(argv[2], base=0) try: vtop(addr, ctx, sys) except addrxlat.BaseException as e: print('Translation failed: {}'.format(e.message))
print_meth(system, 'MACHPHYS_KPHYS') print_meth(system, 'KPHYS_MACHPHYS') print_map(system, 'HW') print() print_map(system, 'KV_PHYS') print() print_map(system, 'KPHYS_DIRECT') print() print_map(system, 'MACHPHYS_KPHYS') print() print_map(system, 'KPHYS_MACHPHYS') if __name__ == '__main__': if len(sys.argv) < 2 or len(sys.argv) > 3: print('Usage: {} <dumpfile> [<ostype>]'.format(sys.argv[0]), file=sys.stderr) exit(1) k = kdumpfile.kdumpfile(sys.argv[1]) meth_names = {} for name, val in addrxlat.__dict__.items(): if name.startswith('SYS_METH_') and name != 'SYS_METH_NUM': meth_names[val] = name[9:] if len(sys.argv) > 2: k.attr['addrxlat.ostype'] = sys.argv[2] dump_addrxlat(k)
print_meth(system, 'KPHYS_MACHPHYS') print_map(system, 'HW') print() print_map(system, 'KV_PHYS') print() print_map(system, 'KPHYS_DIRECT') print() print_map(system, 'MACHPHYS_KPHYS') print() print_map(system, 'KPHYS_MACHPHYS') if __name__ == '__main__': if len(sys.argv) < 2 or len(sys.argv) > 3: print('Usage: {} <dumpfile> [<ostype>]'.format(sys.argv[0]), file=sys.stderr) exit(1) k = kdumpfile.kdumpfile(sys.argv[1]) meth_names = {} for name, val in addrxlat.__dict__.items(): if name.startswith('SYS_METH_') and name != 'SYS_METH_NUM': meth_names[val] = name[9:] if len(sys.argv) > 2: k.attr['addrxlat.ostype'] = sys.argv[2] dump_addrxlat(k)