diff --git a/crash/cache/modules.py b/crash/cache/modules.py new file mode 100644 index 00000000000..1f2b8d1b04c --- /dev/null +++ b/crash/cache/modules.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: + +from __future__ import print_function +import os +import gdb +import sys +from crash.cache import CrashCache +from crash.types.list import list_for_each_entry + +if sys.version_info.major >= 3: + long = int + +class Kmod(): + def __init__(self, obj): + self.name = obj['name'].string() + self.objfile = None + self._module = obj + + def get_base_addr(self): + return long(self._module.address) + + def get_size(self): + return long(self._module['core_size']) + + def load_objfile(self, path): + self.objfile = os.path.abspath(path) + try: + gdb.execute("add-symbol-file {} {}".format(path, self._module['module_core'])) + except gdb.error: + self.objfile = None + print("Error adding symbol informatation") + +class KmodCache(CrashCache): + def __init__(self): + super(KmodCache, self).__init__() + self._modules = {} + self._cache_init = False + + def init_modules_cache(self): + if self._cache_init: return + + module_type = gdb.lookup_type('struct module') + modules = gdb.lookup_symbol('modules', None)[0].value() + for module in list_for_each_entry(modules, module_type, 'list'): + kmod = Kmod(module) + self._modules[kmod.name] = kmod + + self._cache_init = True + + def __len__(self): + return len(self._modules) + + def __getitem__(self, key): + return self._modules[key] + + def __contains__(self, item): + return item in self._modules + + def __iter__(self): + return self._modules.__iter__() + + def values(self): + return self._modules.values() + +cache = KmodCache() + + diff --git a/crash/commands/pymod.py b/crash/commands/pymod.py new file mode 100644 index 00000000000..f56f2b1258d --- /dev/null +++ b/crash/commands/pymod.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: + +from __future__ import print_function + +import gdb +import argparse +import sys +from crash.types.list import list_for_each_entry +from crash.commands import CrashCommand +from crash.cache import modules + +if sys.version_info.major >= 3: + long = int + +class ModCommand(CrashCommand): + """ + """ + def __init__(self, name): + #init parser + parser = argparse.ArgumentParser(prog=name) + group = parser.add_mutually_exclusive_group() + group.add_argument("-s", metavar="module") + parser.add_argument('args', nargs='*') + #initialize module cache + + CrashCommand.__init__(self, "mod", parser) + + def _list_modules(self): + modules_sorted = [] + sort_by_addr = lambda x: long(x.get_base_addr()) + + print("{0:^16} {1:<16} {2:<8} OBJECT FILE".format("MODULE", "NAME", "SIZE")) + + for module in sorted(modules.cache.values(), key=sort_by_addr): + objfile = module.objfile + if objfile is None: + objfile = "(not loaded)" + print("{0:^16x} {1:<16} {2:<8} {3}".format(long(module.get_base_addr()), module.name, module.get_size(), objfile)) + + def _add_objfile(self, module_name, objfile_path): + #Add handling for not loaded module, results in KeyError + kmod = modules.cache[module_name] + kmod.load_objfile(objfile_path) + + def execute(self, argv): + modules.cache.init_modules_cache() + if argv.s is not None: + module_name = argv.s + if len(argv.args): + objfile = argv.args[0] + self._add_objfile(module_name, objfile) + else: + #TODO: Automatically search for the module, perhaps + #merge the stuff from contrib/mod.py + pass + else: + self._list_modules() + +ModCommand("mod")