mirror of https://github.com/geohot/qira
added decorator, time to refactor
This commit is contained in:
parent
4d0772cc1a
commit
f5ddd83787
|
@ -23,5 +23,6 @@ qemu
|
|||
tests/system
|
||||
pin/pin-*
|
||||
pin/obj-*
|
||||
pin/pin.log
|
||||
*~
|
||||
pin.log
|
||||
*~
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue