glib (2.79.0)
1 import gdb
2 import sys
3
4 if sys.version_info[0] >= 3:
5 long = int
6
7
8 # This is not quite right, as local vars may override symname
9 def read_global_var(symname):
10 return gdb.selected_frame().read_var(symname)
11
12
13 def g_quark_to_string(quark):
14 if quark is None:
15 return None
16 quark = long(quark)
17 if quark == 0:
18 return None
19 max_q = None
20 try:
21 val = read_global_var("quarks")
22 try:
23 max_q = long(read_global_var("quark_seq_id"))
24 # quark_seq_id gets optimized out in some builds so work around it
25 except gdb.error:
26 pass
27 except Exception:
28 try:
29 val = read_global_var("g_quarks")
30 try:
31 max_q = long(read_global_var("g_quark_seq_id"))
32 except gdb.error:
33 pass
34 except Exception:
35 return None
36 if max_q is None or quark < max_q:
37 try:
38 return val[quark].string()
39 except gdb.MemoryError:
40 print(f"Invalid quark {quark}")
41 return None
42
43
44 # We override the node printers too, so that node->next is not expanded
45 class ESC[4;38;5;81mGListNodePrinter:
46 "Prints a GList node"
47
48 def __init__(self, val):
49 self.val = val
50
51 def to_string(self):
52 return "{data=%s, next=0x%x, prev=0x%x}" % (
53 str(self.val["data"]),
54 long(self.val["next"]),
55 long(self.val["prev"]),
56 )
57
58
59 class ESC[4;38;5;81mGSListNodePrinter:
60 "Prints a GSList node"
61
62 def __init__(self, val):
63 self.val = val
64
65 def to_string(self):
66 return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
67
68
69 class ESC[4;38;5;81mGListPrinter:
70 "Prints a GList"
71
72 class ESC[4;38;5;81m_iterator:
73 def __init__(self, head, listtype):
74 self.link = head
75 self.listtype = listtype
76 self.count = 0
77
78 def __iter__(self):
79 return self
80
81 def next(self):
82 if self.link == 0:
83 raise StopIteration
84 data = self.link["data"]
85 self.link = self.link["next"]
86 count = self.count
87 self.count = self.count + 1
88 return ("[%d]" % count, data)
89
90 __next__ = next
91
92 def __init__(self, val, listtype):
93 self.val = val
94 self.listtype = listtype
95
96 def children(self):
97 return self._iterator(self.val, self.listtype)
98
99 def to_string(self):
100 return "0x%x" % (long(self.val))
101
102 def display_hint(self):
103 return "array"
104
105
106 class ESC[4;38;5;81mGHashPrinter:
107 "Prints a GHashTable"
108
109 class ESC[4;38;5;81m_iterator:
110 class ESC[4;38;5;81m_pointer_array:
111 def __init__(self, ptr, big_items):
112 self._big_items = big_items
113 self._gpointer_type = gdb.lookup_type("gpointer")
114 item_type = (
115 self._gpointer_type if self._big_items else gdb.lookup_type("guint")
116 )
117
118 self._items = ptr.cast(item_type.pointer())
119
120 def __getitem__(self, item):
121 item = self._items[item]
122
123 if not self._big_items:
124 item = item.cast(self._gpointer_type)
125
126 return item
127
128 def __init__(self, ht, keys_are_strings):
129 self.ht = ht
130 if ht != 0:
131 self.keys = self._pointer_array(ht["keys"], ht["have_big_keys"])
132 self.values = self._pointer_array(ht["values"], ht["have_big_values"])
133 self.hashes = ht["hashes"]
134 self.size = ht["size"]
135 self.pos = 0
136 self.keys_are_strings = keys_are_strings
137 self.value = None
138
139 def __iter__(self):
140 return self
141
142 def next(self):
143 if self.ht == 0:
144 raise StopIteration
145 if self.value is not None:
146 v = self.value
147 self.value = None
148 return v
149 while long(self.pos) < long(self.size):
150 if long(self.hashes[self.pos]) >= 2:
151 key = self.keys[self.pos]
152 val = self.values[self.pos]
153
154 if self.keys_are_strings:
155 key = key.cast(gdb.lookup_type("char").pointer())
156
157 # Queue value for next result
158 self.value = ("[%dv]" % (self.pos), val)
159
160 # Increment pos and return key
161 key = ("[%dk]" % (self.pos), key)
162 self.pos += 1
163 return key
164
165 self.pos += 1
166 raise StopIteration
167
168 __next__ = next
169
170 def __init__(self, val):
171 self.val = val
172 self.keys_are_strings = False
173 try:
174 string_hash = read_global_var("g_str_hash")
175 except Exception:
176 string_hash = None
177 if (
178 self.val != 0
179 and string_hash is not None
180 and self.val["hash_func"] == string_hash
181 ):
182 self.keys_are_strings = True
183
184 def children(self):
185 return self._iterator(self.val, self.keys_are_strings)
186
187 def to_string(self):
188 return "0x%x" % (long(self.val))
189
190 def display_hint(self):
191 return "map"
192
193
194 def pretty_printer_lookup(val):
195 # None yet, want things like hash table and list
196
197 type = val.type.unqualified()
198
199 # If it points to a reference, get the reference.
200 if type.code == gdb.TYPE_CODE_REF:
201 type = type.target()
202
203 if type.code == gdb.TYPE_CODE_PTR:
204 type = type.target().unqualified()
205 t = str(type)
206 if t == "GList":
207 return GListPrinter(val, "GList")
208 if t == "GSList":
209 return GListPrinter(val, "GSList")
210 if t == "GHashTable":
211 return GHashPrinter(val)
212 else:
213 t = str(type)
214 if t == "GList":
215 return GListNodePrinter(val)
216 if t == "GSList *":
217 return GListPrinter(val, "GSList")
218 return None
219
220
221 def register(obj):
222 if obj is None:
223 obj = gdb
224
225 obj.pretty_printers.append(pretty_printer_lookup)
226
227
228 class ESC[4;38;5;81mForeachCommand(ESC[4;38;5;149mgdbESC[4;38;5;149m.ESC[4;38;5;149mCommand):
229 """Foreach on list"""
230
231 def __init__(self):
232 super(ForeachCommand, self).__init__(
233 "gforeach", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL
234 )
235
236 def valid_name(self, name):
237 if not name[0].isalpha():
238 return False
239 return True
240
241 def parse_args(self, arg):
242 i = arg.find(" ")
243 if i <= 0:
244 raise Exception("No var specified")
245 var = arg[:i]
246 if not self.valid_name(var):
247 raise Exception("Invalid variable name")
248
249 while i < len(arg) and arg[i].isspace():
250 i = i + 1
251
252 if arg[i : i + 2] != "in":
253 raise Exception("Invalid syntax, missing in")
254
255 i = i + 2
256
257 while i < len(arg) and arg[i].isspace():
258 i = i + 1
259
260 colon = arg.find(":", i)
261 if colon == -1:
262 raise Exception("Invalid syntax, missing colon")
263
264 val = arg[i:colon]
265
266 colon = colon + 1
267 while colon < len(arg) and arg[colon].isspace():
268 colon = colon + 1
269
270 command = arg[colon:]
271
272 return (var, val, command)
273
274 def do_iter(self, arg, item, command):
275 item = item.cast(gdb.lookup_type("void").pointer())
276 item = long(item)
277 to_eval = "set $%s = (void *)0x%x\n" % (arg, item)
278 gdb.execute(to_eval)
279 gdb.execute(command)
280
281 def slist_iterator(self, arg, container, command):
282 list_element = container.cast(gdb.lookup_type("GSList").pointer())
283 while long(list_element) != 0:
284 self.do_iter(arg, list_element["data"], command)
285 list_element = list_element["next"]
286
287 def list_iterator(self, arg, container, command):
288 list_element = container.cast(gdb.lookup_type("GList").pointer())
289 while long(list_element) != 0:
290 self.do_iter(arg, list_element["data"], command)
291 list_element = list_element["next"]
292
293 def pick_iterator(self, container):
294 t = container.type.unqualified()
295 if t.code == gdb.TYPE_CODE_PTR:
296 t = t.target().unqualified()
297 t = str(t)
298 if t == "GSList":
299 return self.slist_iterator
300 if t == "GList":
301 return self.list_iterator
302 raise Exception("Invalid container type %s" % (str(container.type)))
303
304 def invoke(self, arg, from_tty):
305 (var, container, command) = self.parse_args(arg)
306 container = gdb.parse_and_eval(container)
307 func = self.pick_iterator(container)
308 func(var, container, command)
309
310
311 ForeachCommand()