Implement class methods for DEX and make icj
This commit is contained in:
parent
406000688d
commit
d054008b17
6 changed files with 226 additions and 156 deletions
|
|
@ -396,13 +396,18 @@ static void r_bin_object_free (void /*RBinObject*/ *o_) {
|
|||
// makes no sense to pass in a binfile and set the RBinObject
|
||||
// kinda a clunky functions
|
||||
static int r_bin_object_set_items(RBinFile *binfile, RBinObject *o) {
|
||||
RBin *bin = binfile->rbin;
|
||||
RBinObject *old_o = binfile ? binfile->o : NULL;
|
||||
RBinObject *old_o;
|
||||
RBinPlugin *cp;
|
||||
int i, minlen;
|
||||
RBinPlugin *cp = NULL;
|
||||
if (!binfile || !o || !o->plugin) return R_FALSE;
|
||||
RBin *bin;
|
||||
|
||||
if (!binfile || !o || !o->plugin)
|
||||
return R_FALSE;
|
||||
|
||||
bin = binfile->rbin;
|
||||
old_o = binfile->o;
|
||||
cp = o->plugin;
|
||||
|
||||
if (binfile->rbin->minstrlen>0) {
|
||||
minlen = binfile->rbin->minstrlen;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ static void hashify(char *s, ut64 vaddr) {
|
|||
while (*s) {
|
||||
if (!IS_PRINTABLE(*s)) {
|
||||
if (vaddr && vaddr != UT64_MAX) {
|
||||
sprintf (s, "%"PFMT64d, vaddr);
|
||||
sprintf (s, "_%"PFMT64d, vaddr);
|
||||
} else {
|
||||
ut32 hash = sdb_hash (s);
|
||||
sprintf (s, "%x", hash);
|
||||
|
|
@ -62,17 +62,20 @@ R_API void r_bin_filter_sections (RList *list) {
|
|||
|
||||
R_API void r_bin_filter_classes (RList *list) {
|
||||
Sdb *db = sdb_new0 ();
|
||||
RListIter *iter;
|
||||
RListIter *iter, *iter2;
|
||||
RBinClass *cls;
|
||||
RBinSymbol *sym;
|
||||
r_list_foreach (list, iter, cls) {
|
||||
int namepad_len = strlen (cls->name)+10;
|
||||
int namepad_len = strlen (cls->name)+32;
|
||||
char *namepad = malloc (namepad_len);
|
||||
if (namepad) {
|
||||
strcpy (namepad, cls->name);
|
||||
r_bin_filter_name (db, cls->index, namepad, namepad_len);
|
||||
//hashify (namepad, (ut64)cls->index);
|
||||
free (cls->name);
|
||||
cls->name = namepad;
|
||||
r_list_foreach (cls->methods, iter2, sym) {
|
||||
r_bin_filter_name (db, sym->vaddr, sym->name, sizeof (sym->name));
|
||||
}
|
||||
} else eprintf ("Cannot alloc %d bytes\n", namepad_len);
|
||||
}
|
||||
sdb_free (db);
|
||||
|
|
|
|||
|
|
@ -858,6 +858,7 @@ static int parse_import_stub(struct MACH0_(obj_t)* bin, struct symbol_t *symbol,
|
|||
return R_FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static ut64 get_text_base(struct MACH0_(obj_t)* bin) {
|
||||
ut64 ret = 0LL;
|
||||
struct section_t *sections;
|
||||
|
|
@ -873,6 +874,7 @@ static ut64 get_text_base(struct MACH0_(obj_t)* bin) {
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int inSymtab (struct symbol_t *symbols, int last, const char *name, ut64 addr) {
|
||||
int i;
|
||||
|
|
@ -890,7 +892,7 @@ struct symbol_t* MACH0_(get_symbols)(struct MACH0_(obj_t)* bin) {
|
|||
const char *symstr;
|
||||
struct symbol_t *symbols;
|
||||
int from, to, i, j, s, stridx, symbols_size, symbols_count;
|
||||
ut64 text_base = get_text_base (bin);
|
||||
//ut64 text_base = get_text_base (bin);
|
||||
|
||||
if (!bin || !bin->symtab || !bin->symstr)
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -334,11 +334,156 @@ static char *dex_class_super_name (RBinDexObj *bin, RBinDexClass *c) {
|
|||
return get_string (bin, cid, tid);
|
||||
}
|
||||
|
||||
static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
||||
static int *parse_class (RBinFile *binfile, struct r_bin_dex_obj_t *bin, struct dex_class_t *c, RBinClass *cls) {
|
||||
int *methods;
|
||||
int i, j;
|
||||
char *name;
|
||||
ut64 SF, IF, DM, VM;
|
||||
int i, j;
|
||||
const ut8 *p, *p_end;
|
||||
char *class_name = dex_class_name (bin, c);
|
||||
if (c->class_data_offset==0) {
|
||||
// no method here, just class definition
|
||||
//free (class_name);
|
||||
//free (super_name);
|
||||
return NULL;
|
||||
}
|
||||
methods = calloc (sizeof (ut32), bin->header.method_size);
|
||||
if (!methods)
|
||||
return R_FALSE;
|
||||
dprintf (" class_data_offset: %d\n", c->class_data_offset);
|
||||
p = r_buf_get_at (binfile->buf, c->class_data_offset, NULL);
|
||||
p_end = p + (binfile->buf->length - c->class_data_offset);
|
||||
/* data header */
|
||||
/* walk over class data items */
|
||||
p = r_uleb128 (p, p_end-p, &SF);
|
||||
p = r_uleb128 (p, p_end-p, &IF);
|
||||
p = r_uleb128 (p, p_end-p, &DM);
|
||||
p = r_uleb128 (p, p_end-p, &VM);
|
||||
//eprintf ("METHODS %s %d\n", class_name, DM);
|
||||
//eprintf ("SF %d IF %d DM %d VM %d\n", SF, IF, DM, VM);
|
||||
dprintf (" static fields: %u\n", (ut32)SF);
|
||||
/* static fields */
|
||||
for (j=0; j<SF; j++) {
|
||||
ut64 FI, FA;
|
||||
p = r_uleb128 (p, p_end-p, &FI);
|
||||
p = r_uleb128 (p, p_end-p, &FA);
|
||||
dprintf (" field_idx: %u\n", (ut32)FI);
|
||||
// TODO: retrieve name of field here
|
||||
// TODO: add comment or store that fcn var info in sdb directly
|
||||
dprintf (" field access_flags: 0x%x\n", (ut32)FA);
|
||||
}
|
||||
/* instance fields */
|
||||
dprintf (" instance fields: %u\n", (ut32)IF);
|
||||
for (j=0; j<IF; j++) {
|
||||
ut64 FI, FA;
|
||||
p = r_uleb128 (p, p_end-p, &FI);
|
||||
p = r_uleb128 (p, p_end-p, &FA);
|
||||
dprintf (" field_idx: %u,\n", (ut32)FI);
|
||||
dprintf (" field access_flags: %u,\n", (ut32)FA);
|
||||
}
|
||||
/* direct methods */
|
||||
dprintf (" direct methods: %u\n", (ut32)DM);
|
||||
#if 0
|
||||
// hardcoded DEX limit
|
||||
if (DM>=0xffff) {
|
||||
DM = 0xFFFF;
|
||||
}
|
||||
#endif
|
||||
ut64 omi = 0;
|
||||
for (j=0; j<DM; j++) {
|
||||
char *method_name, *flag_name;
|
||||
ut64 MI, MA, MC;
|
||||
p = r_uleb128 (p, p_end-p, &MI);
|
||||
MI += omi;
|
||||
omi = MI;
|
||||
// the mi is diff
|
||||
#if 0
|
||||
index into the method_ids list for the identity of this method (includes the name and descriptor), represented as a difference from the index of previous element in the list. The index of the first element in a list is represented directly.
|
||||
#endif
|
||||
p = r_uleb128 (p, p_end-p, &MA);
|
||||
p = r_uleb128 (p, p_end-p, &MC);
|
||||
|
||||
if (MI<bin->header.method_size) methods[MI] = 1;
|
||||
if (MC>0 && bin->code_from>MC) bin->code_from = MC;
|
||||
if (MC>0 && bin->code_to<MC) bin->code_to = MC;
|
||||
|
||||
method_name = dex_method_name (bin, MI);
|
||||
dprintf ("METHOD NAME %u\n", (ut32)MI);
|
||||
if (!method_name) method_name = strdup ("unknown");
|
||||
flag_name = flagname (class_name, method_name);
|
||||
dprintf ("f %s @ 0x%x\n", flag_name, (ut32)MC);
|
||||
dprintf (" { name: %d %d %s,\n", (ut32)MC, (ut32)MI, method_name);
|
||||
dprintf (" idx: %u,\n", (ut32)MI);
|
||||
dprintf (" access_flags: 0x%x,\n", (ut32)MA);
|
||||
dprintf (" code_offset: 0x%x },\n", (ut32)MC);
|
||||
/* add symbol */
|
||||
if (flag_name && *flag_name) {
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
strncpy (sym->name, flag_name, sizeof (sym->name)-1);
|
||||
strcpy (sym->type, "FUNC");
|
||||
sym->paddr = sym->vaddr = MC;
|
||||
if (MC>0) { /* avoid methods at 0 paddr */
|
||||
#if 0
|
||||
// TODO: use sdb+pf to show method header
|
||||
ut16 regsz;
|
||||
ut16 ins_size
|
||||
ut16 outs_size
|
||||
ut16 tries_size
|
||||
ut32 debug_info_off
|
||||
ut32 insns_size
|
||||
ut16[insn_size] insns;
|
||||
ut16 padding = 0
|
||||
try_item[tries_size] tries
|
||||
encoded_catch_handler_list handlers
|
||||
#endif
|
||||
sym->paddr += 0x10;
|
||||
r_list_append (bin->methods_list, sym);
|
||||
if (cls) {
|
||||
if (!cls->methods) {
|
||||
cls->methods = r_list_new ();
|
||||
}
|
||||
r_list_append (cls->methods, 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
|
||||
free (sym);
|
||||
}
|
||||
}
|
||||
free (method_name);
|
||||
free (flag_name);
|
||||
}
|
||||
/* virtual methods */
|
||||
dprintf (" virtual methods: %u\n", (ut32)VM);
|
||||
for (j=0; j<VM; j++) {
|
||||
ut64 MI, MA, MC;
|
||||
p = r_uleb128 (p, p_end-p, &MI);
|
||||
p = r_uleb128 (p, p_end-p, &MA);
|
||||
p = r_uleb128 (p, p_end-p, &MC);
|
||||
|
||||
if (MI<bin->header.method_size) methods[MI] = 1;
|
||||
if (MC>0 && bin->code_from>MC) bin->code_from = MC;
|
||||
if (MC>0 && bin->code_to<MC) bin->code_to = MC;
|
||||
|
||||
name = dex_method_name (bin, MI);
|
||||
dprintf (" method name: %s\n", name);
|
||||
dprintf (" method_idx: %u\n", (ut32)MI);
|
||||
dprintf (" method access_flags: %u\n", (ut32)MA);
|
||||
dprintf (" method code_offset: %u\n", (ut32)MC);
|
||||
free (name);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
||||
int i, j;
|
||||
const ut8 *p, *p_end;
|
||||
int *methods = NULL;
|
||||
|
||||
// doublecheck??
|
||||
if (!bin || bin->methods_list)
|
||||
|
|
@ -354,9 +499,6 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
bin->header.method_size = 0;
|
||||
return R_FALSE;
|
||||
}
|
||||
methods = calloc (sizeof (ut32), bin->header.method_size);
|
||||
if (!methods)
|
||||
return R_FALSE;
|
||||
|
||||
/* WrapDown the header sizes to avoid huge allocations */
|
||||
bin->header.method_size = R_MIN (bin->header.method_size, bin->size);
|
||||
|
|
@ -364,7 +506,6 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
bin->header.strings_size = R_MIN (bin->header.strings_size, bin->size);
|
||||
|
||||
if (bin->header.strings_size > bin->size) {
|
||||
free (methods);
|
||||
eprintf ("Invalid strings size\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
|
|
@ -391,136 +532,7 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
continue;
|
||||
}
|
||||
#endif
|
||||
if (c->class_data_offset==0) {
|
||||
// no method here, just class definition
|
||||
free (class_name);
|
||||
free (super_name);
|
||||
continue;
|
||||
}
|
||||
dprintf (" class_data_offset: %d\n", c->class_data_offset);
|
||||
p = r_buf_get_at (arch->buf, c->class_data_offset, NULL);
|
||||
p_end = p + (arch->buf->length - c->class_data_offset);
|
||||
/* data header */
|
||||
/* walk over class data items */
|
||||
{
|
||||
ut64 SF, IF, DM, VM;
|
||||
p = r_uleb128 (p, p_end-p, &SF);
|
||||
p = r_uleb128 (p, p_end-p, &IF);
|
||||
p = r_uleb128 (p, p_end-p, &DM);
|
||||
p = r_uleb128 (p, p_end-p, &VM);
|
||||
//eprintf ("METHODS %s %d\n", class_name, DM);
|
||||
//eprintf ("SF %d IF %d DM %d VM %d\n", SF, IF, DM, VM);
|
||||
dprintf (" static fields: %u\n", (ut32)SF);
|
||||
/* static fields */
|
||||
for (j=0; j<SF; j++) {
|
||||
ut64 FI, FA;
|
||||
p = r_uleb128 (p, p_end-p, &FI);
|
||||
p = r_uleb128 (p, p_end-p, &FA);
|
||||
dprintf (" field_idx: %u\n", (ut32)FI);
|
||||
// TODO: retrieve name of field here
|
||||
// TODO: add comment or store that fcn var info in sdb directly
|
||||
dprintf (" field access_flags: 0x%x\n", (ut32)FA);
|
||||
}
|
||||
/* instance fields */
|
||||
dprintf (" instance fields: %u\n", (ut32)IF);
|
||||
for (j=0; j<IF; j++) {
|
||||
ut64 FI, FA;
|
||||
p = r_uleb128 (p, p_end-p, &FI);
|
||||
p = r_uleb128 (p, p_end-p, &FA);
|
||||
dprintf (" field_idx: %u,\n", (ut32)FI);
|
||||
dprintf (" field access_flags: %u,\n", (ut32)FA);
|
||||
}
|
||||
/* direct methods */
|
||||
dprintf (" direct methods: %u\n", (ut32)DM);
|
||||
#if 0
|
||||
// hardcoded DEX limit
|
||||
if (DM>=0xffff) {
|
||||
DM = 0xFFFF;
|
||||
}
|
||||
#endif
|
||||
ut64 omi = 0;
|
||||
for (j=0; j<DM; j++) {
|
||||
char *method_name, *flag_name;
|
||||
ut64 MI, MA, MC;
|
||||
p = r_uleb128 (p, p_end-p, &MI);
|
||||
MI += omi;
|
||||
omi = MI;
|
||||
// the mi is diff
|
||||
#if 0
|
||||
index into the method_ids list for the identity of this method (includes the name and descriptor), represented as a difference from the index of previous element in the list. The index of the first element in a list is represented directly.
|
||||
#endif
|
||||
p = r_uleb128 (p, p_end-p, &MA);
|
||||
p = r_uleb128 (p, p_end-p, &MC);
|
||||
|
||||
if (MI<bin->header.method_size) methods[MI] = 1;
|
||||
if (MC>0 && bin->code_from>MC) bin->code_from = MC;
|
||||
if (MC>0 && bin->code_to<MC) bin->code_to = MC;
|
||||
|
||||
method_name = dex_method_name (bin, MI);
|
||||
dprintf ("METHOD NAME %u\n", (ut32)MI);
|
||||
if (!method_name) method_name = strdup ("unknown");
|
||||
flag_name = flagname (class_name, method_name);
|
||||
dprintf ("f %s @ 0x%x\n", flag_name, (ut32)MC);
|
||||
dprintf (" { name: %d %d %s,\n", (ut32)MC, (ut32)MI, method_name);
|
||||
dprintf (" idx: %u,\n", (ut32)MI);
|
||||
dprintf (" access_flags: 0x%x,\n", (ut32)MA);
|
||||
dprintf (" code_offset: 0x%x },\n", (ut32)MC);
|
||||
/* add symbol */
|
||||
if (flag_name && *flag_name) {
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
strncpy (sym->name, flag_name, sizeof (sym->name)-1);
|
||||
strcpy (sym->type, "FUNC");
|
||||
sym->paddr = sym->vaddr = MC;
|
||||
if (MC>0) { /* avoid methods at 0 paddr */
|
||||
#if 0
|
||||
// TODO: use sdb+pf to show method header
|
||||
ut16 regsz;
|
||||
ut16 ins_size
|
||||
ut16 outs_size
|
||||
ut16 tries_size
|
||||
ut32 debug_info_off
|
||||
ut32 insns_size
|
||||
ut16[insn_size] insns;
|
||||
ut16 padding = 0
|
||||
try_item[tries_size] tries
|
||||
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
|
||||
free (sym);
|
||||
}
|
||||
}
|
||||
free (method_name);
|
||||
free (flag_name);
|
||||
}
|
||||
/* virtual methods */
|
||||
dprintf (" virtual methods: %u\n", (ut32)VM);
|
||||
for (j=0; j<VM; j++) {
|
||||
ut64 MI, MA, MC;
|
||||
p = r_uleb128 (p, p_end-p, &MI);
|
||||
p = r_uleb128 (p, p_end-p, &MA);
|
||||
p = r_uleb128 (p, p_end-p, &MC);
|
||||
|
||||
if (MI<bin->header.method_size) methods[MI] = 1;
|
||||
if (MC>0 && bin->code_from>MC) bin->code_from = MC;
|
||||
if (MC>0 && bin->code_to<MC) bin->code_to = MC;
|
||||
|
||||
name = dex_method_name (bin, MI);
|
||||
dprintf (" method name: %s\n", name);
|
||||
dprintf (" method_idx: %u\n", (ut32)MI);
|
||||
dprintf (" method access_flags: %u\n", (ut32)MA);
|
||||
dprintf (" method code_offset: %u\n", (ut32)MC);
|
||||
free (name);
|
||||
}
|
||||
}
|
||||
methods = parse_class (arch, bin, c, NULL);
|
||||
dprintf (" ],\n");
|
||||
dprintf ("},");
|
||||
free (class_name);
|
||||
|
|
@ -677,6 +689,10 @@ static RList* classes (RBinFile *arch) {
|
|||
class->addr = entry.class_id + bin->header.class_offset;
|
||||
class->name = cn;
|
||||
//class->addr = class_addr;
|
||||
|
||||
int *methods = parse_class (arch, bin, &entry, class);
|
||||
free (methods);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1511,9 +1511,9 @@ static int bin_fields (RCore *r, int mode, ut64 baddr, int va) {
|
|||
|
||||
static int bin_classes (RCore *r, int mode) {
|
||||
RListIter *iter, *iter2;
|
||||
RBinSymbol *sym;
|
||||
RBinClass *c;
|
||||
RList *cs = r_bin_get_classes (r->bin);
|
||||
const char *methname;
|
||||
if (!cs) return R_FALSE;
|
||||
|
||||
// XXX: support for classes is broken and needs more love
|
||||
|
|
@ -1557,17 +1557,21 @@ static int bin_classes (RCore *r, int mode) {
|
|||
r_cons_printf ("f class.%s @ 0x%"PFMT64x"\n", name, c->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) {
|
||||
r_cons_printf ("f method.%s.%s\n", c->name, methname);
|
||||
r_list_foreach (c->methods, iter2, sym) {
|
||||
r_cons_printf ("f method.%s.%s\n", c->name, sym->name);
|
||||
}
|
||||
} else {
|
||||
r_cons_printf ("class %d @ 0x%"PFMT64x" = %s\n",
|
||||
c->index, c->addr, c->name);
|
||||
r_cons_printf ("0x%08"PFMT64x" class %d %s ",
|
||||
c->addr, c->index, c->name);
|
||||
if (c->super)
|
||||
r_cons_printf (" super = %s\n", c->super);
|
||||
r_list_foreach (c->methods, iter2, methname) {
|
||||
r_cons_printf (" method %s\n", methname);
|
||||
r_cons_printf (" super: %s\n", c->super);
|
||||
r_cons_newline();
|
||||
int m = 0;
|
||||
r_list_foreach (c->methods, iter2, sym) {
|
||||
r_cons_printf ("0x%08"PFMT64x" method %d %s\n", sym->vaddr, m, sym->name);
|
||||
m++;
|
||||
}
|
||||
r_cons_newline ();
|
||||
}
|
||||
// TODO: show belonging methods and fields
|
||||
free (name);
|
||||
|
|
|
|||
|
|
@ -311,11 +311,51 @@ static int cmd_info(void *data, const char *input) {
|
|||
}
|
||||
break;
|
||||
case 'c': // for r2 `ic`
|
||||
if (input[1]== ' ') {
|
||||
eprintf ("TODO: list methods\n");
|
||||
if (input[1]== '?') {
|
||||
eprintf("Usage: ic[jq*] [class-index]\n");
|
||||
} else if (input[1]== ' ' || input[1] == 'q' || input[1] == 'j') {
|
||||
RBinClass *cls;
|
||||
RBinSymbol *sym;
|
||||
RListIter *iter;
|
||||
RBinObject *obj = r_bin_cur_object (core->bin);
|
||||
int idx = r_num_math (core->num, input +2);
|
||||
int count = 0;
|
||||
if (input[2]) {
|
||||
r_list_foreach (obj->classes, iter, cls) {
|
||||
if (idx != count++)
|
||||
continue;
|
||||
switch (input[1]) {
|
||||
case '*':
|
||||
r_list_foreach (cls->methods, iter, sym) {
|
||||
r_cons_printf ("f sym.%s @ 0x%"PFMT64x"\n", sym->name, sym->vaddr);
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
r_cons_printf ("\"class\":\"%s\"", cls->name);
|
||||
r_cons_printf (",\"methods\":[");
|
||||
r_list_foreach (cls->methods, iter, sym) {
|
||||
const char *comma = iter->p? ",": "";
|
||||
r_cons_printf ("%s{\"name\":\"%s\",\"vaddr\":%"PFMT64d"}",
|
||||
comma, sym->name, sym->vaddr);
|
||||
}
|
||||
r_cons_printf ("]");
|
||||
break;
|
||||
default:
|
||||
r_cons_printf ("class %s\n", cls->name);
|
||||
r_list_foreach (cls->methods, iter, sym) {
|
||||
r_cons_printf ("method %s\n", sym->name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
RBININFO ("classes", R_CORE_BIN_ACC_CLASSES);
|
||||
}
|
||||
} else {
|
||||
RBININFO ("classes", R_CORE_BIN_ACC_CLASSES); break;
|
||||
RBININFO ("classes", R_CORE_BIN_ACC_CLASSES);
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
if (input[1]!=' ' || !demangle (core, input+2)) {
|
||||
eprintf ("|Usage: iD lang symbolname\n");
|
||||
|
|
|
|||
Loading…
Reference in a new issue