2009-04-07 Zoltan Varga <vargaz@gmail.com>
[mono.git] / data / gdb / mono-gdb.py
index 5ab441937000f92c12562dc5cf2563a731d59ccd..523aa90061af40f000139566193da07451b71b73 100644 (file)
@@ -33,7 +33,11 @@ class StringPrinter:
         i = 0
         res = ['"']
         while i < len:
-            c = chr ((chars.cast(gdb.Type ("gint64")) + (i * 2)).cast(gdb.Type ("gunichar2").pointer ()).dereference ())
+            val = (chars.cast(gdb.Type ("gint64")) + (i * 2)).cast(gdb.Type ("gunichar2").pointer ()).dereference ()
+            if val >= 256:
+                c = "\u%X" % val
+            else:
+                c = chr (val)
             res.append (c)
             i = i + 1
         res.append ('"')
@@ -45,7 +49,10 @@ def stringify_class_name(ns, name):
             return "byte"
         if name == "String":
             return "string"
-    return "%s.%s" % (ns, name)
+    if ns == "":
+        return name
+    else:
+        return "%s.%s" % (ns, name)
 
 class ArrayPrinter:
     "Print a C# array"
@@ -64,7 +71,10 @@ class ObjectPrinter:
     "Print a C# object"
 
     def __init__(self, val):
-        self.val = val
+        if str(val.type ())[-1] == "&":
+            self.val = val.address.cast (gdb.Type ("MonoObject").pointer ())
+        else:
+            self.val = val.cast (gdb.Type ("MonoObject").pointer ())
 
     class _iterator:
         def __init__(self,obj):
@@ -77,7 +87,15 @@ class ObjectPrinter:
 
         def next(self):
             field = self.iter.next ()
-            return (field.name, self.obj [field.name])
+            try:
+                if str(self.obj [field.name].type ()) == "object":
+                    # Avoid recursion
+                    return (field.name, self.obj [field.name].cast (gdb.Type ("void").pointer ()))
+                else:
+                    return (field.name, self.obj [field.name])
+            except:
+                # Superclass
+                return (field.name, self.obj.cast (gdb.Type ("%s" % (field.name))))
 
     def children(self):
         # FIXME: It would be easier if gdb.Value would support iteration itself
@@ -85,19 +103,23 @@ class ObjectPrinter:
         if int(self.val.cast (gdb.Type ("guint64"))) == 0:
             return {}.__iter__ ()
         try:
-            obj = self.val.cast (gdb.Type ("MonoObject").pointer ()).dereference ()
+            obj = self.val.dereference ()
             class_ns = obj ['vtable'].dereference ()['klass'].dereference ()['name_space'].string ()
             class_name = obj ['vtable'].dereference ()['klass'].dereference ()['name'].string ()
-            gdb_type = gdb.Type ("struct %s.%s" % (class_ns, class_name))
+            if class_name [-2:len(class_name)] == "[]":
+                return {}.__iter__ ()
+            gdb_type = gdb.Type ("struct %s_%s" % (class_ns.replace (".", "_"), class_name))
             return self._iterator(obj.cast (gdb_type))
         except:
+            print sys.exc_info ()[0]
+            print sys.exc_info ()[1]
             return {}.__iter__ ()
 
     def to_string(self):
         if int(self.val.cast (gdb.Type ("guint64"))) == 0:
             return "null"
         try:
-            obj = self.val.cast (gdb.Type ("MonoObject").pointer ()).dereference ()
+            obj = self.val.dereference ()
             class_ns = obj ['vtable'].dereference ()['klass'].dereference ()['name_space'].string ()
             class_name = obj ['vtable'].dereference ()['klass'].dereference ()['name'].string ()
             if class_ns == "System" and class_name == "String":
@@ -119,14 +141,23 @@ class ObjectPrinter:
             # FIXME: This can happen because we don't have liveness information
             return self.val.cast (gdb.Type ("guint64"))
 
+def lookup_pretty_printer(val):
+    t = str (val.type ())
+    if t == "object":
+        return ObjectPrinter (val)
+    if t[0:5] == "class" and t[-1] == "&":
+        return ObjectPrinter (val)    
+    if t == "string":
+        return StringPrinter (val)
+    return None
+
 def register_csharp_printers(obj):
     "Register C# pretty-printers with objfile Obj."
 
     if obj == None:
         obj = gdb
 
-    obj.pretty_printers['object'] = ObjectPrinter
-    obj.pretty_printers['string'] = StringPrinter
+    obj.pretty_printers.append (lookup_pretty_printer)
 
 register_csharp_printers (gdb.current_objfile())