]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - scripts/gdb/linux/symbols.py
UBUNTU: Ubuntu-5.11.0-22.23
[mirror_ubuntu-hirsute-kernel.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
585d730d 18from linux import modules, utils
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
92 def _section_arguments(self, module):
93 try:
94 sect_attrs = module['sect_attrs'].dereference()
95 except gdb.error:
96 return ""
97 attrs = sect_attrs['attrs']
98 section_name_to_address = {
7359608a 99 attrs[n]['battr']['attr']['name'].string(): attrs[n]['address']
276d97d9 100 for n in range(int(sect_attrs['nsections']))}
66051720 101 args = []
8731acc5
IL
102 for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
103 ".text", ".text.hot", ".text.unlikely"]:
66051720
JK
104 address = section_name_to_address.get(section_name)
105 if address:
106 args.append(" -s {name} {addr}".format(
107 name=section_name, addr=str(address)))
108 return "".join(args)
109
110 def load_module_symbols(self, module):
111 module_name = module['name'].string()
ad4db3b2 112 module_addr = str(module['core_layout']['base']).split()[0]
66051720
JK
113
114 module_file = self._get_module_file(module_name)
115 if not module_file and not self.module_files_updated:
116 self._update_module_files()
117 module_file = self._get_module_file(module_name)
118
119 if module_file:
585d730d
IL
120 if utils.is_target_arch('s390'):
121 # Module text is preceded by PLT stubs on s390.
122 module_arch = module['arch']
123 plt_offset = int(module_arch['plt_offset'])
124 plt_size = int(module_arch['plt_size'])
125 module_addr = hex(int(module_addr, 0) + plt_offset + plt_size)
66051720
JK
126 gdb.write("loading @{addr}: {filename}\n".format(
127 addr=module_addr, filename=module_file))
128 cmdline = "add-symbol-file {filename} {addr}{sections}".format(
129 filename=module_file,
130 addr=module_addr,
131 sections=self._section_arguments(module))
132 gdb.execute(cmdline, to_string=True)
6ad18b73 133 if module_name not in self.loaded_modules:
82b41e3d 134 self.loaded_modules.append(module_name)
66051720
JK
135 else:
136 gdb.write("no module object found for '{0}'\n".format(module_name))
137
138 def load_all_symbols(self):
139 gdb.write("loading vmlinux\n")
140
141 # Dropping symbols will disable all breakpoints. So save their states
142 # and restore them afterward.
143 saved_states = []
144 if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
145 for bp in gdb.breakpoints():
146 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
147
148 # drop all current symbols and reload vmlinux
dfe4529e
SB
149 orig_vmlinux = 'vmlinux'
150 for obj in gdb.objfiles():
151 if obj.filename.endswith('vmlinux'):
152 orig_vmlinux = obj.filename
66051720 153 gdb.execute("symbol-file", to_string=True)
dfe4529e 154 gdb.execute("symbol-file {0}".format(orig_vmlinux))
66051720 155
82b41e3d 156 self.loaded_modules = []
fffb944c 157 module_list = modules.module_list()
66051720
JK
158 if not module_list:
159 gdb.write("no modules found\n")
160 else:
161 [self.load_module_symbols(module) for module in module_list]
162
163 for saved_state in saved_states:
164 saved_state['breakpoint'].enabled = saved_state['enabled']
165
166 def invoke(self, arg, from_tty):
552ab2a3 167 self.module_paths = [os.path.expanduser(p) for p in arg.split()]
66051720
JK
168 self.module_paths.append(os.getcwd())
169
170 # enforce update
171 self.module_files = []
172 self.module_files_updated = False
173
174 self.load_all_symbols()
175
82b41e3d 176 if hasattr(gdb, 'Breakpoint'):
6ad18b73 177 if self.breakpoint is not None:
82b41e3d
JK
178 self.breakpoint.delete()
179 self.breakpoint = None
180 self.breakpoint = LoadModuleBreakpoint(
181 "kernel/module.c:do_init_module", self)
182 else:
183 gdb.write("Note: symbol update on module loading not supported "
184 "with this gdb version\n")
185
66051720
JK
186
187LxSymbols()