GNU Linux-libre 5.10.217-gnu1
[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
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
70 ContainerOf()
71
72
73 BIG_ENDIAN = 0
74 LITTLE_ENDIAN = 1
75 target_endianness = None
76
77
78 def get_target_endianness():
79     global target_endianness
80     if target_endianness is None:
81         endian = gdb.execute("show endian", to_string=True)
82         if "little endian" in endian:
83             target_endianness = LITTLE_ENDIAN
84         elif "big endian" in endian:
85             target_endianness = BIG_ENDIAN
86         else:
87             raise gdb.GdbError("unknown endianness '{0}'".format(str(endian)))
88     return target_endianness
89
90
91 def read_memoryview(inf, start, length):
92     m = inf.read_memory(start, length)
93     if type(m) is memoryview:
94         return m
95     return memoryview(m)
96
97
98 def read_u16(buffer, offset):
99     buffer_val = buffer[offset:offset + 2]
100     value = [0, 0]
101
102     if type(buffer_val[0]) is str:
103         value[0] = ord(buffer_val[0])
104         value[1] = ord(buffer_val[1])
105     else:
106         value[0] = buffer_val[0]
107         value[1] = buffer_val[1]
108
109     if get_target_endianness() == LITTLE_ENDIAN:
110         return value[0] + (value[1] << 8)
111     else:
112         return value[1] + (value[0] << 8)
113
114
115 def read_u32(buffer, offset):
116     if get_target_endianness() == LITTLE_ENDIAN:
117         return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
118     else:
119         return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
120
121
122 def read_u64(buffer, offset):
123     if get_target_endianness() == LITTLE_ENDIAN:
124         return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
125     else:
126         return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
127
128
129 def read_ulong(buffer, offset):
130     if get_long_type().sizeof == 8:
131         return read_u64(buffer, offset)
132     else:
133         return read_u32(buffer, offset)
134
135
136 target_arch = None
137
138
139 def is_target_arch(arch):
140     if hasattr(gdb.Frame, 'architecture'):
141         return arch in gdb.newest_frame().architecture().name()
142     else:
143         global target_arch
144         if target_arch is None:
145             target_arch = gdb.execute("show architecture", to_string=True)
146         return arch in target_arch
147
148
149 GDBSERVER_QEMU = 0
150 GDBSERVER_KGDB = 1
151 gdbserver_type = None
152
153
154 def get_gdbserver_type():
155     def exit_handler(event):
156         global gdbserver_type
157         gdbserver_type = None
158         gdb.events.exited.disconnect(exit_handler)
159
160     def probe_qemu():
161         try:
162             return gdb.execute("monitor info version", to_string=True) != ""
163         except gdb.error:
164             return False
165
166     def probe_kgdb():
167         try:
168             thread_info = gdb.execute("info thread 2", to_string=True)
169             return "shadowCPU0" in thread_info
170         except gdb.error:
171             return False
172
173     global gdbserver_type
174     if gdbserver_type is None:
175         if probe_qemu():
176             gdbserver_type = GDBSERVER_QEMU
177         elif probe_kgdb():
178             gdbserver_type = GDBSERVER_KGDB
179         if gdbserver_type is not None and hasattr(gdb, 'events'):
180             gdb.events.exited.connect(exit_handler)
181     return gdbserver_type
182
183
184 def gdb_eval_or_none(expresssion):
185     try:
186         return gdb.parse_and_eval(expresssion)
187     except gdb.error:
188         return None
189
190
191 def dentry_name(d):
192     parent = d['d_parent']
193     if parent == d or parent == 0:
194         return ""
195     p = dentry_name(d['d_parent']) + "/"
196     return p + d['d_iname'].string()