ASoC: Merge up v6.6-rc7
[linux-block.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
66051720 17
b4aff751 18from linux import modules, utils, constants
66051720
JK
19
20
82b41e3d
JK
21if hasattr(gdb, 'Breakpoint'):
22 class LoadModuleBreakpoint(gdb.Breakpoint):
23 def __init__(self, spec, gdb_command):
24 super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
25 self.silent = True
26 self.gdb_command = gdb_command
27
28 def stop(self):
29 module = gdb.parse_and_eval("mod")
30 module_name = module['name'].string()
31 cmd = self.gdb_command
32
33 # enforce update if object file is not found
34 cmd.module_files_updated = False
35
a9c5bcfa
JK
36 # Disable pagination while reporting symbol (re-)loading.
37 # The console input is blocked in this context so that we would
38 # get stuck waiting for the user to acknowledge paged output.
39 show_pagination = gdb.execute("show pagination", to_string=True)
40 pagination = show_pagination.endswith("on.\n")
41 gdb.execute("set pagination off")
42
82b41e3d
JK
43 if module_name in cmd.loaded_modules:
44 gdb.write("refreshing all symbols to reload module "
45 "'{0}'\n".format(module_name))
46 cmd.load_all_symbols()
47 else:
48 cmd.load_module_symbols(module)
a9c5bcfa
JK
49
50 # restore pagination state
51 gdb.execute("set pagination %s" % ("on" if pagination else "off"))
52
82b41e3d
JK
53 return False
54
55
66051720
JK
56class LxSymbols(gdb.Command):
57 """(Re-)load symbols of Linux kernel and currently loaded modules.
58
59The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
60are scanned recursively, starting in the same directory. Optionally, the module
61search path can be extended by a space separated list of paths passed to the
62lx-symbols command."""
63
64 module_paths = []
65 module_files = []
66 module_files_updated = False
82b41e3d
JK
67 loaded_modules = []
68 breakpoint = None
66051720
JK
69
70 def __init__(self):
71 super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
72 gdb.COMPLETE_FILENAME)
73
74 def _update_module_files(self):
75 self.module_files = []
76 for path in self.module_paths:
77 gdb.write("scanning for modules in {0}\n".format(path))
78 for root, dirs, files in os.walk(path):
79 for name in files:
da036ae1 80 if name.endswith(".ko") or name.endswith(".ko.debug"):
66051720
JK
81 self.module_files.append(root + "/" + name)
82 self.module_files_updated = True
83
84 def _get_module_file(self, module_name):
da036ae1 85 module_pattern = ".*/{0}\.ko(?:.debug)?$".format(
276d97d9 86 module_name.replace("_", r"[_\-]"))
66051720
JK
87 for name in self.module_files:
88 if re.match(module_pattern, name) and os.path.exists(name):
89 return name
90 return None
91
1677bf76 92 def _section_arguments(self, module, module_addr):
66051720
JK
93 try:
94 sect_attrs = module['sect_attrs'].dereference()
95 except gdb.error:
1677bf76
KI
96 return str(module_addr)
97
66051720
JK
98 attrs = sect_attrs['attrs']
99 section_name_to_address = {
7359608a 100 attrs[n]['battr']['attr']['name'].string(): attrs[n]['address']
276d97d9 101 for n in range(int(sect_attrs['nsections']))}
1677bf76
KI
102
103 textaddr = section_name_to_address.get(".text", module_addr)
66051720 104 args = []
8731acc5 105 for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
1677bf76 106 ".text.hot", ".text.unlikely"]:
66051720
JK
107 address = section_name_to_address.get(section_name)
108 if address:
109 args.append(" -s {name} {addr}".format(
110 name=section_name, addr=str(address)))
1677bf76
KI
111 return "{textaddr} {sections}".format(
112 textaddr=textaddr, sections="".join(args))
66051720 113
493d4eec 114 def load_module_symbols(self, module):
66051720 115 module_name = module['name'].string()
b4aff751 116 module_addr = str(module['mem'][constants.LX_MOD_TEXT]['base']).split()[0]
66051720 117
493d4eec 118 module_file = self._get_module_file(module_name)
66051720
JK
119 if not module_file and not self.module_files_updated:
120 self._update_module_files()
121 module_file = self._get_module_file(module_name)
122
123 if module_file:
585d730d
IL
124 if utils.is_target_arch('s390'):
125 # Module text is preceded by PLT stubs on s390.
126 module_arch = module['arch']
127 plt_offset = int(module_arch['plt_offset'])
128 plt_size = int(module_arch['plt_size'])
129 module_addr = hex(int(module_addr, 0) + plt_offset + plt_size)
66051720
JK
130 gdb.write("loading @{addr}: {filename}\n".format(
131 addr=module_addr, filename=module_file))
1677bf76 132 cmdline = "add-symbol-file {filename} {sections}".format(
66051720 133 filename=module_file,
1677bf76 134 sections=self._section_arguments(module, module_addr))
66051720 135 gdb.execute(cmdline, to_string=True)
6ad18b73 136 if module_name not in self.loaded_modules:
82b41e3d 137 self.loaded_modules.append(module_name)
66051720
JK
138 else:
139 gdb.write("no module object found for '{0}'\n".format(module_name))
140
141 def load_all_symbols(self):
142 gdb.write("loading vmlinux\n")
143
144 # Dropping symbols will disable all breakpoints. So save their states
145 # and restore them afterward.
146 saved_states = []
147 if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
148 for bp in gdb.breakpoints():
149 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
150
151 # drop all current symbols and reload vmlinux
dfe4529e
SB
152 orig_vmlinux = 'vmlinux'
153 for obj in gdb.objfiles():
3b294118
DA
154 if (obj.filename.endswith('vmlinux') or
155 obj.filename.endswith('vmlinux.debug')):
dfe4529e 156 orig_vmlinux = obj.filename
66051720 157 gdb.execute("symbol-file", to_string=True)
dfe4529e 158 gdb.execute("symbol-file {0}".format(orig_vmlinux))
66051720 159
82b41e3d 160 self.loaded_modules = []
fffb944c 161 module_list = modules.module_list()
66051720
JK
162 if not module_list:
163 gdb.write("no modules found\n")
164 else:
165 [self.load_module_symbols(module) for module in module_list]
166
167 for saved_state in saved_states:
168 saved_state['breakpoint'].enabled = saved_state['enabled']
169
170 def invoke(self, arg, from_tty):
23921540
JB
171 self.module_paths = [os.path.abspath(os.path.expanduser(p))
172 for p in arg.split()]
66051720
JK
173 self.module_paths.append(os.getcwd())
174
175 # enforce update
176 self.module_files = []
177 self.module_files_updated = False
178
179 self.load_all_symbols()
180
82b41e3d 181 if hasattr(gdb, 'Breakpoint'):
6ad18b73 182 if self.breakpoint is not None:
82b41e3d
JK
183 self.breakpoint.delete()
184 self.breakpoint = None
185 self.breakpoint = LoadModuleBreakpoint(
23a67619 186 "kernel/module/main.c:do_init_module", self)
82b41e3d
JK
187 else:
188 gdb.write("Note: symbol update on module loading not supported "
189 "with this gdb version\n")
190
66051720
JK
191
192LxSymbols()