2 # gdb helper commands and functions for Linux kernel debugging
4 # load kernel and module symbols
6 # Copyright (c) Siemens AG, 2011-2013
9 # Jan Kiszka <jan.kiszka@siemens.com>
11 # This work is licensed under the terms of the GNU GPL version 2.
19 from linux import modules, utils
22 class LxSymbols(gdb.Command):
23 """(Re-)load symbols of Linux kernel and currently loaded modules.
25 The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
26 are scanned recursively, starting in the same directory. Optionally, the module
27 search path can be extended by a space separated list of paths passed to the
28 lx-symbols command."""
32 module_files_updated = False
35 super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
36 gdb.COMPLETE_FILENAME)
38 def _update_module_files(self):
39 self.module_files = []
40 for path in self.module_paths:
41 gdb.write("scanning for modules in {0}\n".format(path))
42 for root, dirs, files in os.walk(path):
44 if name.endswith(".ko"):
45 self.module_files.append(root + "/" + name)
46 self.module_files_updated = True
48 def _get_module_file(self, module_name):
49 module_pattern = ".*/{0}\.ko$".format(
50 string.replace(module_name, "_", r"[_\-]"))
51 for name in self.module_files:
52 if re.match(module_pattern, name) and os.path.exists(name):
56 def _section_arguments(self, module):
58 sect_attrs = module['sect_attrs'].dereference()
61 attrs = sect_attrs['attrs']
62 section_name_to_address = {
63 attrs[n]['name'].string() : attrs[n]['address']
64 for n in range(sect_attrs['nsections'])}
66 for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
67 address = section_name_to_address.get(section_name)
69 args.append(" -s {name} {addr}".format(
70 name=section_name, addr=str(address)))
73 def load_module_symbols(self, module):
74 module_name = module['name'].string()
75 module_addr = str(module['module_core']).split()[0]
77 module_file = self._get_module_file(module_name)
78 if not module_file and not self.module_files_updated:
79 self._update_module_files()
80 module_file = self._get_module_file(module_name)
83 gdb.write("loading @{addr}: {filename}\n".format(
84 addr=module_addr, filename=module_file))
85 cmdline = "add-symbol-file {filename} {addr}{sections}".format(
88 sections=self._section_arguments(module))
89 gdb.execute(cmdline, to_string=True)
91 gdb.write("no module object found for '{0}'\n".format(module_name))
93 def load_all_symbols(self):
94 gdb.write("loading vmlinux\n")
96 # Dropping symbols will disable all breakpoints. So save their states
97 # and restore them afterward.
99 if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
100 for bp in gdb.breakpoints():
101 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
103 # drop all current symbols and reload vmlinux
104 gdb.execute("symbol-file", to_string=True)
105 gdb.execute("symbol-file vmlinux")
107 module_list = modules.ModuleList()
109 gdb.write("no modules found\n")
111 [self.load_module_symbols(module) for module in module_list]
113 for saved_state in saved_states:
114 saved_state['breakpoint'].enabled = saved_state['enabled']
116 def invoke(self, arg, from_tty):
117 self.module_paths = arg.split()
118 self.module_paths.append(os.getcwd())
121 self.module_files = []
122 self.module_files_updated = False
124 self.load_all_symbols()