glib/tests: Fix non-debug build of slice test
[glib.git] / gobject / gobject.py
blob48a9309e39c28c843035274b8ee2cafc007a436d
1 import os.path
2 import gdb
3 import glib
4 import sys
6 if sys.version_info[0] >= 3:
7 long = int
9 try:
10 import gdb.backtrace
11 import gdb.command.backtrace
12 except ImportError:
13 print(os.path.basename(__file__) + ": gdb was not built with "
14 "custom backtrace support, disabling.")
15 HAVE_GDB_BACKTRACE = 0
16 else:
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):
25 if typenode == 0:
26 return None
27 val = read_global_var ("static_fundamental_type_nodes")
28 if val == None:
29 return None
30 return val[typenode >> 2].address()
32 gtype = long(gtype)
33 typenode = gtype - gtype % 4
34 if typenode > (255 << 2):
35 typenode = gdb.Value(typenode).cast (gdb.lookup_type("TypeNode").pointer())
36 else:
37 typenode = lookup_fundamental_type (typenode)
38 if typenode != None:
39 return glib.g_quark_to_string (typenode["qname"])
40 return None
42 def is_g_type_instance (val):
43 def is_g_type_instance_helper (type):
44 if str(type) == "GTypeInstance":
45 return True
47 while type.code == gdb.TYPE_CODE_TYPEDEF:
48 type = type.target()
50 if type.code != gdb.TYPE_CODE_STRUCT:
51 return False
53 fields = type.fields()
54 if len (fields) < 1:
55 return False
57 first_field = fields[0]
58 return is_g_type_instance_helper(first_field.type)
60 type = val.type
61 if type.code != gdb.TYPE_CODE_PTR:
62 return False
63 type = type.target()
64 return is_g_type_instance_helper (type)
66 def g_type_name_from_instance (instance):
67 if long(instance) != 0:
68 try:
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)
73 return name
74 except RuntimeError:
75 pass
76 return None
78 class GTypePrettyPrinter:
79 "Prints a GType instance pointer"
81 def __init__ (self, val):
82 self.val = val
84 def to_string (self):
85 name = g_type_name_from_instance (self.val)
86 if name:
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)
94 return None
96 def get_signal_name (id):
97 if id == None:
98 return None
99 id = long(id)
100 if id == 0:
101 return None
102 val = read_global_var ("g_signal_nodes")
103 max_s = read_global_var ("g_n_signal_nodes")
104 max_s = long(max_s)
105 if id < max_s:
106 return val[id]["name"].string()
107 return None
109 class DummyFrame:
110 def __init__ (self, frame):
111 self.frame = frame
113 def name (self):
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)
122 class SignalFrame:
123 def __init__ (self, frames):
124 self.frame = frames[-1]
125 self.frames = frames
127 def name (self):
128 return "signal-emission"
130 def read_var (self, frame, name, array = None):
131 try:
132 v = frame.read_var (name)
133 if v == None or v.is_optimized_out:
134 return None
135 if array != None:
136 array.append (v)
137 return v
138 except ValueError:
139 return None
141 def read_object (self, frame, name, array = None):
142 try:
143 v = frame.read_var (name)
144 if v == None or v.is_optimized_out:
145 return None
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):
149 if array != None:
150 array.append (v)
151 return v
152 return None
153 except ValueError:
154 return None
156 def append (self, array, obj):
157 if obj != None:
158 array.append (obj)
160 def or_join_array (self, array):
161 if len(array) == 0:
162 return "???"
163 else:
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
171 else:
172 return detail
174 def describe (self, stream, full):
175 instances = []
176 signals = []
178 for frame in self.frames:
179 name = frame.name()
180 if name == "signal_emit_unlocked_R":
181 self.read_object (frame, "instance", instances)
182 node = self.read_var (frame, "node")
183 if 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)
195 if signal:
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)
203 if signal:
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)
210 break
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)
220 class GFrameFilter:
221 def __init__ (self, iter):
222 self.queue = []
223 self.iter = iter
225 def __iter__ (self):
226 return self
228 def fill (self):
229 while len(self.queue) <= 6:
230 try:
231 f = self.iter.next ()
232 self.queue.append (f)
233 except StopIteration:
234 return
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":
239 return i
240 return -1
242 def next (self):
243 # Ensure we have enough frames for a full signal emission
244 self.fill()
246 # Are we at the end?
247 if len(self.queue) == 0:
248 raise StopIteration
250 emission = self.find_signal_emission ()
251 if emission > 0:
252 start = emission
253 while True:
254 if start == 0:
255 break
256 prev_name = self.queue[start-1].name()
257 if prev_name.find("_marshal_") or prev_name == "g_closure_invoke":
258 start = start - 1
259 else:
260 break
261 end = emission + 1
262 while end < len(self.queue):
263 if self.queue[end].name() in ["g_signal_emitv",
264 "g_signal_emit_valist",
265 "g_signal_emit",
266 "g_signal_emit_by_name"]:
267 end = end + 1
268 else:
269 break
271 signal_frames = self.queue[start:end]
272 new_frames = []
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)
282 def register (obj):
283 if obj == None:
284 obj = gdb
286 if HAVE_GDB_BACKTRACE:
287 gdb.backtrace.push_frame_filter (GFrameFilter)
288 obj.pretty_printers.append(pretty_printer_lookup)