sanitize host addresses to a valid value when loading IR into recc

This commit is contained in:
Anthony Pesch 2016-12-16 21:03:54 -08:00
parent dd12368992
commit 37b9f52b6c
7 changed files with 64 additions and 35 deletions

View File

@ -160,12 +160,12 @@ static void arm7_translate(void *data, uint32_t addr, struct ir *ir,
struct ir_value *remaining_cycles = ir_load_context(
ir, offsetof(struct armv3_context, remaining_cycles), VALUE_I32);
struct ir_value *done = ir_cmp_sle(ir, remaining_cycles, ir_alloc_i32(ir, 0));
ir_branch_true(ir, done, ir_alloc_ptr(ir, arm7_dispatch_leave));
ir_branch_true(ir, ir_alloc_ptr(ir, arm7_dispatch_leave), done);
/* interrupt check */
struct ir_value *pending_intr = ir_load_context(
ir, offsetof(struct armv3_context, pending_interrupts), VALUE_I32);
ir_branch_true(ir, pending_intr, ir_alloc_ptr(ir, arm7_dispatch_interrupt));
ir_branch_true(ir, ir_alloc_ptr(ir, arm7_dispatch_interrupt), pending_intr);
/* update remaining cycles */
int cycles = (size / 4);

View File

@ -124,12 +124,12 @@ static void sh4_translate(void *data, uint32_t addr, struct ir *ir, int fastmem,
struct ir_value *remaining_cycles = ir_load_context(
ir, offsetof(struct sh4_ctx, remaining_cycles), VALUE_I32);
struct ir_value *done = ir_cmp_sle(ir, remaining_cycles, ir_alloc_i32(ir, 0));
ir_branch_true(ir, done, ir_alloc_ptr(ir, sh4_dispatch_leave));
ir_branch_true(ir, ir_alloc_ptr(ir, sh4_dispatch_leave), done);
/* handle pending interrupts */
struct ir_value *pending_intr = ir_load_context(
ir, offsetof(struct sh4_ctx, pending_interrupts), VALUE_I64);
ir_branch_true(ir, pending_intr, ir_alloc_ptr(ir, sh4_dispatch_interrupt));
ir_branch_true(ir, ir_alloc_ptr(ir, sh4_dispatch_interrupt), pending_intr);
/* update remaining cycles */
remaining_cycles = ir_sub(ir, remaining_cycles, ir_alloc_i32(ir, as.cycles));

View File

@ -1556,31 +1556,31 @@ EMITTER(BRANCH) {
}
EMITTER(BRANCH_FALSE) {
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[0]);
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[1]);
e.test(cond, cond);
if (instr->arg[1]->type == VALUE_LABEL) {
if (instr->arg[0]->type == VALUE_LABEL) {
char name[128];
x64_backend_label_name(name, sizeof(name), instr->arg[1]);
x64_backend_label_name(name, sizeof(name), instr->arg[0]);
e.jz(name);
} else {
void *dst = (void *)instr->arg[1]->i64;
void *dst = (void *)instr->arg[0]->i64;
e.jz(dst);
}
}
EMITTER(BRANCH_TRUE) {
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[0]);
const Xbyak::Reg cond = x64_backend_register(backend, instr->arg[1]);
e.test(cond, cond);
if (instr->arg[1]->type == VALUE_LABEL) {
if (instr->arg[0]->type == VALUE_LABEL) {
char name[128];
x64_backend_label_name(name, sizeof(name), instr->arg[1]);
x64_backend_label_name(name, sizeof(name), instr->arg[0]);
e.jnz(name);
} else {
void *dst = (void *)instr->arg[1]->i64;
void *dst = (void *)instr->arg[0]->i64;
e.jnz(dst);
}
}

View File

@ -63,8 +63,8 @@ static emit_cb emit_callbacks[NUM_SH4_OPS] = {
#define load_pr() ir_load_pr(ir)
#define store_pr(v) ir_store_pr(ir, v)
#define branch(addr) ir_branch_guest(frontend, ir, addr)
#define branch_false(cond, addr) ir_branch_false_guest(frontend, ir, cond, addr)
#define branch_true(cond, addr) ir_branch_true_guest(frontend, ir, cond, addr)
#define branch_false(addr, cond) ir_branch_false_guest(frontend, ir, addr, cond)
#define branch_true(addr, cond) ir_branch_true_guest(frontend, ir, addr, cond)
static struct ir_value *ir_load_guest(struct ir *ir, int flags,
struct ir_value *addr,
@ -198,18 +198,18 @@ static void ir_branch_guest(struct sh4_frontend *frontend, struct ir *ir,
}
static void ir_branch_false_guest(struct sh4_frontend *frontend, struct ir *ir,
struct ir_value *cond,
struct ir_value *addr) {
struct ir_value *addr,
struct ir_value *cond) {
struct ir_value *skip = ir_alloc_label(ir, "skip_%p", addr);
ir_branch_true(ir, cond, skip);
ir_branch_true(ir, skip, cond);
ir_store_context(ir, offsetof(struct sh4_ctx, pc), addr);
ir_label(ir, skip);
}
static void ir_branch_true_guest(struct sh4_frontend *frontend, struct ir *ir,
struct ir_value *cond, struct ir_value *addr) {
struct ir_value *addr, struct ir_value *cond) {
struct ir_value *skip = ir_alloc_label(ir, "skip_%p", addr);
ir_branch_false(ir, cond, skip);
ir_branch_false(ir, skip, cond);
ir_store_context(ir, offsetof(struct sh4_ctx, pc), addr);
ir_label(ir, skip);
}
@ -1203,7 +1203,7 @@ EMITTER(SHLR16) {
EMITTER(BF) {
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
struct ir_value *cond = load_t();
branch_false(cond, ir_alloc_i32(ir, dest_addr));
branch_false(ir_alloc_i32(ir, dest_addr), cond);
}
// code cycles t-bit
@ -1213,7 +1213,7 @@ EMITTER(BFS) {
struct ir_value *cond = load_t();
emit_delay_instr();
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
branch_false(cond, ir_alloc_i32(ir, dest_addr));
branch_false(ir_alloc_i32(ir, dest_addr), cond);
}
// code cycles t-bit
@ -1222,7 +1222,7 @@ EMITTER(BFS) {
EMITTER(BT) {
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
struct ir_value *cond = load_t();
branch_true(cond, ir_alloc_i32(ir, dest_addr));
branch_true(ir_alloc_i32(ir, dest_addr), cond);
}
// code cycles t-bit
@ -1232,7 +1232,7 @@ EMITTER(BTS) {
struct ir_value *cond = load_t();
emit_delay_instr();
uint32_t dest_addr = ((int8_t)i->disp * 2) + i->addr + 4;
branch_true(cond, ir_alloc_i32(ir, dest_addr));
branch_true(ir_alloc_i32(ir, dest_addr), cond);
}
// code cycles t-bit
@ -1504,7 +1504,7 @@ EMITTER(PREF) {
struct ir_value *cond = ir_lshr(ir, addr, ir_alloc_i32(ir, 26));
cond = ir_cmp_ne(ir, cond, ir_alloc_i32(ir, 0x38));
struct ir_value *skip = ir_alloc_label(ir, "skip_%p", cond);
ir_branch_true(ir, cond, skip);
ir_branch_true(ir, skip, cond);
struct ir_value *data = ir_alloc_ptr(ir, frontend->data);
struct ir_value *sq_prefetch = ir_alloc_ptr(ir, frontend->sq_prefetch);

View File

@ -778,22 +778,22 @@ void ir_branch(struct ir *ir, struct ir_value *dst) {
ir_set_arg0(ir, instr, dst);
}
void ir_branch_false(struct ir *ir, struct ir_value *cond,
struct ir_value *dst) {
void ir_branch_false(struct ir *ir, struct ir_value *dst,
struct ir_value *cond) {
CHECK(dst->type == VALUE_LABEL || dst->type == VALUE_I64);
struct ir_instr *instr = ir_append_instr(ir, OP_BRANCH_FALSE, VALUE_V);
ir_set_arg0(ir, instr, cond);
ir_set_arg1(ir, instr, dst);
ir_set_arg0(ir, instr, dst);
ir_set_arg1(ir, instr, cond);
}
void ir_branch_true(struct ir *ir, struct ir_value *cond,
struct ir_value *dst) {
void ir_branch_true(struct ir *ir, struct ir_value *dst,
struct ir_value *cond) {
CHECK(dst->type == VALUE_LABEL || dst->type == VALUE_I64);
struct ir_instr *instr = ir_append_instr(ir, OP_BRANCH_TRUE, VALUE_V);
ir_set_arg0(ir, instr, cond);
ir_set_arg1(ir, instr, dst);
ir_set_arg0(ir, instr, dst);
ir_set_arg1(ir, instr, cond);
}
void ir_call(struct ir *ir, struct ir_value *fn) {

View File

@ -328,9 +328,9 @@ struct ir_value *ir_lshd(struct ir *ir, struct ir_value *a, struct ir_value *n);
/* branches */
void ir_label(struct ir *ir, struct ir_value *lbl);
void ir_branch(struct ir *ir, struct ir_value *dst);
void ir_branch_false(struct ir *ir, struct ir_value *cond,
struct ir_value *dst);
void ir_branch_true(struct ir *ir, struct ir_value *cond, struct ir_value *dst);
void ir_branch_false(struct ir *ir, struct ir_value *dst,
struct ir_value *cond);
void ir_branch_true(struct ir *ir, struct ir_value *dst, struct ir_value *cond);
/* calls */
void ir_call(struct ir *ir, struct ir_value *fn);

View File

@ -39,6 +39,21 @@ static int get_num_instrs(const struct ir *ir) {
return n;
}
static void sanitize_ir(struct ir *ir) {
list_for_each_entry(instr, &ir->instrs, struct ir_instr, it) {
if (instr->op != OP_BRANCH && instr->op != OP_BRANCH_FALSE &&
instr->op != OP_BRANCH_TRUE && instr->op != OP_CALL &&
instr->op != OP_CALL_FALLBACK) {
continue;
}
/* ensure that address are within 2 GB of the code buffer */
uint64_t addr = instr->arg[0]->i64;
addr = (uint64_t)code | (addr & 0x7fffffff);
ir_set_arg0(ir, instr, ir_alloc_i64(ir, addr));
}
}
static void process_file(struct jit *jit, const char *filename,
int disable_dumps) {
struct ir ir = {0};
@ -52,6 +67,9 @@ static void process_file(struct jit *jit, const char *filename,
fclose(input);
CHECK(r);
/* sanitize absolute addresses in the ir */
sanitize_ir(&ir);
/* calculate number of guest instructions */
int guest_num_instrs = 0;
list_for_each_entry(instr, &ir.instrs, struct ir_instr, it) {
@ -164,10 +182,21 @@ int main(int argc, char **argv) {
const char *path = argv[1];
/* initailize jit, stubbing out guest interfaces that are used during
assembly to a valid address */
struct jit *jit = jit_create("recc");
struct jit_guest guest = {0};
guest.r8 = (void *)code;
guest.r16 = (void *)code;
guest.r32 = (void *)code;
guest.w8 = (void *)code;
guest.w16 = (void *)code;
guest.w32 = (void *)code;
struct jit_backend *backend =
x64_backend_create(jit, code, code_size, stack_size);
CHECK(jit_init(jit, &guest, NULL, backend));
if (fs_isfile(path)) {