]> Git Repo - linux.git/blob - scripts/gdb/linux/utils.py
Merge tag 'drm-misc-next-2022-08-20-1' of git://anongit.freedesktop.org/drm/drm-misc...
[linux.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 <[email protected]>
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     return memoryview(inf.read_memory(start, length))
92
93
94 def read_u16(buffer, offset):
95     buffer_val = buffer[offset:offset + 2]
96     value = [0, 0]
97
98     if type(buffer_val[0]) is str:
99         value[0] = ord(buffer_val[0])
100         value[1] = ord(buffer_val[1])
101     else:
102         value[0] = buffer_val[0]
103         value[1] = buffer_val[1]
104
105     if get_target_endianness() == LITTLE_ENDIAN:
106         return value[0] + (value[1] << 8)
107     else:
108         return value[1] + (value[0] << 8)
109
110
111 def read_u32(buffer, offset):
112     if get_target_endianness() == LITTLE_ENDIAN:
113         return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
114     else:
115         return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
116
117
118 def read_u64(buffer, offset):
119     if get_target_endianness() == LITTLE_ENDIAN:
120         return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
121     else:
122         return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
123
124
125 def read_ulong(buffer, offset):
126     if get_long_type().sizeof == 8:
127         return read_u64(buffer, offset)
128     else:
129         return read_u32(buffer, offset)
130
131 atomic_long_counter_offset = atomic_long_type.get_type()['counter'].bitpos
132 atomic_long_counter_sizeof = atomic_long_type.get_type()['counter'].type.sizeof
133
134 def read_atomic_long(buffer, offset):
135     global atomic_long_counter_offset
136     global atomic_long_counter_sizeof
137
138     if atomic_long_counter_sizeof == 8:
139         return read_u64(buffer, offset + atomic_long_counter_offset)
140     else:
141         return read_u32(buffer, offset + atomic_long_counter_offset)
142
143 target_arch = None
144
145
146 def is_target_arch(arch):
147     if hasattr(gdb.Frame, 'architecture'):
148         return arch in gdb.newest_frame().architecture().name()
149     else:
150         global target_arch
151         if target_arch is None:
152             target_arch = gdb.execute("show architecture", to_string=True)
153         return arch in target_arch
154
155
156 GDBSERVER_QEMU = 0
157 GDBSERVER_KGDB = 1
158 gdbserver_type = None
159
160
161 def get_gdbserver_type():
162     def exit_handler(event):
163         global gdbserver_type
164         gdbserver_type = None
165         gdb.events.exited.disconnect(exit_handler)
166
167     def probe_qemu():
168         try:
169             return gdb.execute("monitor info version", to_string=True) != ""
170         except gdb.error:
171             return False
172
173     def probe_kgdb():
174         try:
175             thread_info = gdb.execute("info thread 2", to_string=True)
176             return "shadowCPU0" in thread_info
177         except gdb.error:
178             return False
179
180     global gdbserver_type
181     if gdbserver_type is None:
182         if probe_qemu():
183             gdbserver_type = GDBSERVER_QEMU
184         elif probe_kgdb():
185             gdbserver_type = GDBSERVER_KGDB
186         if gdbserver_type is not None and hasattr(gdb, 'events'):
187             gdb.events.exited.connect(exit_handler)
188     return gdbserver_type
189
190
191 def gdb_eval_or_none(expresssion):
192     try:
193         return gdb.parse_and_eval(expresssion)
194     except gdb.error:
195         return None
196
197
198 def dentry_name(d):
199     parent = d['d_parent']
200     if parent == d or parent == 0:
201         return ""
202     p = dentry_name(d['d_parent']) + "/"
203     return p + d['d_iname'].string()
This page took 0.044858 seconds and 4 git commands to generate.