mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-12 17:48:33 +00:00
Fix memleak in aecu
This commit is contained in:
parent
cb6c12a522
commit
49718325fa
@ -4864,217 +4864,219 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
|
||||
startTime = r_time_now_mono ();
|
||||
}
|
||||
r_cons_break_push (NULL, NULL);
|
||||
repeat:
|
||||
if (r_cons_is_breaked ()) {
|
||||
eprintf ("[+] ESIL emulation interrupted at 0x%08" PFMT64x "\n", addr);
|
||||
return_tail (0);
|
||||
}
|
||||
//Break if we have exceeded esil.timeout
|
||||
if (esiltimeout > 0) {
|
||||
ut64 elapsedTime = r_time_now_mono () - startTime;
|
||||
elapsedTime >>= 20;
|
||||
if (elapsedTime >= esiltimeout) {
|
||||
eprintf ("[ESIL] Timeout exceeded.\n");
|
||||
for (; ; r_anal_op_fini (&op)) {
|
||||
if (r_cons_is_breaked ()) {
|
||||
eprintf ("[+] ESIL emulation interrupted at 0x%08" PFMT64x "\n", addr);
|
||||
return_tail (0);
|
||||
}
|
||||
}
|
||||
if (!esil) {
|
||||
addr = initializeEsil (core);
|
||||
esil = core->anal->esil;
|
||||
//Break if we have exceeded esil.timeout
|
||||
if (esiltimeout > 0) {
|
||||
ut64 elapsedTime = r_time_now_mono () - startTime;
|
||||
elapsedTime >>= 20;
|
||||
if (elapsedTime >= esiltimeout) {
|
||||
eprintf ("[ESIL] Timeout exceeded.\n");
|
||||
return_tail (0);
|
||||
}
|
||||
}
|
||||
if (!esil) {
|
||||
return_tail (0);
|
||||
addr = initializeEsil (core);
|
||||
esil = core->anal->esil;
|
||||
if (!esil) {
|
||||
return_tail (0);
|
||||
}
|
||||
} else {
|
||||
esil->trap = 0;
|
||||
addr = r_reg_getv (core->anal->reg, name);
|
||||
//eprintf ("PC=0x%"PFMT64x"\n", (ut64)addr);
|
||||
}
|
||||
} else {
|
||||
esil->trap = 0;
|
||||
addr = r_reg_getv (core->anal->reg, name);
|
||||
//eprintf ("PC=0x%"PFMT64x"\n", (ut64)addr);
|
||||
}
|
||||
if (prev_addr) {
|
||||
*prev_addr = addr;
|
||||
}
|
||||
if (esil->exectrap) {
|
||||
if (!r_io_is_valid_offset (core->io, addr, R_PERM_X)) {
|
||||
esil->trap = R_ANAL_TRAP_EXEC_ERR;
|
||||
esil->trap_code = addr;
|
||||
eprintf ("[ESIL] Trap, trying to execute on non-executable memory\n");
|
||||
return_tail (1);
|
||||
if (prev_addr) {
|
||||
*prev_addr = addr;
|
||||
}
|
||||
}
|
||||
r_asm_set_pc (core->rasm, addr);
|
||||
// run esil pin command here
|
||||
const char *pincmd = r_anal_pin_call (core->anal, addr);
|
||||
if (pincmd) {
|
||||
r_core_cmd0 (core, pincmd);
|
||||
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
||||
if (addr != pc) {
|
||||
return_tail (1);
|
||||
if (esil->exectrap) {
|
||||
if (!r_io_is_valid_offset (core->io, addr, R_PERM_X)) {
|
||||
esil->trap = R_ANAL_TRAP_EXEC_ERR;
|
||||
esil->trap_code = addr;
|
||||
eprintf ("[ESIL] Trap, trying to execute on non-executable memory\n");
|
||||
return_tail (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
int dataAlign = r_anal_archinfo (esil->anal, R_ANAL_ARCHINFO_DATA_ALIGN);
|
||||
if (dataAlign > 1) {
|
||||
if (addr % dataAlign) {
|
||||
r_asm_set_pc (core->rasm, addr);
|
||||
// run esil pin command here
|
||||
const char *pincmd = r_anal_pin_call (core->anal, addr);
|
||||
if (pincmd) {
|
||||
r_core_cmd0 (core, pincmd);
|
||||
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
||||
if (addr != pc) {
|
||||
return_tail (1);
|
||||
}
|
||||
}
|
||||
int dataAlign = r_anal_archinfo (esil->anal, R_ANAL_ARCHINFO_DATA_ALIGN);
|
||||
if (dataAlign > 1) {
|
||||
if (addr % dataAlign) {
|
||||
if (esil->cmd && esil->cmd_trap) {
|
||||
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_UNALIGNED);
|
||||
}
|
||||
if (breakoninvalid) {
|
||||
r_cons_printf ("[ESIL] Stopped execution in an unaligned instruction (see e??esil.breakoninvalid)\n");
|
||||
return_tail (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
(void) r_io_read_at_mapped (core->io, addr, code, sizeof (code));
|
||||
// TODO: sometimes this is dupe
|
||||
ret = r_anal_op (core->anal, &op, addr, code, sizeof (code), R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_HINT);
|
||||
// if type is JMP then we execute the next N instructions
|
||||
// update the esil pointer because RAnal.op() can change it
|
||||
esil = core->anal->esil;
|
||||
if (op.size < 1 || ret < 1) {
|
||||
if (esil->cmd && esil->cmd_trap) {
|
||||
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_UNALIGNED);
|
||||
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_INVALID);
|
||||
}
|
||||
if (breakoninvalid) {
|
||||
r_cons_printf ("[ESIL] Stopped execution in an unaligned instruction (see e??esil.breakoninvalid)\n");
|
||||
eprintf ("[ESIL] Stopped execution in an invalid instruction (see e??esil.breakoninvalid)\n");
|
||||
return_tail (0);
|
||||
}
|
||||
op.size = 1; // avoid inverted stepping
|
||||
}
|
||||
}
|
||||
(void) r_io_read_at_mapped (core->io, addr, code, sizeof (code));
|
||||
// TODO: sometimes this is dupe
|
||||
ret = r_anal_op (core->anal, &op, addr, code, sizeof (code), R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_HINT);
|
||||
// if type is JMP then we execute the next N instructions
|
||||
// update the esil pointer because RAnal.op() can change it
|
||||
esil = core->anal->esil;
|
||||
if (op.size < 1 || ret < 1) {
|
||||
if (esil->cmd && esil->cmd_trap) {
|
||||
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_INVALID);
|
||||
if (stepOver) {
|
||||
switch (op.type) {
|
||||
case R_ANAL_OP_TYPE_SWI:
|
||||
case R_ANAL_OP_TYPE_UCALL:
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_RCALL:
|
||||
case R_ANAL_OP_TYPE_RJMP:
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
case R_ANAL_OP_TYPE_CRET:
|
||||
case R_ANAL_OP_TYPE_UJMP:
|
||||
if (addr == until_addr) {
|
||||
return_tail (0);
|
||||
} else {
|
||||
r_reg_setv (core->anal->reg, "PC", op.addr + op.size);
|
||||
r_reg_setv (core->dbg->reg, "PC", op.addr + op.size);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (breakoninvalid) {
|
||||
eprintf ("[ESIL] Stopped execution in an invalid instruction (see e??esil.breakoninvalid)\n");
|
||||
return_tail (0);
|
||||
}
|
||||
op.size = 1; // avoid inverted stepping
|
||||
}
|
||||
if (stepOver) {
|
||||
switch (op.type) {
|
||||
case R_ANAL_OP_TYPE_SWI:
|
||||
case R_ANAL_OP_TYPE_UCALL:
|
||||
case R_ANAL_OP_TYPE_CALL:
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_RCALL:
|
||||
case R_ANAL_OP_TYPE_RJMP:
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
case R_ANAL_OP_TYPE_CRET:
|
||||
case R_ANAL_OP_TYPE_UJMP:
|
||||
if (addr == until_addr) {
|
||||
return_tail (0);
|
||||
if (r_config_get_i (core->config, "cfg.r2wars")) {
|
||||
// this is x86 and r2wars specific, shouldnt hurt outside x86
|
||||
ut64 vECX = r_reg_getv (core->anal->reg, "ecx");
|
||||
if (op.prefix & R_ANAL_OP_PREFIX_REP && vECX > 1) {
|
||||
char *tmp = strstr (op.esil.ptr, ",ecx,?{,5,GOTO,}");
|
||||
if (tmp) {
|
||||
tmp[0] = 0;
|
||||
}
|
||||
op.esil.len -= 16;
|
||||
} else {
|
||||
r_reg_setv (core->anal->reg, "PC", op.addr + op.size);
|
||||
r_reg_setv (core->dbg->reg, "PC", op.addr + op.size);
|
||||
r_reg_setv (core->anal->reg, name, addr + op.size);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (r_config_get_i (core->config, "cfg.r2wars")) {
|
||||
// this is x86 and r2wars specific, shouldnt hurt outside x86
|
||||
ut64 vECX = r_reg_getv (core->anal->reg, "ecx");
|
||||
if (op.prefix & R_ANAL_OP_PREFIX_REP && vECX > 1) {
|
||||
char *tmp = strstr (op.esil.ptr, ",ecx,?{,5,GOTO,}");
|
||||
if (tmp) {
|
||||
tmp[0] = 0;
|
||||
}
|
||||
op.esil.len -= 16;
|
||||
} else {
|
||||
r_reg_setv (core->anal->reg, name, addr + op.size);
|
||||
}
|
||||
} else {
|
||||
r_reg_setv (core->anal->reg, name, addr + op.size);
|
||||
}
|
||||
if (ret) {
|
||||
r_anal_esil_set_pc (esil, addr);
|
||||
const char *e = R_STRBUF_SAFEGET (&op.esil);
|
||||
if (core->dbg->trace->enabled) {
|
||||
RReg *reg = core->dbg->reg;
|
||||
core->dbg->reg = core->anal->reg;
|
||||
r_debug_trace_op (core->dbg, &op);
|
||||
core->dbg->reg = reg;
|
||||
} else if (R_STR_ISNOTEMPTY (e)) {
|
||||
r_anal_esil_parse (esil, e);
|
||||
if (core->anal->cur && core->anal->cur->esil_post_loop) {
|
||||
core->anal->cur->esil_post_loop (esil, &op);
|
||||
if (ret) {
|
||||
r_anal_esil_set_pc (esil, addr);
|
||||
const char *e = R_STRBUF_SAFEGET (&op.esil);
|
||||
if (core->dbg->trace->enabled) {
|
||||
RReg *reg = core->dbg->reg;
|
||||
core->dbg->reg = core->anal->reg;
|
||||
r_debug_trace_op (core->dbg, &op);
|
||||
core->dbg->reg = reg;
|
||||
} else if (R_STR_ISNOTEMPTY (e)) {
|
||||
r_anal_esil_parse (esil, e);
|
||||
if (core->anal->cur && core->anal->cur->esil_post_loop) {
|
||||
core->anal->cur->esil_post_loop (esil, &op);
|
||||
}
|
||||
r_anal_esil_stack_free (esil);
|
||||
}
|
||||
r_anal_esil_stack_free (esil);
|
||||
bool isNextFall = false;
|
||||
if (op.type == R_ANAL_OP_TYPE_CJMP) {
|
||||
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
||||
if (pc == addr + op.size) {
|
||||
// do not opdelay here
|
||||
isNextFall = true;
|
||||
}
|
||||
}
|
||||
// only support 1 slot for now
|
||||
if (op.delay && !isNextFall) {
|
||||
ut8 code2[32];
|
||||
ut64 naddr = addr + op.size;
|
||||
RAnalOp op2 = {0};
|
||||
// emulate only 1 instruction
|
||||
r_anal_esil_set_pc (esil, naddr);
|
||||
(void)r_io_read_at (core->io, naddr, code2, sizeof (code2));
|
||||
// TODO: sometimes this is dupe
|
||||
ret = r_anal_op (core->anal, &op2, naddr, code2, sizeof (code2), R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_HINT);
|
||||
if (ret > 0) {
|
||||
switch (op2.type) {
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_CRET:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
// branches are illegal in a delay slot
|
||||
esil->trap = R_ANAL_TRAP_EXEC_ERR;
|
||||
esil->trap_code = addr;
|
||||
eprintf ("[ESIL] Trap, trying to execute a branch in a delay slot\n");
|
||||
return_tail (1);
|
||||
break;
|
||||
}
|
||||
const char *e = R_STRBUF_SAFEGET (&op2.esil);
|
||||
if (R_STR_ISNOTEMPTY (e)) {
|
||||
r_anal_esil_parse (esil, e);
|
||||
}
|
||||
} else {
|
||||
eprintf ("Invalid instruction at 0x%08"PFMT64x"\n", naddr);
|
||||
}
|
||||
r_anal_op_fini (&op2);
|
||||
}
|
||||
tail_return_value = 1;
|
||||
}
|
||||
bool isNextFall = false;
|
||||
if (op.type == R_ANAL_OP_TYPE_CJMP) {
|
||||
// esil->verbose ?
|
||||
// eprintf ("REPE 0x%llx %s => 0x%llx\n", addr, R_STRBUF_SAFEGET (&op.esil), r_reg_getv (core->anal->reg, "PC"));
|
||||
|
||||
ut64 pc = r_reg_getv (core->anal->reg, name);
|
||||
if (core->anal->pcalign > 0) {
|
||||
pc -= (pc % core->anal->pcalign);
|
||||
r_reg_setv (core->anal->reg, name, pc);
|
||||
r_reg_setv (core->dbg->reg, name, pc);
|
||||
}
|
||||
|
||||
st64 follow = (st64)r_config_get_i (core->config, "dbg.follow");
|
||||
if (follow > 0) {
|
||||
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
||||
if (pc == addr + op.size) {
|
||||
// do not opdelay here
|
||||
isNextFall = true;
|
||||
if ((pc < core->offset) || (pc > (core->offset + follow))) {
|
||||
r_core_cmd0 (core, "sr PC");
|
||||
}
|
||||
}
|
||||
// only support 1 slot for now
|
||||
if (op.delay && !isNextFall) {
|
||||
ut8 code2[32];
|
||||
ut64 naddr = addr + op.size;
|
||||
RAnalOp op2 = {0};
|
||||
// emulate only 1 instruction
|
||||
r_anal_esil_set_pc (esil, naddr);
|
||||
(void)r_io_read_at (core->io, naddr, code2, sizeof (code2));
|
||||
// TODO: sometimes this is dupe
|
||||
ret = r_anal_op (core->anal, &op2, naddr, code2, sizeof (code2), R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_HINT);
|
||||
if (ret > 0) {
|
||||
switch (op2.type) {
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
case R_ANAL_OP_TYPE_CRET:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
// branches are illegal in a delay slot
|
||||
esil->trap = R_ANAL_TRAP_EXEC_ERR;
|
||||
esil->trap_code = addr;
|
||||
eprintf ("[ESIL] Trap, trying to execute a branch in a delay slot\n");
|
||||
return_tail (1);
|
||||
break;
|
||||
}
|
||||
const char *e = R_STRBUF_SAFEGET (&op2.esil);
|
||||
if (R_STR_ISNOTEMPTY (e)) {
|
||||
r_anal_esil_parse (esil, e);
|
||||
}
|
||||
} else {
|
||||
eprintf ("Invalid instruction at 0x%08"PFMT64x"\n", naddr);
|
||||
}
|
||||
r_anal_op_fini (&op2);
|
||||
}
|
||||
tail_return_value = 1;
|
||||
}
|
||||
// esil->verbose ?
|
||||
// eprintf ("REPE 0x%llx %s => 0x%llx\n", addr, R_STRBUF_SAFEGET (&op.esil), r_reg_getv (core->anal->reg, "PC"));
|
||||
|
||||
ut64 pc = r_reg_getv (core->anal->reg, name);
|
||||
if (core->anal->pcalign > 0) {
|
||||
pc -= (pc % core->anal->pcalign);
|
||||
r_reg_setv (core->anal->reg, name, pc);
|
||||
r_reg_setv (core->dbg->reg, name, pc);
|
||||
}
|
||||
|
||||
st64 follow = (st64)r_config_get_i (core->config, "dbg.follow");
|
||||
if (follow > 0) {
|
||||
ut64 pc = r_debug_reg_get (core->dbg, "PC");
|
||||
if ((pc < core->offset) || (pc > (core->offset + follow))) {
|
||||
r_core_cmd0 (core, "sr PC");
|
||||
}
|
||||
}
|
||||
// check breakpoints
|
||||
if (r_bp_get_at (core->dbg->bp, pc)) {
|
||||
r_cons_printf ("[ESIL] hit breakpoint at 0x%"PFMT64x "\n", pc);
|
||||
return_tail (0);
|
||||
}
|
||||
// check addr
|
||||
if (until_addr != UT64_MAX) {
|
||||
if (pc == until_addr) {
|
||||
// check breakpoints
|
||||
if (r_bp_get_at (core->dbg->bp, pc)) {
|
||||
r_cons_printf ("[ESIL] hit breakpoint at 0x%"PFMT64x "\n", pc);
|
||||
return_tail (0);
|
||||
}
|
||||
goto repeat;
|
||||
}
|
||||
// check esil
|
||||
if (esil && esil->trap) {
|
||||
if (core->anal->esil->verbose) {
|
||||
eprintf ("TRAP\n");
|
||||
// check addr
|
||||
if (until_addr != UT64_MAX) {
|
||||
if (pc == until_addr) {
|
||||
return_tail (0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return_tail (0);
|
||||
}
|
||||
if (until_expr) {
|
||||
if (r_anal_esil_condition (core->anal->esil, until_expr)) {
|
||||
// check esil
|
||||
if (esil && esil->trap) {
|
||||
if (core->anal->esil->verbose) {
|
||||
eprintf ("ESIL BREAK!\n");
|
||||
eprintf ("TRAP\n");
|
||||
}
|
||||
return_tail (0);
|
||||
}
|
||||
goto repeat;
|
||||
if (until_expr) {
|
||||
if (r_anal_esil_condition (core->anal->esil, until_expr)) {
|
||||
if (core->anal->esil->verbose) {
|
||||
eprintf ("ESIL BREAK!\n");
|
||||
}
|
||||
return_tail (0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tail_return:
|
||||
r_anal_op_fini (&op);
|
||||
|
Loading…
x
Reference in New Issue
Block a user