]> git.karo-electronics.de Git - karo-tx-linux.git/blob - scripts/gdb/linux/symbols.py
bd21a962442855a100180b30e6d1e5a56e4dde7c
[karo-tx-linux.git] / 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 class LxSymbols(gdb.Command):
23     """(Re-)load symbols of Linux kernel and currently loaded modules.
24
25 The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
26 are scanned recursively, starting in the same directory. Optionally, the module
27 search path can be extended by a space separated list of paths passed to the
28 lx-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
127 LxSymbols()