Last active
December 4, 2018 18:56
-
-
Save mikezucc/3cb24a0bc36ef13997bd32210db17db1 to your computer and use it in GitHub Desktop.
Version 1 of the assertion reporting platform
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import lldb | |
import json | |
import subprocess | |
from os.path import expanduser | |
import time | |
import os | |
import sys | |
home = expanduser("~") | |
def getBreakpointIndexesOfCFunction(cFunctionName, interpreter): | |
res = lldb.SBCommandReturnObject() | |
interpreter.HandleCommand('breakpoint list', res) | |
res.Succeeded() | |
output = res.GetOutput() | |
if cFunctionName in output: | |
splits = output.split('\n') | |
return [line.split(':')[0] for line in splits if cFunctionName in line] | |
return [] | |
def deleteBreakpointAtCFunction(cFunctionName, interpreter): | |
res = lldb.SBCommandReturnObject() | |
breakpointIndexes = getBreakpointIndexesOfCFunction(cFunctionName, interpreter) | |
for breakpointIndex in breakpointIndexes: | |
interpreter.HandleCommand('breakpoint delete ' + breakpointIndex, res) | |
def setBreakpointAtCFunction(cFunctionName, interpreter): | |
res = lldb.SBCommandReturnObject() | |
# interpreter.HandleCommand('breakpoint set --name ' + cFunctionName + ' -C breakpointonassert', res) | |
interpreter.HandleCommand('breakpoint set --name ' + cFunctionName, res) | |
breakpointIndexes = getBreakpointIndexesOfCFunction(cFunctionName, interpreter) | |
breakpointID = breakpointIndexes[0] | |
interpreter.HandleCommand('breakpoint command add ' + breakpointID + ' -F "reportassert.BreakpointOnAssert"', res) | |
setCommand = res.Succeeded() | |
interpreter.HandleCommand('breakpoint modify --auto-continue true ' + breakpointID, res) | |
print 'Assert Breakpoint Definition: ' + str(setCommand and res.Succeeded()) | |
def BreakpointOnAssert(frame, bp_loc, dict): | |
thread = frame.GetThread() | |
process = thread.GetProcess() | |
target = process.GetTarget() | |
debugger = target.GetDebugger() | |
interpreter = debugger.GetCommandInterpreter() | |
command_result = lldb.SBCommandReturnObject() | |
# Here we would actually want to reset to the GetAsync old value, however, | |
# I am over prodding the mysterious ethereus Beast that is LLDB PYTHON | |
debugger.SetAsync(False) | |
print "SENDING IP TO THE NSA YEET" | |
processedCallStack = [] | |
for frame in thread.frames: | |
frameName = frame.GetFunction().GetDisplayName() | |
frameValuesList = frame.GetVariables(True, True, False, False) | |
callFrameVariables = [] | |
for value in frameValuesList: | |
try: | |
valueType = value.GetTypeName() | |
if valueType is None: | |
continue | |
path = lldb.SBStream() | |
value.GetExpressionPath(path) | |
expressableName = path.GetData() | |
varNiceValue = value.GetValue() | |
if '*' in str(valueType): | |
debugResult = frame.EvaluateExpression('[' + str(expressableName) + ' debugDescription]') | |
if debugResult is not None: | |
varNiceValue = debugResult.GetSummary() | |
if varNiceValue is None: | |
varNiceValue = "nil or could not access address" | |
callFrameVariables.append({"name": expressableName, "type": valueType, "value": varNiceValue}) | |
except Exception as e: | |
print e | |
x = 1 | |
processedCallStack.append({"frame": str(frameName), "variables": callFrameVariables}) | |
reportTime = time.strftime("%Y-%m-%d %H:%M") | |
report = { "callstack": processedCallStack, | |
"target": str(target), | |
"time": reportTime } | |
print report | |
jsonString = json.dumps(report) | |
with open(home + '/assertion_results', 'w+') as results_file: | |
results_file.write(jsonString) | |
# response = urllib.urlopen('http://localhost:3003/assert', data=jsonString.encode('utf8')) | |
# print response.read().decode('utf8') | |
# reportInvocation = Popen(["python", "~/post_assertion.py"], stdin=None, stdout=None, stderr=None, shell=True) | |
# subprocess.check_output('nix-shell . --run "python ' + home + '/post_assertion.py"', shell=True) | |
# req = urllib2.Request(url, | |
# headers = { | |
# "Content-Type": "application/json", | |
# "Accept": "*/*", | |
# }, data = jsonString) | |
# f = urllib2.urlopen(req) | |
# reportInvocation.wait()we | |
# print reportInvocation.returncode | |
devnull = open(os.devnull, 'wb') # Use this in Python < 3.3 | |
# Python >= 3.3 has subprocess.DEVNULL | |
subprocess.Popen(['nohup', home + '/post_assertion.py'], stdout=devnull, stderr=devnull, preexec_fn=os.setpgrp, shell=True, env='$PATH') | |
debugger.SetAsync(True) | |
return True | |
def __lldb_init_module(debugger, internal_dict): | |
interpreter = debugger.GetCommandInterpreter() | |
res = lldb.SBCommandReturnObject() | |
interpreter.HandleCommand('command script import -r reportassert.py', res) | |
print 'Initialize Script: ' + str(res.Succeeded()) | |
deleteBreakpointAtCFunction('BreakpointFindMe', interpreter) | |
setBreakpointAtCFunction('BreakpointFindMe', interpreter) | |
return None |
Latest: Recursively prints arguments/ visible variables in scope in each frame.
Next: Working on printing ivars
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also originally I thought the subprocess calls were what was hanging LLDB, thats why there are few different methods there