6 if sys.version_info[0] >= 3:
11 import gdb.command.backtrace
13 print(os.path.basename(__file__) + ": gdb was not built with "
14 "custom backtrace support, disabling.")
15 HAVE_GDB_BACKTRACE = 0
17 HAVE_GDB_BACKTRACE = 1
19 # This is not quite right, as local vars may override symname
20 def read_global_var (symname):
21 return gdb.selected_frame().read_var(symname)
23 def g_type_to_name (gtype):
24 def lookup_fundamental_type (typenode):
27 val = read_global_var ("static_fundamental_type_nodes")
30 return val[typenode >> 2].address()
33 typenode = gtype - gtype % 4
34 if typenode > (255 << 2):
35 typenode = gdb.Value(typenode).cast (gdb.lookup_type("TypeNode").pointer())
37 typenode = lookup_fundamental_type (typenode)
39 return glib.g_quark_to_string (typenode["qname"])
42 def is_g_type_instance (val):
43 def is_g_type_instance_helper (type):
44 if str(type) == "GTypeInstance":
47 while type.code == gdb.TYPE_CODE_TYPEDEF:
50 if type.code != gdb.TYPE_CODE_STRUCT:
53 fields = type.fields()
57 first_field = fields[0]
58 return is_g_type_instance_helper(first_field.type)
61 if type.code != gdb.TYPE_CODE_PTR:
64 return is_g_type_instance_helper (type)
66 def g_type_name_from_instance (instance):
67 if long(instance) != 0:
69 inst = instance.cast (gdb.lookup_type("GTypeInstance").pointer())
70 klass = inst["g_class"]
71 gtype = klass["g_type"]
72 name = g_type_to_name (gtype)
78 class GTypePrettyPrinter:
79 "Prints a GType instance pointer"
81 def __init__ (self, val):
85 name = g_type_name_from_instance (self.val)
87 return ("0x%x [%s]")% (long(self.val), name)
88 return ("0x%x") % (long(self.val))
90 def pretty_printer_lookup (val):
91 if is_g_type_instance (val):
92 return GTypePrettyPrinter (val)
96 def get_signal_name (id):
102 val = read_global_var ("g_signal_nodes")
103 max_s = read_global_var ("g_n_signal_nodes")
106 return val[id]["name"].string()
110 def __init__ (self, frame):
114 name = self.frame.name()
115 if name and name.startswith("IA__"):
119 def __getattr__ (self, name):
120 return getattr (self.frame, name)
122 # Monkey patch FrameWrapper to avoid IA__ in symbol names
123 if HAVE_GDB_BACKTRACE:
124 old__init__ = gdb.command.backtrace.FrameWrapper.__init__
125 def monkey_patched_init(self, frame):
127 if name and name.startswith("IA__"):
128 frame = GFrameWrapper(frame)
129 old__init__(self,frame)
130 gdb.command.backtrace.FrameWrapper.__init__ = monkey_patched_init
133 def __init__ (self, frame):
137 return "signal-emission-dummy"
139 def describe (self, stream, full):
140 stream.write (" <...>\n")
142 def __getattr__ (self, name):
143 return getattr (self.frame, name)
146 def __init__ (self, frames):
147 self.frame = frames[-1]
148 self.frames = frames;
151 return "signal-emission"
153 def read_var (self, frame, name, array = None):
155 v = frame.read_var (name)
156 if v == None or v.is_optimized_out:
164 def read_object (self, frame, name, array = None):
166 v = frame.read_var (name)
167 if v == None or v.is_optimized_out:
169 v = v.cast (gdb.lookup_type("GObject").pointer())
170 # Ensure this is a somewhat correct object pointer
171 if v != None and g_type_name_from_instance (v):
179 def append (self, array, obj):
183 def or_join_array (self, array):
188 for i in range(len(array)):
192 for i in range(1, len(array)):
193 s = s + " or %s"%array[i]
197 def describe (self, stream, full):
201 for frame in self.frames:
203 if name == "signal_emit_unlocked_R":
204 self.read_object (frame, "instance", instances)
205 node = self.read_var (frame, "node")
207 signal = node["name"].string()
208 detail = self.read_var (frame, "detail")
209 detail = glib.g_quark_to_string (detail)
211 signal = signal + ":" + detail
212 self.append (signals, signal)
214 if name == "g_signal_emitv":
215 instance_and_params = self.read_var (frame, "instance_and_params")
216 if instance_and_params:
217 instance = instance_and_params[0]["v_pointer"].cast (gdb.Type("GObject").pointer())
218 self.append (instances, instance)
219 id = self.read_var (frame, "signal_id")
220 signal = get_signal_name (id)
222 detail = self.read_var (frame, "detail")
223 detail = glib.g_quark_to_string (detail)
225 signal = signal + ":" + detail
226 self.append (signals, signal)
228 if name == "g_signal_emit_valist" or name == "g_signal_emit":
229 self.read_object (frame, "instance", instances)
230 id = self.read_var (frame, "signal_id")
231 signal = get_signal_name (id)
233 detail = self.read_var (frame, "detail")
234 detail = glib.g_quark_to_string (detail)
236 signal = signal + ":" + detail
237 self.append (signals, signal)
239 if name == "g_signal_emit_by_name":
240 self.read_object (frame, "instance", instances)
241 self.read_var (frame, "detailed_signal", signals)
244 instance = self.or_join_array (instances)
245 signal = self.or_join_array (signals)
247 stream.write (" <emit signal %s on instance %s>\n" % (signal, instance))
249 def __getattr__ (self, name):
250 return getattr (self.frame, name)
253 def __init__ (self, iter):
261 while len(self.queue) <= 6:
263 f = self.iter.next ()
264 self.queue.append (f)
265 except StopIteration:
268 def find_signal_emission (self):
269 for i in range (min (len(self.queue), 3)):
270 if self.queue[i].name() == "signal_emit_unlocked_R":
275 # Ensure we have enough frames for a full signal emission
279 if len(self.queue) == 0:
282 emission = self.find_signal_emission ()
288 prev_name = self.queue[start-1].name()
289 if prev_name.find("_marshal_") or prev_name == "g_closure_invoke":
294 while end < len(self.queue):
295 if self.queue[end].name() in ["g_signal_emitv",
296 "g_signal_emit_valist",
298 "g_signal_emit_by_name"]:
303 signal_frames = self.queue[start:end]
305 for i in range(len(signal_frames)-1):
306 new_frames.append(DummyFrame(signal_frames[i]))
307 new_frames.append(SignalFrame(signal_frames))
309 self.queue[start:end] = new_frames
311 return self.queue.pop(0)
318 if HAVE_GDB_BACKTRACE:
319 gdb.backtrace.push_frame_filter (GFrameFilter)
320 obj.pretty_printers.append(pretty_printer_lookup)