added decorator, time to refactor

This commit is contained in:
George Hotz 2014-08-10 13:51:33 +00:00
parent 4d0772cc1a
commit f5ddd83787
4 changed files with 73 additions and 57 deletions

5
.gitignore vendored
View File

@ -23,5 +23,6 @@ qemu
tests/system
pin/pin-*
pin/obj-*
pin/pin.log
*~
pin.log
*~

View File

@ -271,10 +271,10 @@ def get_instruction_flow(trace, program, minclnum, maxclnum):
if len(r) != 1:
continue
ins = ""
if r[0]['address'] in program.instructions:
ins = program.instructions[r[0]['address']]
if program != None:
if r[0]['address'] in program.instructions:
ins = program.instructions[r[0]['address']]
ret.append((r[0]['address'], r[0]['data'], r[0]['clnum'], ins))
return ret
def get_hacked_depth_map(flow):
@ -283,12 +283,38 @@ def get_hacked_depth_map(flow):
for (address, length, clnum, ins) in flow:
if address in return_stack:
return_stack = return_stack[0:return_stack.index(address)]
if ins[0:5] == "call " or ins[0:6] == "callq ":
if ins[0:5] == "call " or ins[0:6] == "callq " or ins[0:3] == "bl ":
return_stack.append(address+length)
#print return_stack
ret.append(len(return_stack))
return ret
def get_vtimeline_picture(trace):
trace.update_analysis_depends()
maxd = max(trace.dmap)
if maxd == 0:
return None
r = trace.maxclnum-trace.minclnum
sampling = int(math.ceil(r/50000.0))
from PIL import Image # sudo pip install pillow
import base64
import StringIO
im = Image.new( 'RGB', (1, (trace.maxclnum/sampling)+1), "black")
px = im.load()
for i in range(0, r, sampling):
# could average the sampled
c = int((trace.dmap[i]*128.0)/maxd)
px[0, i/sampling] = (0,c,c)
buf = StringIO.StringIO()
im.save(buf, format='PNG')
dat = "data:image/png;base64,"+base64.b64encode(buf.getvalue())
return dat
def analyze(trace, program):
minclnum = trace.db.get_minclnum()
@ -310,36 +336,6 @@ def analyze(trace, program):
#dmap = get_depth_map(fxns, maxclnum)
dmap = get_hacked_depth_map(flow)
maxd = max(dmap)
if maxd == 0:
return None
#print dmap
#print maxclnum, maxd
r = maxclnum-minclnum
sampling = int(math.ceil(r/50000.0))
from PIL import Image # sudo pip install pillow
import base64
import StringIO
im = Image.new( 'RGB', (1, (maxclnum/sampling)+1), "black")
px = im.load()
for i in range(0, r, sampling):
# could average the sampled
c = int((dmap[i]*128.0)/maxd)
#px[0, i] = (int((dmap[i]*255.0)/maxd), 0, 0)
#px[0, i] = (c,c,c)
px[0, i/sampling] = (0,c,c)
#im = im.resize((50, 1000), Image.ANTIALIAS)
buf = StringIO.StringIO()
im.save(buf, format='PNG')
dat = "data:image/png;base64,"+base64.b64encode(buf.getvalue())
return dat
#loops = do_loop_analysis(blocks)
#print loops

View File

@ -1,5 +1,6 @@
from qira_base import *
import qira_config
import qira_analysis
import os
import shutil
import sys
@ -225,7 +226,7 @@ class Program:
return rret
def add_trace(self, fn, i):
self.traces[i] = Trace(fn, i, self.tregs[1], len(self.tregs[0]), self.tregs[2])
self.traces[i] = Trace(fn, i, self, self.tregs[1], len(self.tregs[0]), self.tregs[2])
return self.traces[i]
def execqira(self, args=[], shouldfork=True):
@ -333,10 +334,20 @@ class Program:
self.cda = cachewrap("/tmp/qira_cdacaches", self.proghash, parse_cda)
class Trace:
def __init__(self, fn, forknum, r1, r2, r3):
def __init__(self, fn, forknum, program, r1, r2, r3):
self.forknum = forknum
self.maxclnum = None
self.program = program
self.db = qiradb.Trace(fn, forknum, r1, r2, r3)
self.load_base_memory()
self.update_analysis_depends()
def update_analysis_depends(self):
if self.maxclnum == None or self.db.get_maxclnum() != self.maxclnum:
self.minclnum = self.db.get_minclnum()
self.maxclnum = self.db.get_maxclnum()
self.flow = qira_analysis.get_instruction_flow(self, self.program, self.minclnum, self.maxclnum)
self.dmap = qira_analysis.get_hacked_depth_map(self.flow)
# proxy the db call and fill in base memory
def fetch_memory(self, clnum, address, ln):

View File

@ -2,18 +2,21 @@ from qira_base import *
import qira_config
import os
import sys
import time
basedir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(basedir+"/../cda")
def debug():
return
import inspect
curframe = inspect.currentframe()
calframe = inspect.getouterframes(curframe, 2)
print calframe[1][3],"called"
#print inspect.getargvalues(calframe)
#print args, values
def socket_method(func):
def func_wrapper(*args, **kwargs):
try:
start = time.time()
ret = func(*args, **kwargs)
end = time.time()
print "SOCKET %6.2f ms in %-20s with" % ((end-start)*1000, func.func_name), args
return ret
except Exception, e:
print "error",e,"in",func
return func_wrapper
import qira_socat
import time
@ -83,6 +86,7 @@ def navigateline(fn, ln):
socketio.emit('setiaddr', iaddr, namespace='/qira')
@socketio.on('navigateiaddr', namespace='/qira')
@socket_method
def navigateiaddr(iaddr):
if iaddr == None:
return
@ -94,6 +98,7 @@ def navigateiaddr(iaddr):
socketio.emit('setline', filename, line, namespace='/cda')
@socketio.on('forkat', namespace='/qira')
@socket_method
def forkat(forknum, clnum, pending):
global program
print "forkat",forknum,clnum,pending
@ -127,6 +132,7 @@ def forkat(forknum, clnum, pending):
@socketio.on('deletefork', namespace='/qira')
@socket_method
def deletefork(forknum):
global program
print "deletefork", forknum
@ -138,24 +144,24 @@ def deletefork(forknum):
push_updates()
@socketio.on('doslice', namespace='/qira')
@socket_method
def slice(forknum, clnum):
if forknum not in program.traces:
return
trace = program.traces[forknum]
debug()
data = qira_analysis.slice(trace, clnum)
print "slice",forknum,clnum, data
emit('slice', forknum, data);
@socketio.on('doanalysis', namespace='/qira')
@socket_method
def analysis(forknum):
if forknum not in program.traces:
return
trace = program.traces[forknum]
debug()
# this fails sometimes, who knows why
try:
data = qira_analysis.analyze(trace, program)
data = qira_analysis.get_vtimeline_picture(trace)
except Exception as e:
print "!!! analysis failed on",forknum,"because",e
data = None
@ -163,6 +169,7 @@ def analysis(forknum):
emit('setpicture', {"forknum":forknum, "data":data})
@socketio.on('connect', namespace='/qira')
@socket_method
def connect():
global program
print "client connected", program.get_maxclnum()
@ -170,13 +177,13 @@ def connect():
emit('maxclnum', program.get_maxclnum())
@socketio.on('getclnum', namespace='/qira')
@socket_method
def getclnum(forknum, clnum, types, limit):
if forknum not in program.traces:
return
trace = program.traces[forknum]
if clnum == None or types == None or limit == None:
return
debug()
ret = []
for c in trace.db.fetch_changes_by_clnum(clnum, LIMIT):
if c['type'] not in types:
@ -190,12 +197,12 @@ def getclnum(forknum, clnum, types, limit):
emit('clnum', ret)
@socketio.on('getchanges', namespace='/qira')
@socket_method
def getchanges(forknum, address, typ, cview):
if address == None or typ == None or cview == None:
return
if forknum != -1 and forknum not in program.traces:
return
debug()
address = fhex(address)
if forknum == -1:
@ -208,13 +215,13 @@ def getchanges(forknum, address, typ, cview):
emit('changes', {'type': typ, 'clnums': ret})
@socketio.on('getinstructions', namespace='/qira')
@socket_method
def getinstructions(forknum, clnum, clstart, clend):
if forknum not in program.traces:
return
trace = program.traces[forknum]
if clstart == None or clend == None:
return
debug()
slce = qira_analysis.slice(trace, clnum)
ret = []
for i in range(clstart, clend):
@ -246,26 +253,27 @@ def getinstructions(forknum, clnum, clstart, clend):
emit('instructions', ret)
@socketio.on('getmemory', namespace='/qira')
@socket_method
def getmemory(forknum, clnum, address, ln):
if forknum not in program.traces:
return
trace = program.traces[forknum]
if clnum == None or address == None or ln == None:
return
debug()
address = fhex(address)
dat = trace.fetch_memory(clnum, address, ln)
ret = {'address': address, 'len': ln, 'dat': dat, 'is_big_endian': program.tregs[2], 'ptrsize': program.tregs[1]}
emit('memory', ret)
@socketio.on('getregisters', namespace='/qira')
@socket_method
def getregisters(forknum, clnum):
if forknum not in program.traces:
return
trace = program.traces[forknum]
if clnum == None:
return
debug()
# register names shouldn't be here
# though i'm not really sure where a better place is, qemu has this information
ret = []
@ -297,11 +305,11 @@ def getregisters(forknum, clnum):
emit('registers', ret)
@socketio.on('getstrace', namespace='/qira')
@socket_method
def get_strace(forknum):
if forknum not in program.traces:
return
trace = program.traces[forknum]
debug()
try:
f = open(qira_config.TRACE_FILE_BASE+str(int(forknum))+"_strace").read()
except: