-
Notifications
You must be signed in to change notification settings - Fork 0
/
BreakAfterRegex.py
113 lines (93 loc) · 3.43 KB
/
BreakAfterRegex.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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import lldb
import shlex
import optparse
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand(
'command script add -f BreakAfterRegex.breakAfterRegex bar')
def breakAfterRegex(debugger, command, result, internal_dict):
'''Creates a regular expression breakpoint and adds it.
Once the breakpoint is hit, control will step out of the current
function and print the return value. Useful for stopping on
getter/accessor/initialization methods
'''
command_args = shlex.split(command)
parser = generateOptionParser()
try:
(options, args) = parser.parse_args(command_args)
except:
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit
# (courtesy of OptParse dealing with argument errors by throwing SystemExit)
result.SetError("option parsing failed")
return
target = debugger.GetSelectedTarget()
breakpoint = target.BreakpointCreateByRegex(
' '.join(args), options.module)
if not breakpoint.IsValid()\
or breakpoint.num_locations == 0:
result.AppendWarning(
"Breakpoint isn't valid or hasn't found any hits")
else:
result.AppendMessage("{}".format(breakpoint))
breakpoint.SetScriptCallbackFunction(
"BreakAfterRegex.breakpointHandler")
def breakpointHandler(frame, bp_loc, dict):
'''The function called when the breakpoint
gets triggered
'''
thread = frame.GetThread()
process = frame.GetThread().GetProcess()
debugger = process.GetTarget().GetDebugger()
function_name = frame.GetFunctionName()
debugger.SetAsync(False)
thread.StepOut()
output = evaluateReturnedObject(debugger,
thread, function_name)
if output is not None:
print(output)
return False
def evaluateReturnedObject(debugger, thread, function_name):
'''Grabs the reference from the return register
and returns a string from the evaluated value. TODO ObjC only
'''
res = lldb.SBCommandReturnObject()
interpreter = debugger.GetCommandInterpreter()
target = debugger.GetSelectedTarget()
frame = thread.GetSelectedFrame()
parent_function_name = frame.GetFunctionName()
expression = 'expression -lobjc -O -- {}'.format(
getRegisterString(target))
interpreter.HandleCommand(expression, res)
if res.HasResult():
output = '{}\nbreakpoint: '\
'{}\nobject: {}\nstopped: {}'.format(
'*' * 80,
function_name,
res.GetOutput().replace('\n', ''),
parent_function_name)
return output
else:
return None
def getRegisterString(target):
'''Gets the return register as a string for lldb
based upon the hardware
'''
triple_name = target.GetTriple()
if 'x86_64' in triple_name:
return '$rax'
elif 'i386' in triple_name:
return '$eax'
elif 'arm64' in triple_name:
return '$x0'
elif 'arm' in triple_name:
return '$r0'
raise Exception('Unknown hardware. Womp womp')
def generateOptionParser():
parser = optparse.OptionParser()
parser.add_option("-m", "--module",
action="store",
type="string",
dest="module",
help="constrain regex to module")
return parser