]>
Commit | Line | Data |
---|---|---|
2b514827 JK |
1 | # |
2 | # gdb helper commands and functions for Linux kernel debugging | |
3 | # | |
4 | # common utilities | |
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 | ||
16 | ||
17 | class CachedType: | |
18 | def __init__(self, name): | |
19 | self._type = None | |
20 | self._name = name | |
21 | ||
22 | def _new_objfile_handler(self, event): | |
23 | self._type = None | |
24 | gdb.events.new_objfile.disconnect(self._new_objfile_handler) | |
25 | ||
26 | def get_type(self): | |
27 | if self._type is None: | |
28 | self._type = gdb.lookup_type(self._name) | |
29 | if self._type is None: | |
30 | raise gdb.GdbError( | |
31 | "cannot resolve type '{0}'".format(self._name)) | |
32 | if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'): | |
33 | gdb.events.new_objfile.connect(self._new_objfile_handler) | |
34 | return self._type | |
b0fecd8c JK |
35 | |
36 | ||
37 | long_type = CachedType("long") | |
38 | ||
39 | ||
40 | def get_long_type(): | |
41 | global long_type | |
42 | return long_type.get_type() | |
43 | ||
44 | ||
45 | def offset_of(typeobj, field): | |
46 | element = gdb.Value(0).cast(typeobj) | |
47 | return int(str(element[field].address).split()[0], 16) | |
48 | ||
49 | ||
50 | def container_of(ptr, typeobj, member): | |
51 | return (ptr.cast(get_long_type()) - | |
52 | offset_of(typeobj, member)).cast(typeobj) | |
53 | ||
54 | ||
55 | class ContainerOf(gdb.Function): | |
56 | """Return pointer to containing data structure. | |
57 | ||
58 | $container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the | |
59 | data structure of the type TYPE in which PTR is the address of ELEMENT. | |
60 | Note that TYPE and ELEMENT have to be quoted as strings.""" | |
61 | ||
62 | def __init__(self): | |
63 | super(ContainerOf, self).__init__("container_of") | |
64 | ||
65 | def invoke(self, ptr, typename, elementname): | |
66 | return container_of(ptr, gdb.lookup_type(typename.string()).pointer(), | |
67 | elementname.string()) | |
68 | ||
69 | ContainerOf() | |
7f994963 JK |
70 | |
71 | ||
72 | BIG_ENDIAN = 0 | |
73 | LITTLE_ENDIAN = 1 | |
74 | target_endianness = None | |
75 | ||
76 | ||
77 | def get_target_endianness(): | |
78 | global target_endianness | |
79 | if target_endianness is None: | |
80 | endian = gdb.execute("show endian", to_string=True) | |
81 | if "little endian" in endian: | |
82 | target_endianness = LITTLE_ENDIAN | |
83 | elif "big endian" in endian: | |
84 | target_endianness = BIG_ENDIAN | |
85 | else: | |
a2e73c48 | 86 | raise gdb.GdbError("unknown endianness '{0}'".format(str(endian))) |
7f994963 | 87 | return target_endianness |
78e87817 JK |
88 | |
89 | ||
321958d9 DC |
90 | def read_memoryview(inf, start, length): |
91 | return memoryview(inf.read_memory(start, length)) | |
92 | ||
93 | ||
78e87817 | 94 | def read_u16(buffer): |
321958d9 DC |
95 | value = [0, 0] |
96 | ||
97 | if type(buffer[0]) is str: | |
98 | value[0] = ord(buffer[0]) | |
99 | value[1] = ord(buffer[1]) | |
100 | else: | |
101 | value[0] = buffer[0] | |
102 | value[1] = buffer[1] | |
103 | ||
78e87817 | 104 | if get_target_endianness() == LITTLE_ENDIAN: |
321958d9 | 105 | return value[0] + (value[1] << 8) |
78e87817 | 106 | else: |
321958d9 | 107 | return value[1] + (value[0] << 8) |
78e87817 JK |
108 | |
109 | ||
110 | def read_u32(buffer): | |
111 | if get_target_endianness() == LITTLE_ENDIAN: | |
112 | return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16) | |
113 | else: | |
114 | return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16) | |
115 | ||
116 | ||
117 | def read_u64(buffer): | |
118 | if get_target_endianness() == LITTLE_ENDIAN: | |
119 | return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32) | |
120 | else: | |
121 | return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32) | |
b24e2d21 JK |
122 | |
123 | ||
124 | target_arch = None | |
125 | ||
126 | ||
127 | def is_target_arch(arch): | |
128 | if hasattr(gdb.Frame, 'architecture'): | |
129 | return arch in gdb.newest_frame().architecture().name() | |
130 | else: | |
131 | global target_arch | |
132 | if target_arch is None: | |
133 | target_arch = gdb.execute("show architecture", to_string=True) | |
134 | return arch in target_arch | |
a4d86792 JK |
135 | |
136 | ||
137 | GDBSERVER_QEMU = 0 | |
138 | GDBSERVER_KGDB = 1 | |
139 | gdbserver_type = None | |
140 | ||
141 | ||
142 | def get_gdbserver_type(): | |
143 | def exit_handler(event): | |
144 | global gdbserver_type | |
145 | gdbserver_type = None | |
146 | gdb.events.exited.disconnect(exit_handler) | |
147 | ||
148 | def probe_qemu(): | |
149 | try: | |
150 | return gdb.execute("monitor info version", to_string=True) != "" | |
151 | except: | |
152 | return False | |
153 | ||
154 | def probe_kgdb(): | |
155 | try: | |
156 | thread_info = gdb.execute("info thread 2", to_string=True) | |
157 | return "shadowCPU0" in thread_info | |
158 | except: | |
159 | return False | |
160 | ||
161 | global gdbserver_type | |
162 | if gdbserver_type is None: | |
163 | if probe_qemu(): | |
164 | gdbserver_type = GDBSERVER_QEMU | |
165 | elif probe_kgdb(): | |
166 | gdbserver_type = GDBSERVER_KGDB | |
6ad18b73 | 167 | if gdbserver_type is not None and hasattr(gdb, 'events'): |
a4d86792 JK |
168 | gdb.events.exited.connect(exit_handler) |
169 | return gdbserver_type | |
e78f3d70 KB |
170 | |
171 | ||
172 | def gdb_eval_or_none(expresssion): | |
173 | try: | |
174 | return gdb.parse_and_eval(expresssion) | |
175 | except: | |
176 | return None | |
74627cf2 KB |
177 | |
178 | ||
179 | def dentry_name(d): | |
180 | parent = d['d_parent'] | |
181 | if parent == d or parent == 0: | |
182 | return "" | |
183 | p = dentry_name(d['d_parent']) + "/" | |
184 | return p + d['d_iname'].string() |