mirror of
https://github.com/geohot/qira
synced 2024-12-29 07:19:42 +03:00
added strace support
This commit is contained in:
parent
cf0aa670f6
commit
3a04cb16a9
@ -38,7 +38,7 @@ if __name__ == '__main__':
|
|||||||
else:
|
else:
|
||||||
print "**** running "+program.program
|
print "**** running "+program.program
|
||||||
if is_qira_running or os.fork() == 0: # cute?
|
if is_qira_running or os.fork() == 0: # cute?
|
||||||
os.execvp(program.qirabinary, [program.qirabinary, "-D", "/dev/null", "-d", "in_asm",
|
os.execvp(program.qirabinary, [program.qirabinary, "-strace", "-D", "/dev/null", "-d", "in_asm",
|
||||||
"-singlestep", program.program]+program.args)
|
"-singlestep", program.program]+program.args)
|
||||||
|
|
||||||
if not is_qira_running:
|
if not is_qira_running:
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import qira_log
|
|
||||||
import qira_trace
|
|
||||||
import socket
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import fcntl
|
|
||||||
import signal
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
|
|
||||||
program = None
|
|
||||||
run_id = 0
|
|
||||||
|
|
||||||
|
|
||||||
@socketio.on('getclnum', namespace='/qira')
|
|
||||||
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
|
|
||||||
ret = []
|
|
||||||
for t in types:
|
|
||||||
key = (clnum, t)
|
|
||||||
for c in trace.pydb_clnum[key]:
|
|
||||||
c = c.copy()
|
|
||||||
c['address'] = ghex(c['address'])
|
|
||||||
c['data'] = ghex(c['data'])
|
|
||||||
ret.append(c)
|
|
||||||
if len(ret) >= limit:
|
|
||||||
break
|
|
||||||
if len(ret) >= limit:
|
|
||||||
break
|
|
||||||
emit('clnum', ret)
|
|
||||||
|
|
||||||
@socketio.on('getchanges', namespace='/qira')
|
|
||||||
def getchanges(forknum, address, typ):
|
|
||||||
if address == None or typ == None:
|
|
||||||
return
|
|
||||||
if forknum != -1 and forknum not in program.traces:
|
|
||||||
return
|
|
||||||
address = int(address)
|
|
||||||
if forknum == -1:
|
|
||||||
ret = {}
|
|
||||||
for forknum in program.traces:
|
|
||||||
ret[forknum] = program.traces[forknum].pydb_addr[(address, typ)]
|
|
||||||
emit('changes', {'type': typ, 'clnums': ret})
|
|
||||||
else:
|
|
||||||
emit('changes', {'type': typ, 'clnums': {forknum: program.traces[forknum].pydb_addr[(address, typ)]}})
|
|
||||||
|
|
||||||
@socketio.on('getinstructions', namespace='/qira')
|
|
||||||
def getinstructions(forknum, clstart, clend):
|
|
||||||
if forknum not in program.traces:
|
|
||||||
return
|
|
||||||
trace = program.traces[forknum]
|
|
||||||
if clstart == None or clend == None:
|
|
||||||
return
|
|
||||||
ret = []
|
|
||||||
pydb_clnum = trace.pydb_clnum
|
|
||||||
for i in range(clstart, clend):
|
|
||||||
key = (i, 'I')
|
|
||||||
if key in pydb_clnum:
|
|
||||||
rret = pydb_clnum[key][0]
|
|
||||||
if rret['address'] in program.instructions:
|
|
||||||
rret['instruction'] = program.instructions[rret['address']]
|
|
||||||
ret.append(rret)
|
|
||||||
emit('instructions', ret)
|
|
||||||
|
|
||||||
@socketio.on('getmemory', namespace='/qira')
|
|
||||||
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
|
|
||||||
address = int(address)
|
|
||||||
dat = trace.mem.fetch(clnum, address, ln)
|
|
||||||
ret = {'address': address, 'len': ln, 'dat': dat}
|
|
||||||
emit('memory', ret)
|
|
||||||
|
|
||||||
@socketio.on('getregisters', namespace='/qira')
|
|
||||||
def getregisters(forknum, clnum):
|
|
||||||
if forknum not in program.traces:
|
|
||||||
return
|
|
||||||
trace = program.traces[forknum]
|
|
||||||
#print "getregisters",clnum
|
|
||||||
if clnum == None:
|
|
||||||
return
|
|
||||||
# register names shouldn't be here
|
|
||||||
# though i'm not really sure where a better place is, qemu has this information
|
|
||||||
ret = []
|
|
||||||
REGS = program.tregs[0]
|
|
||||||
REGSIZE = program.tregs[1]
|
|
||||||
for i in range(0, len(REGS)):
|
|
||||||
if i*REGSIZE in trace.regs.daddr:
|
|
||||||
rret = {"name": REGS[i], "address": i*REGSIZE, "value": ghex(trace.regs.daddr[i*REGSIZE].fetch(clnum)), "size": REGSIZE, "regactions": ""}
|
|
||||||
# this +1 is an ugly hack
|
|
||||||
if (clnum+1) in trace.pydb_addr[(i*REGSIZE, 'R')]:
|
|
||||||
rret['regactions'] = "regread"
|
|
||||||
if (clnum+1) in trace.pydb_addr[(i*REGSIZE, 'W')]:
|
|
||||||
if "regread" == rret['regactions']:
|
|
||||||
rret['regactions'] = "regreadwrite"
|
|
||||||
else:
|
|
||||||
rret['regactions'] = "regwrite"
|
|
||||||
ret.append(rret)
|
|
||||||
emit('registers', ret)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def run_middleware():
|
|
||||||
global program
|
|
||||||
print "starting QIRA middleware"
|
|
||||||
|
|
||||||
# run loop run
|
|
||||||
# read in all the traces
|
|
||||||
while 1:
|
|
||||||
time.sleep(0.2)
|
|
||||||
did_update = False
|
|
||||||
for i in os.listdir("/tmp/qira_logs/"):
|
|
||||||
if "_" in i:
|
|
||||||
continue
|
|
||||||
i = int(i)
|
|
||||||
if i not in program.traces:
|
|
||||||
#print "C create trace",qiradb.new_trace("/tmp/qira_logs/"+str(i), i, program.tregs[1], len(program.tregs[0]))
|
|
||||||
qira_trace.Trace(program, i)
|
|
||||||
|
|
||||||
for tn in program.traces:
|
|
||||||
if program.traces[tn].poll():
|
|
||||||
did_update = True
|
|
||||||
|
|
||||||
if did_update:
|
|
||||||
# push to all connected websockets
|
|
||||||
socketio.emit('pmaps', program.pmaps, namespace='/qira')
|
|
||||||
|
|
||||||
# this must happen last
|
|
||||||
socketio.emit('maxclnum', program.get_maxclnum(), namespace='/qira')
|
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ def start_bindserver(program, myss, parent_id, start_cl, loop = False):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
# fingerprint here
|
# fingerprint here
|
||||||
os.execvp(program.qirabinary, [program.qirabinary, "-D", "/dev/null", "-d", "in_asm",
|
os.execvp(program.qirabinary, [program.qirabinary, "-strace", "-D", "/dev/null", "-d", "in_asm",
|
||||||
"-qirachild", "%d %d %d" % (parent_id, start_cl, run_id), "-singlestep",
|
"-qirachild", "%d %d %d" % (parent_id, start_cl, run_id), "-singlestep",
|
||||||
program.program]+program.args)
|
program.program]+program.args)
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import qira_socat
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
QIRA_PORT = 3002
|
QIRA_PORT = 3002
|
||||||
LIMIT = 100
|
LIMIT = 1000
|
||||||
|
|
||||||
from flask import Flask, Response
|
from flask import Flask, Response
|
||||||
from flask.ext.socketio import SocketIO, emit
|
from flask.ext.socketio import SocketIO, emit
|
||||||
@ -189,7 +189,30 @@ def getregisters(forknum, clnum):
|
|||||||
|
|
||||||
emit('registers', ret)
|
emit('registers', ret)
|
||||||
|
|
||||||
|
@socketio.on('getstrace', namespace='/qira')
|
||||||
|
def get_strace(forknum):
|
||||||
|
try:
|
||||||
|
f = open("/tmp/qira_logs/"+str(int(forknum))+"_strace").read()
|
||||||
|
except:
|
||||||
|
return "no strace"
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
for ff in f.split("\n"):
|
||||||
|
if ff == '':
|
||||||
|
continue
|
||||||
|
ff = ff.split(" ")
|
||||||
|
clnum = int(ff[0])
|
||||||
|
if clnum == 0:
|
||||||
|
# filter the boring syscalls
|
||||||
|
continue
|
||||||
|
pid = int(ff[1])
|
||||||
|
sc = " ".join(ff[2:])
|
||||||
|
ret.append({"clnum": clnum, "pid":pid, "sc": sc})
|
||||||
|
emit('strace', ret)
|
||||||
|
|
||||||
|
|
||||||
# ***** generic webserver stuff *****
|
# ***** generic webserver stuff *****
|
||||||
|
|
||||||
|
|
||||||
@app.route('/', defaults={'path': 'index.html'})
|
@app.route('/', defaults={'path': 'index.html'})
|
||||||
@app.route('/<path:path>')
|
@app.route('/<path:path>')
|
||||||
|
@ -18,6 +18,7 @@ if [ ! -d qemu/qemu-latest ]; then
|
|||||||
mv disas.c disas.c.bak
|
mv disas.c disas.c.bak
|
||||||
mv linux-user/qemu.h linux-user/qemu.h.bak
|
mv linux-user/qemu.h linux-user/qemu.h.bak
|
||||||
mv linux-user/main.c linux-user/main.c.bak
|
mv linux-user/main.c linux-user/main.c.bak
|
||||||
|
mv linux-user/strace.c linux-user/strace.c.bak
|
||||||
cd ../../
|
cd ../../
|
||||||
|
|
||||||
sudo apt-get build-dep qemu
|
sudo apt-get build-dep qemu
|
||||||
@ -28,6 +29,7 @@ ln -sf ../../qemu_mods/tci.c tci.c
|
|||||||
ln -sf ../../qemu_mods/disas.c disas.c
|
ln -sf ../../qemu_mods/disas.c disas.c
|
||||||
ln -sf ../../../qemu_mods/qemu.h linux-user/qemu.h
|
ln -sf ../../../qemu_mods/qemu.h linux-user/qemu.h
|
||||||
ln -sf ../../../qemu_mods/main.c linux-user/main.c
|
ln -sf ../../../qemu_mods/main.c linux-user/main.c
|
||||||
|
ln -sf ../../../qemu_mods/strace.c linux-user/strace.c
|
||||||
#./configure --target-list=i386-linux-user,arm-linux-user,x86_64-linux-user,sparc-linux-user,sparc32plus-linux-user --enable-tcg-interpreter --enable-debug-tcg --cpu=unknown
|
#./configure --target-list=i386-linux-user,arm-linux-user,x86_64-linux-user,sparc-linux-user,sparc32plus-linux-user --enable-tcg-interpreter --enable-debug-tcg --cpu=unknown
|
||||||
./configure --target-list=i386-linux-user,x86_64-linux-user,arm-linux-user --enable-tcg-interpreter --enable-debug-tcg --cpu=unknown
|
./configure --target-list=i386-linux-user,x86_64-linux-user,arm-linux-user --enable-tcg-interpreter --enable-debug-tcg --cpu=unknown
|
||||||
make -j32
|
make -j32
|
||||||
|
1625
qemu_mods/strace.c
Normal file
1625
qemu_mods/strace.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -487,11 +487,17 @@ uint32_t GLOBAL_start_clnum = 1;
|
|||||||
int GLOBAL_parent_id = -1, GLOBAL_id = -1;
|
int GLOBAL_parent_id = -1, GLOBAL_id = -1;
|
||||||
|
|
||||||
FILE *GLOBAL_asm_file = NULL;
|
FILE *GLOBAL_asm_file = NULL;
|
||||||
|
FILE *GLOBAL_strace_file = NULL;
|
||||||
|
|
||||||
// should be 0ed on startup
|
// should be 0ed on startup
|
||||||
#define PENDING_CHANGES_MAX_ADDR 0x100
|
#define PENDING_CHANGES_MAX_ADDR 0x100
|
||||||
struct change GLOBAL_pending_changes[PENDING_CHANGES_MAX_ADDR/4];
|
struct change GLOBAL_pending_changes[PENDING_CHANGES_MAX_ADDR/4];
|
||||||
|
|
||||||
|
uint32_t get_current_clnum(void);
|
||||||
|
uint32_t get_current_clnum(void) {
|
||||||
|
return GLOBAL_logstate->changelist_number;
|
||||||
|
}
|
||||||
|
|
||||||
void resize_change_buffer(size_t size) {
|
void resize_change_buffer(size_t size) {
|
||||||
if(ftruncate(GLOBAL_qira_log_fd, size)) {
|
if(ftruncate(GLOBAL_qira_log_fd, size)) {
|
||||||
perror("ftruncate");
|
perror("ftruncate");
|
||||||
@ -508,6 +514,9 @@ void init_QIRA(CPUArchState *env, int id) {
|
|||||||
GLOBAL_CPUArchState = env; // unused
|
GLOBAL_CPUArchState = env; // unused
|
||||||
|
|
||||||
char fn[PATH_MAX];
|
char fn[PATH_MAX];
|
||||||
|
sprintf(fn, "/tmp/qira_logs/%d_strace", id);
|
||||||
|
GLOBAL_strace_file = fopen(fn, "w");
|
||||||
|
|
||||||
sprintf(fn, "/tmp/qira_logs/%d", id);
|
sprintf(fn, "/tmp/qira_logs/%d", id);
|
||||||
|
|
||||||
// unlink it first
|
// unlink it first
|
||||||
@ -784,7 +793,6 @@ int GLOBAL_last_was_syscall = 0;
|
|||||||
uint32_t GLOBAL_last_fork_change = -1;
|
uint32_t GLOBAL_last_fork_change = -1;
|
||||||
target_long last_pc = 0;
|
target_long last_pc = 0;
|
||||||
|
|
||||||
|
|
||||||
void write_out_base(CPUArchState *env, int id);
|
void write_out_base(CPUArchState *env, int id);
|
||||||
void write_out_base(CPUArchState *env, int id) {
|
void write_out_base(CPUArchState *env, int id) {
|
||||||
CPUState *cpu = ENV_GET_CPU(env);
|
CPUState *cpu = ENV_GET_CPU(env);
|
||||||
|
BIN
tests/confound/confound
Executable file
BIN
tests/confound/confound
Executable file
Binary file not shown.
2
web/client/controls.js
vendored
2
web/client/controls.js
vendored
@ -55,5 +55,5 @@ window.onkeydown = function(e) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// don't pull the window
|
// don't pull the window
|
||||||
window.onmousewheel = function() { return false; }
|
//window.onmousewheel = function() { return false; }
|
||||||
|
|
||||||
|
26
web/client/strace.js
Normal file
26
web/client/strace.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
stream = io.connect("http://localhost:3002/qira");
|
||||||
|
|
||||||
|
stream.on('strace', function(msg) {
|
||||||
|
p(msg);
|
||||||
|
$('#strace')[0].innerHTML = "";
|
||||||
|
UI.insert(UI.renderWithData(Template.strace, {strace: msg}), $('#strace')[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.strace.ischange = function() {
|
||||||
|
var clnum = Session.get("clnum");
|
||||||
|
if (this.clnum == clnum) return 'highlight';
|
||||||
|
else return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
Deps.autorun(function() {
|
||||||
|
var forknum = Session.get("forknum");
|
||||||
|
var maxclnum = Session.get("max_clnum");
|
||||||
|
stream.emit("getstrace", forknum);
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.strace.events({
|
||||||
|
'click .change': function() {
|
||||||
|
Session.set('clnum', this.clnum);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -177,3 +177,10 @@ body {
|
|||||||
background: linear-gradient(to right, #666644, #EEEE44);
|
background: linear-gradient(to right, #666644, #EEEE44);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#strace {
|
||||||
|
font-family: monospace;
|
||||||
|
height: 150px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
<div class="panelthing" id="hexeditor">
|
<div class="panelthing" id="hexeditor">
|
||||||
{{> memviewer}}
|
{{> memviewer}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="panelthing" id="strace">
|
||||||
|
{{> strace}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
@ -35,6 +38,15 @@
|
|||||||
<input spellcheck="false" id="control_daddr" class="control datamemory" value="{{daddr}}" />
|
<input spellcheck="false" id="control_daddr" class="control datamemory" value="{{daddr}}" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="strace">
|
||||||
|
{{#each strace}}
|
||||||
|
<div class="syscall">
|
||||||
|
<div class="change {{ischange}}">{{clnum}}</div>
|
||||||
|
{{sc}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</template>
|
||||||
|
|
||||||
<template name="idump">
|
<template name="idump">
|
||||||
{{#each instructions}}
|
{{#each instructions}}
|
||||||
<div class="instruction">
|
<div class="instruction">
|
||||||
|
@ -14,7 +14,10 @@ UI.body.contentParts.push(UI.Component.extend({render: (function() {
|
|||||||
}, "\n", Spacebars.include(self.lookupTemplate("datachanges")), "\n"), "\n", HTML.DIV({
|
}, "\n", Spacebars.include(self.lookupTemplate("datachanges")), "\n"), "\n", HTML.DIV({
|
||||||
"class": "panelthing",
|
"class": "panelthing",
|
||||||
id: "hexeditor"
|
id: "hexeditor"
|
||||||
}, "\n", Spacebars.include(self.lookupTemplate("memviewer")), "\n"), "\n") ];
|
}, "\n", Spacebars.include(self.lookupTemplate("memviewer")), "\n"), "\n", HTML.DIV({
|
||||||
|
"class": "panelthing",
|
||||||
|
id: "strace"
|
||||||
|
}, "\n", Spacebars.include(self.lookupTemplate("strace")), "\n"), "\n") ];
|
||||||
})}));
|
})}));
|
||||||
Meteor.startup(function () { if (! UI.body.INSTANTIATED) { UI.body.INSTANTIATED = true; UI.DomRange.insert(UI.render(UI.body).dom, document.body); } });
|
Meteor.startup(function () { if (! UI.body.INSTANTIATED) { UI.body.INSTANTIATED = true; UI.DomRange.insert(UI.render(UI.body).dom, document.body); } });
|
||||||
|
|
||||||
@ -52,6 +55,27 @@ Template.__define__("controls", (function() {
|
|||||||
}) ];
|
}) ];
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
Template.__define__("strace", (function() {
|
||||||
|
var self = this;
|
||||||
|
var template = this;
|
||||||
|
return UI.Each(function() {
|
||||||
|
return Spacebars.call(self.lookup("strace"));
|
||||||
|
}, UI.block(function() {
|
||||||
|
var self = this;
|
||||||
|
return [ "\n ", HTML.DIV({
|
||||||
|
"class": "syscall"
|
||||||
|
}, "\n ", HTML.DIV({
|
||||||
|
"class": [ "change ", function() {
|
||||||
|
return Spacebars.mustache(self.lookup("ischange"));
|
||||||
|
} ]
|
||||||
|
}, function() {
|
||||||
|
return Spacebars.mustache(self.lookup("clnum"));
|
||||||
|
}), "\n ", function() {
|
||||||
|
return Spacebars.mustache(self.lookup("sc"));
|
||||||
|
}, "\n "), "\n" ];
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
|
||||||
Template.__define__("idump", (function() {
|
Template.__define__("idump", (function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var template = this;
|
var template = this;
|
||||||
|
Loading…
Reference in New Issue
Block a user