GNU Linux-libre 5.15.137-gnu
[releases.git] / scripts / gdb / linux / utils.py
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 atomic_long_type = CachedType("atomic_long_t")
39
40 def get_long_type():
41     global long_type
42     return long_type.get_type()
43
44 def offset_of(typeobj, field):
45     element = gdb.Value(0).cast(typeobj)
46     return int(str(element[field].address).split()[0], 16)
47
48
49 def container_of(ptr, typeobj, member):
50     return (ptr.cast(get_long_type()) -
51             offset_of(typeobj, member)).cast(typeobj)
52
53
54 class ContainerOf(gdb.Function):
55     """Return pointer to containing data structure.
56
57 $container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
58 data structure of the type TYPE in which PTR is the address of ELEMENT.
59 Note that TYPE and ELEMENT have to be quoted as strings."""
60
61     def __init__(self):
62         super(ContainerOf, self).__init__("container_of")
63
64     def invoke(self, ptr, typename, elementname):
65         return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
66                             elementname.string())
67
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.GdbError("unknown endianness '{0}'".format(str(endian)))
87     return target_endianness
88
89
90 def read_memoryview(inf, start, length):
91     m = inf.read_memory(start, length)
92     if type(m) is memoryview:
93         return m
94     return memoryview(m)
95
96
97 def read_u16(buffer, offset):
98     buffer_val = buffer[offset:offset + 2]
99     value = [0, 0]
100
101     if type(buffer_val[0]) is str:
102         value[0] = ord(buffer_val[0])
103         value[1] = ord(buffer_val[1])
104     else:
105         value[0] = buffer_val[0]
106         value[1] = buffer_val[1]
107
108     if get_target_endianness() == LITTLE_ENDIAN:
109         return value[0] + (value[1] << 8)
110     else:
111         return value[1] + (value[0] << 8)
112
113
114 def read_u32(buffer, offset):
115     if get_target_endianness() == LITTLE_ENDIAN:
116         return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
117     else:
118         return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
119
120
121 def read_u64(buffer, offset):
122     if get_target_endianness() == LITTLE_ENDIAN:
123         return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
124     else:
125         return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
126
127
128 def read_ulong(buffer, offset):
129     if get_long_type().sizeof == 8:
130         return read_u64(buffer, offset)
131     else:
132         return read_u32(buffer, offset)
133
134 atomic_long_counter_offset = atomic_long_type.get_type()['counter'].bitpos
135 atomic_long_counter_sizeof = atomic_long_type.get_type()['counter'].type.sizeof
136
137 def read_atomic_long(buffer, offset):
138     global atomic_long_counter_offset
139     global atomic_long_counter_sizeof
140
141     if atomic_long_counter_sizeof == 8:
142         return read_u64(buffer, offset + atomic_long_counter_offset)
143     else:
144         return read_u32(buffer, offset + atomic_long_counter_offset)
145
146 target_arch = None
147
148
149 def is_target_arch(arch):
150     if hasattr(gdb.Frame, 'architecture'):
151         return arch in gdb.newest_frame().architecture().name()
152     else:
153         global target_arch
154         if target_arch is None:
155             target_arch = gdb.execute("show architecture", to_string=True)
156         return arch in target_arch
157
158
159 GDBSERVER_QEMU = 0
160 GDBSERVER_KGDB = 1
161 gdbserver_type = None
162
163
164 def get_gdbserver_type():
165     def exit_handler(event):
166         global gdbserver_type
167         gdbserver_type = None
168         gdb.events.exited.disconnect(exit_handler)
169
170     def probe_qemu():
171         try:
172             return gdb.execute("monitor info version", to_string=True) != ""
173         except gdb.error:
174             return False
175
176     def probe_kgdb():
177         try:
178             thread_info = gdb.execute("info thread 2", to_string=True)
179             return "shadowCPU0" in thread_info
180         except gdb.error:
181             return False
182
183     global gdbserver_type
184     if gdbserver_type is None:
185         if probe_qemu():
186             gdbserver_type = GDBSERVER_QEMU
187         elif probe_kgdb():
188             gdbserver_type = GDBSERVER_KGDB
189         if gdbserver_type is not None and hasattr(gdb, 'events'):
190             gdb.events.exited.connect(exit_handler)
191     return gdbserver_type
192
193
194 def gdb_eval_or_none(expresssion):
195     try:
196         return gdb.parse_and_eval(expresssion)
197     except gdb.error:
198         return None
199
200
201 def dentry_name(d):
202     parent = d['d_parent']
203     if parent == d or parent == 0:
204         return ""
205     p = dentry_name(d['d_parent']) + "/"
206     return p + d['d_iname'].string()