Welcome to mirror list, hosted at ThFree Co, Russian Federation.

mono.py « lldb « data - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8fe9641165f99e58f50e57be76295f7263933986 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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."