Add new command 'aesb' step back for ESIL (#8052)

* Add new command aets
* Add new command aesb, step back for ESIL
* Add session key
This commit is contained in:
Ren Kimura 2017-07-29 19:59:41 +09:00 committed by Anton Kochkov
parent e7a2f2cc8c
commit 0e4aa83d16
9 changed files with 178 additions and 13 deletions

View File

@ -32,7 +32,7 @@ OBJLIBS+=cond.o value.o cc.o diff.o types.o fcnstore.o
OBJLIBS+=hint.o anal.o data.o xrefs.o esil.o sign.o
OBJLIBS+=anal_ex.o switch.o state.o cycles.o
OBJLIBS+=esil_stats.o esil_trace.o flirt.o labels.o
OBJLIBS+=esil2reil.o pin.o
OBJLIBS+=esil2reil.o pin.o session.o
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/xtensa-modules.o
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/xtensa-isa.o
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/elf32-xtensa.o

View File

@ -89,6 +89,7 @@ R_API RAnalEsil *r_anal_esil_new(int stacksize, int iotrap) {
esil->ops = sdb_new0 ();
esil->iotrap = iotrap;
esil->interrupts = sdb_new0 ();
esil->sessions = r_list_newf (r_anal_esil_session_free);
return esil;
}
@ -204,6 +205,7 @@ R_API void r_anal_esil_free(RAnalEsil *esil) {
if (esil->anal && esil->anal->cur && esil->anal->cur->esil_fini) {
esil->anal->cur->esil_fini (esil);
}
r_list_free (esil->sessions);
free (esil->cmd_intr);
free (esil->cmd_trap);
free (esil->cmd_mdev);

View File

@ -70,6 +70,7 @@ files=[
'pin.c',
'ref.c',
'reflines.c',
'session.c',
'sign.c',
'state.c',
'switch.c',

79
libr/anal/session.c Normal file
View File

@ -0,0 +1,79 @@
/* radare - LGPL - Copyright 2017 - rkx1209 */
#include <r_anal.h>
#include <r_types.h>
#include <r_util.h>
#include <r_bind.h>
R_API void r_anal_esil_session_free(RAnalEsilSession *session) {
free (session->data);
free (session);
}
R_API void r_anal_esil_session_list(RAnalEsil *esil) {
if (!esil || !esil->sessions) {
return;
}
RListIter *iter;
RAnalEsilSession *session;
ut64 idx = 0;
r_list_foreach (esil->sessions, iter, session) {
esil->anal->cb_printf ("[%d] 0x%08"PFMT64x "\n", idx++, session->key);
}
}
R_API RAnalEsilSession *r_anal_esil_session_add(RAnalEsil *esil) {
if (!esil) {
return NULL;
}
RAnalEsilSession *session = R_NEW0 (RAnalEsilSession);
const char *name = r_reg_get_name (esil->anal->reg, R_REG_NAME_PC);
ut32 i;
if (!session) {
return NULL;
}
if (!esil->stack_addr || !esil->stack_size) {
R_FREE (session);
return NULL;
}
session->key = r_reg_getv (esil->anal->reg, name);
session->addr = esil->stack_addr;
session->size = esil->stack_size;
session->data = (ut8 *) R_NEWS0 (ut8 *, session->size);
if (!session->data) {
R_FREE (session);
return NULL;
}
/* Save current register */
for (i = 0; i < R_REG_TYPE_LAST; i++) {
session->reg[i] = r_list_tail (esil->anal->reg->regset[i].pool);
}
r_reg_arena_push (esil->anal->reg);
/* Save current memory dump */
esil->anal->iob.read_at (esil->anal->iob.io, session->addr, session->data, session->size);
r_list_append (esil->sessions, session);
return session;
}
R_API void r_anal_esil_session_set(RAnalEsil *esil, RAnalEsilSession *session) {
if (!esil || !session) {
return;
}
ut32 i;
RListIter *iter;
/* Restore registers */
for (i = 0; i < R_REG_TYPE_LAST; i++) {
iter = session->reg[i];
RRegArena *arena = iter->data;
if (esil->anal->reg->regset[i].arena->bytes) {
if (esil->anal->reg->regset[i].arena->size >= arena->size) {
memcpy (esil->anal->reg->regset[i].arena->bytes, arena->bytes, arena->size);
}
}
}
/* Restore memory dump */
esil->anal->iob.write_at (esil->anal->iob.io, session->addr, session->data, session->size);
}

View File

@ -212,7 +212,7 @@ static int stack_clean (RCore *core, ut64 addr, RAnalFunction *fcn) {
const char *esil = sdb_fmt (-1, "%d,%s,-=", offset, sp);
r_anal_esil_parse (core->anal->esil, esil);
r_anal_esil_stack_free (core->anal->esil);
r_core_esil_step (core, UT64_MAX, NULL);
r_core_esil_step (core, UT64_MAX, NULL, NULL);
ret = op->size;
}
r_anal_op_free (op);
@ -265,7 +265,7 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, true);
r_anal_esil_set_pc (core->anal->esil, addr);
} else {
r_core_esil_step (core, UT64_MAX, NULL);
r_core_esil_step (core, UT64_MAX, NULL, NULL);
r_anal_op_free (op);
r_core_cmd0 (core, ".ar*");
addr = r_reg_getv (core->anal->reg, pc);

View File

@ -6,8 +6,6 @@
/* hacky inclusion */
#include "anal_vt.c"
#define ESIL_STACK_NAME "esil.ram"
static const char *help_msg_a[] = {
"Usage:", "a", "[abdefFghoprxstc] [...]",
"aa", "[?]", "analyze all (fcns + bbs) (aa0 to avoid sub renaming)",
@ -92,7 +90,9 @@ static const char *help_msg_ae[] = {
"aep", "[?] [addr]", "manage esil pin hooks",
"aepc", " [addr]", "change esil PC to this address",
"aer", " [..]", "handle ESIL registers like 'ar' or 'dr' does",
"aets", "[?]", "ESIL Trace session",
"aes", "", "perform emulated debugger step",
"aesb", "", "step back",
"aeso", " ", "step over",
"aesu", " [addr]", "step until given address",
"aesue", " [esil]", "step until esil expression match",
@ -181,6 +181,13 @@ static const char *help_msg_aep[] = {
NULL
};
static const char *help_msg_aets[] = {
"Usage:", "aets ", " [...]",
"aets", "", "List all ESIL trace sessions",
"aets+", "", "Add ESIL trace session",
NULL
};
static const char *help_msg_af[] = {
"Usage:", "af", "",
"af", " ([name]) ([addr])", "analyze functions (start at addr or $$)",
@ -2662,7 +2669,7 @@ void cmd_anal_reg(RCore *core, const char *str) {
R_API bool r_core_esil_cmd(RAnalEsil *esil, const char *cmd, ut64 a1, ut64 a2);
R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr) {
R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr, ut64 *prev_addr) {
// Stepping
int ret;
ut8 code[256];
@ -2714,6 +2721,9 @@ repeat:
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_section_get_rwx (core->io, addr) & R_IO_EXEC)) {
esil->trap = R_ANAL_TRAP_EXEC_ERR;
@ -2853,6 +2863,30 @@ out_return_zero:
return 0;
}
R_API int r_core_esil_step_back(RCore *core) {
RAnalEsil *esil = core->anal->esil;
RListIter *tail;
const char *name = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
ut64 prev = 0;
ut64 end = r_reg_getv (core->anal->reg, name);
if (!esil || !(tail = r_list_tail (esil->sessions))) {
return 0;
}
RAnalEsilSession *before = (RAnalEsilSession *) tail->data;
//eprintf ("Execute until 0x%08"PFMT64x"\n", end);
r_anal_esil_session_set (esil, before);
r_core_esil_step (core, end, NULL, &prev);
//eprintf ("Before 0x%08"PFMT64x"\n", prev);
r_anal_esil_session_set (esil, before);
r_core_esil_step (core, prev, NULL, NULL);
return 1;
}
static void cmd_address_info(RCore *core, const char *addrstr, int fmt) {
ut64 addr, type;
if (!addrstr || !*addrstr) {
@ -2967,6 +3001,7 @@ static void initialize_stack (RCore *core, ut64 addr, ut64 size) {
}
static void cmd_esil_mem(RCore *core, const char *input) {
RAnalEsil *esil = core->anal->esil;
ut64 curoff = core->offset;
const char *patt = "";
ut64 addr = 0x100000;
@ -2993,6 +3028,10 @@ static void cmd_esil_mem(RCore *core, const char *input) {
} else {
cmd_esil_mem (core, "");
}
if (esil) {
esil->stack_addr = addr;
esil->stack_size = size;
}
initialize_stack (core, addr, size);
return;
}
@ -3089,6 +3128,10 @@ static void cmd_esil_mem(RCore *core, const char *input) {
r_core_cmdf (core, "S 0x%"PFMT64x" 0x%"PFMT64x" %d %d "
ESIL_STACK_NAME, addr, addr, size, size);
}
if (esil) {
esil->stack_addr = addr;
esil->stack_size = size;
}
initialize_stack (core, addr, size);
// r_core_cmdf (core, "wopD 0x%"PFMT64x" @ 0x%"PFMT64x, size, addr);
r_core_seek (core, curoff, 0);
@ -3465,6 +3508,7 @@ static void cmd_anal_esil(RCore *core, const char *input) {
case 's': // "aes"
// "aes" "aeso" "aesu" "aesue"
// aes -> single step
// aesb -> single step back
// aeso -> single step over
// aesu -> until address
// aesue -> until esil expression
@ -3480,18 +3524,24 @@ static void cmd_anal_esil(RCore *core, const char *input) {
if (!op) {
break;
}
r_core_esil_step (core, UT64_MAX, NULL);
r_core_esil_step (core, UT64_MAX, NULL, NULL);
r_debug_reg_set (core->dbg, "PC", pc + op->size);
r_anal_esil_set_pc (esil, pc + op->size);
r_core_cmd0 (core, ".ar*");
} break;
case 'b': // "aesb"
if (!r_core_esil_step_back (core)) {
eprintf ("cannnot step back\n");
}
r_core_cmd0 (core, ".ar*");
break;
case 'u': // "aesu"
if (input[2] == 'e') {
until_expr = input + 3;
} else {
until_addr = r_num_math (core->num, input + 2);
}
r_core_esil_step (core, until_addr, until_expr);
r_core_esil_step (core, until_addr, until_expr, NULL);
r_core_cmd0 (core, ".ar*");
break;
case 'o': // "aeso"
@ -3501,12 +3551,12 @@ static void cmd_anal_esil(RCore *core, const char *input) {
if (op && op->type == R_ANAL_OP_TYPE_CALL) {
until_addr = op->addr + op->size;
}
r_core_esil_step (core, until_addr, until_expr);
r_core_esil_step (core, until_addr, until_expr, NULL);
r_anal_op_free (op);
r_core_cmd0 (core, ".ar*");
break;
default:
r_core_esil_step (core, until_addr, until_expr);
r_core_esil_step (core, until_addr, until_expr, NULL);
r_core_cmd0 (core, ".ar*");
break;
}
@ -3531,7 +3581,7 @@ static void cmd_anal_esil(RCore *core, const char *input) {
eprintf ("trap at 0x%08" PFMT64x "\n", addr);
break;
}
ret = r_core_esil_step (core, UT64_MAX, NULL);
ret = r_core_esil_step (core, UT64_MAX, NULL, NULL);
r_anal_op_free (op);
if (core->anal->esil->trap || core->anal->esil->trap_code) {
break;
@ -3556,7 +3606,7 @@ static void cmd_anal_esil(RCore *core, const char *input) {
else if (input[1] == 'u')
until_addr = r_num_math (core->num, input + 2);
else until_expr = "0";
r_core_esil_step (core, until_addr, until_expr);
r_core_esil_step (core, until_addr, until_expr, NULL);
}
break;
case 'i': // "aei"
@ -3678,6 +3728,19 @@ static void cmd_anal_esil(RCore *core, const char *input) {
r_anal_esil_free (esil);
break;
}
case 's': // "aets"
switch (input[2]) {
case 0:
r_anal_esil_session_list (esil);
break;
case '+':
r_anal_esil_session_add (esil);
break;
default:
r_core_cmd_help (core, help_msg_aets);
break;
}
break;
default:
eprintf ("Unknown command. Use `aetr`.\n");
break;

View File

@ -1,4 +1,5 @@
/* radare - LGPL - Copyright 2017 - rkx1209 */
#include <r_debug.h>
R_API void r_debug_session_free(RDebugSession *session) {

View File

@ -965,8 +965,17 @@ typedef struct r_anal_reil {
// must be a char
#define ESIL_INTERNAL_PREFIX '$'
#define ESIL_STACK_NAME "esil.ram"
#define ESIL struct r_anal_esil_t
typedef struct r_anal_esil_session_t {
ut64 key;
ut64 addr;
ut64 size;
ut8 *data;
RListIter *reg[R_REG_TYPE_LAST];
} RAnalEsilSession;
typedef struct r_anal_esil_callbacks_t {
void *user;
/* callbacks */
@ -998,6 +1007,8 @@ typedef struct r_anal_esil_t {
int verbose;
ut64 flags;
ut64 address;
ut64 stack_addr;
ut32 stack_size;
int delay; // mapped to $ds in ESIL
ut64 jump_target; // mapped to $jt in ESIL
int jump_target_set; // mapped to $js in ESIL
@ -1024,6 +1035,7 @@ typedef struct r_anal_esil_t {
char *mdev_range; // string containing the r_str_range to match for read/write accesses
bool (*cmd)(ESIL *esil, const char *name, ut64 a0, ut64 a1);
void *user;
RList *sessions; // <RAnalEsilSession*>
} RAnalEsil;
#undef ESIL
@ -1267,6 +1279,12 @@ R_API int r_anal_esil_fire_interrupt (RAnalEsil *esil, int interrupt);
R_API void r_anal_esil_mem_ro(RAnalEsil *esil, int mem_readonly);
R_API void r_anal_esil_stats(RAnalEsil *esil, int enable);
/* session */
R_API void r_anal_esil_session_list(RAnalEsil *esil);
R_API RAnalEsilSession *r_anal_esil_session_add(RAnalEsil *esil);
R_API void r_anal_esil_session_set(RAnalEsil *esil, RAnalEsilSession *session);
R_API void r_anal_esil_session_free(RAnalEsilSession *session);
/* pin */
R_API void r_anal_pin_init(RAnal *a);
R_API void r_anal_pin_fini(RAnal *a);

View File

@ -370,7 +370,8 @@ R_API int r_core_anal_search_xrefs(RCore *core, ut64 from, ut64 to, int rad);
R_API int r_core_anal_data (RCore *core, ut64 addr, int count, int depth, int wordsize);
R_API void r_core_anal_coderefs(RCore *core, ut64 addr, int gv);
R_API int r_core_anal_refs(RCore *core, const char *input);
R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr);
R_API int r_core_esil_step(RCore *core, ut64 until_addr, const char *until_expr, ut64 *prev_addr);
R_API int r_core_esil_step_back(RCore *core);
R_API int r_core_anal_bb(RCore *core, RAnalFunction *fcn, ut64 at, int head);
R_API ut64 r_core_anal_get_bbaddr(RCore *core, ut64 addr);
R_API int r_core_anal_bb_seek(RCore *core, ut64 addr);