Commit | Line | Data |
---|---|---|
850202e1 JK |
1 | # |
2 | # gdb helper commands and functions for Linux kernel debugging | |
3 | # | |
4 | # module tools | |
5 | # | |
6 | # Copyright (c) Siemens AG, 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 | ||
5403727f | 16 | from linux import cpus, utils |
850202e1 JK |
17 | |
18 | ||
19 | module_type = utils.CachedType("struct module") | |
20 | ||
21 | ||
22 | class ModuleList: | |
23 | def __init__(self): | |
24 | global module_type | |
25 | self.module_ptr_type = module_type.get_type().pointer() | |
26 | modules = gdb.parse_and_eval("modules") | |
27 | self.curr_entry = modules['next'] | |
28 | self.end_of_list = modules.address | |
29 | ||
30 | def __iter__(self): | |
31 | return self | |
32 | ||
33 | def next(self): | |
34 | entry = self.curr_entry | |
35 | if entry != self.end_of_list: | |
36 | self.curr_entry = entry['next'] | |
37 | return utils.container_of(entry, self.module_ptr_type, "list") | |
38 | else: | |
39 | raise StopIteration | |
7b599ef5 JK |
40 | |
41 | ||
42 | def find_module_by_name(name): | |
43 | for module in ModuleList(): | |
44 | if module['name'].string() == name: | |
45 | return module | |
46 | return None | |
47 | ||
48 | ||
49 | class LxModule(gdb.Function): | |
50 | """Find module by name and return the module variable. | |
51 | ||
52 | $lx_module("MODULE"): Given the name MODULE, iterate over all loaded modules | |
53 | of the target and return that module variable which MODULE matches.""" | |
54 | ||
55 | def __init__(self): | |
56 | super(LxModule, self).__init__("lx_module") | |
57 | ||
58 | def invoke(self, mod_name): | |
59 | mod_name = mod_name.string() | |
60 | module = find_module_by_name(mod_name) | |
61 | if module: | |
62 | return module.dereference() | |
63 | else: | |
64 | raise gdb.GdbError("Unable to find MODULE " + mod_name) | |
65 | ||
66 | ||
67 | LxModule() | |
5403727f JK |
68 | |
69 | ||
70 | class LxLsmod(gdb.Command): | |
71 | """List currently loaded modules.""" | |
72 | ||
73 | _module_use_type = utils.CachedType("struct module_use") | |
74 | ||
75 | def __init__(self): | |
76 | super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA) | |
77 | ||
78 | def invoke(self, arg, from_tty): | |
79 | gdb.write( | |
80 | "Address{0} Module Size Used by\n".format( | |
81 | " " if utils.get_long_type().sizeof == 8 else "")) | |
82 | ||
83 | for module in ModuleList(): | |
84 | ref = 0 | |
85 | module_refptr = module['refptr'] | |
86 | for cpu in cpus.CpuList("cpu_possible_mask"): | |
87 | refptr = cpus.per_cpu(module_refptr, cpu) | |
88 | ref += refptr['incs'] | |
89 | ref -= refptr['decs'] | |
90 | ||
91 | gdb.write("{address} {name:<19} {size:>8} {ref}".format( | |
92 | address=str(module['module_core']).split()[0], | |
93 | name=module['name'].string(), | |
94 | size=module['core_size'], | |
95 | ref=ref)) | |
96 | ||
97 | source_list = module['source_list'] | |
98 | t = self._module_use_type.get_type().pointer() | |
99 | entry = source_list['next'] | |
100 | first = True | |
101 | while entry != source_list.address: | |
102 | use = utils.container_of(entry, t, "source_list") | |
103 | gdb.write("{separator}{name}".format( | |
104 | separator=" " if first else ",", | |
105 | name=use['source']['name'].string())) | |
106 | first = False | |
107 | entry = entry['next'] | |
108 | gdb.write("\n") | |
109 | ||
110 | ||
111 | LxLsmod() |