moving ./qira logic into the server for socat magic

This commit is contained in:
George Hotz 2014-07-16 11:36:02 -07:00
parent b7d75f29ae
commit 3883f80aaf
11 changed files with 197 additions and 44 deletions

0
middleware/__init__.py Normal file
View File

View File

@ -7,7 +7,7 @@ def file_binary():
instructions = {}
return subprocess.Popen(
["file", "-L", "/tmp/qira_binary"],
stdout = subprocess.PIPE).communicate()[0]
stdout = subprocess.PIPE).communicate()[0].strip()
def objdump_binary():
instructions = {}

View File

@ -9,17 +9,6 @@ SIZE_MASK = 0xFF
LOGFILE = "/tmp/qira_log"
"""
def flag_to_pytype(flags):
if flags & IS_START:
typ = "i"
elif flags & IS_MEM:
typ = "m"
else:
typ = "r"
return typ
"""
def flag_to_type(flags):
if flags & IS_START:
typ = "I"
@ -38,7 +27,7 @@ def get_log_length(fn):
dat = open(fn).read(4)
return struct.unpack("I", dat)[0]
except:
return 0
return None
def read_log(fn, seek=1, cnt=0):
f = open(fn)

View File

@ -2,10 +2,12 @@
from qira_log import *
from qira_memory import *
from qira_binary import *
import socket
import threading
import time
import sys
import os
import subprocess
from collections import defaultdict
from flask import Flask, Response
@ -76,20 +78,30 @@ def process(log_entries):
return db_changes
def init():
global instructions, pmaps, regs, mem, maxclnum, pydb_addr, pydb_clnum
def init_file(fil):
global instructions, pmaps
global REGS, REGSIZE
# delete the logs
try:
os.mkdir("/tmp/qira_logs")
except:
pass
for i in os.listdir("/tmp/qira_logs"):
os.unlink("/tmp/qira_logs/"+i)
# create the binary symlink
try:
os.unlink("/tmp/qira_binary")
except:
pass
os.symlink(fil, "/tmp/qira_binary")
instructions = {}
pmaps = {}
regs = Memory()
mem = Memory()
maxclnum = 1
print "reset program state"
instructions = objdump_binary()
mem_commit_base_binary(mem)
print "mem commit done"
# get file type
fb = file_binary()
print fb
X86REGS = (['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI', 'EIP'], 4)
@ -99,10 +111,20 @@ def init():
else:
(REGS, REGSIZE) = X86REGS
def init_db():
global instructions, pmaps, regs, mem, maxclnum, pydb_addr, pydb_clnum
regs = Memory()
mem = Memory()
maxclnum = 1
print "reset program state"
mem_commit_base_binary(mem)
print "mem commit done"
pydb_addr = defaultdict(list)
pydb_clnum = defaultdict(list)
#meteor_init(0)
# ***** after this line is the new server stuff *****
@ -161,7 +183,6 @@ def getmemory(m):
@socketio.on('getregisters', namespace='/qira')
def getregisters(clnum):
global REGS, REGSIZE
#print "getregisters",clnum
if clnum == None:
return
@ -203,7 +224,6 @@ def serve(path):
return Response(dat, mimetype="text/html")
def run_socketio():
print "starting socketio server..."
socketio.run(app, port=3002)
@ -216,9 +236,11 @@ def run_middleware():
while 1:
time.sleep(0.05)
max_changes = get_log_length(LOGFILE)
if max_changes == None:
continue
if max_changes < changes_committed:
print "RESTART..."
init()
init_db()
changes_committed = 1
if changes_committed < max_changes:
sys.stdout.write("going from %d to %d..." % (changes_committed,max_changes))
@ -243,9 +265,51 @@ def run_middleware():
print "done", maxclnum
changes_committed = max_changes
import fcntl
def run_bindserver():
# wait for a connection
ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ss.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#ss.setblocking(1)
ss.bind(("127.0.0.1", 4000))
ss.listen(5)
while 1:
(cs, address) = ss.accept()
print "**** CLIENT",cs, address, cs.fileno()
if os.fork() == 0:
fd = cs.fileno()
# python nonblocking is a lie...
fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL, 0) & ~os.O_NONBLOCK)
os.dup2(fd, 0)
os.dup2(fd, 1)
os.dup2(fd, 2)
os.execvp('qira-i386', ["qira-i386", "-singlestep", "/tmp/qira_binary"]+sys.argv[2:])
#os.execvp('strace', ['strace', '/tmp/qira_binary'])
#os.execvp('/tmp/qira_binary', ['/tmp/qira_binary'])
print os.wait()
print "**** CLIENT RETURNED"
if __name__ == '__main__':
init()
# create the file symlink
init_file(os.path.realpath(sys.argv[1]))
init_db()
# bindserver runs in a fork
if os.fork() == 0:
run_bindserver()
# start the http server
http = threading.Thread(target=run_socketio)
http.start()
t = threading.Thread(target=run_middleware)
t.start()
run_socketio()
#run_socketio()
# have to wait for something
http.join()

View File

@ -17,7 +17,8 @@ fi
cd qemu/qemu-latest
ln -sf ../../qemu_mods/tci.c tci.c
ln -sf ../../../qemu_mods/qemu.h linux-user/qemu.h
./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 --enable-tcg-interpreter --enable-debug-tcg --cpu=unknown
make -j32

View File

@ -430,7 +430,7 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
//#define QIRA_DEBUG printf
// prototypes
void init_QIRA(CPUArchState *env);
void init_QIRA(CPUArchState *env, int id);
void add_change(target_ulong addr, uint64_t data, uint32_t flags);
void track_load(target_ulong a, uint64_t data, int size);
void track_store(target_ulong a, uint64_t data, int size);
@ -468,6 +468,8 @@ struct logstate {
uint32_t change_count;
uint32_t changelist_number;
uint32_t is_filtered;
uint32_t first_changelist_number;
int parent_id;
};
struct logstate *GLOBAL_logstate;
@ -485,11 +487,17 @@ void resize_change_buffer(size_t size) {
if (GLOBAL_change_buffer == NULL) QIRA_DEBUG("MMAP FAILED!\n");
}
void init_QIRA(CPUArchState *env) {
void init_QIRA(CPUArchState *env, int id) {
char fn[PATH_MAX];
QIRA_DEBUG("init QIRA called\n");
GLOBAL_CPUArchState = env;
sprintf(fn, "/tmp/qira_logs/%d", id);
// for compat
unlink("/tmp/qira_log");
GLOBAL_qira_log_fd = open("/tmp/qira_log", O_RDWR | O_CREAT, 0644);
if(symlink(fn, "/tmp/qira_log") == -1) QIRA_DEBUG("log symlink failed\n");
GLOBAL_qira_log_fd = open(fn, O_RDWR | O_CREAT, 0644);
GLOBAL_change_size = 1;
GLOBAL_QIRA_did_init = 1;
memset(GLOBAL_pending_changes, 0, (PENDING_CHANGES_MAX_ADDR/4) * sizeof(struct change));
@ -499,7 +507,10 @@ void init_QIRA(CPUArchState *env) {
// skip the first change
GLOBAL_logstate->change_count = 1;
GLOBAL_logstate->changelist_number = 0;
GLOBAL_logstate->first_changelist_number = 0;
GLOBAL_logstate->is_filtered = 0;
GLOBAL_logstate->parent_id = -1;
}
void add_change(target_ulong addr, uint64_t data, uint32_t flags) {
@ -537,7 +548,7 @@ void commit_pending_changes(void) {
// all loads and store happen in libraries...
void track_load(target_ulong addr, uint64_t data, int size) {
QIRA_DEBUG("load: 0x%x:%d\n", addr, size);
QIRA_DEBUG("load: 0x%x:%d\n", addr, size);
add_change(addr, data, IS_MEM | size);
}
@ -547,14 +558,14 @@ void track_store(target_ulong addr, uint64_t data, int size) {
}
void track_read(target_ulong base, target_ulong offset, target_ulong data, int size) {
QIRA_DEBUG("read: %x+%x:%d = %x\n", base, offset, size, data);
if ((int)offset < 0) return;
QIRA_DEBUG("read: %x+%x:%d = %x\n", base, offset, size, data);
if (GLOBAL_logstate->is_filtered == 0) add_change(offset, data, size);
}
void track_write(target_ulong base, target_ulong offset, target_ulong data, int size) {
if ((int)offset < 0) return;
QIRA_DEBUG("write: %x+%x:%d = %x\n", base, offset, size, data);
if ((int)offset < 0) return;
if (GLOBAL_logstate->is_filtered == 0) add_change(offset, data, IS_WRITE | size);
else add_pending_change(offset, data, IS_WRITE | size);
}
@ -563,9 +574,9 @@ void track_kernel_read(void *host_addr, target_ulong guest_addr, long len) {
if (unlikely(GLOBAL_QIRA_did_init == 0)) return;
// this is generating tons of changes, and maybe not too useful
/*QIRA_DEBUG("kernel_read: %p %X %d\n", host_addr, guest_addr, len);
/*QIRA_DEBUG("kernel_read: %p %X %ld\n", host_addr, guest_addr, len);
long i = 0;
for (; i < len; i+=4) add_change(guest_addr+i, ((unsigned int*)host_addr)[i], IS_MEM | 32);
//for (; i < len; i+=4) add_change(guest_addr+i, ((unsigned int*)host_addr)[i], IS_MEM | 32);
for (; i < len; i+=1) add_change(guest_addr+i, ((unsigned char*)host_addr)[i], IS_MEM | 8);*/
}
@ -574,7 +585,7 @@ void track_kernel_write(void *host_addr, target_ulong guest_addr, long len) {
// clamp at 0x40, badness
//if (len > 0x40) len = 0x40;
QIRA_DEBUG("kernel_write: %p %X %d\n", host_addr, guest_addr, len);
QIRA_DEBUG("kernel_write: %p %X %ld\n", host_addr, guest_addr, len);
long i = 0;
//for (; i < len; i+=4) add_change(guest_addr+i, ((unsigned int*)host_addr)[i], IS_MEM | IS_WRITE | 32);
for (; i < len; i+=1) add_change(guest_addr+i, ((unsigned char*)host_addr)[i], IS_MEM | IS_WRITE | 8);
@ -641,14 +652,72 @@ void track_kernel_write(void *host_addr, target_ulong guest_addr, long len) {
# define qemu_st_beq(X) stq_be_p(g2h(W(taddr,X,64)), X)
#endif
void run_QIRA_log(CPUArchState *env, int this_id, int to_change);
void run_QIRA_log(CPUArchState *env, int this_id, int to_change) {
char fn[PATH_MAX];
sprintf(fn, "/tmp/qira_logs/%d", this_id);
int qira_log_fd = open(fn, O_RDWR, 0644);
struct logstate plogstate;
if (read(qira_log_fd, &plogstate, sizeof(plogstate)) != sizeof(plogstate)) {
printf("HEADER READ ISSUE!\n");
return;
}
// check if this one has a parent and recurse here
QIRA_DEBUG("parent is %d with first_change %d\n", plogstate.parent_id, plogstate.first_changelist_number);
if (plogstate.parent_id != -1) {
run_QIRA_log(env, plogstate.parent_id, plogstate.first_changelist_number);
}
struct change pchange;
// skip the first change
lseek(qira_log_fd, sizeof(pchange), SEEK_SET);
while(1) {
if (read(qira_log_fd, &pchange, sizeof(pchange)) != sizeof(pchange)) {
printf("READ ISSUE!\n");
break;
}
if (pchange.changelist_number == to_change) break;
QIRA_DEBUG("running old change %lX %d\n", pchange.address, pchange.changelist_number);
uint32_t flags = pchange.flags;
if ((flags & IS_VALID) && !(flags & IS_START) && (flags & IS_WRITE)) {
void *base;
if (flags & IS_MEM) { base = g2h(pchange.address); }
else { base = ((void *)env) + pchange.address; }
memcpy(base, &pchange.data, (flags&SIZE_MASK) >> 3);
}
}
GLOBAL_logstate->first_changelist_number = to_change;
GLOBAL_logstate->changelist_number = to_change-1;
GLOBAL_logstate->parent_id = this_id;
}
/* Interpret pseudo code in tb. */
uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
{
#ifdef QIRA_TRACKING
if (unlikely(GLOBAL_QIRA_did_init == 0)) init_QIRA(env);
CPUState *cpu = ENV_GET_CPU(env);
TranslationBlock *tb = cpu->current_tb;
if (unlikely(GLOBAL_QIRA_did_init == 0)) {
// these three arguments (parent_id, start_clnum, id) must be passed into QIRA
int parent_id = -1, start_clnum, id = 0;
FILE *f = fopen("/tmp/qira_state", "rb");
if (f != NULL) {
if (fscanf(f, "%d %d %d", &parent_id, &start_clnum, &id) != 3) {
printf("CORRUPT STATE!\n");
}
fclose(f);
}
init_QIRA(env, id);
if (parent_id != -1) run_QIRA_log(env, parent_id, start_clnum);
return 0;
}
// hacky check
if (tb->pc > 0x40000000) {
//if (0) {
@ -786,6 +855,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
t0 = *tb_ptr++;
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_read(t1, t2, *(uint8_t *)(t1 + t2), 32);
tci_write_reg8(t0, *(uint8_t *)(t1 + t2));
break;
case INDEX_op_ld8s_i32:
@ -806,12 +876,14 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
t0 = tci_read_r8(&tb_ptr);
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_write(t1, t2, t0, 32);
*(uint8_t *)(t1 + t2) = t0;
break;
case INDEX_op_st16_i32:
t0 = tci_read_r16(&tb_ptr);
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_write(t1, t2, t0, 32);
*(uint16_t *)(t1 + t2) = t0;
break;
case INDEX_op_st_i32:
@ -1057,6 +1129,7 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
t0 = *tb_ptr++;
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_read(t1, t2, *(uint8_t *)(t1 + t2), 8);
tci_write_reg8(t0, *(uint8_t *)(t1 + t2));
break;
case INDEX_op_ld8s_i64:
@ -1068,12 +1141,14 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
t0 = *tb_ptr++;
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_read(t1, t2, *(uint32_t *)(t1 + t2), 32);
tci_write_reg32(t0, *(uint32_t *)(t1 + t2));
break;
case INDEX_op_ld32s_i64:
t0 = *tb_ptr++;
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_read(t1, t2, *(int32_t *)(t1 + t2), 32);
tci_write_reg32s(t0, *(int32_t *)(t1 + t2));
break;
case INDEX_op_ld_i64:
@ -1087,18 +1162,21 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
t0 = tci_read_r8(&tb_ptr);
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_write(t1, t2, t0, 64);
*(uint8_t *)(t1 + t2) = t0;
break;
case INDEX_op_st16_i64:
t0 = tci_read_r16(&tb_ptr);
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_write(t1, t2, t0, 64);
*(uint16_t *)(t1 + t2) = t0;
break;
case INDEX_op_st32_i64:
t0 = tci_read_r32(&tb_ptr);
t1 = tci_read_r(&tb_ptr);
t2 = tci_read_s32(&tb_ptr);
track_write(t1, t2, t0, 64);
*(uint32_t *)(t1 + t2) = t0;
break;
case INDEX_op_st_i64:

5
qira
View File

@ -9,6 +9,7 @@ fi
BIN=$(readlink -f $1)
FILE=$(file $BIN)
mkdir -p /tmp/qira_logs/
ln -sf "$BIN" /tmp/qira_binary
# build qemu if we have the source
@ -19,11 +20,9 @@ if [ -d "qemu/qemu-latest" ]; then
popd
fi
# detect which qemu to run based on the file
shift
# TODO: use $FILE to detect which qira to call
#echo $FILE
# detect which qemu to run based on the file
if [[ $FILE == *SPARC32PLUS* ]]; then
qira-sparc32plus -singlestep /tmp/qira_binary $@
elif [[ $FILE == *ARM* ]]; then

5
scripts/dump_log.py Normal file
View File

@ -0,0 +1,5 @@
from middleware import qira_log
logs = qira_log.read_log(qira_log.LOGFILE)
for l in logs:
print "address: %8x data: %8x clnum: %4d flags: %s" % (l[0], l[1], l[2], qira_log.flag_to_type(l[3]))

1
scripts/middleware Symbolic link
View File

@ -0,0 +1 @@
../middleware

16
tests/echo.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
int main() {
char buf[0x100];
printf("swag is king\n");
fflush(stdout);
fprintf(stderr, "error is king\n");
fflush(stderr);
while (1) {
int a = read(0, buf, 0x100);
if (a <= 0) break;
write(1, buf, a);
}
return -1;
}

View File

@ -1,4 +1,4 @@
mov eax, 10
mov eax, 3
fail:
mov ebx, 2