Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / scripts / gdb / linux / symbols.py
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
14 import gdb
15 import os
16 import re
17 import string
18
19 from linux import modules, utils
20
21
22 if 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             # Disable pagination while reporting symbol (re-)loading.
38             # The console input is blocked in this context so that we would
39             # get stuck waiting for the user to acknowledge paged output.
40             show_pagination = gdb.execute("show pagination", to_string=True)
41             pagination = show_pagination.endswith("on.\n")
42             gdb.execute("set pagination off")
43
44             if module_name in cmd.loaded_modules:
45                 gdb.write("refreshing all symbols to reload module "
46                           "'{0}'\n".format(module_name))
47                 cmd.load_all_symbols()
48             else:
49                 cmd.load_module_symbols(module)
50
51             # restore pagination state
52             gdb.execute("set pagination %s" % ("on" if pagination else "off"))
53
54             return False
55
56
57 class LxSymbols(gdb.Command):
58     """(Re-)load symbols of Linux kernel and currently loaded modules.
59
60 The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
61 are scanned recursively, starting in the same directory. Optionally, the module
62 search path can be extended by a space separated list of paths passed to the
63 lx-symbols command."""
64
65     module_paths = []
66     module_files = []
67     module_files_updated = False
68     loaded_modules = []
69     breakpoint = None
70
71     def __init__(self):
72         super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
73                                         gdb.COMPLETE_FILENAME)
74
75     def _update_module_files(self):
76         self.module_files = []
77         for path in self.module_paths:
78             gdb.write("scanning for modules in {0}\n".format(path))
79             for root, dirs, files in os.walk(path):
80                 for name in files:
81                     if name.endswith(".ko"):
82                         self.module_files.append(root + "/" + name)
83         self.module_files_updated = True
84
85     def _get_module_file(self, module_name):
86         module_pattern = ".*/{0}\.ko$".format(
87             module_name.replace("_", r"[_\-]"))
88         for name in self.module_files:
89             if re.match(module_pattern, name) and os.path.exists(name):
90                 return name
91         return None
92
93     def _section_arguments(self, module):
94         try:
95             sect_attrs = module['sect_attrs'].dereference()
96         except gdb.error:
97             return ""
98         attrs = sect_attrs['attrs']
99         section_name_to_address = {
100             attrs[n]['name'].string() : attrs[n]['address']
101             for n in range(int(sect_attrs['nsections']))}
102         args = []
103         for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
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()
112         module_addr = str(module['module_core']).split()[0]
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:
120             gdb.write("loading @{addr}: {filename}\n".format(
121                 addr=module_addr, filename=module_file))
122             cmdline = "add-symbol-file {filename} {addr}{sections}".format(
123                 filename=module_file,
124                 addr=module_addr,
125                 sections=self._section_arguments(module))
126             gdb.execute(cmdline, to_string=True)
127             if not module_name in self.loaded_modules:
128                 self.loaded_modules.append(module_name)
129         else:
130             gdb.write("no module object found for '{0}'\n".format(module_name))
131
132     def load_all_symbols(self):
133         gdb.write("loading vmlinux\n")
134
135         # Dropping symbols will disable all breakpoints. So save their states
136         # and restore them afterward.
137         saved_states = []
138         if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
139             for bp in gdb.breakpoints():
140                 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
141
142         # drop all current symbols and reload vmlinux
143         gdb.execute("symbol-file", to_string=True)
144         gdb.execute("symbol-file vmlinux")
145
146         self.loaded_modules = []
147         module_list = modules.module_list()
148         if not module_list:
149             gdb.write("no modules found\n")
150         else:
151             [self.load_module_symbols(module) for module in module_list]
152
153         for saved_state in saved_states:
154             saved_state['breakpoint'].enabled = saved_state['enabled']
155
156     def invoke(self, arg, from_tty):
157         self.module_paths = arg.split()
158         self.module_paths.append(os.getcwd())
159
160         # enforce update
161         self.module_files = []
162         self.module_files_updated = False
163
164         self.load_all_symbols()
165
166         if hasattr(gdb, 'Breakpoint'):
167             if not self.breakpoint is None:
168                 self.breakpoint.delete()
169                 self.breakpoint = None
170             self.breakpoint = LoadModuleBreakpoint(
171                 "kernel/module.c:do_init_module", self)
172         else:
173             gdb.write("Note: symbol update on module loading not supported "
174                       "with this gdb version\n")
175
176
177 LxSymbols()