scripts/gdb: define maintainer
[deliverable/linux.git] / scripts / gdb / linux / symbols.py
CommitLineData
66051720
JK
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# load kernel and module symbols
5#
6# Copyright (c) Siemens AG, 2011-2013
7#
8# Authors:
9# Jan Kiszka <jan.kiszka@siemens.com>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15import os
16import re
17import string
18
19from linux import modules, utils
20
21
82b41e3d
JK
22if hasattr(gdb, 'Breakpoint'):
23 class LoadModuleBreakpoint(gdb.Breakpoint):
24 def __init__(self, spec, gdb_command):
25 super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
26 self.silent = True
27 self.gdb_command = gdb_command
28
29 def stop(self):
30 module = gdb.parse_and_eval("mod")
31 module_name = module['name'].string()
32 cmd = self.gdb_command
33
34 # enforce update if object file is not found
35 cmd.module_files_updated = False
36
37 if module_name in cmd.loaded_modules:
38 gdb.write("refreshing all symbols to reload module "
39 "'{0}'\n".format(module_name))
40 cmd.load_all_symbols()
41 else:
42 cmd.load_module_symbols(module)
43 return False
44
45
66051720
JK
46class LxSymbols(gdb.Command):
47 """(Re-)load symbols of Linux kernel and currently loaded modules.
48
49The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
50are scanned recursively, starting in the same directory. Optionally, the module
51search path can be extended by a space separated list of paths passed to the
52lx-symbols command."""
53
54 module_paths = []
55 module_files = []
56 module_files_updated = False
82b41e3d
JK
57 loaded_modules = []
58 breakpoint = None
66051720
JK
59
60 def __init__(self):
61 super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
62 gdb.COMPLETE_FILENAME)
63
64 def _update_module_files(self):
65 self.module_files = []
66 for path in self.module_paths:
67 gdb.write("scanning for modules in {0}\n".format(path))
68 for root, dirs, files in os.walk(path):
69 for name in files:
70 if name.endswith(".ko"):
71 self.module_files.append(root + "/" + name)
72 self.module_files_updated = True
73
74 def _get_module_file(self, module_name):
75 module_pattern = ".*/{0}\.ko$".format(
276d97d9 76 module_name.replace("_", r"[_\-]"))
66051720
JK
77 for name in self.module_files:
78 if re.match(module_pattern, name) and os.path.exists(name):
79 return name
80 return None
81
82 def _section_arguments(self, module):
83 try:
84 sect_attrs = module['sect_attrs'].dereference()
85 except gdb.error:
86 return ""
87 attrs = sect_attrs['attrs']
88 section_name_to_address = {
89 attrs[n]['name'].string() : attrs[n]['address']
276d97d9 90 for n in range(int(sect_attrs['nsections']))}
66051720
JK
91 args = []
92 for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
93 address = section_name_to_address.get(section_name)
94 if address:
95 args.append(" -s {name} {addr}".format(
96 name=section_name, addr=str(address)))
97 return "".join(args)
98
99 def load_module_symbols(self, module):
100 module_name = module['name'].string()
101 module_addr = str(module['module_core']).split()[0]
102
103 module_file = self._get_module_file(module_name)
104 if not module_file and not self.module_files_updated:
105 self._update_module_files()
106 module_file = self._get_module_file(module_name)
107
108 if module_file:
109 gdb.write("loading @{addr}: {filename}\n".format(
110 addr=module_addr, filename=module_file))
111 cmdline = "add-symbol-file {filename} {addr}{sections}".format(
112 filename=module_file,
113 addr=module_addr,
114 sections=self._section_arguments(module))
115 gdb.execute(cmdline, to_string=True)
82b41e3d
JK
116 if not module_name in self.loaded_modules:
117 self.loaded_modules.append(module_name)
66051720
JK
118 else:
119 gdb.write("no module object found for '{0}'\n".format(module_name))
120
121 def load_all_symbols(self):
122 gdb.write("loading vmlinux\n")
123
124 # Dropping symbols will disable all breakpoints. So save their states
125 # and restore them afterward.
126 saved_states = []
127 if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
128 for bp in gdb.breakpoints():
129 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
130
131 # drop all current symbols and reload vmlinux
132 gdb.execute("symbol-file", to_string=True)
133 gdb.execute("symbol-file vmlinux")
134
82b41e3d 135 self.loaded_modules = []
fffb944c 136 module_list = modules.module_list()
66051720
JK
137 if not module_list:
138 gdb.write("no modules found\n")
139 else:
140 [self.load_module_symbols(module) for module in module_list]
141
142 for saved_state in saved_states:
143 saved_state['breakpoint'].enabled = saved_state['enabled']
144
145 def invoke(self, arg, from_tty):
146 self.module_paths = arg.split()
147 self.module_paths.append(os.getcwd())
148
149 # enforce update
150 self.module_files = []
151 self.module_files_updated = False
152
153 self.load_all_symbols()
154
82b41e3d
JK
155 if hasattr(gdb, 'Breakpoint'):
156 if not self.breakpoint is None:
157 self.breakpoint.delete()
158 self.breakpoint = None
159 self.breakpoint = LoadModuleBreakpoint(
160 "kernel/module.c:do_init_module", self)
161 else:
162 gdb.write("Note: symbol update on module loading not supported "
163 "with this gdb version\n")
164
66051720
JK
165
166LxSymbols()
This page took 0.032056 seconds and 5 git commands to generate.