diff options
Diffstat (limited to 'scripts/gdb/linux/utils.py')
-rw-r--r-- | scripts/gdb/linux/utils.py | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py new file mode 100644 index 000000000000..128c306db3ee --- /dev/null +++ b/scripts/gdb/linux/utils.py | |||
@@ -0,0 +1,156 @@ | |||
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 | ||
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() | ||
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(str(endian))) | ||
87 | return target_endianness | ||
88 | |||
89 | |||
90 | def read_u16(buffer): | ||
91 | if get_target_endianness() == LITTLE_ENDIAN: | ||
92 | return ord(buffer[0]) + (ord(buffer[1]) << 8) | ||
93 | else: | ||
94 | return ord(buffer[1]) + (ord(buffer[0]) << 8) | ||
95 | |||
96 | |||
97 | def read_u32(buffer): | ||
98 | if get_target_endianness() == LITTLE_ENDIAN: | ||
99 | return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16) | ||
100 | else: | ||
101 | return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16) | ||
102 | |||
103 | |||
104 | def read_u64(buffer): | ||
105 | if get_target_endianness() == LITTLE_ENDIAN: | ||
106 | return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32) | ||
107 | else: | ||
108 | return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32) | ||
109 | |||
110 | |||
111 | target_arch = None | ||
112 | |||
113 | |||
114 | def is_target_arch(arch): | ||
115 | if hasattr(gdb.Frame, 'architecture'): | ||
116 | return arch in gdb.newest_frame().architecture().name() | ||
117 | else: | ||
118 | global target_arch | ||
119 | if target_arch is None: | ||
120 | target_arch = gdb.execute("show architecture", to_string=True) | ||
121 | return arch in target_arch | ||
122 | |||
123 | |||
124 | GDBSERVER_QEMU = 0 | ||
125 | GDBSERVER_KGDB = 1 | ||
126 | gdbserver_type = None | ||
127 | |||
128 | |||
129 | def get_gdbserver_type(): | ||
130 | def exit_handler(event): | ||
131 | global gdbserver_type | ||
132 | gdbserver_type = None | ||
133 | gdb.events.exited.disconnect(exit_handler) | ||
134 | |||
135 | def probe_qemu(): | ||
136 | try: | ||
137 | return gdb.execute("monitor info version", to_string=True) != "" | ||
138 | except: | ||
139 | return False | ||
140 | |||
141 | def probe_kgdb(): | ||
142 | try: | ||
143 | thread_info = gdb.execute("info thread 2", to_string=True) | ||
144 | return "shadowCPU0" in thread_info | ||
145 | except: | ||
146 | return False | ||
147 | |||
148 | global gdbserver_type | ||
149 | if gdbserver_type is None: | ||
150 | if probe_qemu(): | ||
151 | gdbserver_type = GDBSERVER_QEMU | ||
152 | elif probe_kgdb(): | ||
153 | gdbserver_type = GDBSERVER_KGDB | ||
154 | if not gdbserver_type is None and hasattr(gdb, 'events'): | ||
155 | gdb.events.exited.connect(exit_handler) | ||
156 | return gdbserver_type | ||