aboutsummaryrefslogtreecommitdiff
path: root/Release/share/glib-2.0/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'Release/share/glib-2.0/gdb')
-rw-r--r--Release/share/glib-2.0/gdb/glib_gdb.py261
-rw-r--r--Release/share/glib-2.0/gdb/gobject_gdb.py295
2 files changed, 556 insertions, 0 deletions
diff --git a/Release/share/glib-2.0/gdb/glib_gdb.py b/Release/share/glib-2.0/gdb/glib_gdb.py
new file mode 100644
index 0000000..38f101a
--- /dev/null
+++ b/Release/share/glib-2.0/gdb/glib_gdb.py
@@ -0,0 +1,261 @@
+import gdb
+import sys
+
+if sys.version_info[0] >= 3:
+ long = int
+
+# 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_quark_to_string (quark):
+ if quark == None:
+ return None
+ quark = long(quark)
+ if quark == 0:
+ return None
+ try:
+ val = read_global_var ("quarks")
+ max_q = long(read_global_var ("quark_seq_id"))
+ except:
+ try:
+ val = read_global_var ("g_quarks")
+ max_q = long(read_global_var ("g_quark_seq_id"))
+ except:
+ return None;
+ if quark < max_q:
+ return val[quark].string()
+ return None
+
+# We override the node printers too, so that node->next is not expanded
+class GListNodePrinter:
+ "Prints a GList node"
+
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ return "{data=%s, next=0x%x, prev=0x%x}" % (str(self.val["data"]), long(self.val["next"]), long(self.val["prev"]))
+
+class GSListNodePrinter:
+ "Prints a GSList node"
+
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
+
+class GListPrinter:
+ "Prints a GList"
+
+ class _iterator:
+ def __init__(self, head, listtype):
+ self.link = head
+ self.listtype = listtype
+ self.count = 0
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if self.link == 0:
+ raise StopIteration
+ data = self.link['data']
+ self.link = self.link['next']
+ count = self.count
+ self.count = self.count + 1
+ return ('[%d]' % count, data)
+
+ __next__ = next
+
+ def __init__ (self, val, listtype):
+ self.val = val
+ self.listtype = listtype
+
+ def children(self):
+ return self._iterator(self.val, self.listtype)
+
+ def to_string (self):
+ return "0x%x" % (long(self.val))
+
+ def display_hint (self):
+ return "array"
+
+class GHashPrinter:
+ "Prints a GHashTable"
+
+ class _iterator:
+ def __init__(self, ht, keys_are_strings):
+ self.ht = ht
+ if ht != 0:
+ self.keys = ht["keys"]
+ self.values = ht["values"]
+ self.hashes = ht["hashes"]
+ self.size = ht["size"]
+ self.pos = 0
+ self.keys_are_strings = keys_are_strings
+ self.value = None
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ if self.ht == 0:
+ raise StopIteration
+ if self.value != None:
+ v = self.value
+ self.value = None
+ return v
+ while long(self.pos) < long(self.size):
+ self.pos = self.pos + 1
+ if long (self.hashes[self.pos]) >= 2:
+ key = self.keys[self.pos]
+ val = self.values[self.pos]
+
+ if self.keys_are_strings:
+ key = key.cast (gdb.lookup_type("char").pointer())
+
+ # Queue value for next result
+ self.value = ('[%dv]'% (self.pos), val)
+
+ # Return key
+ return ('[%dk]'% (self.pos), key)
+ raise StopIteration
+
+ __next__ = next
+
+ def __init__ (self, val):
+ self.val = val
+ self.keys_are_strings = False
+ try:
+ string_hash = read_global_var ("g_str_hash")
+ except:
+ string_hash = None
+ if self.val != 0 and string_hash != None and self.val["hash_func"] == string_hash:
+ self.keys_are_strings = True
+
+ def children(self):
+ return self._iterator(self.val, self.keys_are_strings)
+
+ def to_string (self):
+ return "0x%x" % (long(self.val))
+
+ def display_hint (self):
+ return "map"
+
+def pretty_printer_lookup (val):
+ # None yet, want things like hash table and list
+
+ type = val.type.unqualified()
+
+ # If it points to a reference, get the reference.
+ if type.code == gdb.TYPE_CODE_REF:
+ type = type.target ()
+
+ if type.code == gdb.TYPE_CODE_PTR:
+ type = type.target().unqualified()
+ t = str(type)
+ if t == "GList":
+ return GListPrinter(val, "GList")
+ if t == "GSList":
+ return GListPrinter(val, "GSList")
+ if t == "GHashTable":
+ return GHashPrinter(val)
+ else:
+ t = str(type)
+ if t == "GList":
+ return GListNodePrinter(val)
+ if t == "GSList *":
+ return GListPrinter(val, "GSList")
+ return None
+
+def register (obj):
+ if obj == None:
+ obj = gdb
+
+ obj.pretty_printers.append(pretty_printer_lookup)
+
+class ForeachCommand (gdb.Command):
+ """Foreach on list"""
+
+ def __init__ (self):
+ super (ForeachCommand, self).__init__ ("gforeach",
+ gdb.COMMAND_DATA,
+ gdb.COMPLETE_SYMBOL)
+
+ def valid_name (self, name):
+ if not name[0].isalpha():
+ return False
+ return True
+
+ def parse_args (self, arg):
+ i = arg.find(" ")
+ if i <= 0:
+ raise Exception ("No var specified")
+ var = arg[:i]
+ if not self.valid_name(var):
+ raise Exception ("Invalid variable name")
+
+ while i < len (arg) and arg[i].isspace():
+ i = i + 1
+
+ if arg[i:i+2] != "in":
+ raise Exception ("Invalid syntax, missing in")
+
+ i = i + 2
+
+ while i < len (arg) and arg[i].isspace():
+ i = i + 1
+
+ colon = arg.find (":", i)
+ if colon == -1:
+ raise Exception ("Invalid syntax, missing colon")
+
+ val = arg[i:colon]
+
+ colon = colon + 1
+ while colon < len (arg) and arg[colon].isspace():
+ colon = colon + 1
+
+ command = arg[colon:]
+
+ return (var, val, command)
+
+ def do_iter(self, arg, item, command):
+ item = item.cast (gdb.lookup_type("void").pointer())
+ item = long(item)
+ to_eval = "set $%s = (void *)0x%x\n"%(arg, item)
+ gdb.execute(to_eval)
+ gdb.execute(command)
+
+ def slist_iterator (self, arg, container, command):
+ l = container.cast (gdb.lookup_type("GSList").pointer())
+ while long(l) != 0:
+ self.do_iter (arg, l["data"], command)
+ l = l["next"]
+
+ def list_iterator (self, arg, container, command):
+ l = container.cast (gdb.lookup_type("GList").pointer())
+ while long(l) != 0:
+ self.do_iter (arg, l["data"], command)
+ l = l["next"]
+
+ def pick_iterator (self, container):
+ t = container.type.unqualified()
+ if t.code == gdb.TYPE_CODE_PTR:
+ t = t.target().unqualified()
+ t = str(t)
+ if t == "GSList":
+ return self.slist_iterator
+ if t == "GList":
+ return self.list_iterator
+ raise Exception("Invalid container type %s"%(str(container.type)))
+
+ def invoke (self, arg, from_tty):
+ (var, container, command) = self.parse_args(arg)
+ container = gdb.parse_and_eval (container)
+ func = self.pick_iterator(container)
+ func(var, container, command)
+
+ForeachCommand ()
diff --git a/Release/share/glib-2.0/gdb/gobject_gdb.py b/Release/share/glib-2.0/gdb/gobject_gdb.py
new file mode 100644
index 0000000..8c30220
--- /dev/null
+++ b/Release/share/glib-2.0/gdb/gobject_gdb.py
@@ -0,0 +1,295 @@
+import os.path
+import gdb
+import glib_gdb
+import sys
+
+if sys.version_info[0] >= 3:
+ long = int
+else:
+ import itertools
+ map = itertools.imap
+
+# FrameDecorator is new in gdb 7.7, so we adapt to its absence.
+try:
+ import gdb.FrameDecorator
+ HAVE_GDB_FRAMEDECORATOR = True
+ FrameDecorator = gdb.FrameDecorator.FrameDecorator
+except ImportError:
+ HAVE_GDB_FRAMEDECORATOR = False
+
+# 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_gdb.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):
+ 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()
+ return None
+
+def frame_name(frame):
+ return str(frame.function())
+
+def frame_var(frame, var):
+ return frame.inferior_frame().read_var(var)
+
+
+class SignalFrame(FrameDecorator):
+ def __init__ (self, frames):
+ FrameDecorator.__init__(self, frames[-1])
+ self.frame = frames[-1]
+ self.frames = frames
+
+ def name (self):
+ return "signal-emission"
+
+ def read_var (self, frame, name, array = None):
+ try:
+ v = frame_var (frame, name)
+ 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:
+ v = frame_var (frame, name)
+ 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 "???"
+ else:
+ return ' or '.join(set(map(str, array)))
+
+ def get_detailed_signal_from_frame(self, frame, signal):
+ detail = self.read_var (frame, "detail")
+ detail = glib_gdb.g_quark_to_string (detail)
+ if detail is not None:
+ return signal + ":" + detail
+ else:
+ return detail
+
+ def function (self):
+ instances = []
+ signals = []
+
+ for frame in self.frames:
+ name = frame_name(frame)
+ if name == "signal_emit_unlocked_R":
+ self.read_object (frame, "instance", instances)
+ node = self.read_var (frame, "node")
+ if node:
+ signal = node["name"].string()
+ signal = self.get_detailed_signal_from_frame(frame, signal)
+ self.append(signals, signal)
+
+ 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:
+ signal = self.get_detailed_signal_from_frame(frame, signal)
+ 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:
+ signal = self.get_detailed_signal_from_frame(frame, signal)
+ 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)
+
+ return "<emit signal %s on instance %s>" % (signal, instance)
+
+ def elided (self):
+ return self.frames[0:-1]
+
+ def describe (self, stream, full):
+ stream.write (" " + self.function () + "\n")
+
+class GFrameDecorator:
+ def __init__ (self, iter):
+ self.queue = []
+ self.iter = iter
+
+ def __iter__ (self):
+ return self
+
+ def fill (self):
+ while len(self.queue) <= 8:
+ try:
+ f = next(self.iter)
+ self.queue.append (f)
+ except StopIteration:
+ return
+
+ def find_signal_emission (self):
+ for i in range (min (len(self.queue), 3)):
+ if frame_name(self.queue[i]) == "signal_emit_unlocked_R":
+ return i
+ return -1
+
+ def next (self):
+ # 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
+ prev_name = frame_name(self.queue[start-1])
+ if prev_name.find("_marshal_") >= 0 or prev_name == "g_closure_invoke":
+ start = start - 1
+ else:
+ break
+ end = emission + 1
+ while end < len(self.queue):
+ 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"]:
+ end = end + 1
+ else:
+ break
+
+ signal_frames = self.queue[start:end]
+ new_frames = [SignalFrame(signal_frames)]
+ self.queue[start:end] = new_frames
+
+ return self.queue.pop(0)
+
+ def __next__ (self):
+ return self.next()
+
+class GFrameFilter(object):
+ name = 'glib'
+ enabled = True
+ priority = 100
+
+ def filter(self, iterator):
+ return GFrameDecorator(iterator)
+
+def register (obj):
+ if obj == None:
+ obj = gdb
+
+ if HAVE_GDB_FRAMEDECORATOR:
+ filter = GFrameFilter()
+ obj.frame_filters[filter.name] = filter
+ obj.pretty_printers.append(pretty_printer_lookup)