Merge tag 'pci-v6.16-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
[linux-2.6-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
28939c3e 17import struct
66051720 18
e0349c46 19from itertools import count
b4aff751 20from linux import modules, utils, constants
66051720
JK
21
22
82b41e3d
JK
23if hasattr(gdb, 'Breakpoint'):
24 class LoadModuleBreakpoint(gdb.Breakpoint):
25 def __init__(self, spec, gdb_command):
26 super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
27 self.silent = True
28 self.gdb_command = gdb_command
29
30 def stop(self):
31 module = gdb.parse_and_eval("mod")
32 module_name = module['name'].string()
33 cmd = self.gdb_command
34
35 # enforce update if object file is not found
36 cmd.module_files_updated = False
37
a9c5bcfa
JK
38 # Disable pagination while reporting symbol (re-)loading.
39 # The console input is blocked in this context so that we would
40 # get stuck waiting for the user to acknowledge paged output.
e97c4a27
IL
41 with utils.pagination_off():
42 if module_name in cmd.loaded_modules:
43 gdb.write("refreshing all symbols to reload module "
44 "'{0}'\n".format(module_name))
45 cmd.load_all_symbols()
46 else:
47 cmd.load_module_symbols(module)
a9c5bcfa 48
82b41e3d
JK
49 return False
50
51
28939c3e
IL
52def get_vmcore_s390():
53 with utils.qemu_phy_mem_mode():
54 vmcore_info = 0x0e0c
55 paddr_vmcoreinfo_note = gdb.parse_and_eval("*(unsigned long long *)" +
56 hex(vmcore_info))
c164679b
IL
57 if paddr_vmcoreinfo_note == 0 or paddr_vmcoreinfo_note & 1:
58 # In the early boot case, extract vm_layout.kaslr_offset from the
59 # vmlinux image in physical memory.
60 if paddr_vmcoreinfo_note == 0:
61 kaslr_offset_phys = 0
62 else:
63 kaslr_offset_phys = paddr_vmcoreinfo_note - 1
64 with utils.pagination_off():
65 gdb.execute("symbol-file {0} -o {1}".format(
66 utils.get_vmlinux(), hex(kaslr_offset_phys)))
67 kaslr_offset = gdb.parse_and_eval("vm_layout.kaslr_offset")
68 return "KERNELOFFSET=" + hex(kaslr_offset)[2:]
28939c3e
IL
69 inferior = gdb.selected_inferior()
70 elf_note = inferior.read_memory(paddr_vmcoreinfo_note, 12)
71 n_namesz, n_descsz, n_type = struct.unpack(">III", elf_note)
72 desc_paddr = paddr_vmcoreinfo_note + len(elf_note) + n_namesz + 1
73 return gdb.parse_and_eval("(char *)" + hex(desc_paddr)).string()
74
75
76def get_kerneloffset():
77 if utils.is_target_arch('s390'):
78 try:
79 vmcore_str = get_vmcore_s390()
80 except gdb.error as e:
81 gdb.write("{}\n".format(e))
82 return None
83 return utils.parse_vmcore(vmcore_str).kerneloffset
84 return None
85
86
66051720
JK
87class LxSymbols(gdb.Command):
88 """(Re-)load symbols of Linux kernel and currently loaded modules.
89
90The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
91are scanned recursively, starting in the same directory. Optionally, the module
92search path can be extended by a space separated list of paths passed to the
93lx-symbols command."""
94
95 module_paths = []
96 module_files = []
97 module_files_updated = False
82b41e3d
JK
98 loaded_modules = []
99 breakpoint = None
66051720
JK
100
101 def __init__(self):
102 super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
103 gdb.COMPLETE_FILENAME)
104
105 def _update_module_files(self):
106 self.module_files = []
107 for path in self.module_paths:
108 gdb.write("scanning for modules in {0}\n".format(path))
109 for root, dirs, files in os.walk(path):
110 for name in files:
da036ae1 111 if name.endswith(".ko") or name.endswith(".ko.debug"):
66051720
JK
112 self.module_files.append(root + "/" + name)
113 self.module_files_updated = True
114
115 def _get_module_file(self, module_name):
ded79af4 116 module_pattern = r".*/{0}\.ko(?:.debug)?$".format(
276d97d9 117 module_name.replace("_", r"[_\-]"))
66051720
JK
118 for name in self.module_files:
119 if re.match(module_pattern, name) and os.path.exists(name):
120 return name
121 return None
122
1677bf76 123 def _section_arguments(self, module, module_addr):
66051720
JK
124 try:
125 sect_attrs = module['sect_attrs'].dereference()
126 except gdb.error:
1677bf76
KI
127 return str(module_addr)
128
e0349c46
AQ
129 section_name_to_address = {}
130 for i in count():
131 # this is a NULL terminated array
132 if sect_attrs['grp']['bin_attrs'][i] == 0x0:
133 break
134
135 attr = sect_attrs['grp']['bin_attrs'][i].dereference()
136 section_name_to_address[attr['attr']['name'].string()] = attr['private']
1677bf76
KI
137
138 textaddr = section_name_to_address.get(".text", module_addr)
66051720 139 args = []
8731acc5 140 for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
1677bf76 141 ".text.hot", ".text.unlikely"]:
66051720
JK
142 address = section_name_to_address.get(section_name)
143 if address:
144 args.append(" -s {name} {addr}".format(
145 name=section_name, addr=str(address)))
1677bf76
KI
146 return "{textaddr} {sections}".format(
147 textaddr=textaddr, sections="".join(args))
66051720 148
493d4eec 149 def load_module_symbols(self, module):
66051720 150 module_name = module['name'].string()
b4aff751 151 module_addr = str(module['mem'][constants.LX_MOD_TEXT]['base']).split()[0]
66051720 152
493d4eec 153 module_file = self._get_module_file(module_name)
66051720
JK
154 if not module_file and not self.module_files_updated:
155 self._update_module_files()
156 module_file = self._get_module_file(module_name)
157
158 if module_file:
585d730d
IL
159 if utils.is_target_arch('s390'):
160 # Module text is preceded by PLT stubs on s390.
161 module_arch = module['arch']
162 plt_offset = int(module_arch['plt_offset'])
163 plt_size = int(module_arch['plt_size'])
164 module_addr = hex(int(module_addr, 0) + plt_offset + plt_size)
66051720
JK
165 gdb.write("loading @{addr}: {filename}\n".format(
166 addr=module_addr, filename=module_file))
1677bf76 167 cmdline = "add-symbol-file {filename} {sections}".format(
66051720 168 filename=module_file,
1677bf76 169 sections=self._section_arguments(module, module_addr))
66051720 170 gdb.execute(cmdline, to_string=True)
6ad18b73 171 if module_name not in self.loaded_modules:
82b41e3d 172 self.loaded_modules.append(module_name)
66051720
JK
173 else:
174 gdb.write("no module object found for '{0}'\n".format(module_name))
175
176 def load_all_symbols(self):
177 gdb.write("loading vmlinux\n")
178
179 # Dropping symbols will disable all breakpoints. So save their states
180 # and restore them afterward.
181 saved_states = []
182 if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
183 for bp in gdb.breakpoints():
184 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
185
186 # drop all current symbols and reload vmlinux
3545414f 187 orig_vmlinux = utils.get_vmlinux()
66051720 188 gdb.execute("symbol-file", to_string=True)
28939c3e
IL
189 kerneloffset = get_kerneloffset()
190 if kerneloffset is None:
191 offset_arg = ""
192 else:
193 offset_arg = " -o " + hex(kerneloffset)
194 gdb.execute("symbol-file {0}{1}".format(orig_vmlinux, offset_arg))
66051720 195
82b41e3d 196 self.loaded_modules = []
fffb944c 197 module_list = modules.module_list()
66051720
JK
198 if not module_list:
199 gdb.write("no modules found\n")
200 else:
201 [self.load_module_symbols(module) for module in module_list]
202
203 for saved_state in saved_states:
204 saved_state['breakpoint'].enabled = saved_state['enabled']
205
206 def invoke(self, arg, from_tty):
23921540
JB
207 self.module_paths = [os.path.abspath(os.path.expanduser(p))
208 for p in arg.split()]
66051720
JK
209 self.module_paths.append(os.getcwd())
210
211 # enforce update
212 self.module_files = []
213 self.module_files_updated = False
214
215 self.load_all_symbols()
216
2c259a91
EB
217 if not modules.has_modules():
218 return
219
82b41e3d 220 if hasattr(gdb, 'Breakpoint'):
6ad18b73 221 if self.breakpoint is not None:
82b41e3d
JK
222 self.breakpoint.delete()
223 self.breakpoint = None
224 self.breakpoint = LoadModuleBreakpoint(
23a67619 225 "kernel/module/main.c:do_init_module", self)
82b41e3d
JK
226 else:
227 gdb.write("Note: symbol update on module loading not supported "
228 "with this gdb version\n")
229
66051720
JK
230
231LxSymbols()