Enhace ARM disassembly and code analysis

This commit is contained in:
pancake 2012-11-05 06:01:55 +01:00
parent 7c1e0c85d9
commit 21c4d1c5f5
4 changed files with 1339 additions and 1284 deletions

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2007-2011 */
/* radare - LGPL - Copyright 2007-2012 */
/* pancake<nopcode.org> */
#include <string.h>
@ -102,6 +102,7 @@ static int op_thumb(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int le
op->type = R_ANAL_OP_TYPE_JMP;
op->jump = addr+4+(delta<<1);
op->fail = addr+4;
op->eob = 1;
} else if ( (ins & _(B1111,B1111,0,0)) == _(B0100,B0111,0,0) ) {
// BLX
op->type = R_ANAL_OP_TYPE_UJMP;
@ -121,6 +122,7 @@ static int op_thumb(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int le
}
static int arm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
unsigned char ndata[4];
struct arm_insn *arminsn;
ut32 branch_dst_addr, i = 0;
ut32* code = (ut32 *)data;
@ -130,11 +132,19 @@ static int arm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
return 0;
memset (op, '\0', sizeof (RAnalOp));
arminsn = arm_new();
arm_set_thumb(arminsn, R_FALSE);
arm_set_input_buffer(arminsn, data);
arm_set_pc(arminsn, addr);
arm_set_thumb (arminsn, R_FALSE);
arm_set_input_buffer (arminsn, data);
arm_set_pc (arminsn, addr);
op->addr = addr;
op->type = R_ANAL_OP_TYPE_UNK;
if (anal->big_endian) {
b = data = ndata;
ndata[0]=data[3];
ndata[1]=data[2];
ndata[2]=data[1];
ndata[3]=data[0];
}
#if 0
op->jump = op->fail = -1;
op->ref = op->value = -1;
@ -147,19 +157,29 @@ static int arm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
codeA[0], codeA[1], codeA[2], codeA[3]);
#endif
// 0x000037b8 00:0000 0 800000ef svc 0x00000080
if (b[2] ==0xa0 && b[3]==0xe1) {
int n = (b[0]<<16) + b[1];
op->type = R_ANAL_OP_TYPE_MOV;
switch (n) {
case 0:
case 0x0110: case 0x0220: case 0x0330: case 0x0440:
case 0x0550: case 0x0660: case 0x0770: case 0x0880:
case 0x0990: case 0x0aa0: case 0x0bb0: case 0x0cc0:
op->type = R_ANAL_OP_TYPE_NOP;
break;
}
} else
if (b[3]==0xef) {
op->type = R_ANAL_OP_TYPE_SWI;
op->value = (b[0] | (b[1]<<8) | (b[2]<<2));
} else
if (b[3]==0xe5) {
if (b[2]==0x9f) {
/* STORE */
/* LDR/STR */
op->type = R_ANAL_OP_TYPE_STORE;
op->stackop = R_ANAL_STACK_SET;
//printf ("FUCKING PT Rpc AT 0x%08llx + %d\n", addr, b[0]);
//op->ref = 4+addr+b[0]+(b[1]&4<<8);
op->ref = 8+addr+b[0]+((b[1]&0xf)<<8);
op->ref = 12+addr+b[0]+((b[1]&0xf)<<8);
op->refptr = R_TRUE;
} else
if ((b[1]&0xf0) == 0xf0) {
@ -223,7 +243,8 @@ static int arm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
}
if (IS_EXITPOINT (code[i])) {
branch_dst_addr = disarm_branch_offset (addr, code[i]&0x00FFFFFF);
b=data;
branch_dst_addr = disarm_branch_offset (addr, b[0] | (b[1]<<8) | (b[2]<<16)); //code[i]&0x00FFFFFF);
op->ref = 0;
if (IS_BRANCHL (code[i])) {
if (IS_BRANCH (code[i])) {
@ -238,7 +259,9 @@ static int arm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
} else if (IS_BRANCH (code[i])) {
if (IS_CONDAL (code[i])) {
op->type = R_ANAL_OP_TYPE_JMP;
//op->type = R_ANAL_OP_TYPE_NOP;
op->jump = branch_dst_addr;
op->fail = UT64_MAX;
op->eob = 1;
} else {
op->type = R_ANAL_OP_TYPE_CJMP;
@ -252,8 +275,8 @@ static int arm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
op->eob = 1;
}
}
op->jump = arminsn->jmp;
op->fail = arminsn->fail;
//op->jump = arminsn->jmp;
//op->fail = arminsn->fail;
arm_free(arminsn);
return op->length;
}
@ -263,6 +286,7 @@ static int set_reg_profile(RAnal *anal) {
return r_reg_set_profile_string (anal->reg,
"=pc r15\n"
"=sp r14\n" // XXX
"=bp r14\n" // XXX
"=a0 r0\n"
"=a1 r1\n"
"=a2 r2\n"

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,7 @@ static int config_bigendian_callback(void *user, void *data) {
RCore *core = (RCore *) user;
RConfigNode *node = (RConfigNode *) data;
core->assembler->big_endian = node->i_value;
core->anal->big_endian = node->i_value;
return R_TRUE;
}

View File

@ -343,11 +343,15 @@ toro:
char *sign = r_anal_fcn_to_string (core->anal, f);
if (f->type == R_ANAL_FCN_TYPE_LOC) {
r_cons_printf ("|- %s (%d)\n| ", f->name, f->size);
} else
r_cons_printf ("/ %s: %s (%d)\n| ",
(f->type==R_ANAL_FCN_TYPE_FCN||f->type==R_ANAL_FCN_TYPE_SYM)?"function":
(f->type==R_ANAL_FCN_TYPE_IMP)?"import":"loc",
f->name, f->size);
} else {
const char *fmt = show_color?
"/ "Color_MAGENTA"%s: "Color_YELLOW"%s"Color_RESET" (%d)\n| ":
"/ %s: %s (%d)\n| ";
r_cons_printf (fmt,
(f->type==R_ANAL_FCN_TYPE_FCN||f->type==R_ANAL_FCN_TYPE_SYM)?"function":
(f->type==R_ANAL_FCN_TYPE_IMP)?"import":"loc",
f->name, f->size);
}
if (sign) r_cons_printf ("// %s\n", sign);
free (sign);
pre = "| ";
@ -367,7 +371,9 @@ toro:
if (show_lines && refline)
r_cons_strcat (refline);
if (show_offset)
printoffset (at, show_color, (at==dest), show_offseg);
// printoffset (at, show_color, (at==dest), show_offseg);
//r_cons_printf ("__________ ");
r_cons_printf ("; -------- ");
if (show_functions)
r_cons_printf ("%s:\n%s", flag->name, f?"| ":" ");
else r_cons_printf ("%s:\n", flag->name);
@ -402,7 +408,10 @@ toro:
// TODO: filter string (r_str_unscape)
{
char *out = r_str_unscape (mi->str);
r_cons_printf ("string (%"PFMT64d"): \"%s\"\n", mi->size, out);
if (show_color)
r_cons_printf (" .string "Color_YELLOW"\"%s\""Color_RESET" ; len=%"PFMT64d"\n", out, mi->size);
else
r_cons_printf (" .string \"%s\" ; len=%"PFMT64d"\n", out, mi->size);
free (out);
}
ret = (int)mi->size;
@ -642,17 +651,19 @@ toro:
R_META_TYPE_ANY, R_META_WHERE_HERE);
if (mi2) {
char *str = r_str_unscape (mi2->str);
r_cons_printf (" (at=0x%08"PFMT64x") (len=%"PFMT64d") \"%s\" ", analop.ref, mi2->size, str);
r_cons_printf (" \"%s\" @ 0x%08"PFMT64x":%"PFMT64d,
str, analop.ref, mi2->size);
free (str);
} else r_cons_printf ("; => 0x%08x ", word);
} else {
if (mi2->type == R_META_TYPE_STRING) {
char *str = r_str_unscape (mi2->str);
r_cons_printf (" (at=0x%08x) (len=%"PFMT64d") \"%s\" ", word, mi2->size, str);
r_cons_printf (" (at=0x%08x) (len=%"PFMT64d
") \"%s\" ", word, mi2->size, str);
free (str);
} else r_cons_printf ("unknown type '%c'\n", mi2->type);
}
}
} else r_cons_printf (" ; => 0x%08"PFMT64x"\n", analop.ref); //addr+idx+analop.ref);
}
if (show_comments && show_comment_right && comment) {
int c = r_cons_get_column ();