]>
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: | |
86 | raise gdb.GdgError("unknown endianness '{0}'".format(endian)) | |
87 | return target_endianness |