anal->esil can't be null now, improve default initialization ##esil

* Fix anal.gp initialization with esil traps
* Adapt tests to use aeim when needed
* Improve pde initialization with r2 -c
* Requires 2nd round review, added comments
This commit is contained in:
pancake 2023-07-17 01:43:56 +02:00 committed by GitHub
parent 4e44a218b6
commit dcfc36ede5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 167 additions and 311 deletions

View File

@ -120,7 +120,8 @@ R_API RAnal *r_anal_new(void) {
anal->sdb_classes_attrs = sdb_ns (anal->sdb_classes, "attrs", 1);
anal->zign_path = strdup ("");
anal->cb_printf = (PrintfCallback) printf;
anal->esil = NULL; // nul on purpose, otherwise many analysisi fail O_O
anal->esil = r_esil_new (4096, 0, 1);
anal->esil->anal = anal;
(void)r_anal_pin_init (anal);
(void)r_anal_xrefs_init (anal);
anal->diff_thbb = R_ANAL_THRESHOLDBB;

View File

@ -72,7 +72,7 @@ R_API char *r_bin_filter_name(RBinFile *bf, HtPU *db, ut64 vaddr, char *name) {
resname = p;
}
// two symbols at different addresses and same name wtf
R_LOG_DEBUG ("Found duplicated symbol '%s'", name);
R_LOG_DEBUG ("Found duplicated symbol '%s'", resname);
}
return resname;
}

View File

@ -785,7 +785,8 @@ R_API RList *r_bin_get_strings(RBin *bin) {
return o ? o->strings : NULL;
}
R_API int r_bin_is_string(RBin *bin, ut64 va) {
// XXX R2_590 this is super slow - remove this function because is used 1 time and from core and we can use rflags for this
R_API bool r_bin_is_string(RBin *bin, ut64 va) {
RBinString *string;
RListIter *iter;
RList *list = r_bin_get_strings (bin);

View File

@ -5,9 +5,7 @@
#define LOOP_MAX 10
static bool anal_emul_init(RCore *core, RConfigHold *hc, RDebugTrace **dt, REsilTrace **et) {
if (!core->anal->esil) {
return false;
}
r_return_val_if_fail (core && core->anal && core->anal->esil, false);
*dt = core->dbg->trace;
*et = core->anal->esil->trace;
core->dbg->trace = r_debug_trace_new ();
@ -456,55 +454,6 @@ static int bb_cmpaddr(const void *_a, const void *_b) {
return a->addr > b->addr ? 1 : (a->addr < b->addr ? -1 : 0);
}
#define SLOW_STEP 1
static bool fast_step(RCore *core, RAnalOp *aop) {
#if SLOW_STEP
return r_core_esil_step (core, UT64_MAX, NULL, NULL, false);
#else
REsil *esil = core->anal->esil;
const char *e = R_STRBUF_SAFEGET (&aop->esil);
if (R_STR_ISEMPTY (e)) {
return false;
}
if (!esil) {
r_core_cmd_call (core, "aei");
// addr = initializeEsil (core);
esil = core->anal->esil;
if (!esil) {
return false;
}
} else {
esil->trap = 0;
//eprintf ("PC=0x%"PFMT64x"\n", (ut64)addr);
}
// const char *name = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
// ut64 addr = r_reg_getv (core->anal->reg, name);
int ret = (aop->type == R_ANAL_OP_TYPE_ILL) ? -1: aop->size;
// TODO: sometimes this is dupe
// 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 (aop->size < 1 || ret < 1) {
return false;
}
// r_esil_parse (esil, e);
#if 1
RReg *reg = core->dbg->reg;
core->dbg->reg = core->anal->reg;
r_esil_set_pc (esil, aop->addr);
r_debug_trace_op (core->dbg, aop); // calls esil.parse() internally
core->dbg->reg = reg;
#else
r_debug_trace_op (core->dbg, aop); // calls esil.parse() internally
#endif
// select next instruction
const char *pcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
r_reg_setv (core->anal->reg, pcname, aop->addr + aop->size);
r_esil_stack_free (esil);
return true;
#endif
}
R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
const int op_tions = R_ARCH_OP_MASK_BASIC | R_ARCH_OP_MASK_VAL | R_ARCH_OP_MASK_ESIL | R_ARCH_OP_MASK_HINT;
RAnalBlock *bb;
@ -514,11 +463,6 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
r_return_if_fail (core && core->anal && fcn);
if (!core->anal->esil) {
R_LOG_WARN ("Please run aeim");
return;
}
RAnal *anal = core->anal;
Sdb *TDB = anal->sdb_types;
bool chk_constraint = r_config_get_b (core->config, "anal.types.constraint");
@ -629,7 +573,7 @@ repeat:
// just analyze statically the instruction if its a call, dont emulate it
r_reg_setv (core->dbg->reg, pc, addr + ret);
} else {
fast_step (core, &aop);
r_core_esil_step (core, UT64_MAX, NULL, NULL, false);
}
// maybe the basic block is gone after the step...

View File

@ -3685,20 +3685,11 @@ static bool anal_block_cb(RAnalBlock *bb, BlockRecurseCtx *ctx) {
if (r_cons_is_breaked ()) {
break;
}
#if 0
RAnalOp *hop = r_core_anal_op (core, opaddr, mask);
if (!hop) {
break;
}
memcpy (&op, hop, sizeof (RAnalOp));
free (hop);
#else
pos = (opaddr - bb->addr);
if (r_anal_op (core->anal, &op, opaddr, buf + pos, bb->size - pos, mask) < 1) {
r_anal_op_fini (&op);
break;
}
#endif
r_anal_extract_rarg (core->anal, &op, fcn, reg_set, &ctx->count);
if (!ctx->argonly) {
if (op.stackop == R_ANAL_STACK_INC) {
@ -5241,7 +5232,7 @@ static bool esilbreak_reg_write(REsil *esil, const char *name, ut64 *val) {
switch (op->type) {
case R_ANAL_OP_TYPE_UCALL: // BLX
case R_ANAL_OP_TYPE_UJMP: // BX
// maybe UJMP/UCALL is enough here
// R2_590 - maybe UJMP/UCALL is enough here
if (!(*val & 1)) {
r_anal_hint_set_bits (anal, *val, 32);
} else {
@ -5570,16 +5561,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str /* len */, const char *
}
esilbreak_last_read = UT64_MAX;
r_io_read_at (core->io, start, buf, iend + 1);
if (!ESIL) {
r_core_cmd_call (core, "aei");
ESIL = core->anal->esil;
if (!ESIL) {
R_LOG_ERROR ("ESIL is not initialized");
return;
}
r_core_cmd_call (core, "aeim");
ESIL = core->anal->esil;
}
// maybe r_core_cmd_call (core, "aeim");
const char *kspname = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
if (R_STR_ISEMPTY (kspname)) {
R_LOG_ERROR ("No =SP defined in the reg profile");

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2022 - pancake */
/* radare - LGPL - Copyright 2009-2023 - pancake */
#define R_LOG_ORIGIN "cfile"
#include <r_core.h>
@ -34,14 +34,18 @@ static bool its_a_mips(RCore *core) {
}
static void loadGP(RCore *core) {
// R2R db/cmd/cmd_eval
if (its_a_mips (core)) {
ut64 e0 = r_num_math (core->num, "entry0");
ut64 gp = r_num_math (core->num, "loc._gp");
if ((!gp || gp == UT64_MAX) && (e0 && e0 != UT64_MAX)) {
r_config_set (core->config, "anal.roregs", "zero");
r_core_cmd0 (core, "10aes@entry0");
r_config_set (core->config, "anal.roregs", "zero,gp");
r_core_cmd0 (core, "aeim; s entry0;dr PC=entry0");
r_config_set (core->config, "anal.roregs", "zero"); // gp is writable here
r_core_cmd0 (core, "10aes");
gp = r_reg_getv (core->anal->reg, "gp");
r_core_cmd0 (core, "dr0;aeim");
r_reg_setv (core->anal->reg, "gp", gp);
r_config_set (core->config, "anal.roregs", "zero,gp");
}
R_LOG_DEBUG ("[mips] gp: 0x%08"PFMT64x, gp);
r_config_set_i (core->config, "anal.gp", gp);
@ -867,6 +871,7 @@ R_API RIODesc *r_core_file_open_many(RCore *r, const char *file, int perm, ut64
const int pillow = 0x4000;
loadaddr += sz + rest + pillow;
}
r_esil_setup (r->anal->esil, r->anal, 0, 0, false);
}
}
return first;
@ -921,6 +926,7 @@ R_API RIODesc *r_core_file_open(RCore *r, const char *file, int flags, ut64 load
r_io_use_fd (r->io, fd->fd);
r_esil_setup (r->anal->esil, r->anal, 0, 0, false);
if (r_config_get_b (r->config, "cfg.debug")) {
bool swstep = true;
if (r->dbg->current && r->dbg->current->plugin.canstep) {

View File

@ -2205,15 +2205,21 @@ static void cmd_syscall_do(RCore *core, st64 n, ut64 addr) {
static inline REsil *esil_new_setup(RCore *core) {
int stacksize = r_config_get_i (core->config, "esil.stack.depth");
int iotrap = r_config_get_i (core->config, "esil.iotrap");
bool iotrap = r_config_get_b (core->config, "esil.iotrap");
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
REsil *esil = r_esil_new (stacksize, iotrap, addrsize);
if (esil) {
int romem = r_config_get_i (core->config, "esil.romem");
int stats = r_config_get_i (core->config, "esil.stats");
esil->anal = core->anal;
r_io_bind (core->io, &(core->anal->iob));
bool romem = r_config_get_b (core->config, "esil.romem");
bool stats = r_config_get_b (core->config, "esil.stats");
bool nonull = r_config_get_b (core->config, "esil.nonull");
r_esil_setup (esil, core->anal, romem, stats, nonull);
esil->verbose = r_config_get_i (core->config, "esil.verbose");
esil->cmd = r_core_esil_cmd;
const char *et = r_config_get (core->config, "cmd.esil.trap");
esil->cmd_trap = R_STR_ISNOTEMPTY (et)? strdup (et): NULL;
}
return esil;
}
@ -2275,14 +2281,17 @@ static void core_anal_bytes(RCore *core, const ut8 *buf, int len, int nops, int
ut64 addr;
PJ *pj = NULL;
int totalsize = 0;
#if 0
#if 1
REsil *esil = r_esil_new (256, 0, 0);
r_esil_setup (esil, core->anal, false, false, false);
esil->user = &ec;
esil->user = &core;
esil->cb.mem_read = mr;
esil->cb.mem_write = mw;
#else
REsil *esil = NULL;
REsil *esil = core->anal->esil;
//esil->user = &ec;
esil->cb.mem_read = mr;
esil->cb.mem_write = mw;
#endif
// Variables required for setting up ESIL to REIL conversion
@ -2542,21 +2551,14 @@ static void core_anal_bytes(RCore *core, const ut8 *buf, int len, int nops, int
pj_end (pj);
} else if (fmt == 'r') {
if (R_STR_ISNOTEMPTY (esilstr)) {
if (core->anal->esil) {
if (use_color) {
r_cons_printf ("%s0x%" PFMT64x Color_RESET " %s\n", color, core->offset + idx, esilstr);
} else {
r_cons_printf ("0x%" PFMT64x " %s\n", core->offset + idx, esilstr);
}
esil = core->anal->esil;
r_esil_parse (esil, esilstr);
r_esil_dumpstack (esil);
r_esil_stack_free (esil);
esil = NULL;
if (use_color) {
r_cons_printf ("%s0x%" PFMT64x Color_RESET " %s\n", color, core->offset + idx, esilstr);
} else {
R_LOG_ERROR ("ESIL is not initialized. Run `aei`");
break;
r_cons_printf ("0x%" PFMT64x " %s\n", core->offset + idx, esilstr);
}
r_esil_parse (core->anal->esil, esilstr);
r_esil_dumpstack (core->anal->esil);
r_esil_stack_free (core->anal->esil);
} else {
// ignored/skipped eprintf ("No esil for '%s'\n", op.mnemonic);
}
@ -5907,50 +5909,6 @@ void cmd_anal_reg(RCore *core, const char *str) {
}
}
static ut64 initializeEsil(RCore *core) {
int exectrap = r_config_get_i (core->config, "esil.exectrap");
REsil *esil = esil_new_setup (core);
if (esil) {
r_esil_free (core->anal->esil);
core->anal->esil = esil;
} else {
return UT64_MAX;
}
ut64 addr;
esil->cmd = r_core_esil_cmd;
{
const char *cmd_esil_step = r_config_get (core->config, "cmd.esil.step");
if (cmd_esil_step && *cmd_esil_step) {
esil->cmd_step = strdup (cmd_esil_step);
}
const char *cmd_esil_step_out = r_config_get (core->config, "cmd.esil.stepout");
if (cmd_esil_step_out && *cmd_esil_step_out) {
esil->cmd_step_out = strdup (cmd_esil_step_out);
}
{
const char *s = r_config_get (core->config, "cmd.esil.intr");
if (s) {
char *my = strdup (s);
if (my) {
r_config_set (core->config, "cmd.esil.intr", my);
free (my);
}
}
}
}
esil->exectrap = exectrap;
const RList *entries = r_bin_get_entries (core->bin);
if (entries && !r_list_empty (entries)) {
RBinAddr *entry = (RBinAddr *)r_list_get_n (entries, 0);
RBinInfo *info = r_bin_get_info (core->bin);
addr = info->has_va? entry->vaddr: entry->paddr;
} else {
addr = core->offset;
}
// set memory read only
return addr;
}
R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr, ut64 *prev_addr, bool stepOver) {
#define return_tail(x) { tail_return_value = x; goto tail_return; }
int tail_return_value = 0;
@ -5958,13 +5916,13 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
ut8 code[32];
RAnalOp op = {0};
REsil *esil = core->anal->esil;
// esil->trap = 0;
const char *_pcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
if (R_STR_ISEMPTY (_pcname)) {
R_LOG_ERROR ("Cannot find =PC in current reg profile");
return 0;
}
char *pcname = strdup (_pcname);
ut64 addr = r_reg_getv (core->anal->reg, pcname);
const bool r2wars = r_config_get_b (core->config, "cfg.r2wars");
const bool breakoninvalid = r_config_get_b (core->config, "esil.breakoninvalid");
const int esiltimeout = r_config_get_i (core->config, "esil.timeout");
@ -5974,13 +5932,27 @@ 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);
ut64 addr = -1;
ut64 oaddr = -1;
int minopsz = r_arch_info (core->anal->arch, R_ARCH_INFO_MIN_OP_SIZE);
ut64 naddr = addr + minopsz;
bool notfirst = false;
for (; true; r_anal_op_fini (&op)) {
esil->trap = 0;
oaddr = addr;
addr = r_reg_getv (core->anal->reg, "PC");
if (notfirst && addr == oaddr) {
r_reg_setv (core->anal->reg, "PC", naddr);
addr = naddr;
} else {
notfirst = true;
}
R_LOG_DEBUG ("esil step at 0x%08"PFMT64x, addr);
if (r_cons_is_breaked ()) {
R_LOG_INFO ("[+] ESIL emulation interrupted at 0x%08" PFMT64x, addr);
return_tail (0);
}
//Break if we have exceeded esil.timeout
// Break if we have exceeded esil.timeout
if (esiltimeout > 0) {
ut64 elapsedTime = r_time_now_mono () - startTime;
elapsedTime >>= 20;
@ -5989,34 +5961,17 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
return_tail (0);
}
}
if (!esil) {
addr = initializeEsil (core);
esil = core->anal->esil;
if (!esil) {
return_tail (0);
}
} else {
esil->trap = 0;
addr = r_reg_getv (core->anal->reg, pcname);
}
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;
R_LOG_INFO ("[ESIL] Trap, trying to execute on non-executable memory");
return_tail (1);
}
} else {
if (!r_io_is_valid_offset (core->io, addr, 0)) {
esil->trap = R_ANAL_TRAP_EXEC_ERR;
esil->trap_code = addr;
R_LOG_INFO ("[ESIL] Trap, trying to execute on non-executable memory");
return_tail (1);
}
const int perm = esil->exectrap ? R_PERM_X: 0;
if (!r_io_is_valid_offset (core->io, addr, perm)) {
esil->trap = R_ANAL_TRAP_EXEC_ERR;
esil->trap_code = addr;
R_LOG_INFO ("[ESIL] Trap, trying to execute on non-executable memory");
return_tail (1);
}
// eprintf ("addr %llx\n", addr);
r_asm_set_pc (core->rasm, addr);
// run esil pin command here
const char *pincmd = r_anal_pin_call (core->anal, addr);
@ -6024,14 +5979,14 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
r_core_cmd0 (core, pincmd);
ut64 pc = r_reg_getv (core->anal->reg, pcname);
if (addr != pc) {
eprintf ("pincmd fail\n");
R_LOG_ERROR ("pincmd fail");
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) {
if (esil->cmd && R_STR_ISNOTEMPTY (esil->cmd_trap)) {
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_UNALIGNED);
}
if (breakoninvalid) {
@ -6043,18 +5998,22 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
(void) r_io_read_at (core->io, addr, code, sizeof (code));
// TODO: sometimes this is dupe
ret = r_anal_op (core->anal, &op, addr, code, sizeof (code), R_ARCH_OP_MASK_ESIL | R_ARCH_OP_MASK_HINT);
naddr = addr + op.size;
// 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) {
// eprintf ("esil trap\n");
if (esil->cmd && R_STR_ISNOTEMPTY (esil->cmd_trap)) {
esil->cmd (esil, esil->cmd_trap, addr, R_ANAL_TRAP_INVALID);
}
if (breakoninvalid) {
R_LOG_INFO ("Stopped execution in an invalid instruction (see e??esil.breakoninvalid)");
return_tail (0);
}
op.size = 1; // avoid inverted stepping
if (op.size < 1) {
op.size = 1; // avoid inverted stepping
}
}
if (stepOver) {
switch (op.type) {
@ -6074,7 +6033,6 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
r_reg_setv (core->anal->reg, pcname, op.addr + op.size);
r_reg_setv (core->dbg->reg, pcname, op.addr + op.size);
}
eprintf ("blaaa\n");
return_tail (1);
}
}
@ -6107,7 +6065,8 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
} else if (R_STR_ISNOTEMPTY (e)) {
r_esil_parse (esil, e);
if (esil->trap) {
R_LOG_WARN ("ESIL TRAP ON %s at 0x%08"PFMT64x, e,addr );
R_LOG_WARN ("ESIL TRAP %d/%d ON %s at 0x%08"PFMT64x,
esil->trap, esil->trap_code, e, addr);
if (r_config_get_b (core->config, "esil.exectrap")) {
R_LOG_INFO ("ESIL TRAP ignored");
esil->trap = false;
@ -6119,6 +6078,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
core->anal->cur->esil_post_loop (esil, &op);
}
#endif
// warn if esil stack is not empty
r_esil_stack_free (esil);
}
bool isNextFall = false;
@ -6137,7 +6097,7 @@ R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr,
// only support 1 slot for now
if (op.delay && !isNextFall) {
ut8 code2[32];
ut64 naddr = addr + op.size;
// ut64 naddr = addr + op.size;
RAnalOp op2 = {0};
// emulate only 1 instruction
r_esil_set_pc (esil, naddr);
@ -6225,12 +6185,14 @@ tail_return:
R_API bool r_core_esil_step_back(RCore *core) {
r_return_val_if_fail (core && core->anal, false);
#if 0
if (!core->anal->esil || !core->anal->esil->trace) {
R_LOG_INFO ("Run `aeim` to initialize the esil VM and enable e dbg.trace=true");
return false;
}
#endif
REsil *esil = core->anal->esil;
if (esil->trace->idx > 0) {
if (esil && esil->trace->idx > 0) {
r_esil_trace_restore (esil, esil->trace->idx - 1);
return true;
}
@ -6440,28 +6402,14 @@ static void cmd_esil_mem(RCore *core, const char *input) {
RFlagItem *fi;
char uri[32];
char nomalloc[256];
if (!esil) {
esil = esil_new_setup (core);
if (!esil) {
return;
}
r_esil_free (core->anal->esil);
core->anal->esil = esil;
{
const char *s = r_config_get (core->config, "cmd.esil.intr");
if (s) {
char *my = strdup (s);
if (my) {
r_config_set (core->config, "cmd.esil.intr", my);
free (my);
}
}
}
}
if (*input == '?') {
r_core_cmd_help (core, help_msg_aeim);
return;
}
if (r_config_get_b (core->config, "cfg.debug")) {
R_LOG_WARN ("When cfg.debug is set, I refuse to create a fake stack");
return;
}
if (input[0] == 'p') {
fi = r_flag_get (core->flags, "aeim.stack");
@ -6519,7 +6467,7 @@ static void cmd_esil_mem(RCore *core, const char *input) {
name = r_str_newf ("mem.0x%" PFMT64x "_0x%x", addr, size);
}
if (*input == '-') {
if (esil->stack_fd > 2) { //0, 1, 2 are reserved for stdio/stderr
if (esil->stack_fd > 2) { // 0, 1, 2 are reserved for stdio/stderr
r_io_fd_close (core->io, esil->stack_fd);
// no need to kill the maps, r_io_map_cleanup does that for us in the close
esil->stack_fd = 0;
@ -6577,37 +6525,6 @@ static void cmd_esil_mem(RCore *core, const char *input) {
r_core_seek (core, curoff, false);
}
#if 0
static ut64 opc = UT64_MAX;
static ut8 *regstate = NULL;
static void esil_init(RCore *core) {
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
int nonull = r_config_get_i (core->config, "esil.nonull");
opc = r_reg_getv (core->anal->reg, pc);
if (!opc || opc==UT64_MAX) {
opc = core->offset;
}
if (!core->anal->esil) {
core->anal->esil = esil_new_from_core (core);
if (!core->anal->esil) {
R_FREE (regstate);
return;
}
r_esil_setup (core->anal->esil, core->anal, 0, 0, nonull);
}
free (regstate);
regstate = r_reg_arena_peek (core->anal->reg);
}
static void esil_fini(RCore *core) {
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
r_reg_arena_poke (core->anal->reg, regstate);
r_reg_setv (core->anal->reg, pc, opc);
R_FREE (regstate);
}
#endif
typedef struct {
RList *regs;
RList *regread;
@ -6986,27 +6903,30 @@ static bool cmd_aea(RCore* core, int mode, ut64 addr, int length) {
static void cmd_aespc(RCore *core, ut64 addr, ut64 until_addr, int ninstr) {
REsil *esil = core->anal->esil;
int i, j = 0;
ut8 *buf;
RAnalOp aop = {0};
int ret , bsize = R_MAX (4096, core->blocksize);
const int mininstrsz = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
const int minopcode = R_MAX (1, mininstrsz);
const char *pc = r_reg_get_name (core->dbg->reg, R_REG_NAME_PC);
#if 0
// eprintf (" aesB %llx %llx %d\n", addr, until_addr, off); // 0x%08llx %d %s\n", aop.addr, ret, aop.mnemonic);
if (!esil) {
R_LOG_DEBUG ("cmd_espc: creating new esil instance");
core->anal->esil = esil = esil_new_setup (core);
esil = esil_new_setup (core);
if (!esil) {
return;
}
r_esil_free (core->anal->esil);
core->anal->esil = esil;
}
buf = malloc (bsize);
#endif
ut8 *buf = malloc (bsize);
if (!buf) {
R_LOG_ERROR ("Cannot allocate %d byte(s)", bsize);
return;
}
if (addr == -1) {
if (addr == UT64_MAX) {
addr = r_reg_getv (core->dbg->reg, pc);
}
ut64 cursp = r_reg_getv (core->dbg->reg, "SP");
@ -7223,9 +7143,13 @@ static bool regwrite_hook(REsil *esil, const char *name, ut64 *val) {
static void __anal_esil_function(RCore *core, ut64 addr) {
RListIter *iter;
RAnalBlock *bb;
#if 0
if (!core->anal->esil) {
r_core_cmd_call (core, "aei");
r_core_cmd_call (core, "aeim");
}
#endif
if (!sdb_const_get (core->sdb, "aeim.fd", 0)) {
r_core_cmd_call (core, "aeim"); // should be set by default imho
}
void *u = core->anal->esil->user;
core->anal->esil->user = core;
@ -7557,32 +7481,26 @@ static void cmd_anal_esil(RCore *core, const char *input, bool verbose) {
// 'aer' is an alias for 'ar'
cmd_anal_reg (core, input + 1);
break;
case '*':
case '*': // "aeq"
// XXX: this is wip, not working atm
if (core->anal->esil) {
r_cons_printf ("trap: %d\n", core->anal->esil->trap);
r_cons_printf ("trap-code: %d\n", core->anal->esil->trap_code);
} else {
R_LOG_WARN ("esil vm is not initialized. Please run `aei`");
}
r_cons_printf ("trap: %d\n", core->anal->esil->trap);
r_cons_printf ("trap-code: %d\n", core->anal->esil->trap_code);
break;
case ' ':
case 'q':
//r_esil_eval (core->anal, input + 1);
if (!esil) {
core->anal->esil = esil = esil_new_setup (core);
if (!esil) {
return;
}
}
case 'q': // "aeq"
r_esil_set_pc (esil, core->offset);
r_esil_parse (esil, input + 1);
r_esil_parse (esil, r_str_trim_head_ro (input + 1));
if (verbose && *input != 'q') {
r_esil_dumpstack (esil);
}
r_esil_stack_free (esil);
break;
case 's': // "aes" "aeso" "aesu" "aesue"
#if 0
r_core_cmd0 (core, "ae `aoe@r:PC`");
r_core_cmd0 (core, ".ar*");
break;
#endif
// aes -> single step
// aesb -> single step back
// aeso -> single step over
@ -7852,20 +7770,14 @@ static void cmd_anal_esil(RCore *core, const char *input, bool verbose) {
cmd_esil_mem (core, "?");
break;
case '-':
if (esil) {
sdb_reset (esil->stats);
}
r_esil_free (esil);
core->anal->esil = NULL;
r_esil_reset (esil);
break;
case 0: // "aei"
r_esil_free (esil);
esil = core->anal->esil = esil_new_setup (core);
if (!esil) {
return;
}
// reinitialize
{
esil = esil_new_setup (core);
if (esil) {
r_esil_free (core->anal->esil);
core->anal->esil = esil;
r_esil_reset (esil);
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
if (pc && r_reg_getv (core->anal->reg, pc) == 0LL) {
reg_name_roll_set (core, "PC", core->offset);
@ -7979,10 +7891,12 @@ static void cmd_anal_esil(RCore *core, const char *input, bool verbose) {
case 's': // "aets"
switch (input[2]) {
case '+': // "aets+"
#if 0
if (!esil) {
R_LOG_ERROR ("ESIL is not initialized. Use `aeim` first");
break;
}
#endif
if (esil->trace) {
R_LOG_INFO ("ESIL trace already started");
break;
@ -12667,6 +12581,7 @@ static int cmd_anal_all(RCore *core, const char *input) {
if (input[2] == '?') {
r_core_cmd_help_match (core, help_msg_aae, "aaef", true);
} else {
r_core_cmd0 (core, "aeim");
RListIter *it;
RAnalFunction *fcn;
ut64 cur_seek = core->offset;
@ -12694,6 +12609,7 @@ static int cmd_anal_all(RCore *core, const char *input) {
*addr = 0;
addr = (char *)r_str_trim_head_ro (addr + 1);
}
r_core_cmd0 (core, "aeim");
r_core_anal_esil (core, len, addr);
free (arg);
} else {

View File

@ -353,6 +353,7 @@ static RCoreHelpMessage help_msg_dr = {
"dr", " <register>=<val>", "set register value",
"dr.", " >$snapshot", "capture current register values in r2 alias file",
"dr,", " [table-query]", "enumerate registers in table format",
"dr0", "", "zero-fill the register arena, reset their state",
"dr8", "[1|2|4|8] [type]", "display hexdump of gpr arena (WIP)",
"dr=", "", "show registers in columns",
"dr?", "<register>", "show value of given register",

View File

@ -4964,6 +4964,7 @@ static void ds_print_esil_anal_init(RDisasmState *ds) {
if (!pc) {
return;
}
r_esil_setup (core->anal->esil, core->anal, 0, 0, 1);
ds->esil_old_pc = r_reg_getv (core->anal->reg, pc);
if (!ds->esil_old_pc || ds->esil_old_pc == UT64_MAX) {
ds->esil_old_pc = core->offset;
@ -4972,17 +4973,6 @@ static void ds_print_esil_anal_init(RDisasmState *ds) {
// XXX. stackptr not computed without asm.emu, when its not required
return;
}
if (!core->anal->esil) {
int iotrap = r_config_get_i (core->config, "esil.iotrap");
int esd = r_config_get_i (core->config, "esil.stack.depth");
unsigned int addrsize = r_config_get_i (core->config, "esil.addr.size");
if (!(core->anal->esil = r_esil_new (esd, iotrap, addrsize))) {
R_FREE (ds->esil_regstate);
return;
}
r_esil_setup (core->anal->esil, core->anal, 0, 0, 1);
}
core->anal->esil->user = ds;
free (ds->esil_regstate);
R_FREE (core->anal->last_disasm_reg);
@ -7344,6 +7334,7 @@ static bool read_ahead(RIO *io, ut8 **buf, size_t *buf_sz, ut64 address, size_t
}
R_API int r_core_disasm_pde(RCore *core, int nb_opcodes, int mode) {
// R2R db/cmd/cmd_pde
if (nb_opcodes < 1) {
return 0;
}
@ -7360,14 +7351,8 @@ R_API int r_core_disasm_pde(RCore *core, int nb_opcodes, int mode) {
}
pj_a (pj);
}
if (!core->anal->esil) {
r_core_cmd_call (core, "aei");
if (!r_config_get_b (core->config, "cfg.debug")) {
r_core_cmd_call (core, "aeim");
}
}
// R2_590 - maybe here r_core_cmd_call (core, "aeim");
REsil *esil = core->anal->esil;
r_reg_arena_push (reg);
RConfigHold *chold = r_config_hold_new (core->config);
r_config_hold (chold, "io.cache", "asm.lines", NULL);
r_config_set_b (core->config, "io.cache", true);
@ -7381,7 +7366,19 @@ R_API int r_core_disasm_pde(RCore *core, int nb_opcodes, int mode) {
size_t buf_sz = 0x100, block_sz = 0, block_instr = 0;
ut64 block_start = r_reg_get_value (reg, pc);
size_t i = 0;
const ut64 op_addr = r_reg_get_value (reg, pc);
ut8 *buf = malloc (buf_sz);
if (op_addr == 0) {
const RList *entries = r_bin_get_entries (core->bin);
if (entries && !r_list_empty (entries)) {
RBinAddr *entry = (RBinAddr *)r_list_get_n (entries, 0);
RBinInfo *info = r_bin_get_info (core->bin);
block_start = info->has_va? entry->vaddr: entry->paddr;
r_reg_set_value (reg, pc, block_start);
r_core_cmd0 (core, ".dr*");
}
}
r_reg_arena_push (reg);
if (!buf) {
goto leave;
}

View File

@ -113,6 +113,9 @@ R_API REsil *r_esil_new(int stacksize, int iotrap, unsigned int addrsize) {
r_esil_plugins_init (esil);
esil->addrmask = genmask (addrsize - 1);
esil->trace = r_esil_trace_new (esil);
int stats = 1;
r_esil_stats (esil, stats);
r_esil_setup_ops (esil);
return esil;
}
@ -149,22 +152,11 @@ R_API void r_esil_del_op(REsil *esil, const char *op) {
static bool r_esil_fire_trap(REsil *esil, int trap_type, int trap_code) {
r_return_val_if_fail (esil, false);
if (esil->cmd) {
if (esil->cmd && R_STR_ISNOTEMPTY (esil->cmd_trap)) {
if (esil->cmd (esil, esil->cmd_trap, trap_type, trap_code)) {
return true;
}
}
#if 0
/// XXX
if (esil->anal) {
RAnalPlugin *ap = esil->anal->cur;
if (ap && ap->esil_trap) {
if (ap->esil_trap (esil, trap_type, trap_code)) {
return true;
}
}
}
#endif
#if 0
REsilTrapCB icb;
icb = (REsilTrapCB)sdb_ptr_get (esil->traps, i, 0);
@ -190,7 +182,7 @@ R_API void r_esil_free(REsil *esil) {
RArchPluginEsilCallback esil_cb = R_UNWRAP3 (as, plugin, esilcb);
if (esil_cb) {
if (!esil_cb (as, R_ARCH_ESIL_FINI)) {
R_LOG_WARN ("Failed to properly cleanup esil for arch plugin");
R_LOG_DEBUG ("Failed to properly cleanup esil for arch plugin");
}
}
}
@ -3989,7 +3981,7 @@ R_API void r_esil_setup_ops(REsil *esil) {
}
/* register callbacks using this anal module. */
R_API bool r_esil_setup(REsil *esil, RAnal *anal, int romem, int stats, int nonull) {
R_API bool r_esil_setup(REsil *esil, RAnal *anal, bool romem, bool stats, bool nonull) {
r_return_val_if_fail (esil, false);
//esil->debug = 0;
esil->anal = anal;
@ -4026,9 +4018,10 @@ R_API bool r_esil_setup(REsil *esil, RAnal *anal, int romem, int stats, int nonu
}
}
return true;
#if 0
// ESIL from arch
return (anal->cur && anal->cur->esil_init)
? anal->cur->esil_init (esil): true;
#endif
}
R_API void r_esil_reset(REsil *esil) {
esil->trap = 0;
r_return_if_fail (esil);
sdb_reset (esil->stats);
}

View File

@ -38,7 +38,7 @@ static bool hook_NOP_mem_write(REsil *esil, ut64 addr, const ut8 *buf, int len)
return true;
}
R_API void r_esil_mem_ro(REsil *esil, int mem_readonly) {
R_API void r_esil_mem_ro(REsil *esil, bool mem_readonly) {
if (mem_readonly) {
esil->cb.hook_mem_write = hook_NOP_mem_write;
} else {
@ -46,7 +46,7 @@ R_API void r_esil_mem_ro(REsil *esil, int mem_readonly) {
}
}
R_API void r_esil_stats(REsil *esil, int enable) {
R_API void r_esil_stats(REsil *esil, bool enable) {
if (enable) {
if (esil->stats) {
sdb_reset (esil->stats);

View File

@ -757,7 +757,7 @@ R_API RList *r_bin_file_get_trycatch(RBinFile *bf);
R_API RList *r_bin_get_symbols(RBin *bin);
R_API RVecRBinSymbol *r_bin_get_symbols_vec(RBin *bin);
R_API RList *r_bin_reset_strings(RBin *bin);
R_API int r_bin_is_string(RBin *bin, ut64 va);
R_API bool r_bin_is_string(RBin *bin, ut64 va);
R_API int r_bin_is_big_endian(RBin *bin);
R_API int r_bin_is_static(RBin *bin);
R_API ut64 r_bin_get_vaddr(RBin *bin, ut64 paddr, ut64 vaddr);

View File

@ -274,8 +274,9 @@ typedef struct r_esil_active_plugin_t {
} REsilActivePlugin;
R_API REsil *r_esil_new(int stacksize, int iotrap, unsigned int addrsize);
R_API void r_esil_reset(REsil *esil);
R_API void r_esil_set_pc(REsil *esil, ut64 addr);
R_API bool r_esil_setup(REsil *esil, struct r_anal_t *anal, int romem, int stats, int nonull);
R_API bool r_esil_setup(REsil *esil, struct r_anal_t *anal, bool romem, bool stats, bool nonull);
R_API void r_esil_setup_macros(REsil *esil);
R_API void r_esil_setup_ops(REsil *esil);
R_API void r_esil_free(REsil *esil);
@ -330,8 +331,8 @@ R_API bool r_esil_plugin_remove(REsil *esil, REsilPlugin *plugin);
R_API bool r_esil_plugin_activate(REsil *esil, const char *name);
R_API void r_esil_plugin_deactivate(REsil *esil, const char *name);
R_API void r_esil_mem_ro(REsil *esil, int mem_readonly);
R_API void r_esil_stats(REsil *esil, int enable);
R_API void r_esil_mem_ro(REsil *esil, bool mem_readonly);
R_API void r_esil_stats(REsil *esil, bool enable);
/* trace */
R_API REsilTrace *r_esil_trace_new(REsil *esil);

View File

@ -4,7 +4,6 @@ const ioqjsPlugin = {
desc: "Simple io plugin in javascript",
license: "MIT",
check: function (uri, perm) {
console.log("CHECK.JS");
return uri.startsWith("qjs://");
},
open: function (uri, perm) {

View File

@ -940,6 +940,8 @@ pd 9 @ main
EOF
EXPECT=<<EOF
;-- main:
;-- pc:
;-- r15:
0x0000050c 80b5 push {r7, lr}
0x0000050e 00af add r7, sp, 0
0x00000510 034b ldr r3, [0x00000520] ; [0x520:4]=94

View File

@ -331,6 +331,7 @@ RUN
NAME=ppc-update-suffix-esil
FILE=bins/elf/a6ppc.out
CMDS=<<EOF
aeim
40ds
dr?r3
dr?r4
@ -339,9 +340,9 @@ dr?r3
dr?r4
EOF
EXPECT=<<EOF
0xffffffbf
0x00177fbf
0x10000107
0xffffffc1
0x00177fc1
0x1000010a
EOF
RUN

View File

@ -452,6 +452,7 @@ CMDS=<<EOF
e asm.flags=false
e asm.comments=false
e anal.vars.stackname = true
aeim
wx 80b483b000af78600b467b8013467b707b78002b03d07a887b689a6103e07b881a047b689a6100bf0c37bd465df8047b7047
af
aaef

10
test/db/esil/cmd Normal file
View File

@ -0,0 +1,10 @@
NAME=cmd.esil.trap
FILE=-
CMDS=<<EOF
e cmd.esil.trap=?e hello world
ae 2,1,TRAP
EOF
EXPECT=<<EOF
hello world 1 2
EOF
RUN

View File

@ -1748,6 +1748,7 @@ CMDS=<<EOF
e io.va=true
e asm.arch=mips
e asm.bits=32
aeim
ar > /dev/null
ar v0=8
ar a0=0x00400b48