Import Upstream version 2.72.4
This commit is contained in:
commit
4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions
352
gobject/gobject_gdb.py
Normal file
352
gobject/gobject_gdb.py
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
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_typenode(gtype):
|
||||
def lookup_fundamental_type(typenode):
|
||||
if typenode == 0:
|
||||
return None
|
||||
val = read_global_var("static_fundamental_type_nodes")
|
||||
if val is 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)
|
||||
return typenode
|
||||
|
||||
|
||||
def g_type_to_name(gtype):
|
||||
typenode = g_type_to_typenode(gtype)
|
||||
if typenode is not 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 is_g_type_class_instance(val):
|
||||
type = val.type
|
||||
if type.code != gdb.TYPE_CODE_PTR:
|
||||
return False
|
||||
return str(type.target()) == "GTypeClass"
|
||||
|
||||
|
||||
class GTypeHandlePrettyPrinter:
|
||||
"Prints a GType instance"
|
||||
|
||||
def __init__(self, val, hint=""):
|
||||
self.val = val
|
||||
self.hint = hint
|
||||
|
||||
def to_string(self):
|
||||
typenode = g_type_to_typenode(self.val)
|
||||
if typenode is not None:
|
||||
name = glib_gdb.g_quark_to_string(typenode["qname"])
|
||||
s = ("0x%x [%s%s") % (long(self.val), self.hint, name)
|
||||
for i in range(1, int(typenode["n_supers"])):
|
||||
node = g_type_to_typenode(typenode["supers"][i])
|
||||
if node:
|
||||
name = glib_gdb.g_quark_to_string(node["qname"])
|
||||
else:
|
||||
name = "???"
|
||||
s += "/" + name
|
||||
return s + "]"
|
||||
else:
|
||||
return ("0x%x") % (long(self.val))
|
||||
|
||||
|
||||
def pretty_printer_lookup(val):
|
||||
if is_g_type_instance(val):
|
||||
return GTypePrettyPrinter(val)
|
||||
if str(val.type) == "GType":
|
||||
return GTypeHandlePrettyPrinter(val)
|
||||
if is_g_type_class_instance(val):
|
||||
return GTypeHandlePrettyPrinter(val["g_type"], "g_type: ")
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_signal_name(id):
|
||||
if id is 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 is None or v.is_optimized_out:
|
||||
return None
|
||||
if array is not 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 is 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 is not None and g_type_name_from_instance(v):
|
||||
if array is not None:
|
||||
array.append(v)
|
||||
return v
|
||||
return None
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def append(self, array, obj):
|
||||
if obj is not 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 is None:
|
||||
obj = gdb
|
||||
|
||||
if HAVE_GDB_FRAMEDECORATOR:
|
||||
filter = GFrameFilter()
|
||||
obj.frame_filters[filter.name] = filter
|
||||
obj.pretty_printers.append(pretty_printer_lookup)
|
||||
Loading…
Add table
Add a link
Reference in a new issue