blob: 7f36aee32ac66d97a71135bff1d96336bc2c0a45 [file] [log] [blame]
Jan Kiszka2b514822015-02-17 13:46:38 -08001#
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
14import gdb
15
16
17class 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
Jan Kiszkab0fecd82015-02-17 13:46:41 -080035
36
37long_type = CachedType("long")
Antonio Borneo45382d62022-07-19 14:28:31 +020038atomic_long_type = CachedType("atomic_long_t")
Jan Kiszkab0fecd82015-02-17 13:46:41 -080039
40def get_long_type():
41 global long_type
42 return long_type.get_type()
43
Jan Kiszkab0fecd82015-02-17 13:46:41 -080044def offset_of(typeobj, field):
45 element = gdb.Value(0).cast(typeobj)
46 return int(str(element[field].address).split()[0], 16)
47
48
49def container_of(ptr, typeobj, member):
50 return (ptr.cast(get_long_type()) -
51 offset_of(typeobj, member)).cast(typeobj)
52
53
54class ContainerOf(gdb.Function):
55 """Return pointer to containing data structure.
56
57$container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
58data structure of the type TYPE in which PTR is the address of ELEMENT.
59Note 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
Stephen Boyd494dbe02019-05-14 15:46:02 -070068
Jan Kiszkab0fecd82015-02-17 13:46:41 -080069ContainerOf()
Jan Kiszka7f994962015-02-17 13:46:58 -080070
71
72BIG_ENDIAN = 0
73LITTLE_ENDIAN = 1
74target_endianness = None
75
76
77def 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:
ThiƩbaud Weksteena2e73c42015-06-30 14:58:16 -070086 raise gdb.GdbError("unknown endianness '{0}'".format(str(endian)))
Jan Kiszka7f994962015-02-17 13:46:58 -080087 return target_endianness
Jan Kiszka78e87812015-02-17 13:47:01 -080088
89
Dom Cote321958d2016-05-23 16:25:16 -070090def read_memoryview(inf, start, length):
Peng Liu14383692023-03-21 14:19:29 +080091 m = inf.read_memory(start, length)
92 if type(m) is memoryview:
93 return m
94 return memoryview(m)
Dom Cote321958d2016-05-23 16:25:16 -070095
96
Joel Colledgeca210ba2019-10-18 20:19:26 -070097def read_u16(buffer, offset):
98 buffer_val = buffer[offset:offset + 2]
Dom Cote321958d2016-05-23 16:25:16 -070099 value = [0, 0]
100
Joel Colledgeca210ba2019-10-18 20:19:26 -0700101 if type(buffer_val[0]) is str:
102 value[0] = ord(buffer_val[0])
103 value[1] = ord(buffer_val[1])
Jan Kiszka78e87812015-02-17 13:47:01 -0800104 else:
Joel Colledgeca210ba2019-10-18 20:19:26 -0700105 value[0] = buffer_val[0]
106 value[1] = buffer_val[1]
Dom Cote321958d2016-05-23 16:25:16 -0700107
108 if get_target_endianness() == LITTLE_ENDIAN:
109 return value[0] + (value[1] << 8)
110 else:
111 return value[1] + (value[0] << 8)
Jan Kiszka78e87812015-02-17 13:47:01 -0800112
113
Joel Colledgeca210ba2019-10-18 20:19:26 -0700114def read_u32(buffer, offset):
Jan Kiszka78e87812015-02-17 13:47:01 -0800115 if get_target_endianness() == LITTLE_ENDIAN:
Joel Colledgeca210ba2019-10-18 20:19:26 -0700116 return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
Jan Kiszka78e87812015-02-17 13:47:01 -0800117 else:
Joel Colledgeca210ba2019-10-18 20:19:26 -0700118 return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
Jan Kiszka78e87812015-02-17 13:47:01 -0800119
120
Joel Colledgeca210ba2019-10-18 20:19:26 -0700121def read_u64(buffer, offset):
Jan Kiszka78e87812015-02-17 13:47:01 -0800122 if get_target_endianness() == LITTLE_ENDIAN:
Joel Colledgeca210ba2019-10-18 20:19:26 -0700123 return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
Jan Kiszka78e87812015-02-17 13:47:01 -0800124 else:
Joel Colledgeca210ba2019-10-18 20:19:26 -0700125 return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
Jan Kiszkab24e2d22015-02-17 13:47:12 -0800126
127
John Ogness3e0d0752020-08-14 23:31:24 +0206128def 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
Antonio Borneo45382d62022-07-19 14:28:31 +0200134atomic_long_counter_offset = atomic_long_type.get_type()['counter'].bitpos
135atomic_long_counter_sizeof = atomic_long_type.get_type()['counter'].type.sizeof
136
137def 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)
John Ogness3e0d0752020-08-14 23:31:24 +0206145
Jan Kiszkab24e2d22015-02-17 13:47:12 -0800146target_arch = None
147
148
149def 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
Jan Kiszkaa4d86792015-02-17 13:47:18 -0800157
158
159GDBSERVER_QEMU = 0
160GDBSERVER_KGDB = 1
161gdbserver_type = None
162
163
164def 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) != ""
Stephen Boyd494dbe02019-05-14 15:46:02 -0700173 except gdb.error:
Jan Kiszkaa4d86792015-02-17 13:47:18 -0800174 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
Stephen Boyd494dbe02019-05-14 15:46:02 -0700180 except gdb.error:
Jan Kiszkaa4d86792015-02-17 13:47:18 -0800181 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
ThiƩbaud Weksteen6ad18b72015-06-30 14:58:18 -0700189 if gdbserver_type is not None and hasattr(gdb, 'events'):
Jan Kiszkaa4d86792015-02-17 13:47:18 -0800190 gdb.events.exited.connect(exit_handler)
191 return gdbserver_type
Kieran Binghame78f3d72016-05-23 16:24:48 -0700192
193
194def gdb_eval_or_none(expresssion):
195 try:
196 return gdb.parse_and_eval(expresssion)
Stephen Boyd494dbe02019-05-14 15:46:02 -0700197 except gdb.error:
Kieran Binghame78f3d72016-05-23 16:24:48 -0700198 return None
Kieran Bingham74627cf2016-05-23 16:24:53 -0700199
200
201def 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()