2 # Author: Zoltan Varga (vargaz@gmail.com)
7 # This is a mono support mode for lldb
10 # Comments about the lldb python api:
11 # - there are no accessors, i.e. valobj["name"]
12 # - http://lldb.llvm.org/python_reference/index.html seems to be outdated
13 # - there is no autoload support, i.e. can't load this file automatically
14 # when 'mono' is the debugger target.
18 # FIXME: Generate enums from runtime enums
21 MONO_TYPE_BOOLEAN
= 0x02
33 MONO_TYPE_STRING
= 0x0e
35 MONO_TYPE_BYREF
= 0x10
36 MONO_TYPE_VALUETYPE
= 0x11
37 MONO_TYPE_CLASS
= 0x12
39 MONO_TYPE_ARRAY
= 0x14
40 MONO_TYPE_GENERICINST
= 0x15
41 MONO_TYPE_TYPEDBYREF
= 0x16
44 MONO_TYPE_FNPTR
= 0x1b
45 MONO_TYPE_OBJECT
= 0x1c
46 MONO_TYPE_SZARRAY
= 0x1d
49 primitive_type_names
= {
50 MONO_TYPE_BOOLEAN
: "bool",
51 MONO_TYPE_CHAR
: "char",
52 MONO_TYPE_I1
: "sbyte",
53 MONO_TYPE_U1
: "byte",
54 MONO_TYPE_I2
: "short",
55 MONO_TYPE_U2
: "ushort",
57 MONO_TYPE_U4
: "uint",
58 MONO_TYPE_I8
: "long",
59 MONO_TYPE_U8
: "ulong",
60 MONO_TYPE_R4
: "float",
61 MONO_TYPE_R8
: "double",
62 MONO_TYPE_STRING
: "string"
66 # Helper functions for working with the lldb python api
69 def member(val
, member_name
):
70 return val
.GetChildMemberWithName (member_name
)
72 def string_member(val
, member_name
):
73 return val
.GetChildMemberWithName (member_name
).GetSummary ()[1:-1]
76 return val
.deref
.addr
.GetOffset () == 0
78 def stringify_class_name(ns
, name
):
87 return "{0}.{1}".format (ns
, name
)
90 # Pretty printers for mono runtime types
93 def stringify_type (type):
94 "Print a MonoType structure"
95 ttype
= member(type, "type").GetValueAsUnsigned()
96 if primitive_type_names
.has_key (ttype
):
97 return primitive_type_names
[ttype
]
99 return "<MonoTypeEnum 0x{0:x}>".format (ttype
)
101 def stringify_ginst (ginst
):
102 "Print a MonoGenericInst structure"
103 len = int(member(ginst
, "type_argc").GetValue())
104 argv
= member(ginst
, "type_argv")
107 t
= argv
.GetChildAtIndex(i
, False, True)
110 res
+= stringify_type(t
)
113 def print_type(valobj
, internal_dict
):
117 return stringify_type (type)
119 def print_class (valobj
, internal_dict
):
123 aname
= member (member (member (klass
, "image"), "assembly"), "aname")
124 basename
= "[{0}]{1}".format (string_member (aname
, "name"), (stringify_class_name (string_member (klass
, "name_space"), string_member (klass
, "name"))))
125 gclass
= member (klass
, "generic_class")
126 if not isnull (gclass
):
127 ginst
= member (member (gclass
, "context"), "class_inst")
128 return "{0}<{1}>".format (basename
, stringify_ginst (ginst
))
131 def print_method (valobj
, internal_dict
):
135 klass
= member (method
, "klass")
136 return "{0}:{1}()".format (print_class (klass
, None), string_member (valobj
, "name"))
138 def print_domain(valobj
, internal_dict
):
142 target
= domain
.target
143 root
= target
.FindFirstGlobalVariable("mono_root_domain")
144 name
= string_member (domain
, "friendly_name")
145 if root
.IsValid () and root
.deref
.addr
.GetOffset () == root
.deref
.addr
.GetOffset ():
148 return "[{0}]".format (name
)
150 def print_object(valobj
, internal_dict
):
154 domain
= member (member (obj
, "vtable"), "domain")
155 klass
= member (member (obj
, "vtable"), "klass")
156 return print_domain (domain
, None) + print_class (klass
, None)
158 # Register pretty printers
159 # FIXME: This cannot pick up the methods define in this module, leading to warnings
160 lldb
.debugger
.HandleCommand ("type summary add -w mono -F mono.print_method MonoMethod")
161 lldb
.debugger
.HandleCommand ("type summary add -w mono -F mono.print_class MonoClass")
162 lldb
.debugger
.HandleCommand ("type summary add -w mono -F mono.print_type MonoType")
163 lldb
.debugger
.HandleCommand ("type summary add -w mono -F mono.print_domain MonoDomain")
164 lldb
.debugger
.HandleCommand ("type summary add -w mono -F mono.print_object MonoObject")
165 lldb
.debugger
.HandleCommand ("type category enable mono")
167 # Helper commands for runtime debugging
168 # These resume the target
169 # Print the method at the current ip
170 lldb
.debugger
.HandleCommand ("command alias pip p mono_print_method_from_ip((void*)$pc)")
171 # Print the method at the provided ip
172 lldb
.debugger
.HandleCommand ("command regex pmip 's/^$/p mono_print_method_from_ip((void*)$pc)/' 's/(.+)/p mono_print_method_from_ip((void*)(%1))/'")
174 print "Mono support mode loaded."