diff options
author | Zoltan Varga <vargaz@gmail.com> | 2015-01-23 00:42:56 +0300 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2015-01-23 00:42:56 +0300 |
commit | 879cd1bed141646212069a3088c19ccee2b2eaae (patch) | |
tree | e7013a392de9453075fc2c1210e67ec18ba56585 /data | |
parent | af7a963fc015637d9aa2b55e592d78d0034dc6aa (diff) |
[runtime] Add a preliminary mono support mode for lldb. Currently, pretty printing some runtime types is supported.
Diffstat (limited to 'data')
-rw-r--r-- | data/lldb/mono.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/data/lldb/mono.py b/data/lldb/mono.py new file mode 100644 index 00000000000..8fe9641165f --- /dev/null +++ b/data/lldb/mono.py @@ -0,0 +1,174 @@ +# +# Author: Zoltan Varga (vargaz@gmail.com) +# License: MIT/X11 +# + +# +# This is a mono support mode for lldb +# + +# Comments about the lldb python api: +# - there are no accessors, i.e. valobj["name"] +# - http://lldb.llvm.org/python_reference/index.html seems to be outdated +# - there is no autoload support, i.e. can't load this file automatically +# when 'mono' is the debugger target. + +import lldb + +# FIXME: Generate enums from runtime enums +MONO_TYPE_END = 0x00 +MONO_TYPE_VOID = 0x01 +MONO_TYPE_BOOLEAN = 0x02 +MONO_TYPE_CHAR = 0x03 +MONO_TYPE_I1 = 0x04 +MONO_TYPE_U1 = 0x05 +MONO_TYPE_I2 = 0x06 +MONO_TYPE_U2 = 0x07 +MONO_TYPE_I4 = 0x08 +MONO_TYPE_U4 = 0x09 +MONO_TYPE_I8 = 0x0a +MONO_TYPE_U8 = 0x0b +MONO_TYPE_R4 = 0x0c +MONO_TYPE_R8 = 0x0d +MONO_TYPE_STRING = 0x0e +MONO_TYPE_PTR = 0x0f +MONO_TYPE_BYREF = 0x10 +MONO_TYPE_VALUETYPE = 0x11 +MONO_TYPE_CLASS = 0x12 +MONO_TYPE_VAR = 0x13 +MONO_TYPE_ARRAY = 0x14 +MONO_TYPE_GENERICINST= 0x15 +MONO_TYPE_TYPEDBYREF = 0x16 +MONO_TYPE_I = 0x18 +MONO_TYPE_U = 0x19 +MONO_TYPE_FNPTR = 0x1b +MONO_TYPE_OBJECT = 0x1c +MONO_TYPE_SZARRAY = 0x1d +MONO_TYPE_MVAR = 0x1e + +primitive_type_names = { + MONO_TYPE_BOOLEAN : "bool", + MONO_TYPE_CHAR : "char", + MONO_TYPE_I1 : "sbyte", + MONO_TYPE_U1 : "byte", + MONO_TYPE_I2 : "short", + MONO_TYPE_U2 : "ushort", + MONO_TYPE_I4 : "int", + MONO_TYPE_U4 : "uint", + MONO_TYPE_I8 : "long", + MONO_TYPE_U8 : "ulong", + MONO_TYPE_R4 : "float", + MONO_TYPE_R8 : "double", + MONO_TYPE_STRING : "string" + } + +# +# Helper functions for working with the lldb python api +# + +def member(val, member_name): + return val.GetChildMemberWithName (member_name) + +def string_member(val, member_name): + return val.GetChildMemberWithName (member_name).GetSummary ()[1:-1] + +def isnull(val): + return val.deref.addr.GetOffset () == 0 + +def stringify_class_name(ns, name): + if ns == "System": + if name == "Byte": + return "byte" + if name == "String": + return "string" + if ns == "": + return name + else: + return "{0}.{1}".format (ns, name) + +# +# Pretty printers for mono runtime types +# + +def stringify_type (type): + "Print a MonoType structure" + ttype = member(type, "type").GetValueAsUnsigned() + if primitive_type_names.has_key (ttype): + return primitive_type_names [ttype] + else: + return "<MonoTypeEnum 0x{0:x}>".format (ttype) + +def stringify_ginst (ginst): + "Print a MonoGenericInst structure" + len = int(member(ginst, "type_argc").GetValue()) + argv = member(ginst, "type_argv") + res="" + for i in range(len): + t = argv.GetChildAtIndex(i, False, True) + if i > 0: + res += ", " + res += stringify_type(t) + return res + +def print_type(valobj, internal_dict): + type = valobj + if isnull (type): + return "" + return stringify_type (type) + +def print_class (valobj, internal_dict): + klass = valobj + if isnull (klass): + return "" + aname = member (member (member (klass, "image"), "assembly"), "aname") + basename = "[{0}]{1}".format (string_member (aname, "name"), (stringify_class_name (string_member (klass, "name_space"), string_member (klass, "name")))) + gclass = member (klass, "generic_class") + if not isnull (gclass): + ginst = member (member (gclass, "context"), "class_inst") + return "{0}<{1}>".format (basename, stringify_ginst (ginst)) + return basename + +def print_method (valobj, internal_dict): + method = valobj + if isnull (method): + return "" + klass = member (method, "klass") + return "{0}:{1}()".format (print_class (klass, None), string_member (valobj, "name")) + +def print_domain(valobj, internal_dict): + domain = valobj + if isnull (domain): + return "" + target = domain.target + root = target.FindFirstGlobalVariable("mono_root_domain") + name = string_member (domain, "friendly_name") + if root.IsValid () and root.deref.addr.GetOffset () == root.deref.addr.GetOffset (): + return "[root]" + else: + return "[{0}]".format (name) + +def print_object(valobj, internal_dict): + obj = valobj + if isnull (obj): + return "" + domain = member (member (obj, "vtable"), "domain") + klass = member (member (obj, "vtable"), "klass") + return print_domain (domain, None) + print_class (klass, None) + +# Register pretty printers +# FIXME: This cannot pick up the methods define in this module, leading to warnings +lldb.debugger.HandleCommand ("type summary add -w mono -F mono.print_method MonoMethod") +lldb.debugger.HandleCommand ("type summary add -w mono -F mono.print_class MonoClass") +lldb.debugger.HandleCommand ("type summary add -w mono -F mono.print_type MonoType") +lldb.debugger.HandleCommand ("type summary add -w mono -F mono.print_domain MonoDomain") +lldb.debugger.HandleCommand ("type summary add -w mono -F mono.print_object MonoObject") +lldb.debugger.HandleCommand ("type category enable mono") + +# Helper commands for runtime debugging +# These resume the target +# Print the method at the current ip +lldb.debugger.HandleCommand ("command alias pip p mono_print_method_from_ip((void*)$pc)") +# Print the method at the provided ip +lldb.debugger.HandleCommand ("command regex pmip 's/^$/p mono_print_method_from_ip((void*)$pc)/' 's/(.+)/p mono_print_method_from_ip((void*)(%1))/'") + +print "Mono support mode loaded." |