Backport https://github.com/dotnet/runtime/pull/71436 (#21519)
[mono-project.git] / data / lldb / mono.py
blob8fe9641165f99e58f50e57be76295f7263933986
2 # Author: Zoltan Varga (vargaz@gmail.com)
3 # License: MIT/X11
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.
16 import lldb
18 # FIXME: Generate enums from runtime enums
19 MONO_TYPE_END = 0x00
20 MONO_TYPE_VOID = 0x01
21 MONO_TYPE_BOOLEAN = 0x02
22 MONO_TYPE_CHAR = 0x03
23 MONO_TYPE_I1 = 0x04
24 MONO_TYPE_U1 = 0x05
25 MONO_TYPE_I2 = 0x06
26 MONO_TYPE_U2 = 0x07
27 MONO_TYPE_I4 = 0x08
28 MONO_TYPE_U4 = 0x09
29 MONO_TYPE_I8 = 0x0a
30 MONO_TYPE_U8 = 0x0b
31 MONO_TYPE_R4 = 0x0c
32 MONO_TYPE_R8 = 0x0d
33 MONO_TYPE_STRING = 0x0e
34 MONO_TYPE_PTR = 0x0f
35 MONO_TYPE_BYREF = 0x10
36 MONO_TYPE_VALUETYPE = 0x11
37 MONO_TYPE_CLASS = 0x12
38 MONO_TYPE_VAR = 0x13
39 MONO_TYPE_ARRAY = 0x14
40 MONO_TYPE_GENERICINST= 0x15
41 MONO_TYPE_TYPEDBYREF = 0x16
42 MONO_TYPE_I = 0x18
43 MONO_TYPE_U = 0x19
44 MONO_TYPE_FNPTR = 0x1b
45 MONO_TYPE_OBJECT = 0x1c
46 MONO_TYPE_SZARRAY = 0x1d
47 MONO_TYPE_MVAR = 0x1e
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",
56 MONO_TYPE_I4 : "int",
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]
75 def isnull(val):
76 return val.deref.addr.GetOffset () == 0
78 def stringify_class_name(ns, name):
79 if ns == "System":
80 if name == "Byte":
81 return "byte"
82 if name == "String":
83 return "string"
84 if ns == "":
85 return name
86 else:
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]
98 else:
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")
105 res=""
106 for i in range(len):
107 t = argv.GetChildAtIndex(i, False, True)
108 if i > 0:
109 res += ", "
110 res += stringify_type(t)
111 return res
113 def print_type(valobj, internal_dict):
114 type = valobj
115 if isnull (type):
116 return ""
117 return stringify_type (type)
119 def print_class (valobj, internal_dict):
120 klass = valobj
121 if isnull (klass):
122 return ""
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))
129 return basename
131 def print_method (valobj, internal_dict):
132 method = valobj
133 if isnull (method):
134 return ""
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):
139 domain = valobj
140 if isnull (domain):
141 return ""
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 ():
146 return "[root]"
147 else:
148 return "[{0}]".format (name)
150 def print_object(valobj, internal_dict):
151 obj = valobj
152 if isnull (obj):
153 return ""
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."