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 return "signal-emission-dummy"
116 def describe (self
, stream
, full
):
117 stream
.write (" <...>\n")
119 def __getattr__ (self
, name
):
120 return getattr (self
.frame
, name
)
123 def __init__ (self
, frames
):
124 self
.frame
= frames
[-1]
128 return "signal-emission"
130 def read_var (self
, frame
, name
, array
= None):
132 v
= frame
.read_var (name
)
133 if v
== None or v
.is_optimized_out
:
141 def read_object (self
, frame
, name
, array
= None):
143 v
= frame
.read_var (name
)
144 if v
== None or v
.is_optimized_out
:
146 v
= v
.cast (gdb
.lookup_type("GObject").pointer())
147 # Ensure this is a somewhat correct object pointer
148 if v
!= None and g_type_name_from_instance (v
):
156 def append (self
, array
, obj
):
160 def or_join_array (self
, array
):
164 return ' or '.join(set(array
))
166 def get_detailed_signal_from_frame(self
, frame
, signal
):
167 detail
= self
.read_var (frame
, "detail")
168 detail
= glib
.g_quark_to_string (detail
)
169 if detail
is not None:
170 return signal
+ ":" + detail
174 def describe (self
, stream
, full
):
178 for frame
in self
.frames
:
180 if name
== "signal_emit_unlocked_R":
181 self
.read_object (frame
, "instance", instances
)
182 node
= self
.read_var (frame
, "node")
184 signal
= node
["name"].string()
185 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
186 self
.append(signals
, signal
)
188 if name
== "g_signal_emitv":
189 instance_and_params
= self
.read_var (frame
, "instance_and_params")
190 if instance_and_params
:
191 instance
= instance_and_params
[0]["v_pointer"].cast (gdb
.Type("GObject").pointer())
192 self
.append (instances
, instance
)
193 id = self
.read_var (frame
, "signal_id")
194 signal
= get_signal_name (id)
196 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
197 self
.append (signals
, signal
)
199 if name
== "g_signal_emit_valist" or name
== "g_signal_emit":
200 self
.read_object (frame
, "instance", instances
)
201 id = self
.read_var (frame
, "signal_id")
202 signal
= get_signal_name (id)
204 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
205 self
.append (signals
, signal
)
207 if name
== "g_signal_emit_by_name":
208 self
.read_object (frame
, "instance", instances
)
209 self
.read_var (frame
, "detailed_signal", signals
)
212 instance
= self
.or_join_array (instances
)
213 signal
= self
.or_join_array (signals
)
215 stream
.write (" <emit signal %s on instance %s>\n" % (signal
, instance
))
217 def __getattr__ (self
, name
):
218 return getattr (self
.frame
, name
)
221 def __init__ (self
, iter):
229 while len(self
.queue
) <= 6:
231 f
= self
.iter.next ()
232 self
.queue
.append (f
)
233 except StopIteration:
236 def find_signal_emission (self
):
237 for i
in range (min (len(self
.queue
), 3)):
238 if self
.queue
[i
].name() == "signal_emit_unlocked_R":
243 # Ensure we have enough frames for a full signal emission
247 if len(self
.queue
) == 0:
250 emission
= self
.find_signal_emission ()
256 prev_name
= self
.queue
[start
-1].name()
257 if prev_name
.find("_marshal_") or prev_name
== "g_closure_invoke":
262 while end
< len(self
.queue
):
263 if self
.queue
[end
].name() in ["g_signal_emitv",
264 "g_signal_emit_valist",
266 "g_signal_emit_by_name"]:
271 signal_frames
= self
.queue
[start
:end
]
273 for i
in range(len(signal_frames
)-1):
274 new_frames
.append(DummyFrame(signal_frames
[i
]))
275 new_frames
.append(SignalFrame(signal_frames
))
277 self
.queue
[start
:end
] = new_frames
279 return self
.queue
.pop(0)
286 if HAVE_GDB_BACKTRACE
:
287 gdb
.backtrace
.push_frame_filter (GFrameFilter
)
288 obj
.pretty_printers
.append(pretty_printer_lookup
)