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_name (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
)
40 return glib_gdb
.g_quark_to_string (typenode
["qname"])
43 def is_g_type_instance (val
):
44 def is_g_type_instance_helper (type):
45 if str(type) == "GTypeInstance":
48 while type.code
== gdb
.TYPE_CODE_TYPEDEF
:
51 if type.code
!= gdb
.TYPE_CODE_STRUCT
:
54 fields
= type.fields()
58 first_field
= fields
[0]
59 return is_g_type_instance_helper(first_field
.type)
62 if type.code
!= gdb
.TYPE_CODE_PTR
:
65 return is_g_type_instance_helper (type)
67 def g_type_name_from_instance (instance
):
68 if long(instance
) != 0:
70 inst
= instance
.cast (gdb
.lookup_type("GTypeInstance").pointer())
71 klass
= inst
["g_class"]
72 gtype
= klass
["g_type"]
73 name
= g_type_to_name (gtype
)
79 class GTypePrettyPrinter
:
80 "Prints a GType instance pointer"
82 def __init__ (self
, val
):
86 name
= g_type_name_from_instance (self
.val
)
88 return ("0x%x [%s]")% (long(self
.val
), name
)
89 return ("0x%x") % (long(self
.val
))
91 def pretty_printer_lookup (val
):
92 if is_g_type_instance (val
):
93 return GTypePrettyPrinter (val
)
97 def get_signal_name (id):
103 val
= read_global_var ("g_signal_nodes")
104 max_s
= read_global_var ("g_n_signal_nodes")
107 return val
[id]["name"].string()
110 def frame_name(frame
):
111 return str(frame
.function())
113 def frame_var(frame
, var
):
114 return frame
.inferior_frame().read_var(var
)
117 class SignalFrame(FrameDecorator
):
118 def __init__ (self
, frames
):
119 FrameDecorator
.__init
__(self
, frames
[-1])
120 self
.frame
= frames
[-1]
124 return "signal-emission"
126 def read_var (self
, frame
, name
, array
= None):
128 v
= frame_var (frame
, name
)
129 if v
== None or v
.is_optimized_out
:
137 def read_object (self
, frame
, name
, array
= None):
139 v
= frame_var (frame
, name
)
140 if v
== None or v
.is_optimized_out
:
142 v
= v
.cast (gdb
.lookup_type("GObject").pointer())
143 # Ensure this is a somewhat correct object pointer
144 if v
!= None and g_type_name_from_instance (v
):
152 def append (self
, array
, obj
):
156 def or_join_array (self
, array
):
160 return ' or '.join(set(map(str, array
)))
162 def get_detailed_signal_from_frame(self
, frame
, signal
):
163 detail
= self
.read_var (frame
, "detail")
164 detail
= glib_gdb
.g_quark_to_string (detail
)
165 if detail
is not None:
166 return signal
+ ":" + detail
174 for frame
in self
.frames
:
175 name
= frame_name(frame
)
176 if name
== "signal_emit_unlocked_R":
177 self
.read_object (frame
, "instance", instances
)
178 node
= self
.read_var (frame
, "node")
180 signal
= node
["name"].string()
181 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
182 self
.append(signals
, signal
)
184 if name
== "g_signal_emitv":
185 instance_and_params
= self
.read_var (frame
, "instance_and_params")
186 if instance_and_params
:
187 instance
= instance_and_params
[0]["v_pointer"].cast (gdb
.Type("GObject").pointer())
188 self
.append (instances
, instance
)
189 id = self
.read_var (frame
, "signal_id")
190 signal
= get_signal_name (id)
192 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
193 self
.append (signals
, signal
)
195 if name
== "g_signal_emit_valist" or name
== "g_signal_emit":
196 self
.read_object (frame
, "instance", instances
)
197 id = self
.read_var (frame
, "signal_id")
198 signal
= get_signal_name (id)
200 signal
= self
.get_detailed_signal_from_frame(frame
, signal
)
201 self
.append (signals
, signal
)
203 if name
== "g_signal_emit_by_name":
204 self
.read_object (frame
, "instance", instances
)
205 self
.read_var (frame
, "detailed_signal", signals
)
208 instance
= self
.or_join_array (instances
)
209 signal
= self
.or_join_array (signals
)
211 return "<emit signal %s on instance %s>" % (signal
, instance
)
214 return self
.frames
[0:-1]
216 def describe (self
, stream
, full
):
217 stream
.write (" " + self
.function () + "\n")
219 class GFrameDecorator
:
220 def __init__ (self
, iter):
228 while len(self
.queue
) <= 8:
231 self
.queue
.append (f
)
232 except StopIteration:
235 def find_signal_emission (self
):
236 for i
in range (min (len(self
.queue
), 3)):
237 if frame_name(self
.queue
[i
]) == "signal_emit_unlocked_R":
242 # Ensure we have enough frames for a full signal emission
246 if len(self
.queue
) == 0:
249 emission
= self
.find_signal_emission ()
255 prev_name
= frame_name(self
.queue
[start
-1])
256 if prev_name
.find("_marshal_") >= 0 or prev_name
== "g_closure_invoke":
261 while end
< len(self
.queue
):
262 if frame_name(self
.queue
[end
]) in ["g_signal_emitv",
263 "g_signal_emit_valist",
265 "g_signal_emit_by_name",
266 "_g_closure_invoke_va"]:
271 signal_frames
= self
.queue
[start
:end
]
272 new_frames
= [SignalFrame(signal_frames
)]
273 self
.queue
[start
:end
] = new_frames
275 return self
.queue
.pop(0)
280 class GFrameFilter(object):
285 def filter(self
, iterator
):
286 return GFrameDecorator(iterator
)
292 if HAVE_GDB_FRAMEDECORATOR
:
293 filter = GFrameFilter()
294 obj
.frame_filters
[filter.name
] = filter
295 obj
.pretty_printers
.append(pretty_printer_lookup
)