6 import gdb.command.backtrace
8 print(os.path.basename(__file__) + ": gdb was not built with "
9 "custom backtrace support, disabling.")
10 HAVE_GDB_BACKTRACE = 0
12 HAVE_GDB_BACKTRACE = 1
14 # This is not quite right, as local vars may override symname
15 def read_global_var (symname):
16 return gdb.selected_frame().read_var(symname)
18 def g_type_to_name (gtype):
19 def lookup_fundamental_type (typenode):
22 val = read_global_var ("static_fundamental_type_nodes")
25 return val[typenode >> 2].address()
28 typenode = gtype - gtype % 4
29 if typenode > (255 << 2):
30 typenode = gdb.Value(typenode).cast (gdb.lookup_type("TypeNode").pointer())
32 typenode = lookup_fundamental_type (typenode)
34 return glib.g_quark_to_string (typenode["qname"])
37 def is_g_type_instance (val):
38 def is_g_type_instance_helper (type):
39 if str(type) == "GTypeInstance":
42 while type.code == gdb.TYPE_CODE_TYPEDEF:
45 if type.code != gdb.TYPE_CODE_STRUCT:
48 fields = type.fields()
52 first_field = fields[0]
53 return is_g_type_instance_helper(first_field.type)
56 if type.code != gdb.TYPE_CODE_PTR:
59 return is_g_type_instance_helper (type)
61 def g_type_name_from_instance (instance):
62 if long(instance) != 0:
64 inst = instance.cast (gdb.lookup_type("GTypeInstance").pointer())
65 klass = inst["g_class"]
66 gtype = klass["g_type"]
67 name = g_type_to_name (gtype)
73 class GTypePrettyPrinter:
74 "Prints a GType instance pointer"
76 def __init__ (self, val):
80 name = g_type_name_from_instance (self.val)
82 return ("0x%x [%s]")% (long(self.val), name)
83 return ("0x%x") % (long(self.val))
85 def pretty_printer_lookup (val):
86 if is_g_type_instance (val):
87 return GTypePrettyPrinter (val)
91 def get_signal_name (id):
97 val = read_global_var ("g_signal_nodes")
98 max_s = read_global_var ("g_n_signal_nodes")
101 return val[id]["name"].string()
105 def __init__ (self, frame):
109 name = self.frame.name()
110 if name and name.startswith("IA__"):
114 def __getattr__ (self, name):
115 return getattr (self.frame, name)
117 # Monkey patch FrameWrapper to avoid IA__ in symbol names
118 if HAVE_GDB_BACKTRACE:
119 old__init__ = gdb.command.backtrace.FrameWrapper.__init__
120 def monkey_patched_init(self, frame):
122 if name and name.startswith("IA__"):
123 frame = GFrameWrapper(frame)
124 old__init__(self,frame)
125 gdb.command.backtrace.FrameWrapper.__init__ = monkey_patched_init
128 def __init__ (self, frame):
132 return "signal-emission-dummy"
134 def describe (self, stream, full):
135 stream.write (" <...>\n")
137 def __getattr__ (self, name):
138 return getattr (self.frame, name)
141 def __init__ (self, frames):
142 self.frame = frames[-1]
143 self.frames = frames;
146 return "signal-emission"
148 def read_var (self, frame, name, array = None):
150 v = frame.read_var (name)
151 if v == None or v.is_optimized_out:
159 def read_object (self, frame, name, array = None):
161 v = frame.read_var (name)
162 if v == None or v.is_optimized_out:
164 v = v.cast (gdb.lookup_type("GObject").pointer())
165 # Ensure this is a somewhat correct object pointer
166 if v != None and g_type_name_from_instance (v):
174 def append (self, array, obj):
178 def or_join_array (self, array):
183 for i in range(len(array)):
187 for i in range(1, len(array)):
188 s = s + " or %s"%array[i]
192 def describe (self, stream, full):
196 for frame in self.frames:
198 if name == "signal_emit_unlocked_R":
199 self.read_object (frame, "instance", instances)
200 node = self.read_var (frame, "node")
202 signal = node["name"].string()
203 detail = self.read_var (frame, "detail")
204 detail = glib.g_quark_to_string (detail)
206 signal = signal + ":" + detail
207 self.append (signals, signal)
209 if name == "g_signal_emitv":
210 instance_and_params = self.read_var (frame, "instance_and_params")
211 if instance_and_params:
212 instance = instance_and_params[0]["v_pointer"].cast (gdb.Type("GObject").pointer())
213 self.append (instances, instance)
214 id = self.read_var (frame, "signal_id")
215 signal = get_signal_name (id)
217 detail = self.read_var (frame, "detail")
218 detail = glib.g_quark_to_string (detail)
220 signal = signal + ":" + detail
221 self.append (signals, signal)
223 if name == "g_signal_emit_valist" or name == "g_signal_emit":
224 self.read_object (frame, "instance", instances)
225 id = self.read_var (frame, "signal_id")
226 signal = get_signal_name (id)
228 detail = self.read_var (frame, "detail")
229 detail = glib.g_quark_to_string (detail)
231 signal = signal + ":" + detail
232 self.append (signals, signal)
234 if name == "g_signal_emit_by_name":
235 self.read_object (frame, "instance", instances)
236 self.read_var (frame, "detailed_signal", signals)
239 instance = self.or_join_array (instances)
240 signal = self.or_join_array (signals)
242 stream.write (" <emit signal %s on instance %s>\n" % (signal, instance))
244 def __getattr__ (self, name):
245 return getattr (self.frame, name)
248 def __init__ (self, iter):
256 while len(self.queue) <= 6:
258 f = self.iter.next ()
259 self.queue.append (f)
260 except StopIteration:
263 def find_signal_emission (self):
264 for i in range (min (len(self.queue), 3)):
265 if self.queue[i].name() == "signal_emit_unlocked_R":
270 # Ensure we have enough frames for a full signal emission
274 if len(self.queue) == 0:
277 emission = self.find_signal_emission ()
283 prev_name = self.queue[start-1].name()
284 if prev_name.find("_marshal_") or prev_name == "g_closure_invoke":
289 while end < len(self.queue):
290 if self.queue[end].name() in ["g_signal_emitv",
291 "g_signal_emit_valist",
293 "g_signal_emit_by_name"]:
298 signal_frames = self.queue[start:end]
300 for i in range(len(signal_frames)-1):
301 new_frames.append(DummyFrame(signal_frames[i]))
302 new_frames.append(SignalFrame(signal_frames))
304 self.queue[start:end] = new_frames
306 return self.queue.pop(0)
313 if HAVE_GDB_BACKTRACE:
314 gdb.backtrace.push_frame_filter (GFrameFilter)
315 obj.pretty_printers.append(pretty_printer_lookup)