support for args, removing qira_binary soon

This commit is contained in:
George Hotz 2014-07-21 11:08:29 -07:00
parent d3a727c16a
commit 08fe8e4eab
16 changed files with 215 additions and 42 deletions

Binary file not shown.

Binary file not shown.

View File

@ -126,7 +126,14 @@ int websocket_thread(void *) {
info.uid = -1;
info.options = 0;
// i assume this does the bind?
context = libwebsocket_create_context(&info);
if (context == NULL) {
msg("websocket init failed\n");
return -1;
}
msg("yay websockets\n");
while (websockets_running) {

View File

@ -1,4 +1,5 @@
# QIRA would be a better place if these things came from QEMU
# ALL DEAD CODE, remove ELFFile
import subprocess
from elftools.elf.elffile import ELFFile
@ -46,6 +47,11 @@ def mem_commit_base_binary(prog, mem):
# should we gate the segment on something?
# i think any data actually in the ELF file is good
print " committing %x with len %x" % (vaddr, len(data))
# old method was too slow
mem.bcommit(vaddr, data)
"""
for i in range(0, len(data)):
mem.commit(0, vaddr+i, ord(data[i]))
"""

View File

@ -19,10 +19,12 @@ class Address:
class Memory:
def __init__(this):
this.daddr = {}
this.backing = {}
def copy(this):
new = Memory()
new.daddr = this.daddr.copy()
new.backing = this.backing # no copy required
return new
def fetch(this, clnum, addr, l):
@ -32,8 +34,17 @@ class Memory:
rret = this.daddr[i].fetch(clnum)
if rret != None:
ret[i] = rret
else:
# slow
for (s, e) in this.backing:
if s <= i and i < e:
ret[i] = ord(this.backing[(s,e)][i-s])
return ret
# backing commit
def bcommit(this, addr, dat):
this.backing[(addr, addr+len(dat))] = dat
def dump(this):
ret = {}
for i in this.daddr:

View File

@ -208,6 +208,8 @@ def run_middleware():
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:
qira_trace.Trace(program, i)
@ -272,6 +274,8 @@ def start_bindserver(myss, parent_id, start_cl, loop = False):
def get_next_run_id():
ret = -1
for i in os.listdir("/tmp/qira_logs/"):
if "_" in i:
continue
ret = max(ret, int(i))
return ret+1

View File

@ -2,6 +2,7 @@ import qira_binary
import qira_log
import qira_memory
import threading
import struct
from collections import defaultdict
import os
import sys
@ -38,22 +39,28 @@ class Program:
self.pmaps = {}
#self.instructions = qira_binary.objdump_binary(prog)
self.instructions = {}
"""
self.basemem = qira_memory.Memory()
print "committing base memory..."
qira_binary.mem_commit_base_binary(prog, self.basemem)
"""
# get file type
self.fb = qira_binary.file_binary(prog)
if 'ARM' in self.fb:
#self.fb = qira_binary.file_binary(prog)
self.fb = struct.unpack("H", open(prog).read(0x18)[0x12:0x14])[0]
print "e_machine is",hex(self.fb)
if self.fb == 0x28:
self.tregs = ARMREGS
self.qirabinary = "qira-arm"
elif 'x86-64' in self.fb:
elif self.fb == 0x3e:
self.tregs = X64REGS
self.qirabinary = "qira-x86_64"
else:
elif self.fb == 0x03:
self.tregs = X86REGS
self.qirabinary = "qira-i386"
else:
print "BINARY TYPE NOT SUPPORTED"
# no traces yet
self.traces = {}
@ -77,7 +84,7 @@ class Program:
# hacks
addr = int(d.split(" ")[0].strip(":"), 16)
#print repr(d)
if 'ARM' in self.fb:
if self.fb == 0x28: # ARM
inst = d[d.rfind(" ")+2:]
else:
inst = d[d.find(":")+3:]
@ -106,7 +113,8 @@ class Trace:
def reset(self):
self.regs = qira_memory.Memory()
self.mem = self.program.basemem.copy()
self.mem = qira_memory.Memory()
#self.mem = self.program.basemem.copy()
self.minclnum = -1
self.maxclnum = 1
@ -118,6 +126,23 @@ class Trace:
self.pydb_addr = defaultdict(list)
self.pydb_clnum = defaultdict(list)
for ln in open("/tmp/qira_logs/"+str(self.forknum)+"_base").read().split("\n"):
ln = ln.split(" ")
if len(ln) < 3:
continue
(ss, se) = ln[0].split("-")
ss = int(ss, 16)
se = int(se, 16)
offset = int(ln[1])
fn = ' '.join(ln[2:])
f = open(fn)
f.seek(offset)
dat = f.read(se-ss)
self.mem.bcommit(ss, dat)
f.close()
print hex(ss)+"-"+hex(se), offset, fn
# *** HANDLER FOR qira_log ***
def process(self, log_entries):
for (address, data, clnum, flags) in log_entries:

View File

@ -19,9 +19,10 @@ if [ ! -d qemu/qemu-latest ]; then
mv linux-user/qemu.h linux-user/qemu.h.bak
mv linux-user/main.c linux-user/main.c.bak
cd ../../
sudo apt-get build-dep qemu
fi
sudo apt-get build-dep qemu
cd qemu/qemu-latest
ln -sf ../../qemu_mods/tci.c tci.c
ln -sf ../../qemu_mods/disas.c disas.c

View File

@ -425,6 +425,8 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/file.h>
#include "qemu.h"
#define QIRA_DEBUG(...) {}
//#define QIRA_DEBUG qemu_debug
@ -447,10 +449,12 @@ void track_read(target_ulong base, target_ulong offset, target_ulong data, int s
void track_write(target_ulong base, target_ulong offset, target_ulong data, int size);
void add_pending_change(target_ulong addr, uint64_t data, uint32_t flags);
void commit_pending_changes(void);
void track_kernel_read(void *host_addr, target_ulong guest_addr, long len);
void track_kernel_write(void *host_addr, target_ulong guest_addr, long len);
void resize_change_buffer(size_t size);
// defined in qemu.h
//void track_kernel_read(void *host_addr, target_ulong guest_addr, long len);
//void track_kernel_write(void *host_addr, target_ulong guest_addr, long len);
#define IS_VALID 0x80000000
#define IS_WRITE 0x40000000
#define IS_MEM 0x20000000
@ -501,9 +505,9 @@ void resize_change_buffer(size_t size) {
void init_QIRA(CPUArchState *env, int id) {
QIRA_DEBUG("init QIRA called\n");
GLOBAL_QIRA_did_init = 1;
GLOBAL_CPUArchState = env; // unused
char fn[PATH_MAX];
GLOBAL_CPUArchState = env;
sprintf(fn, "/tmp/qira_logs/%d", id);
// unlink it first
@ -681,7 +685,8 @@ void track_kernel_write(void *host_addr, target_ulong guest_addr, long len) {
#endif
// poorly written, and it fills in holes
int get_next_id() {
int get_next_id(void);
int get_next_id(void) {
char fn[PATH_MAX];
int this_id = 0;
struct stat junk;
@ -694,7 +699,6 @@ int get_next_id() {
}
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);
@ -754,12 +758,13 @@ void run_QIRA_log(CPUArchState *env, int this_id, int to_change) {
bool is_filtered_address(target_ulong pc);
bool is_filtered_address(target_ulong pc) {
// to remove the warning
uint64_t bpc = (uint64_t)pc;
// TODO(geohot): FIX THIS!, filter anything that isn't the user binary and not dynamic
return ((pc > 0x40000000 && pc < 0xf6800000) || pc >= 0x100000000);
return ((bpc > 0x40000000 && bpc < 0xf6800000) || bpc >= 0x100000000);
}
void real_target_disas(FILE *out, CPUArchState *env, target_ulong code, target_ulong size, int flags);
void target_disas(FILE *out, CPUArchState *env, target_ulong code, target_ulong size, int flags);
void target_disas(FILE *out, CPUArchState *env, target_ulong code, target_ulong size, int flags) {
if (unlikely(GLOBAL_asm_file == NULL)) {
GLOBAL_asm_file = fopen("/tmp/qira_asm", "a");
@ -779,18 +784,85 @@ int GLOBAL_last_was_syscall = 0;
uint32_t GLOBAL_last_fork_change = -1;
target_long last_pc = 0;
void write_out_base(CPUArchState *env, int id);
void write_out_base(CPUArchState *env, int id) {
CPUState *cpu = ENV_GET_CPU(env);
TaskState *ts = (TaskState *)cpu->opaque;
char fn[PATH_MAX];
char envfn[PATH_MAX];
sprintf(envfn, "/tmp/qira_logs/%d_env", id);
FILE *envf = fopen(envfn, "wb");
target_ulong ss = ts->info->start_stack;
target_ulong se = (ts->info->start_stack + (TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK;
fwrite(g2h(ss), 1, se-ss, envf);
fclose(envf);
sprintf(fn, "/tmp/qira_logs/%d_base", id);
FILE *f = fopen(fn, "w");
// code copied from linux-user/syscall.c
FILE *maps = fopen("/proc/self/maps", "r");
char *line = NULL;
size_t len = 0;
while (getline(&line, &len, maps) != -1) {
int fields, dev_maj, dev_min, inode;
uint64_t min, max, offset;
char flag_r, flag_w, flag_x, flag_p;
char path[512] = "";
fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
" %512s", &min, &max, &flag_r, &flag_w, &flag_x,
&flag_p, &offset, &dev_maj, &dev_min, &inode, path);
if ((fields < 10) || (fields > 11)) { continue; }
if (h2g_valid(min) && h2g_valid(max) && strlen(path) && flag_w == '-') {
fprintf(f, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx " %"PRIx64" %s\n", h2g(min), h2g(max), offset, path);
//printf("%p - %p -- %s", h2g(min), h2g(max), line);
//fflush(stdout);
}
/*printf("%s", line);
fflush(stdout);*/
}
// env
fprintf(f, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx " %"PRIx64"\n", ss, se, (uint64_t)0, envfn);
fclose(f);
}
/* Interpret pseudo code in tb. */
uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
{
#ifdef QIRA_TRACKING
CPUState *cpu = ENV_GET_CPU(env);
TranslationBlock *tb = cpu->current_tb;
//TaskState *ts = (TaskState *)cpu->opaque;
if (unlikely(GLOBAL_QIRA_did_init == 0)) {
// do initial core dump
/*struct rlimit core_limit, core_limit_old;
getrlimit(RLIMIT_CORE, &core_limit_old);
core_limit.rlim_cur = RLIM_INFINITY;
core_limit.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &core_limit);
(*ts->bprm->core_dump)(0, env);
setrlimit(RLIMIT_CORE, &core_limit_old);*/
/*page_dump(stderr);
fflush(stderr);*/
write_out_base(env, GLOBAL_id);
// these three arguments (parent_id, start_clnum, id) must be passed into QIRA
if (GLOBAL_parent_id != -1) {
run_QIRA_log(env, GLOBAL_parent_id, GLOBAL_start_clnum);
}
init_QIRA(env, GLOBAL_id);
return 0;
}
@ -894,14 +966,14 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
#ifdef R_EAX
struct change *a = NULL;
if (t0 == helper_load_seg) {
if ((void*)t0 == helper_load_seg) {
if (GLOBAL_logstate->is_filtered == 1) {
commit_pending_changes();
}
a = track_syscall_begin(env, FAKE_SYSCALL_LOADSEG);
a->data = a1<<32 | a2;
//printf("LOAD SEG %x %x %x %x\n", a0, a1, a2, a3);
} else if (t0 == helper_raise_interrupt) {
} else if ((void*)t0 == helper_raise_interrupt) {
if (GLOBAL_logstate->is_filtered == 1) {
commit_pending_changes();
// syscalls always get a change?

BIN
tests/argtest Executable file

Binary file not shown.

9
tests/argtest.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
for (i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
}

BIN
tests/argtest_static Executable file

Binary file not shown.

11
tests/procselfmaps.c Normal file
View File

@ -0,0 +1,11 @@
#include <stdio.h>
char buf[0x1000];
int main() {
FILE *f = fopen("/proc/self/maps", "rb");
buf[fread(buf, 1, 0x1000, f)] = '\0';
fclose(f);
printf("%s\n", buf);
return 0;
}

View File

@ -58,15 +58,59 @@ function zoom_out_max(dontforce) {
else Session.set("cview", [0, max]);
}
// uniform events everywhere
var baseevents = {
'mousedown .datamemory': function(e) { return false; },
'mousedown .datainstruction': function(e) { return false; },
// ugh highlights
'click .datamemory': function(e) {
var daddr = parseInt(e.target.innerHTML, 16);
update_dview(daddr);
},
'click .datainstruction': function(e) {
var daddr = parseInt(e.target.innerHTML, 16);
update_dview(daddr);
},
'contextmenu .datainstruction': function(e) {
// right click to follow in instruction dump
// add menu maybe?
var iaddr = parseInt(e.target.innerHTML, 16);
Session.set("dirtyiaddr", true);
Session.set('iaddr', iaddr);
return false;
},
'click .data': function(e) {
var daddr = parseInt(e.target.getAttribute('daddr'));
Session.set('daddr', daddr);
},
};
// uniform events everywhere
// ugh duplicated code, i'm bad at javascript
var basedblevents = {
'mousedown .datamemory': function(e) { return false; },
'mousedown .datainstruction': function(e) { return false; },
// ugh highlights
'dblclick .datamemory': function(e) {
var daddr = parseInt(e.target.innerHTML, 16);
update_dview(daddr);
},
'dblclick .datainstruction': function(e) {
var daddr = parseInt(e.target.innerHTML, 16);
update_dview(daddr);
},
'contextmenu .datainstruction': function(e) {
// right click to follow in instruction dump
// add menu maybe?
var iaddr = parseInt(e.target.innerHTML, 16);
Session.set("dirtyiaddr", true);
Session.set('iaddr', iaddr);
return false;
},
'click .data': function(e) {
var daddr = parseInt(e.target.getAttribute('daddr'));
Session.set('daddr', daddr);
},
};

View File

@ -33,8 +33,12 @@ Template.idump.events({
'click .change': function() {
Session.set('clnum', this.clnum);
},
'mousedown .datainstruction': function(e) { return false; },
'click .datainstruction': function() {
Session.set('iaddr', this.address);
},
'dblclick .datainstruction': function() {
update_dview(this.address);
}
});

View File

@ -84,30 +84,6 @@ stream.on('memory', function(msg) {
});
Template.memviewer.events({
'dblclick .datamemory': function(e) {
var daddr = parseInt(e.target.innerHTML, 16);
update_dview(daddr);
},
'dblclick .datainstruction': function(e) {
var daddr = parseInt(e.target.innerHTML, 16);
update_dview(daddr);
},
'contextmenu .datainstruction': function(e) {
// right click to follow in instruction dump
// add menu maybe?
var iaddr = parseInt(e.target.innerHTML, 16);
Session.set("dirtyiaddr", true);
Session.set('iaddr', iaddr);
return false;
},
'click .data': function(e) {
var daddr = parseInt(e.target.getAttribute('daddr'));
Session.set('daddr', daddr);
},
});
Template.regviewer.events(baseevents);
Template.regviewer.hexvalue = function() {
return this.value;
@ -138,10 +114,13 @@ stream.on('registers', function(msg) {
UI.insert(UI.renderWithData(Template.regviewer, {regs: msg}), $('#regviewer')[0]);
});
// *** datachanges ***
// events, add the editing here
Template.memviewer.events(basedblevents);
Template.regviewer.events(baseevents);
Template.datachanges.events(baseevents);
// *** datachanges ***
Template.datachanges.hexaddress = function() {
return this.address;
};