Fixes for thumb/arm string references and endian refptr

This commit is contained in:
pancake 2016-06-10 19:09:13 +02:00
parent 3081b3b5d6
commit b829244c19
4 changed files with 96 additions and 73 deletions

View File

@ -498,11 +498,12 @@ static int analop64_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int l
return 0;
}
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, bool thumb) {
bool hascond = false;
int i;
char str[32][32];
int msr_flags;
int pcdelta = (thumb ? 4 : 8 ) - op->size;
r_strbuf_init (&op->esil);
r_strbuf_set (&op->esil, "");
switch (insn->detail->arm.cc) {
@ -678,22 +679,18 @@ r4,r5,r6,3,sp,[*],12,sp,+=
case ARM_INS_SADD16:
case ARM_INS_SADD8:
case ARM_INS_ADD:
if (strcmp (ARG(2), "")) {
if (!strcmp (ARG(2), "")) {
if (!strcmp (ARG(1), "pc")) {
// that 2>>2<< is for & 0xfffffffc
// (the address of the current instruction + 4) AND &FFFFFFFC.
// to clear 2 lower bits
int delta = 4;
if (a->bits == 32) {
delta = 8;
int delta = thumb ? 4 : 8;
if (thumb) {
delta -= op->size;
if (!(addr & 2))
delta += 2;
}
r_strbuf_appendf (&op->esil,
"%d,%"PFMT64d",+,%s,+=", delta, op->addr, ARG(0));
//"2,2,4,%s,+,>>,<<,%s,+=", ARG(1), ARG(0));
//"2,2,4,%"PFMT64d",+,>>,<<,%s,+=", op->addr, ARG(0));
//"4,%s,+,0xfffffffc,&,%s,+=", ARG(1), ARG(0));
"%d,2,2,%s,>>,<<,+,%s,+=",
delta, ARG(1), ARG(0));
} else {
// THUMB
if (!strcmp (ARG(0), ARG(1))) {
r_strbuf_appendf (&op->esil, "2,%s,*=", ARG(0));
} else {
@ -701,12 +698,17 @@ r4,r5,r6,3,sp,[*],12,sp,+=
}
}
} else {
if (!strcmp (ARG(0),ARG(1))) {
r_strbuf_appendf (&op->esil, "%s,%s,+=", ARG(2), ARG(0));
} else if (!strcmp (ARG(2),"0")) {
r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), ARG(0));
if (!strcmp (ARG(1), "pc")) {
int delta = 4; //thumb ? 4 : 8;
r_strbuf_appendf (&op->esil, "%d,%s,+,%s,+,%s,=", delta, ARG(2), ARG(1), ARG(0));
} else {
r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0));
if (!strcmp (ARG(0), ARG(1))) {
r_strbuf_appendf (&op->esil, "%s,%s,+=", ARG(2), ARG(0));
} else if (!strcmp (ARG(2),"0")) {
r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), ARG(0));
} else {
r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0));
}
}
}
break;
@ -743,46 +745,31 @@ r4,r5,r6,3,sp,[*],12,sp,+=
case ARM_INS_LDREXH:
case ARM_INS_LDR:
addr &= ~3LL;
if (MEMDISP(1)<0) {
if (MEMDISP(1) < 0) {
if (REGBASE(1) == ARM_REG_PC) {
op->refptr = 4;
op->ptr = addr + op->size - MEMDISP(1);
op->ptr = addr + pcdelta - MEMDISP(1);
r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=",
MEMBASE(1), MEMDISP(1), REG(0));
"$$", MEMDISP(1), REG(0));
} else {
r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=",
MEMBASE(1), +MEMDISP(1), REG(0));
MEMBASE(1), MEMDISP(1), REG(0));
}
} else {
if (REGBASE(1) == ARM_REG_PC) {
int pcdelta = 8;
switch (a->bits) {
case 16:
pcdelta = 4; // op->size * 2;
op->refptr = 4;
op->ptr = addr + pcdelta + MEMDISP(1);
pcdelta = 0; // not needed for esil
break;
case 32:
pcdelta = 4;
if (ISREG(1)) {
// cant resolve register values magically
} else {
op->ptr = addr + 8 + MEMDISP(1);
op->refptr = 4;
}
break;
}
const char *pc = "$$"; //MEMBASE(1);
op->refptr = 4;
op->ptr = addr + pcdelta + MEMDISP(1);
if (ISMEM(1) && LSHIFT2(1)) {
r_strbuf_appendf (&op->esil, "%d,%s,+,%d,%s,<<,+,[4],%s,=",
pcdelta, MEMBASE(1), LSHIFT2(1), MEMINDEX(1), REG(0));
r_strbuf_appendf (&op->esil, "2,2,%d,%s,+,>>,<<,%d,%s,<<,+,[4],%s,=",
pcdelta, pc, LSHIFT2(1), MEMINDEX(1), REG(0));
} else {
if (ISREG(1)) {
r_strbuf_appendf (&op->esil, "%d,%s,+,%s,+,[4],%s,=",
pcdelta, MEMBASE(1), MEMINDEX(1), REG(0));
r_strbuf_appendf (&op->esil, "2,2,%d,%s,+,>>,<<,%s,+,[4],%s,=",
pcdelta, pc, MEMINDEX(1), REG(0));
} else {
r_strbuf_appendf (&op->esil, "%d,%s,+,%d,+,[4],%s,=",
pcdelta, MEMBASE(1), MEMDISP(1), REG(0));
r_strbuf_appendf (&op->esil, "2,2,%d,%s,+,>>,<<,%d,+,[4],%s,=",
pcdelta, pc, MEMDISP(1), REG(0));
}
}
} else {
@ -799,7 +786,6 @@ r4,r5,r6,3,sp,[*],12,sp,+=
}
}
}
op->refptr = 4;
}
break;
case ARM_INS_MSR:
@ -1034,7 +1020,7 @@ static int cond_cs2r2(int cc) {
return cc;
}
static void anop32 (RAnalOp *op, cs_insn *insn) {
static void anop32 (RAnalOp *op, cs_insn *insn, bool thumb) {
const ut64 addr = op->addr;
int i;
op->cond = cond_cs2r2 (insn->detail->arm.cc);
@ -1098,8 +1084,9 @@ jmp $$ + 4 + ( [delta] * 2 )
case ARM_INS_ADD:
op->type = R_ANAL_OP_TYPE_ADD;
if (REGID(1) == ARM_REG_PC) {
op->ptr = addr + 8 + IMM(2);
op->refptr = 0;
op->ptr = (addr & ~3) + (thumb ? 4 : 8) + IMM(2);
//if (addr & 2) { op->ptr += 2; }
op->refptr = 4;
}
break;
case ARM_INS_VMOV:
@ -1298,6 +1285,7 @@ static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
if (n<1) {
op->type = R_ANAL_OP_TYPE_ILL;
} else {
bool thumb = cs_insn_group (handle, insn, ARM_GRP_THUMB);
op->size = insn->size;
if (a->bits == 64) {
anop64 (op, insn);
@ -1305,9 +1293,9 @@ static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
analop64_esil (a, op, addr, buf, len, &handle, insn);
}
} else {
anop32 (op, insn);
anop32 (op, insn, thumb);
if (a->decode) {
analop_esil (a, op, addr, buf, len, &handle, insn);
analop_esil (a, op, addr, buf, len, &handle, insn, thumb);
}
}
cs_free (insn, n);

View File

@ -314,8 +314,9 @@ static int bin_strings(RCore *r, int mode, int va) {
r_list_foreach (list, iter, string) {
const char *section_name, *type_string;
ut64 paddr, vaddr, addr;
if (!string_filter (r, string->string))
if (!string_filter (r, string->string)) {
continue;
}
paddr = string->paddr;
vaddr = r_bin_get_vaddr (bin, paddr, string->vaddr);
addr = va ? vaddr : paddr;

View File

@ -640,8 +640,9 @@ static void ds_build_op_str(RDisasmState *ds) {
ds->opstr = strdup (ds->str);
core->parser->flagspace = ofs; // ???
} else {
if (!ds->opstr)
ds->opstr = strdup (asm_str?asm_str:"");
if (!ds->opstr) {
ds->opstr = strdup (asm_str? asm_str: "");
}
}
}
if (ds->use_esil) {
@ -649,11 +650,13 @@ static void ds_build_op_str(RDisasmState *ds) {
free (ds->opstr);
ds->opstr = strdup (R_STRBUF_SAFEGET (&ds->analop.esil));
} else {
char *p = malloc (strlen (ds->opstr)+6); /* What's up '\0' ? */
strcpy (p, "TODO,");
strcpy (p+5, ds->opstr);
free (ds->opstr);
ds->opstr = p;
char *p = malloc (strlen (ds->opstr) + 6); /* What's up '\0' ? */
if (p) {
strcpy (p, "TODO,");
strcpy (p + 5, ds->opstr);
free (ds->opstr);
ds->opstr = p;
}
}
}
free (asm_str);
@ -2241,15 +2244,20 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
}
if (p == UT64_MAX) {
/* do nothing */
} else if (((st64)p)>0) {
} else if (((st64)p) > 0) {
const char *kind;
char *msg = calloc(sizeof(char), len);
char *msg = calloc (sizeof (char), len);
RFlagItem *f, *f2;
r_io_read_at (core->io, p, (ut8*)msg, len-1);
r_io_read_at (core->io, p, (ut8*)msg, len - 1);
if (ds->analop.refptr) {
ut64 num = r_read_le64 (msg);
ut64 num;
if (core->print->big_endian) {
num = r_read_le64 (msg);
} else {
num = r_read_be64 (msg);
}
// TODO: make this more complete
switch (ds->analop.refptr) {
case 1: num &= UT8_MAX; break;
@ -2270,7 +2278,7 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
r_cons_printf (" ; 0x%"PFMT64x"%s%s", p, *flag?" ; ":"", flag);
} else {
f = NULL;
if (n==UT32_MAX || n==UT64_MAX) {
if (n == UT32_MAX || n == UT64_MAX) {
r_cons_printf (" ; [0x%"PFMT64x":%d]=-1", p, ds->analop.refptr);
} else if (n == n32 && (n32>-512 && n32 <512)) {
r_cons_printf (" ; [0x%"PFMT64x":%d]=%"PFMT64d, p, ds->analop.refptr, n);
@ -2319,19 +2327,19 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
DOALIGN();
if (*msg) {
r_cons_printf (" ; \"%s\" @ 0x%"PFMT64x, msg, p);
r_cons_printf (" ; \"%s\"", msg); // @ 0x%"PFMT64x, msg, p);
} else {
r_cons_printf (" ; %s", f->name);
}
} else {
if (p==UT64_MAX || p==UT32_MAX) {
if (p == UT64_MAX || p == UT32_MAX) {
DOALIGN();
r_cons_printf (" ; -1", p);
} else if (((char)p>0) && p>='!' && p<='~') {
char ch = p;
DOALIGN();
r_cons_printf (" ; '%c'", ch);
} else if (p>10) {
} else if (p > 10) {
if ((st64)p<0) {
// resolve local var if possible
RAnalVar *v = r_anal_var_get (core->anal, ds->at, 'v', 1, (int)p);
@ -2353,13 +2361,14 @@ static void ds_print_ptr(RDisasmState *ds, int len, int idx) {
}
}
}
kind = r_anal_data_kind (core->anal, p, (const ut8*)msg, len-1);
kind = r_anal_data_kind (core->anal, p, (const ut8*)msg, len - 1);
if (kind) {
if (!strcmp (kind, "text")) {
r_str_filter (msg, 0);
if (*msg) {
DOALIGN();
r_cons_printf (" ; \"%s\" @ 0x%"PFMT64x, msg, p);
//r_cons_printf (" ; \"%s\" @ 0x%"PFMT64x, msg, p);
r_cons_printf (" ; \"%s\"", msg); // @ 0x%"PFMT64x, msg, p);
}
} else if (!strcmp (kind, "invalid")){
int *n = (int*)&p;
@ -2432,9 +2441,9 @@ static int myregwrite(RAnalEsil *esil, const char *name, ut64 val) {
}
}
memset (str, 0, sizeof (str));
if (val != 0LL) {
#if 0
RFlagItem *fi = r_flag_get_i (esil->anal->flb.f, val);
if (fi) {
strncpy (str, fi->name, sizeof (str)-1);
@ -2460,6 +2469,29 @@ static int myregwrite(RAnalEsil *esil, const char *name, ut64 val) {
} else {
msg = r_str_newf ("%s", str);
}
#endif
(void)r_io_read_at (esil->anal->iob.io, val, (ut8*)str, sizeof (str)-1);
str[sizeof (str)-1] = 0;
if (*str && r_str_is_printable (str)) {
// do nothing
msg = r_str_newf ("\"%s\"", str);
} else {
str[0] = 0;
if (*n32 == 0) {
// msg = strdup ("NULL");
} else if (*n32 == UT32_MAX) {
/* nothing */
} else {
if (ds && !ds->show_emu_str) {
msg = r_str_newf ("-> 0x%x", *n32);
}
}
}
RFlagItem *fi = r_flag_get_i (esil->anal->flb.f, val);
if (fi) {
msg = r_str_concatf (msg, " %s", fi->name);
}
}
if (ds && ds->show_emu_str) {
if (msg && *msg) r_cons_printf ("; %s", msg);
@ -2498,7 +2530,6 @@ static void ds_print_esil_anal_init(RDisasmState *ds) {
static void ds_print_esil_anal_fini(RDisasmState *ds) {
if (ds->show_emu && ds->esil_regstate) {
RCore* core = ds->core;
const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
r_reg_arena_poke (core->anal->reg, ds->esil_regstate);
r_reg_setv (core->anal->reg, pc, ds->esil_old_pc);
@ -2542,6 +2573,7 @@ static void ds_print_esil_anal(RDisasmState *ds) {
esil = core->anal->esil;
pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
r_reg_setv (core->anal->reg, pc, ds->at + ds->analop.size);
//r_reg_setv (core->anal->reg, pc, ds->at);
esil->cb.hook_reg_write = myregwrite;
if (ds->show_emu_write) {
esil->cb.hook_mem_write = mymemwrite0;
@ -2551,6 +2583,7 @@ static void ds_print_esil_anal(RDisasmState *ds) {
ds->esil_likely = 0;
r_anal_esil_parse (esil, R_STRBUF_SAFEGET (&ds->analop.esil));
r_anal_esil_stack_free (esil);
switch (ds->analop.type) {
case R_ANAL_OP_TYPE_SWI: {
char *s = cmd_syscall_dostr (core, -1);

View File

@ -26,8 +26,9 @@ static int visual_repeat_thread(RThread *th) {
RCore *core = th->user;
int i = 0;
for (;;) {
if (core->cons->breaked)
if (core->cons->breaked) {
break;
}
visual_refresh (core);
r_cons_flush ();
r_cons_gotoxy (0, 0);