mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-14 00:38:55 +00:00
Fix dalvik<->dex class and method name resolutions
This commit is contained in:
parent
120a9c4b29
commit
acd5e4b999
@ -8,9 +8,7 @@
|
||||
#include "../../asm/arch/dalvik/opcode.h"
|
||||
|
||||
static int dalvik_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
|
||||
int sz = 1;
|
||||
|
||||
sz = dalvik_opcodes[data[0]].len;
|
||||
int sz = dalvik_opcodes[data[0]].len;
|
||||
if (op == NULL)
|
||||
return sz;
|
||||
|
||||
@ -274,12 +272,20 @@ static int dalvik_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int l
|
||||
case 0xb8: // invokestatic
|
||||
case 0xb6: // invokevirtual
|
||||
case 0x6e: // invoke-virtual
|
||||
case 0xef: // execute-inline/range
|
||||
case 0xf0: // invoke-object-init-range
|
||||
case 0xf9: // invoke-virtual-quick/range
|
||||
case 0xfb: // invoke-super-quick/range
|
||||
{
|
||||
ut32 vB = (data[3]<<8) | data[2];
|
||||
op->jump = anal->binb.get_offset (
|
||||
anal->binb.bin, 'm', vB);
|
||||
op->fail = addr + sz;
|
||||
op->type = R_ANAL_OP_TYPE_CALL;
|
||||
}
|
||||
break;
|
||||
case 0x27: // throw
|
||||
case 0xee: // execute-inline
|
||||
case 0xef: // execute-inline/range
|
||||
case 0xed: // throw-verification-error
|
||||
op->type = R_ANAL_OP_TYPE_SWI;
|
||||
break;
|
||||
|
@ -337,16 +337,17 @@ static int dalvik_disassemble (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
vC = (buf[5]<<8) | buf[4];
|
||||
if (buf[0] == 0x25) { // filled-new-array/range
|
||||
offset = R_ASM_GET_OFFSET(a, 'c', vB);
|
||||
if (offset == -1)
|
||||
if (offset == UT64_MAX)
|
||||
sprintf (str, " {v%i..v%i}, class+%i", vC, vC+vA-1, vB);
|
||||
else
|
||||
sprintf (str, " {v%i..v%i}, 0x%"PFMT64x, vC, vC+vA-1, offset);
|
||||
} else {
|
||||
offset = R_ASM_GET_OFFSET(a, 'm', vB);
|
||||
if (offset == -1)
|
||||
if (offset == UT64_MAX)
|
||||
sprintf (str, " {v%i..v%i}, method+%i", vC, vC+vA-1, vB);
|
||||
else
|
||||
else {
|
||||
sprintf (str, " {v%i..v%i}, 0x%"PFMT64x, vC, vC+vA-1, offset);
|
||||
}
|
||||
}
|
||||
strasm = r_str_concat (strasm, str);
|
||||
break;
|
||||
@ -374,16 +375,18 @@ static int dalvik_disassemble (RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
strasm = r_str_concat (strasm, str);
|
||||
if (buf[0] == 0x24) { // filled-new-array
|
||||
offset = R_ASM_GET_OFFSET(a, 'c', vB);
|
||||
if (offset == -1)
|
||||
if (offset == UT64_MAX) {
|
||||
sprintf (str, ", class+%i", vB);
|
||||
else
|
||||
} else {
|
||||
sprintf (str, ", 0x%"PFMT64x" ; 0x%x", offset, vB);
|
||||
}
|
||||
} else {
|
||||
offset = R_ASM_GET_OFFSET(a, 'm', vB);
|
||||
if (offset == -1)
|
||||
if (offset == UT64_MAX) {
|
||||
sprintf (str, ", method+%i", vB);
|
||||
else
|
||||
} else {
|
||||
sprintf (str, ", 0x%"PFMT64x" ; 0x%x", offset, vB);
|
||||
}
|
||||
|
||||
}
|
||||
strasm = r_str_concat (strasm, str);
|
||||
|
@ -6,4 +6,5 @@ TARGET_DALVIK=asm_dalvik.${EXT_SO}
|
||||
ALL_TARGETS+=${TARGET_DALVIK}
|
||||
|
||||
${TARGET_DALVIK}: ${OBJ_DALVIK}
|
||||
${CC} $(call libname,asm_dalvik) ${LDFLAGS} -I../arch/dalvik ${CFLAGS} -o asm_dalvik.${EXT_SO} ${OBJ_DALVIK}
|
||||
${CC} $(call libname,asm_dalvik) ${LDFLAGS} \
|
||||
-I../arch/dalvik ${CFLAGS} -o asm_dalvik.${EXT_SO} ${OBJ_DALVIK}
|
||||
|
@ -1612,11 +1612,9 @@ R_API RBinObject *r_bin_get_object(RBin *bin) {
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
R_API RList* /*<RBinClass>*/r_bin_get_classes(RBin *bin) {
|
||||
RBinObject *o = r_bin_cur_object (bin);
|
||||
if (o)
|
||||
return o->classes;
|
||||
if (o) return o->classes;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1626,7 +1624,6 @@ R_API RBinClass *r_bin_class_new (RBinFile *binfile, const char *name, const cha
|
||||
RBinClass *c;
|
||||
if (!o)
|
||||
return NULL;
|
||||
|
||||
list = o->classes;
|
||||
if (!name) return NULL;
|
||||
c = r_bin_class_get (binfile, name);
|
||||
|
@ -16,6 +16,8 @@
|
||||
#define dprintf if (0)eprintf
|
||||
#endif
|
||||
|
||||
static Sdb *mdb= NULL;
|
||||
|
||||
static int check(RBinFile *arch);
|
||||
static int check_bytes(const ut8 *buf, ut64 length);
|
||||
|
||||
@ -233,7 +235,7 @@ static char *getstr (RBinDexObj *bin, int idx) {
|
||||
buf2 = r_uleb128 (buf, sizeof (buf), &len);
|
||||
uleblen = (size_t)(buf2 - buf);
|
||||
if (len>0 && len < R_BIN_SIZEOF_STRINGS) {
|
||||
char *str = malloc (len+1);
|
||||
char *str = calloc (1, len+1);
|
||||
if (!str) return NULL;
|
||||
r_buf_read_at (bin->b, (bin->strings[idx])+uleblen,
|
||||
(ut8*)str, len); //uleblen);
|
||||
@ -253,7 +255,15 @@ static char *get_string (RBinDexObj *bin, int cid, int idx) {
|
||||
return NULL;
|
||||
c_name = getstr (bin, cid);
|
||||
m_name = getstr (bin, idx);
|
||||
res = r_str_newf ("%s.%s", c_name, m_name);
|
||||
if (c_name && *c_name==',') {
|
||||
res = r_str_newf ("%s", m_name);
|
||||
} else {
|
||||
if (c_name && m_name) {
|
||||
res = r_str_newf ("%s.%s", c_name, m_name);
|
||||
} else {
|
||||
res = r_str_newf ("UNKNOWN");
|
||||
}
|
||||
}
|
||||
free (c_name);
|
||||
free (m_name);
|
||||
return res;
|
||||
@ -273,6 +283,18 @@ static char *dex_method_name (RBinDexObj *bin, int idx) {
|
||||
return get_string (bin, cid, tid);
|
||||
}
|
||||
|
||||
static char *dex_class_name_byid (RBinDexObj *bin, int cid) {
|
||||
int tid;
|
||||
if (!bin || !bin->types)
|
||||
return NULL;
|
||||
//cid = c->super_class;
|
||||
if (cid<0 || cid >= bin->header.types_size)
|
||||
return NULL;
|
||||
tid = bin->types [cid].descriptor_id;
|
||||
//int sid = bin->strings[tid];
|
||||
return get_string (bin, cid, tid);
|
||||
}
|
||||
|
||||
static char *dex_class_name (RBinDexObj *bin, RBinDexClass *c) {
|
||||
int cid, tid;
|
||||
if (!bin || !c || !bin->types)
|
||||
@ -451,6 +473,11 @@ encoded_catch_handler_list handlers
|
||||
#endif
|
||||
sym->paddr += 0x10;
|
||||
r_list_append (bin->methods_list, sym);
|
||||
/* cache in sdb */
|
||||
if (!mdb) {
|
||||
mdb = sdb_new0 ();
|
||||
}
|
||||
sdb_num_set (mdb, sdb_fmt(0, "method.%d", MI), sym->paddr, 0);
|
||||
} else {
|
||||
//r_list_append (bin->methods_list, sym);
|
||||
// XXX memleak sym
|
||||
@ -564,6 +591,7 @@ static RList* methods (RBinFile *arch) {
|
||||
return bin->methods_list;
|
||||
}
|
||||
|
||||
// wtf?
|
||||
static void __r_bin_class_free(RBinClass *p) {
|
||||
r_bin_class_free (p);
|
||||
}
|
||||
@ -571,11 +599,11 @@ static void __r_bin_class_free(RBinClass *p) {
|
||||
static RList* classes (RBinFile *arch) {
|
||||
struct r_bin_dex_obj_t *bin = (struct r_bin_dex_obj_t *) arch->o->bin_obj;
|
||||
struct dex_class_t entry;
|
||||
const int len = 100;
|
||||
RList *ret = NULL;
|
||||
char *name = NULL;
|
||||
RBinClass *class;
|
||||
int i;
|
||||
const int len = 100;
|
||||
char *name = NULL;
|
||||
|
||||
if (bin->header.class_size>bin->size) {
|
||||
eprintf ("Too many classes %d\n", bin->header.class_size);
|
||||
@ -585,10 +613,9 @@ static RList* classes (RBinFile *arch) {
|
||||
return NULL;
|
||||
ret->free = (RListFree)__r_bin_class_free;
|
||||
for (i = 0; i < bin->header.class_size; i++) {
|
||||
ut64 class_addr = (ut64) bin->header.class_offset + (sizeof (struct dex_class_t)*i);
|
||||
// ETOOSLOW
|
||||
r_buf_read_at (bin->b, (ut64) bin->header.class_offset
|
||||
+ (sizeof (struct dex_class_t)*i), (ut8*)&entry,
|
||||
sizeof (struct dex_class_t));
|
||||
r_buf_read_at (bin->b, class_addr, (ut8*)&entry, sizeof (struct dex_class_t));
|
||||
// TODO: implement sections.. each section specifies a class boundary
|
||||
{
|
||||
free (name);
|
||||
@ -614,10 +641,12 @@ static RList* classes (RBinFile *arch) {
|
||||
class = R_NEW0 (RBinClass);
|
||||
// get source file name (ClassName.java)
|
||||
// TODO: use RConstr here
|
||||
class->name = strdup (name[0]<0x41? name+1: name);
|
||||
class->index = entry.class_id;
|
||||
//class->name = strdup (name[0]<0x41? name+1: name);
|
||||
class->name = dex_class_name_byid (bin, entry.class_id);
|
||||
class->index = entry.class_id + bin->header.class_offset;
|
||||
// find reference to this class instance
|
||||
//class->addr = class_addr;
|
||||
r_list_append (ret, class);
|
||||
|
||||
dprintf ("class.%s=%d\n", name[0]==12?name+1:name, entry.class_id);
|
||||
dprintf ("# access_flags = %x;\n", entry.access_flags);
|
||||
dprintf ("# super_class = %d;\n", entry.super_class);
|
||||
@ -651,16 +680,36 @@ static RList* entries(RBinFile *arch) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
//TODO
|
||||
static ut64 offset_of_method_idx(RBinFile *arch, struct r_bin_dex_obj_t *dex, int idx) {
|
||||
int off = dex->header.method_offset +idx;
|
||||
//(sizeof (struct dex_method_t)*idx);
|
||||
const char *name = dex_method_name (dex, idx);
|
||||
//eprintf ("idx=%d off=%d (%s)\n", idx, off, name);
|
||||
//off = sdb_num_get (mdb, name, NULL);
|
||||
off = sdb_num_get (mdb, sdb_fmt(0, "method.%d", idx), 0);
|
||||
//p = r_uleb128 (p, p_end-p, &MI);
|
||||
// READ CODE
|
||||
return off;
|
||||
}
|
||||
|
||||
//TODO must return ut64 imho
|
||||
static int getoffset (RBinFile *arch, int type, int idx) {
|
||||
struct r_bin_dex_obj_t *dex = arch->o->bin_obj;
|
||||
switch (type) {
|
||||
case 'm': // methods
|
||||
if (dex->header.method_size > idx)
|
||||
return dex->header.method_offset +
|
||||
(sizeof (struct dex_method_t)*idx);
|
||||
//if (dex->header.method_size > idx)
|
||||
// return offset_of_method_idx (arch, dex, idx);
|
||||
return offset_of_method_idx (arch, dex, idx);
|
||||
break;
|
||||
case 'c': // class
|
||||
if (dex->header.class_size > idx) {
|
||||
int off = dex->header.class_offset +idx;
|
||||
//(sizeof (struct dex_class_t)*idx);
|
||||
//const char *name = dex_class_name_byid (dex, idx);
|
||||
//eprintf ("idx=%d off=%d (%s)\n", idx, off, name);
|
||||
//p = r_uleb128 (p, p_end-p, &MI);
|
||||
return off;
|
||||
}
|
||||
break;
|
||||
case 'f': // fields
|
||||
if (dex->header.fields_size > idx)
|
||||
|
@ -1449,19 +1449,30 @@ static int bin_classes (RCore *r, int mode) {
|
||||
iter->p?",":"", c->name, c->index);
|
||||
}
|
||||
r_cons_printf ("]");
|
||||
} else
|
||||
if (mode & R_CORE_BIN_SIMPLE) {
|
||||
} else if (mode & R_CORE_BIN_SIMPLE) {
|
||||
r_list_foreach (cs, iter, c) {
|
||||
r_cons_printf ("0x%08"PFMT64x" %s %s\n",
|
||||
c->index, c->name, c->super?c->super:"");
|
||||
}
|
||||
} else
|
||||
if (mode & R_CORE_BIN_SET) {
|
||||
} else if (mode & R_CORE_BIN_SET) {
|
||||
// Nothing to set.
|
||||
} else {
|
||||
r_flag_space_set (r->flags, "classes");
|
||||
r_list_foreach (cs, iter, c) {
|
||||
char str[R_FLAG_NAME_SIZE+1];
|
||||
char *name = strdup (c->name);
|
||||
ut64 addr = c->index; //c->addr? c->addr : c->index;
|
||||
r_name_filter (name, 0);
|
||||
snprintf (str, R_FLAG_NAME_SIZE, "class.%s", name);
|
||||
r_flag_set (r->flags, str, addr, 1, 0);
|
||||
}
|
||||
} else {
|
||||
r_cons_printf ("fs classes\n");
|
||||
r_list_foreach (cs, iter, c) {
|
||||
char *name = strdup (c->name);
|
||||
ut64 addr = c->index; //c->addr? c->addr : c->index;
|
||||
r_name_filter (name, 0);
|
||||
if (mode) {
|
||||
r_cons_printf ("f class.%s @ %d\n", c->name, c->index);
|
||||
r_cons_printf ("f class.%s @ 0x%"PFMT64x"\n", name, addr);
|
||||
if (c->super)
|
||||
r_cons_printf ("f super.%s.%s @ %d\n", c->name, c->super, c->index);
|
||||
r_list_foreach (c->methods, iter2, methname) {
|
||||
@ -1476,6 +1487,7 @@ static int bin_classes (RCore *r, int mode) {
|
||||
}
|
||||
}
|
||||
// TODO: show belonging methods and fields
|
||||
free (name);
|
||||
}
|
||||
}
|
||||
return R_TRUE;
|
||||
@ -1538,7 +1550,8 @@ static void bin_mem_print (RList *mems, int perms, int depth) {
|
||||
if (mem) {
|
||||
for (i=0; i < depth; i++)
|
||||
r_cons_printf (" ");
|
||||
r_cons_printf ("%8s addr=0x%016"PFMT64x" size=%6d perms=[%s]\n", mem->name, mem->addr, mem->size, r_str_rwx_i (mem->perms & perms));
|
||||
r_cons_printf ("%8s addr=0x%016"PFMT64x" size=%6d perms=[%s]\n",
|
||||
mem->name, mem->addr, mem->size, r_str_rwx_i (mem->perms & perms));
|
||||
if (mem->mirrors)
|
||||
bin_mem_print (mem->mirrors, (mem->perms & perms), (depth + 1)); //sorry, but anything else would be inefficient
|
||||
}
|
||||
|
@ -970,6 +970,7 @@ eprintf ("++ EFL = 0x%08x %d\n", ctx.EFlags, r_offsetof (CONTEXT, EFlags));
|
||||
unsigned int inferior_thread_count = 0;
|
||||
R_DEBUG_REG_T *regs = (R_DEBUG_REG_T*)buf;
|
||||
unsigned int gp_count = R_DEBUG_STATE_SZ; //sizeof (R_DEBUG_REG_T);
|
||||
int tid = dbg->tid;
|
||||
|
||||
#if 0
|
||||
// if uncommented, it will break x86-32 debugging from x86-64 (ios simulator f.ex)
|
||||
|
@ -274,6 +274,7 @@ typedef struct r_bin_class_t {
|
||||
char *super;
|
||||
char *visibility_str;
|
||||
int index;
|
||||
//ut64 addr;
|
||||
RList *methods; // <RBinSymbol>
|
||||
RList *fields; // <RBinField>
|
||||
int visibility;
|
||||
|
Loading…
Reference in New Issue
Block a user