X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=data%2Fgdb%2Fmono-gdb.py;h=ce34d357f643f46953e45518289e7dc796853b9d;hb=c8ec5331fc8effd75eace4cddab4ef1c274d2030;hp=bde4d588f09a390ec1ef261943d008ea2e043d27;hpb=dab64ac1b846859a61db9e16faed198fa680feae;p=mono.git diff --git a/data/gdb/mono-gdb.py b/data/gdb/mono-gdb.py index bde4d588f09..ce34d357f64 100644 --- a/data/gdb/mono-gdb.py +++ b/data/gdb/mono-gdb.py @@ -10,6 +10,7 @@ # - run mono under gdb, or attach to a mono process started with --debug=gdb using gdb. # +from __future__ import print_function import os class StringPrinter: @@ -30,7 +31,7 @@ class StringPrinter: while i < len: val = (chars.cast(gdb.lookup_type ("gint64")) + (i * 2)).cast(gdb.lookup_type ("gunichar2").pointer ()).dereference () if val >= 256: - c = "\u%X" % val + c = "\u%X".format (val) else: c = chr (val) res.append (c) @@ -47,7 +48,7 @@ def stringify_class_name(ns, name): if ns == "": return name else: - return "%s.%s" % (ns, name) + return "%s.%s".format (ns, name) class ArrayPrinter: "Print a C# array" @@ -60,7 +61,7 @@ class ArrayPrinter: def to_string(self): obj = self.val.cast (gdb.lookup_type ("MonoArray").pointer ()).dereference () length = obj ['max_length'] - return "%s [%d]" % (stringify_class_name (self.class_ns, self.class_name [0:len(self.class_name) - 2]), int(length)) + return "%s [%d]".format (stringify_class_name (self.class_ns, self.class_name [0:len(self.class_name) - 2]), int(length)) class ObjectPrinter: "Print a C# object" @@ -90,7 +91,7 @@ class ObjectPrinter: return (field.name, self.obj [field.name]) except: # Superclass - return (field.name, self.obj.cast (gdb.lookup_type ("%s" % (field.name)))) + return (field.name, self.obj.cast (gdb.lookup_type ("%s".format (field.name)))) def children(self): # FIXME: It would be easier if gdb.Value would support iteration itself @@ -103,11 +104,14 @@ class ObjectPrinter: class_name = obj ['vtable'].dereference ()['klass'].dereference ()['name'].string () if class_name [-2:len(class_name)] == "[]": return {}.__iter__ () - gdb_type = gdb.lookup_type ("struct %s_%s" % (class_ns.replace (".", "_"), class_name)) - return self._iterator(obj.cast (gdb_type)) + try: + gdb_type = gdb.lookup_type ("struct %s_%s".format (class_ns.replace (".", "_"), class_name)) + return self._iterator(obj.cast (gdb_type)) + except: + return {}.__iter__ () except: - print sys.exc_info ()[0] - print sys.exc_info ()[1] + print (sys.exc_info ()[0]) + print (sys.exc_info ()[1]) return {}.__iter__ () def to_string(self): @@ -123,16 +127,16 @@ class ObjectPrinter: return ArrayPrinter (self.val,class_ns,class_name).to_string () if class_ns != "": try: - gdb_type = gdb.lookup_type ("struct %s.%s" % (class_ns, class_name)) + gdb_type = gdb.lookup_type ("struct %s.%s".format (class_ns, class_name)) except: # Maybe there is no debug info for that type - return "%s.%s" % (class_ns, class_name) + return "%s.%s".format (class_ns, class_name) #return obj.cast (gdb_type) - return "%s.%s" % (class_ns, class_name) + return "%s.%s".format (class_ns, class_name) return class_name except: - print sys.exc_info ()[0] - print sys.exc_info ()[1] + print (sys.exc_info ()[0]) + print (sys.exc_info ()[1]) # FIXME: This can happen because we don't have liveness information return self.val.cast (gdb.lookup_type ("guint64")) @@ -148,9 +152,9 @@ class MonoMethodPrinter: val = self.val.dereference () klass = val ["klass"].dereference () class_name = stringify_class_name (klass ["name_space"].string (), klass ["name"].string ()) - return "\"%s:%s ()\"" % (class_name, val ["name"].string ()) + return "\"%s:%s ()\"".format (class_name, val ["name"].string ()) # This returns more info but requires calling into the inferior - #return "\"%s\"" % (gdb.parse_and_eval ("mono_method_full_name (%s, 1)" % (str (int (self.val.cast (gdb.lookup_type ("guint64")))))).string ()) + #return "\"%s\"".format (gdb.parse_and_eval ("mono_method_full_name (%s, 1)".format (str (int (self.val.cast (gdb.lookup_type ("guint64")))))).string ()) class MonoClassPrinter: "Print a MonoClass structure" @@ -158,14 +162,143 @@ class MonoClassPrinter: def __init__(self, val): self.val = val - def to_string(self): + def to_string_inner(self, add_quotes): if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: return "0x0" klass = self.val.dereference () class_name = stringify_class_name (klass ["name_space"].string (), klass ["name"].string ()) - return "\"%s\"" % (class_name) + if klass ["generic_class"].cast (gdb.lookup_type ("guint64")) != 0: + class_name = "%s<%s>".format (class_name, str (klass ["generic_class"]["context"]["class_inst"])) + if add_quotes: + return "\"%s\"".format (class_name) + else: + return class_name # This returns more info but requires calling into the inferior - #return "\"%s\"" % (gdb.parse_and_eval ("mono_type_full_name (&((MonoClass*)%s)->byval_arg)" % (str (int ((self.val).cast (gdb.lookup_type ("guint64"))))))) + #return "\"%s\"".format (gdb.parse_and_eval ("mono_type_full_name (&((MonoClass*)%s)->byval_arg)".format (str (int ((self.val).cast (gdb.lookup_type ("guint64"))))))) + + def to_string(self): + try: + return self.to_string_inner (True) + except: + #print (sys.exc_info ()[0]) + #print (sys.exc_info ()[1]) + return str(self.val.cast (gdb.lookup_type ("gpointer"))) + +class MonoGenericInstPrinter: + "Print a MonoGenericInst structure" + + def __init__(self, val): + self.val = val + + def to_string(self): + if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: + return "0x0" + inst = self.val.dereference () + inst_len = inst ["type_argc"] + inst_args = inst ["type_argv"] + inst_str = "" + for i in range(0, inst_len): + print (inst_args) + type_printer = MonoTypePrinter (inst_args [i]) + if i > 0: + inst_str = inst_str + ", " + inst_str = inst_str + type_printer.to_string () + return inst_str + +class MonoGenericClassPrinter: + "Print a MonoGenericClass structure" + + def __init__(self, val): + self.val = val + + def to_string_inner(self): + gclass = self.val.dereference () + container_str = str(gclass ["container_class"]) + class_inst = gclass ["context"]["class_inst"] + class_inst_str = "" + if int(class_inst.cast (gdb.lookup_type ("guint64"))) != 0: + class_inst_str = str(class_inst) + method_inst = gclass ["context"]["method_inst"] + method_inst_str = "" + if int(method_inst.cast (gdb.lookup_type ("guint64"))) != 0: + method_inst_str = str(method_inst) + return "%s, [%s], [%s]>".format (container_str, class_inst_str, method_inst_str) + + def to_string(self): + try: + return self.to_string_inner () + except: + #print (sys.exc_info ()[0]) + #print (sys.exc_info ()[1]) + return str(self.val.cast (gdb.lookup_type ("gpointer"))) + +class MonoTypePrinter: + "Print a MonoType structure" + + def __init__(self, val): + self.val = val + + def to_string_inner(self, csharp): + try: + t = self.val.dereference () + + kind = str (t ["type"]).replace ("MONO_TYPE_", "").lower () + info = "" + + if kind == "class": + p = MonoClassPrinter(t ["data"]["klass"]) + info = p.to_string () + elif kind == "genericinst": + info = str(t ["data"]["generic_class"]) + + if info != "": + return "{%s, %s}".format (kind, info) + else: + return "{%s}".format (kind) + except: + #print (sys.exc_info ()[0]) + #print (sys.exc_info ()[1]) + return str(self.val.cast (gdb.lookup_type ("gpointer"))) + + def to_string(self): + return self.to_string_inner (False) + +class MonoMethodRgctxPrinter: + "Print a MonoMethodRgctx structure" + + def __init__(self, val): + self.val = val + + def to_string(self): + rgctx = self.val.dereference () + klass = rgctx ["class_vtable"].dereference () ["klass"] + klass_printer = MonoClassPrinter (klass) + inst = rgctx ["method_inst"].dereference () + inst_len = inst ["type_argc"] + inst_args = inst ["type_argv"] + inst_str = "" + for i in range(0, inst_len): + print (inst_args) + type_printer = MonoTypePrinter (inst_args [i]) + if i > 0: + inst_str = inst_str + ", " + inst_str = inst_str + type_printer.to_string () + return "MRGCTX[%s, [%s]]".format (klass_printer.to_string(), inst_str) + +class MonoVTablePrinter: + "Print a MonoVTable structure" + + def __init__(self, val): + self.val = val + + def to_string(self): + if int(self.val.cast (gdb.lookup_type ("guint64"))) == 0: + return "0x0" + vtable = self.val.dereference () + klass = vtable ["klass"] + klass_printer = MonoClassPrinter (klass) + + return "vtable(%s)".format (klass_printer.to_string ()) def lookup_pretty_printer(val): t = str (val.type) @@ -175,10 +308,22 @@ def lookup_pretty_printer(val): return ObjectPrinter (val) if t == "string": return StringPrinter (val) + if t == "MonoString *": + return StringPrinter (val) if t == "MonoMethod *": return MonoMethodPrinter (val) if t == "MonoClass *": return MonoClassPrinter (val) + if t == "MonoType *": + return MonoTypePrinter (val) + if t == "MonoGenericInst *": + return MonoGenericInstPrinter (val) + if t == "MonoGenericClass *": + return MonoGenericClassPrinter (val) + if t == "MonoMethodRuntimeGenericContext *": + return MonoMethodRgctxPrinter (val) + if t == "MonoVTable *": + return MonoVTablePrinter (val) return None def register_csharp_printers(obj): @@ -189,10 +334,21 @@ def register_csharp_printers(obj): obj.pretty_printers.append (lookup_pretty_printer) +# This command will flush the debugging info collected by the runtime +class XdbCommand (gdb.Command): + def __init__ (self): + super (XdbCommand, self).__init__ ("xdb", gdb.COMMAND_NONE, + gdb.COMPLETE_COMMAND) + + def invoke(self, arg, from_tty): + gdb.execute ("call mono_xdebug_flush ()") + register_csharp_printers (gdb.current_objfile()) +XdbCommand () + gdb.execute ("set environment MONO_XDEBUG gdb") -print "Mono support loaded." +print ("Mono support loaded.")