6 if sys
.version_info
[0] >= 3:
12 # FrameDecorator is new in gdb 7.7, so we adapt to its absence.
14 import gdb
.FrameDecorator
15 HAVE_GDB_FRAMEDECORATOR
= True
16 FrameDecorator
= gdb
.FrameDecorator
.FrameDecorator
18 HAVE_GDB_FRAMEDECORATOR
= False
20 # This is not quite right, as local vars may override symname
21 def read_global_var (symname
):
22 return gdb
.selected_frame().read_var(symname
)
24 def g_type_to_typenode (gtype
):
25 def lookup_fundamental_type (typenode
):
28 val
= read_global_var ("static_fundamental_type_nodes")
31 return val
[typenode
>> 2].address
34 typenode
= gtype
- gtype
% 4
35 if typenode
> (255 << 2):
36 typenode
= gdb
.Value(typenode
).cast (gdb
.lookup_type("TypeNode").pointer())
38 typenode
= lookup_fundamental_type (typenode
)
41 def g_type_to_name (gtype
):
42 typenode
= g_type_to_typenode(gtype
)
44 return glib_gdb
.g_quark_to_string (typenode
["qname"])
47 def is_g_type_instance (val
):
48 def is_g_type_instance_helper (type):
49 if str(type) == "GTypeInstance":
52 while type.code
== gdb
.TYPE_CODE_TYPEDEF
:
55 if type.code
!= gdb
.TYPE_CODE_STRUCT
:
58 fields
= type.fields()
62 first_field
= fields
[0]
63 return is_g_type_instance_helper(first_field
.type)
66 if type.code
!= gdb
.TYPE_CODE_PTR
:
69 return is_g_type_instance_helper (type)
71 def g_type_name_from_instance (instance
):
72 if long(instance
) != 0:
74 inst
= instance
.cast (gdb
.lookup_type("GTypeInstance").pointer())
75 klass
= inst
["g_class"]
76 gtype
= klass
["g_type"]
77 name
= g_type_to_name (gtype
)
83 class GTypePrettyPrinter
:
84 "Prints a GType instance pointer"
86 def __init__ (self
, val
):
90 name
= g_type_name_from_instance (self
.val
)
92 return ("0x%x [%s]")% (long(self
.val
), name
)
93 return ("0x%x") % (long(self
.val
))
95 def is_g_type_class_instance (val
):
97 if type.code
!= gdb
.TYPE_CODE_PTR
:
99 return str(type.target()) == "GTypeClass"
101 class GTypeHandlePrettyPrinter
:
102 "Prints a GType instance"
104 def __init__ (self
, val
, hint
= ""):
108 def to_string (self
):
109 typenode
= g_type_to_typenode(self
.val
)
111 name
= glib_gdb
.g_quark_to_string (typenode
["qname"])
112 s
= ("0x%x [%s%s")% (long(self
.val
), self
.hint
, name
)
113 for i
in range (1, int(typenode
["n_supers"])):
114 node
= g_type_to_typenode(typenode
["supers"][i
])
116 name
= glib_gdb
.g_quark_to_string(node
["qname"])
122 return ("0x%x") % (long(self
.val
))
124 def pretty_printer_lookup (val
):
125 if is_g_type_instance (val
):
126 return GTypePrettyPrinter (val
)
127 if str(val
.type) == "GType":
128 return GTypeHandlePrettyPrinter (val
)
129 if is_g_type_class_instance (val
):
130 return GTypeHandlePrettyPrinter (val
["g_type"], "g_type: ")
134 def get_signal_name (id):
140 val
= read_global_var ("g_signal_nodes")
141 max_s
= read_global_var ("g_n_signal_nodes")
144 return val
[id]["name"].string()
147 def frame_name(frame
):
148 return str(frame
.function())
150 def frame_var(frame
, var
):
151 return frame
.inferior_frame().read_var(var
)
154 class SignalFrame(FrameDecorator
):
155 def __init__ (self
, frames
):
156 FrameDecorator
.__init
__(self
, frames
[-1])
157 self
.frame
= frames
[-1]
161 return "signal-emission"
163 def read_var (self
, frame
, name
, array
= None):
165 v
= frame_var (frame
, name
)
166 if v
is None or v
.is_optimized_out
:
174 def read_object (self
, frame
, name
, array
= None):
176 v
= frame_var (frame
, name
)
177 if v
is None or v
.is_optimized_out
:
179 v
= v
.cast (gdb
.lookup_type("GObject").pointer())
180 # Ensure this is a somewhat correct object pointer
181 if v
!= None and g_type_name_from_instance (v
):
189 def append (self
, array
, obj
):
193 def or_join_array (self
, array
):
197 return ' or '.join(set(map(str, array
)))
199 def get_detailed_signal_from_frame(self
, frame
, signal
):
200 detail
= self
.read_var (frame
, "detail")
201 detail
= glib_gdb
.g_quark_to_string (detail
)
202 if detail
is not None:
203 return signal
+ ":" + detail
211 for frame
in self
.frames
:
212 name
= frame_name(frame
)
213 if name
== "signal_emit_unlocked_R":
214 self
.read_object (frame
, "instance", instances
)
215 node
= self
.read_var (frame
, "node")
217 signal
= node
["name"].string()
218 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
219 self
.append(signals
, signal
)
221 if name
== "g_signal_emitv":
222 instance_and_params
= self
.read_var (frame
, "instance_and_params")
223 if instance_and_params
:
224 instance
= instance_and_params
[0]["v_pointer"].cast (gdb
.Type("GObject").pointer())
225 self
.append (instances
, instance
)
226 id = self
.read_var (frame
, "signal_id")
227 signal
= get_signal_name (id)
229 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
230 self
.append (signals
, signal
)
232 if name
== "g_signal_emit_valist" or name
== "g_signal_emit":
233 self
.read_object (frame
, "instance", instances
)
234 id = self
.read_var (frame
, "signal_id")
235 signal
= get_signal_name (id)
237 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
238 self
.append (signals
, signal
)
240 if name
== "g_signal_emit_by_name":
241 self
.read_object (frame
, "instance", instances
)
242 self
.read_var (frame
, "detailed_signal", signals
)
245 instance
= self
.or_join_array (instances
)
246 signal
= self
.or_join_array (signals
)
248 return "<emit signal %s on instance %s>" % (signal
, instance
)
251 return self
.frames
[0:-1]
253 def describe (self
, stream
, full
):
254 stream
.write (" " + self
.function () + "\n")
256 class GFrameDecorator
:
257 def __init__ (self
, iter):
265 while len(self
.queue
) <= 8:
268 self
.queue
.append (f
)
269 except StopIteration:
272 def find_signal_emission (self
):
273 for i
in range (min (len(self
.queue
), 3)):
274 if frame_name(self
.queue
[i
]) == "signal_emit_unlocked_R":
279 # Ensure we have enough frames for a full signal emission
283 if len(self
.queue
) == 0:
286 emission
= self
.find_signal_emission ()
292 prev_name
= frame_name(self
.queue
[start
-1])
293 if prev_name
.find("_marshal_") >= 0 or prev_name
== "g_closure_invoke":
298 while end
< len(self
.queue
):
299 if frame_name(self
.queue
[end
]) in ["g_signal_emitv",
300 "g_signal_emit_valist",
302 "g_signal_emit_by_name",
303 "_g_closure_invoke_va"]:
308 signal_frames
= self
.queue
[start
:end
]
309 new_frames
= [SignalFrame(signal_frames
)]
310 self
.queue
[start
:end
] = new_frames
312 return self
.queue
.pop(0)
317 class GFrameFilter(object):
322 def filter(self
, iterator
):
323 return GFrameDecorator(iterator
)
329 if HAVE_GDB_FRAMEDECORATOR
:
330 filter = GFrameFilter()
331 obj
.frame_filters
[filter.name
] = filter
332 obj
.pretty_printers
.append(pretty_printer_lookup
)