aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2015-02-17 16:46:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 17:34:53 -0500
commit66051720b84127cac32f34a30c91390c0ebf898f (patch)
tree88691dacbeb44bea0912ae7f6482d1b424676065 /scripts
parent850202e17df68c51593bab36a26c8d9279f8c029 (diff)
scripts/gdb: add lx-symbols command
This is probably the most useful helper when debugging kernel modules: lx-symbols first reloads vmlinux. Then it searches recursively for *.ko files in the specified paths and the current directory. Finally it walks the kernel's module list, issuing the necessary add-symbol-file command for each loaded module so that gdb knows which module symbol corresponds to which address. It also looks up variable sections (bss, data, rodata) and appends their address to the add-symbole-file command line. This allows to access global module variables just like any other variable. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Wessel <jason.wessel@windriver.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ben Widawsky <ben@bwidawsk.net> Cc: Borislav Petkov <bp@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/gdb/linux/symbols.py127
-rw-r--r--scripts/gdb/vmlinux-gdb.py1
2 files changed, 128 insertions, 0 deletions
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
new file mode 100644
index 000000000000..bd21a9624428
--- /dev/null
+++ b/scripts/gdb/linux/symbols.py
@@ -0,0 +1,127 @@
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
22class LxSymbols(gdb.Command):
23 """(Re-)load symbols of Linux kernel and currently loaded modules.
24
25The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
26are scanned recursively, starting in the same directory. Optionally, the module
27search path can be extended by a space separated list of paths passed to the
28lx-symbols command."""
29
30 module_paths = []
31 module_files = []
32 module_files_updated = False
33
34 def __init__(self):
35 super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
36 gdb.COMPLETE_FILENAME)
37
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):
43 for name in files:
44 if name.endswith(".ko"):
45 self.module_files.append(root + "/" + name)
46 self.module_files_updated = True
47
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):
53 return name
54 return None
55
56 def _section_arguments(self, module):
57 try:
58 sect_attrs = module['sect_attrs'].dereference()
59 except gdb.error:
60 return ""
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'])}
65 args = []
66 for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
67 address = section_name_to_address.get(section_name)
68 if address:
69 args.append(" -s {name} {addr}".format(
70 name=section_name, addr=str(address)))
71 return "".join(args)
72
73 def load_module_symbols(self, module):
74 module_name = module['name'].string()
75 module_addr = str(module['module_core']).split()[0]
76
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)
81
82 if module_file:
83 gdb.write("loading @{addr}: {filename}\n".format(
84 addr=module_addr, filename=module_file))
85 cmdline = "add-symbol-file {filename} {addr}{sections}".format(
86 filename=module_file,
87 addr=module_addr,
88 sections=self._section_arguments(module))
89 gdb.execute(cmdline, to_string=True)
90 else:
91 gdb.write("no module object found for '{0}'\n".format(module_name))
92
93 def load_all_symbols(self):
94 gdb.write("loading vmlinux\n")
95
96 # Dropping symbols will disable all breakpoints. So save their states
97 # and restore them afterward.
98 saved_states = []
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})
102
103 # drop all current symbols and reload vmlinux
104 gdb.execute("symbol-file", to_string=True)
105 gdb.execute("symbol-file vmlinux")
106
107 module_list = modules.ModuleList()
108 if not module_list:
109 gdb.write("no modules found\n")
110 else:
111 [self.load_module_symbols(module) for module in module_list]
112
113 for saved_state in saved_states:
114 saved_state['breakpoint'].enabled = saved_state['enabled']
115
116 def invoke(self, arg, from_tty):
117 self.module_paths = arg.split()
118 self.module_paths.append(os.getcwd())
119
120 # enforce update
121 self.module_files = []
122 self.module_files_updated = False
123
124 self.load_all_symbols()
125
126
127LxSymbols()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 649584105a72..0b0faa4cb5a0 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -23,3 +23,4 @@ except:
23 "work.\n") 23 "work.\n")
24else: 24else:
25 import linux.utils 25 import linux.utils
26 import linux.symbols