4 import gdb
.command
.backtrace
6 # This is not quite right, as local vars may override symname
7 def read_global_var (symname
):
8 return gdb
.selected_frame().read_var(symname
)
10 def g_type_to_name (gtype
):
11 def lookup_fundamental_type (typenode
):
14 val
= read_global_var ("static_fundamental_type_nodes")
17 return val
[typenode
>> 2].address()
20 typenode
= gtype
- gtype
% 4
21 if typenode
> (255 << 2):
22 typenode
= gdb
.Value(typenode
).cast (gdb
.lookup_type("TypeNode").pointer())
24 typenode
= lookup_fundamental_type (typenode
)
26 return glib
.g_quark_to_string (typenode
["qname"])
29 def is_g_type_instance (val
):
30 def is_g_type_instance_helper (type):
31 if str(type) == "GTypeInstance":
34 while type.code
== gdb
.TYPE_CODE_TYPEDEF
:
37 if type.code
!= gdb
.TYPE_CODE_STRUCT
:
40 fields
= type.fields()
44 first_field
= fields
[0]
45 return is_g_type_instance_helper(first_field
.type)
48 if type.code
!= gdb
.TYPE_CODE_PTR
:
51 return is_g_type_instance_helper (type)
53 def g_type_name_from_instance (instance
):
54 if long(instance
) != 0:
56 inst
= instance
.cast (gdb
.lookup_type("GTypeInstance").pointer())
57 klass
= inst
["g_class"]
58 gtype
= klass
["g_type"]
59 name
= g_type_to_name (gtype
)
65 class GTypePrettyPrinter
:
66 "Prints a GType instance pointer"
68 def __init__ (self
, val
):
72 name
= g_type_name_from_instance (self
.val
)
74 return ("0x%x [%s]")% (long(self
.val
), name
)
75 return ("0x%x") % (long(self
.val
))
77 def pretty_printer_lookup (val
):
78 if is_g_type_instance (val
):
79 return GTypePrettyPrinter (val
)
83 def get_signal_name (id):
89 val
= read_global_var ("g_signal_nodes")
90 max_s
= read_global_var ("g_n_signal_nodes")
93 return val
[id]["name"].string()
97 def __init__ (self
, frame
):
101 name
= self
.frame
.name()
102 if name
and name
.startswith("IA__"):
106 def __getattr__ (self
, name
):
107 return getattr (self
.frame
, name
)
109 # Monkey patch FrameWrapper to avoid IA__ in symbol names
110 old__init__
= gdb
.command
.backtrace
.FrameWrapper
.__init
__
111 def monkey_patched_init(self
, frame
):
113 if name
and name
.startswith("IA__"):
114 frame
= GFrameWrapper(frame
)
115 old__init__(self
,frame
)
116 gdb
.command
.backtrace
.FrameWrapper
.__init
__ = monkey_patched_init
119 def __init__ (self
, frame
):
123 return "signal-emission-dummy"
125 def describe (self
, stream
, full
):
126 stream
.write (" <...>\n")
128 def __getattr__ (self
, name
):
129 return getattr (self
.frame
, name
)
132 def __init__ (self
, frames
):
133 self
.frame
= frames
[-1]
134 self
.frames
= frames
;
137 return "signal-emission"
139 def read_var (self
, frame
, name
, array
= None):
141 v
= frame
.read_var (name
)
142 if v
== None or v
.is_optimized_out
:
150 def read_object (self
, frame
, name
, array
= None):
152 v
= frame
.read_var (name
)
153 if v
== None or v
.is_optimized_out
:
155 v
= v
.cast (gdb
.lookup_type("GObject").pointer())
156 # Ensure this is a somewhat correct object pointer
157 if v
!= None and g_type_name_from_instance (v
):
165 def append (self
, array
, obj
):
169 def or_join_array (self
, array
):
174 for i
in range(len(array
)):
178 for i
in range(1, len(array
)):
179 s
= s
+ " or %s"%array
[i
]
183 def describe (self
, stream
, full
):
187 for frame
in self
.frames
:
189 if name
== "signal_emit_unlocked_R":
190 self
.read_object (frame
, "instance", instances
)
191 node
= self
.read_var (frame
, "node")
193 signal
= node
["name"].string()
194 detail
= self
.read_var (frame
, "detail")
195 detail
= glib
.g_quark_to_string (detail
)
197 signal
= signal
+ ":" + detail
198 self
.append (signals
, signal
)
200 if name
== "g_signal_emitv":
201 instance_and_params
= self
.read_var (frame
, "instance_and_params")
202 if instance_and_params
:
203 instance
= instance_and_params
[0]["v_pointer"].cast (gdb
.Type("GObject").pointer())
204 self
.append (instances
, instance
)
205 id = self
.read_var (frame
, "signal_id")
206 signal
= get_signal_name (id)
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_emit_valist" or name
== "g_signal_emit":
215 self
.read_object (frame
, "instance", instances
)
216 id = self
.read_var (frame
, "signal_id")
217 signal
= get_signal_name (id)
219 detail
= self
.read_var (frame
, "detail")
220 detail
= glib
.g_quark_to_string (detail
)
222 signal
= signal
+ ":" + detail
223 self
.append (signals
, signal
)
225 if name
== "g_signal_emit_by_name":
226 self
.read_object (frame
, "instance", instances
)
227 self
.read_var (frame
, "detailed_signal", signals
)
230 instance
= self
.or_join_array (instances
)
231 signal
= self
.or_join_array (signals
)
233 stream
.write (" <emit signal %s on instance %s>\n" % (signal
, instance
))
235 def __getattr__ (self
, name
):
236 return getattr (self
.frame
, name
)
239 def __init__ (self
, iter):
247 while len(self
.queue
) <= 6:
249 f
= self
.iter.next ()
250 self
.queue
.append (f
)
251 except StopIteration:
254 def find_signal_emission (self
):
255 for i
in range (min (len(self
.queue
), 3)):
256 if self
.queue
[i
].name() == "signal_emit_unlocked_R":
261 # Ensure we have enough frames for a full signal emission
265 if len(self
.queue
) == 0:
268 emission
= self
.find_signal_emission ()
274 prev_name
= self
.queue
[start
-1].name()
275 if prev_name
.find("_marshal_") or prev_name
== "g_closure_invoke":
280 while end
< len(self
.queue
):
281 if self
.queue
[end
].name() in ["g_signal_emitv",
282 "g_signal_emit_valist",
284 "g_signal_emit_by_name"]:
289 signal_frames
= self
.queue
[start
:end
]
291 for i
in range(len(signal_frames
)-1):
292 new_frames
.append(DummyFrame(signal_frames
[i
]))
293 new_frames
.append(SignalFrame(signal_frames
))
295 self
.queue
[start
:end
] = new_frames
297 return self
.queue
.pop(0)
304 gdb
.backtrace
.push_frame_filter (GFrameFilter
)
305 obj
.pretty_printers
.append(pretty_printer_lookup
)