| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 | ## 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 enumsMONO_TYPE_END        = 0x00MONO_TYPE_VOID       = 0x01MONO_TYPE_BOOLEAN    = 0x02MONO_TYPE_CHAR       = 0x03MONO_TYPE_I1         = 0x04MONO_TYPE_U1         = 0x05MONO_TYPE_I2         = 0x06MONO_TYPE_U2         = 0x07MONO_TYPE_I4         = 0x08MONO_TYPE_U4         = 0x09MONO_TYPE_I8         = 0x0aMONO_TYPE_U8         = 0x0bMONO_TYPE_R4         = 0x0cMONO_TYPE_R8         = 0x0dMONO_TYPE_STRING     = 0x0eMONO_TYPE_PTR        = 0x0fMONO_TYPE_BYREF      = 0x10MONO_TYPE_VALUETYPE  = 0x11MONO_TYPE_CLASS      = 0x12MONO_TYPE_VAR	     = 0x13MONO_TYPE_ARRAY      = 0x14MONO_TYPE_GENERICINST= 0x15MONO_TYPE_TYPEDBYREF = 0x16MONO_TYPE_I          = 0x18MONO_TYPE_U          = 0x19MONO_TYPE_FNPTR      = 0x1bMONO_TYPE_OBJECT     = 0x1cMONO_TYPE_SZARRAY    = 0x1dMONO_TYPE_MVAR	     = 0x1eprimitive_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 () == 0def 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 resdef 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 basenamedef 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 warningslldb.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 iplldb.debugger.HandleCommand ("command alias pip p mono_print_method_from_ip((void*)$pc)")# Print the method at the provided iplldb.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."
 |