-
Notifications
You must be signed in to change notification settings - Fork 5.6k
/
Copy pathlldb_commands.py
118 lines (88 loc) · 4.22 KB
/
lldb_commands.py
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
"""Add user-defined commands to MongoDB."""
import argparse
import shlex
def __lldb_init_module(debugger, *_args):
"""Register custom commands."""
debugger.HandleCommand(
"command script add -o -f lldb_commands.PrintGlobalServiceContext mongodb-service-context"
)
debugger.HandleCommand(
"command script add -o -f lldb_commands.PrintGlobalServiceContext mongodb-dump-locks"
)
debugger.HandleCommand(
"command script add -o -f lldb_commands.BreakpointOnAssert mongodb-breakpoint-assert"
)
debugger.HandleCommand(
"command script add -o -f lldb_commands.MongoDBFindBreakpoint mongodb-find-breakpoint"
)
debugger.HandleCommand("command script add -o -f lldb_commands.DumpGSC mongodb-gsc")
debugger.HandleCommand("command alias mongodb-help help")
#######################
# Command Definitions #
#######################
def PrintGlobalServiceContext(debugger, *_args):
"""Provide the mongodb-service-context command.
Emulates the same convenience command available in GDB
integrations to print the globalServiceContext.
"""
debugger.HandleCommand("print *globalServiceContext")
def MongoDBDumpLocks(debugger, *_args):
"""Dump locks in the mongod process."""
debugger.HandleCommand("call mongo::dumpLockManager()")
def BreakpointOnAssert(debugger, command, _exec_ctx, _result, _internal_dict):
"""Set a breakpoint on MongoDB uassert that throws the specified error code."""
arg_strs = shlex.split(command)
parser = argparse.ArgumentParser(description="Set a breakpoint on a usassert code.")
parser.add_argument("code", metavar="N", type=int, help="uassert code")
args = parser.parse_args(arg_strs)
debugger.HandleCommand(
'breakpoint set -n mongo::uassertedWithLocation -c "(int)status._error.px->code == %s"'
% args.code
)
def MongoDBFindBreakpoint(debugger, _command, exec_ctx, _result, _internal_dict):
"""Find the thread that triggered a breakpoint from 'debugger.cpp'."""
process = exec_ctx.process
print("Threads: %d" % (len(process.threads)))
thread_num = 0
for thread_index, thread in enumerate(process.threads):
frame_count = min(thread.num_frames, 10)
for frame_index in range(frame_count):
frame_str = thread.frames[frame_index].__str__()
# Find the frame that has a call to `execCallback` the function `src/mongo/util/debugger.cpp` uses
if "execCallback" in frame_str:
thread_num = thread_index + 1
break
if thread_num:
break
print("Switching thread to thread that hit breakpoint: %s" % (thread_num))
debugger.HandleCommand("thread select %d" % (thread_num))
def DumpGSC(_debugger, _command, exec_ctx, _result, _internal_dict):
"""Dump the global service context as a hash table."""
gsc_list = exec_ctx.target.FindGlobalVariables("globalServiceContext", 1)
print(gsc_list)
gsc = gsc_list[0]
decorations = gsc.GetChildMemberWithName("_decorations")
registry = decorations.GetChildMemberWithName("_registry")
decoration_info = registry.GetChildMemberWithName("_decorationInfo")
decoration_data = decorations.GetChildMemberWithName("_decorationData").child[0]
print(decoration_info.num_children)
for child in range(decoration_info.num_children):
di = decoration_info.children[child]
constructor = di.GetChildMemberWithName("constructor").__str__()
index = (
di.GetChildMemberWithName("descriptor")
.GetChildMemberWithName("_index")
.GetValueAsUnsigned()
)
type_name = constructor
type_name = type_name[0 : len(type_name) - 1]
type_name = type_name[0 : type_name.rindex(">")]
type_name = type_name[type_name.index("constructAt<") :].replace("constructAt<", "")
# If the type is a pointer type, strip the * at the end.
if type_name.endswith("*"):
type_name = type_name[0 : len(type_name) - 1]
type_name = type_name.rstrip()
type_t = exec_ctx.target.FindTypes(type_name).GetTypeAtIndex(0)
offset_ptr = decoration_data.GetChildAtIndex(index, False, True)
value = offset_ptr.Cast(type_t)
print(value)