| 
									
										
										
										
											2010-03-23 15:18:12 +00:00
										 |  |  | import os.path | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | import gdb | 
					
						
							|  |  |  | import glib | 
					
						
							| 
									
										
										
										
											2013-12-18 07:14:38 +11:00
										 |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if sys.version_info[0] >= 3: | 
					
						
							|  |  |  |     long = int | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  | else: | 
					
						
							|  |  |  |     import itertools | 
					
						
							|  |  |  |     map = itertools.imap | 
					
						
							| 
									
										
										
										
											2013-12-18 07:14:38 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  | # FrameDecorator is new in gdb 7.7, so we adapt to its absence. | 
					
						
							| 
									
										
										
										
											2010-03-23 15:18:12 +00:00
										 |  |  | try: | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |     import gdb.FrameDecorator | 
					
						
							|  |  |  |     HAVE_GDB_FRAMEDECORATOR = True | 
					
						
							|  |  |  |     FrameDecorator = gdb.FrameDecorator.FrameDecorator | 
					
						
							| 
									
										
										
										
											2010-03-23 15:18:12 +00:00
										 |  |  | except ImportError: | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |     HAVE_GDB_FRAMEDECORATOR = False | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # This is not quite right, as local vars may override symname | 
					
						
							|  |  |  | def read_global_var (symname): | 
					
						
							|  |  |  |     return gdb.selected_frame().read_var(symname) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def g_type_to_name (gtype): | 
					
						
							|  |  |  |     def lookup_fundamental_type (typenode): | 
					
						
							|  |  |  |         if typenode == 0: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |         val = read_global_var ("static_fundamental_type_nodes") | 
					
						
							|  |  |  |         if val == None: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |         return val[typenode >> 2].address() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtype = long(gtype) | 
					
						
							|  |  |  |     typenode = gtype - gtype % 4 | 
					
						
							|  |  |  |     if typenode > (255 << 2): | 
					
						
							|  |  |  |         typenode = gdb.Value(typenode).cast (gdb.lookup_type("TypeNode").pointer()) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         typenode = lookup_fundamental_type (typenode) | 
					
						
							|  |  |  |     if typenode != None: | 
					
						
							|  |  |  |         return glib.g_quark_to_string (typenode["qname"]) | 
					
						
							|  |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def is_g_type_instance (val): | 
					
						
							|  |  |  |     def is_g_type_instance_helper (type): | 
					
						
							|  |  |  |         if str(type) == "GTypeInstance": | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while type.code == gdb.TYPE_CODE_TYPEDEF: | 
					
						
							|  |  |  |             type = type.target() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if type.code != gdb.TYPE_CODE_STRUCT: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fields = type.fields() | 
					
						
							|  |  |  |         if len (fields) < 1: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         first_field = fields[0] | 
					
						
							|  |  |  |         return is_g_type_instance_helper(first_field.type) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     type = val.type | 
					
						
							|  |  |  |     if type.code != gdb.TYPE_CODE_PTR: | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     type = type.target() | 
					
						
							|  |  |  |     return is_g_type_instance_helper (type) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def g_type_name_from_instance (instance): | 
					
						
							|  |  |  |     if long(instance) != 0: | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             inst = instance.cast (gdb.lookup_type("GTypeInstance").pointer()) | 
					
						
							|  |  |  |             klass = inst["g_class"] | 
					
						
							|  |  |  |             gtype = klass["g_type"] | 
					
						
							|  |  |  |             name = g_type_to_name (gtype) | 
					
						
							|  |  |  |             return name | 
					
						
							|  |  |  |         except RuntimeError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class GTypePrettyPrinter: | 
					
						
							|  |  |  |     "Prints a GType instance pointer" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__ (self, val): | 
					
						
							|  |  |  |         self.val = val | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def to_string (self): | 
					
						
							|  |  |  |         name = g_type_name_from_instance (self.val) | 
					
						
							|  |  |  |         if name: | 
					
						
							|  |  |  |             return ("0x%x [%s]")% (long(self.val), name) | 
					
						
							|  |  |  |         return  ("0x%x") % (long(self.val)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def pretty_printer_lookup (val): | 
					
						
							|  |  |  |     if is_g_type_instance (val): | 
					
						
							|  |  |  |         return GTypePrettyPrinter (val) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_signal_name (id): | 
					
						
							| 
									
										
										
										
											2013-09-19 11:55:47 -04:00
										 |  |  |     if id == None: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     id = long(id) | 
					
						
							|  |  |  |     if id == 0: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     val = read_global_var ("g_signal_nodes") | 
					
						
							|  |  |  |     max_s = read_global_var ("g_n_signal_nodes") | 
					
						
							|  |  |  |     max_s = long(max_s) | 
					
						
							|  |  |  |     if id < max_s: | 
					
						
							|  |  |  |         return val[id]["name"].string() | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  | def frame_name(frame): | 
					
						
							|  |  |  |     return str(frame.function()) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  | def frame_var(frame, var): | 
					
						
							|  |  |  |     return frame.inferior_frame().read_var(var) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  | class SignalFrame(FrameDecorator): | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |     def __init__ (self, frames): | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |         FrameDecorator.__init__(self, frames[-1]) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |         self.frame = frames[-1] | 
					
						
							| 
									
										
										
										
											2013-09-19 11:55:47 -04:00
										 |  |  |         self.frames = frames | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def name (self): | 
					
						
							|  |  |  |         return "signal-emission" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def read_var (self, frame, name, array = None): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |             v = frame_var (frame, name) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |             if v == None or v.is_optimized_out: | 
					
						
							|  |  |  |                 return None | 
					
						
							|  |  |  |             if array != None: | 
					
						
							|  |  |  |                 array.append (v) | 
					
						
							|  |  |  |             return v | 
					
						
							|  |  |  |         except ValueError: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def read_object (self, frame, name, array = None): | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |             v = frame_var (frame, name) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |             if v == None or v.is_optimized_out: | 
					
						
							|  |  |  |                 return None | 
					
						
							|  |  |  |             v = v.cast (gdb.lookup_type("GObject").pointer()) | 
					
						
							|  |  |  |             # Ensure this is a somewhat correct object pointer | 
					
						
							|  |  |  |             if v != None and g_type_name_from_instance (v): | 
					
						
							|  |  |  |                 if array != None: | 
					
						
							|  |  |  |                     array.append (v) | 
					
						
							|  |  |  |                 return v | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |         except ValueError: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def append (self, array, obj): | 
					
						
							|  |  |  |         if obj != None: | 
					
						
							|  |  |  |             array.append (obj) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def or_join_array (self, array): | 
					
						
							|  |  |  |         if len(array) == 0: | 
					
						
							|  |  |  |             return "???" | 
					
						
							| 
									
										
										
										
											2013-09-19 15:41:09 -04:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |             return ' or '.join(set(map(str, array))) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-19 15:24:16 -04:00
										 |  |  |     def get_detailed_signal_from_frame(self, frame, signal): | 
					
						
							|  |  |  |         detail = self.read_var (frame, "detail") | 
					
						
							|  |  |  |         detail = glib.g_quark_to_string (detail) | 
					
						
							|  |  |  |         if detail is not None: | 
					
						
							|  |  |  |             return signal + ":" + detail | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return detail | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |     def function (self): | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |         instances = [] | 
					
						
							|  |  |  |         signals = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for frame in self.frames: | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |             name = frame_name(frame) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |             if name == "signal_emit_unlocked_R": | 
					
						
							|  |  |  |                 self.read_object (frame, "instance", instances) | 
					
						
							|  |  |  |                 node = self.read_var (frame, "node") | 
					
						
							|  |  |  |                 if node: | 
					
						
							|  |  |  |                     signal = node["name"].string() | 
					
						
							| 
									
										
										
										
											2013-09-19 15:24:16 -04:00
										 |  |  |                     signal = self.get_detailed_signal_from_frame(frame, signal) | 
					
						
							|  |  |  |                     self.append(signals, signal) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if name == "g_signal_emitv": | 
					
						
							|  |  |  |                 instance_and_params = self.read_var (frame, "instance_and_params") | 
					
						
							|  |  |  |                 if instance_and_params: | 
					
						
							|  |  |  |                     instance = instance_and_params[0]["v_pointer"].cast (gdb.Type("GObject").pointer()) | 
					
						
							|  |  |  |                     self.append (instances, instance) | 
					
						
							|  |  |  |                 id = self.read_var (frame, "signal_id") | 
					
						
							|  |  |  |                 signal = get_signal_name (id) | 
					
						
							|  |  |  |                 if signal: | 
					
						
							| 
									
										
										
										
											2013-09-19 15:24:16 -04:00
										 |  |  |                     signal = self.get_detailed_signal_from_frame(frame, signal) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |                     self.append (signals, signal) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if name == "g_signal_emit_valist" or name == "g_signal_emit": | 
					
						
							|  |  |  |                 self.read_object (frame, "instance", instances) | 
					
						
							|  |  |  |                 id = self.read_var (frame, "signal_id") | 
					
						
							|  |  |  |                 signal = get_signal_name (id) | 
					
						
							|  |  |  |                 if signal: | 
					
						
							| 
									
										
										
										
											2013-09-19 15:24:16 -04:00
										 |  |  |                     signal = self.get_detailed_signal_from_frame(frame, signal) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |                     self.append (signals, signal) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if name == "g_signal_emit_by_name": | 
					
						
							|  |  |  |                 self.read_object (frame, "instance", instances) | 
					
						
							|  |  |  |                 self.read_var (frame, "detailed_signal", signals) | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         instance = self.or_join_array (instances) | 
					
						
							|  |  |  |         signal = self.or_join_array (signals) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |         return "<emit signal %s on instance %s>" %  (signal, instance) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def elided (self): | 
					
						
							|  |  |  |         return self.frames[0:-1] | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |     def describe (self, stream, full): | 
					
						
							|  |  |  |         stream.write (" " + self.function () + "\n") | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  | class GFrameDecorator: | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |     def __init__ (self, iter): | 
					
						
							|  |  |  |         self.queue = [] | 
					
						
							|  |  |  |         self.iter = iter | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __iter__ (self): | 
					
						
							|  |  |  |         return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def fill (self): | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |         while len(self.queue) <= 8: | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |                 f = next(self.iter) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |                 self.queue.append (f) | 
					
						
							|  |  |  |             except StopIteration: | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def find_signal_emission (self): | 
					
						
							|  |  |  |         for i in range (min (len(self.queue), 3)): | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |             if frame_name(self.queue[i]) == "signal_emit_unlocked_R": | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |                 return i | 
					
						
							|  |  |  |         return -1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-16 15:24:37 -04:00
										 |  |  |     def next (self): | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |         # Ensure we have enough frames for a full signal emission | 
					
						
							|  |  |  |         self.fill() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Are we at the end? | 
					
						
							|  |  |  |         if len(self.queue) == 0: | 
					
						
							|  |  |  |             raise StopIteration | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         emission = self.find_signal_emission () | 
					
						
							|  |  |  |         if emission > 0: | 
					
						
							|  |  |  |             start = emission | 
					
						
							|  |  |  |             while True: | 
					
						
							|  |  |  |                 if start == 0: | 
					
						
							|  |  |  |                     break | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |                 prev_name = frame_name(self.queue[start-1]) | 
					
						
							|  |  |  |                 if prev_name.find("_marshal_") >= 0 or prev_name == "g_closure_invoke": | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |                     start = start - 1 | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |             end = emission + 1 | 
					
						
							|  |  |  |             while end < len(self.queue): | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |                 if frame_name(self.queue[end]) in ["g_signal_emitv", | 
					
						
							|  |  |  |                                                    "g_signal_emit_valist", | 
					
						
							|  |  |  |                                                    "g_signal_emit", | 
					
						
							|  |  |  |                                                    "g_signal_emit_by_name", | 
					
						
							|  |  |  |                                                    "_g_closure_invoke_va"]: | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |                     end = end + 1 | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             signal_frames = self.queue[start:end] | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |             new_frames = [SignalFrame(signal_frames)] | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |             self.queue[start:end] = new_frames | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return self.queue.pop(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-16 15:24:37 -04:00
										 |  |  |     def __next__ (self): | 
					
						
							|  |  |  |         return self.next() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  | class GFrameFilter(object): | 
					
						
							|  |  |  |     name = 'glib' | 
					
						
							|  |  |  |     enabled = True | 
					
						
							|  |  |  |     priority = 100 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def filter(self, iterator): | 
					
						
							|  |  |  |         return GFrameDecorator(iterator) | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | def register (obj): | 
					
						
							|  |  |  |     if obj == None: | 
					
						
							|  |  |  |         obj = gdb | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 19:16:00 +00:00
										 |  |  |     if HAVE_GDB_FRAMEDECORATOR: | 
					
						
							|  |  |  |         filter = GFrameFilter() | 
					
						
							|  |  |  |         obj.frame_filters[filter.name] = filter | 
					
						
							| 
									
										
										
										
											2009-09-18 17:15:32 +02:00
										 |  |  |     obj.pretty_printers.append(pretty_printer_lookup) |