Initial implementation of extracting class info from symbols

This commit is contained in:
pancake 2017-04-10 12:52:42 +02:00
parent 1cf650aceb
commit fb47d2ce74
5 changed files with 160 additions and 105 deletions

View File

@ -84,11 +84,42 @@ static RBinFile *r_bin_file_new_from_bytes(RBin *bin, const char *file,
const char *xtrname, ut64 offset,
bool steal_ptr);
static int getoffset(RBin *bin, int type, int idx);
static const char *getname(RBin *bin, int type, int idx);
static int r_bin_file_object_add(RBinFile *binfile, RBinObject *o);
static void binobj_set_baddr(RBinObject *o, ut64 baddr);
static ut64 binobj_a2b(RBinObject *o, ut64 addr);
static int getoffset(RBin *bin, int type, int idx) {
RBinFile *a = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (a);
if (plugin && plugin->get_offset) {
return plugin->get_offset (a, type, idx);
}
return -1;
}
static const char *getname(RBin *bin, int type, int idx) {
RBinFile *a = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (a);
if (plugin && plugin->get_name) {
return plugin->get_name (a, type, idx);
}
return NULL;
}
static int r_bin_file_object_add(RBinFile *binfile, RBinObject *o) {
if (!o) {
return false;
}
r_list_append (binfile->objs, o);
r_bin_file_set_cur_binfile_obj (binfile->rbin, binfile, o);
return true;
}
static void binobj_set_baddr(RBinObject *o, ut64 baddr) {
if (!o || baddr == UT64_MAX) {
return;
}
o->baddr_shift = baddr - o->baddr;
}
static ut64 binobj_a2b(RBinObject *o, ut64 addr) {
return addr + (o? o->baddr_shift: 0);
}
static void filterStrings (RBin *bin, RList *strings) {
RBinString *ptr;
@ -571,6 +602,72 @@ static void r_bin_object_free(void /*RBinObject*/ *o_) {
R_FREE (o);
}
static char *swiftField(const char *dn, const char *cn) {
char *p = strstr (dn, ".getter_");
if (!p) {
p = strstr (dn, ".setter_");
if (!p) {
p = strstr (dn, ".method_");
}
}
if (p) {
char *q = strstr (dn, cn);
if (q && q[strlen (cn)] == '.') {
q = strdup (q + strlen (cn) + 1);
char *r = strchr (q, '.');
if (r) {
*r = 0;
}
return q;
}
}
return NULL;
}
R_API RList *r_bin_classes_from_symbols (RBinFile *bf, RBinObject *o) {
RBinSymbol *sym;
RListIter *iter;
RList *symbols = o->symbols;
RList *classes = o->classes;
if (!classes) {
classes = r_list_newf ((RListFree)r_bin_class_free);
}
r_list_foreach (symbols, iter, sym) {
if (sym->name[0] != '_') {
continue;
}
const char *cn = sym->classname;
if (cn) {
RBinClass *c = r_bin_class_new (bf, sym->classname, NULL, 0);
if (!c) {
continue;
}
// swift specific
char *dn = sym->dname;
char *fn = swiftField (dn, cn);
if (fn) {
// eprintf ("FIELD %s %s\n", cn, fn);
RBinField *f = r_bin_field_new (sym->paddr, sym->vaddr, sym->size, fn, NULL, NULL);
r_list_append (c->fields, f);
free (fn);
} else {
char *mn = strstr (dn, "..");
if (mn) {
// eprintf ("META %s %s\n", sym->classname, mn);
} else {
char *mn = strstr (dn, cn);
if (mn && mn[strlen(cn)] == '.') {
mn += strlen (cn) + 1;
// eprintf ("METHOD %s %s\n", sym->classname, mn);
r_list_append (c->methods, sym);
}
}
}
}
}
return classes;
}
// XXX - change this to RBinObject instead of RBinFile
// makes no sense to pass in a binfile and set the RBinObject
// kinda a clunky functions
@ -676,9 +773,14 @@ R_API int r_bin_object_set_items(RBinFile *binfile, RBinObject *o) {
if (bin->filter_rules & R_BIN_REQ_CLASSES) {
if (cp->classes) {
o->classes = cp->classes (binfile);
if (bin->filter) {
r_bin_filter_classes (o->classes);
if (r_bin_lang_swift (binfile)) {
o->classes = r_bin_classes_from_symbols (binfile, o);
}
} else {
o->classes = r_bin_classes_from_symbols (binfile, o);
}
if (bin->filter) {
r_bin_filter_classes (o->classes);
}
}
if (cp->lines) {
@ -1038,17 +1140,19 @@ static void r_bin_file_free(void /*RBinFile*/ *bf_) {
RBinFile *a = bf_;
RBinPlugin *plugin = r_bin_file_cur_plugin (a);
if (!a) return;
if (!a) {
return;
}
// Binary format objects are connected to the
// RBinObject, so the plugin must destroy the
// format data first
if (plugin && plugin->destroy)
if (plugin && plugin->destroy) {
plugin->destroy (a);
if (a->curxtr && a->curxtr->destroy && a->xtr_obj)
}
if (a->curxtr && a->curxtr->destroy && a->xtr_obj) {
a->curxtr->free_xtr ((void *)(a->xtr_obj));
}
r_buf_free (a->buf);
// TODO: unset related sdb namespaces
if (a && a->sdb_addrinfo) {
@ -1064,15 +1168,6 @@ static void r_bin_file_free(void /*RBinFile*/ *bf_) {
free (a);
}
static int r_bin_file_object_add(RBinFile *binfile, RBinObject *o) {
if (!o) {
return false;
}
r_list_append (binfile->objs, o);
r_bin_file_set_cur_binfile_obj (binfile->rbin, binfile, o);
return true;
}
static RBinFile *r_bin_file_create_append(RBin *bin, const char *file,
const ut8 *bytes, ut64 sz,
ut64 file_sz, int rawstr, int fd,
@ -1284,7 +1379,6 @@ static RBinFile *r_bin_file_new(RBin *bin, const char *file, const ut8 *bytes,
if (!res && steal_ptr) { // we own the ptr, free on error
free((void*) bytes);
}
binfile->rbin = bin;
binfile->file = strdup (file);
binfile->rawstr = rawstr;
@ -1477,11 +1571,11 @@ R_API int r_bin_xtr_add(RBin *bin, RBinXtrPlugin *foo) {
if (foo->init) {
foo->init (bin->user);
}
// avoid duplicates
r_list_foreach (bin->binxtrs, it, xtr) {
if (!strcmp (xtr->name, foo->name))
if (!strcmp (xtr->name, foo->name)) {
return false;
}
}
r_list_append (bin->binxtrs, foo);
return true;
@ -1639,13 +1733,6 @@ R_API ut64 r_bin_get_laddr(RBin *bin) {
return o? o->loadaddr: UT64_MAX;
}
static void binobj_set_baddr(RBinObject *o, ut64 baddr) {
if (!o || baddr == UT64_MAX) {
return;
}
o->baddr_shift = baddr - o->baddr;
}
R_API void r_bin_set_baddr(RBin *bin, ut64 baddr) {
RBinObject *o = r_bin_cur_object (bin);
binobj_set_baddr (o, baddr);
@ -1798,7 +1885,6 @@ R_API int r_bin_is_string(RBin *bin, ut64 va) {
return false;
}
//callee must not free the symbol
R_API RBinSymbol *r_bin_get_symbol_at_vaddr(RBin *bin, ut64 addr) {
//use skiplist here
@ -1813,7 +1899,6 @@ R_API RBinSymbol *r_bin_get_symbol_at_vaddr(RBin *bin, ut64 addr) {
return NULL;
}
//callee must not free the symbol
R_API RBinSymbol *r_bin_get_symbol_at_paddr(RBin *bin, ut64 addr) {
//use skiplist here
@ -2100,9 +2185,9 @@ R_API int r_bin_select_by_ids(RBin *bin, ut32 binfile_id, ut32 binobj_id) {
binfile = r_bin_file_find_by_id (bin, binfile_id);
obj = binfile? r_bin_file_object_find_by_id (binfile, binobj_id): NULL;
}
if (!binfile || !obj) return false;
if (!binfile || !obj) {
return false;
}
return obj && binfile && r_bin_file_set_cur_binfile_obj (bin, binfile, obj);
}
@ -2137,8 +2222,8 @@ static void list_xtr_archs(RBin *bin, int mode) {
bits = xtr_data->metadata->bits;
switch (mode) {
case 'q':
bin->cb_printf ("%s\n", arch);
break;
bin->cb_printf ("%s\n", arch);
break;
case 'j':
bin->cb_printf (
"%s{\"arch\":\"%s\",\"bits\":%d,"
@ -2279,24 +2364,6 @@ R_API void r_bin_set_user_ptr(RBin *bin, void *user) {
bin->user = user;
}
static int getoffset(RBin *bin, int type, int idx) {
RBinFile *a = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (a);
if (plugin && plugin->get_offset) {
return plugin->get_offset (a, type, idx);
}
return -1;
}
static const char *getname(RBin *bin, int type, int idx) {
RBinFile *a = r_bin_cur (bin);
RBinPlugin *plugin = r_bin_file_cur_plugin (a);
if (plugin && plugin->get_name) {
return plugin->get_name (a, type, idx);
}
return NULL;
}
R_API void r_bin_bind(RBin *bin, RBinBind *b) {
if (b) {
b->bin = bin;
@ -2321,8 +2388,7 @@ R_API RBuffer *r_bin_create(RBin *bin, const ut8 *code, int codelen,
return NULL;
}
R_API RBuffer *r_bin_package(RBin *bin, const char *type, const char *file,
RList *files) {
R_API RBuffer *r_bin_package(RBin *bin, const char *type, const char *file, RList *files) {
if (!strcmp (type, "zip")) {
#if 0
int zep = 0;
@ -2418,6 +2484,14 @@ R_API RList * /*<RBinClass>*/ r_bin_get_classes(RBin *bin) {
return o? o->classes: NULL;
}
R_API void r_bin_class_free(RBinClass *c) {
free (c->name);
free (c->super);
r_list_free (c->methods);
r_list_free (c->fields);
free (c);
}
R_API RBinClass *r_bin_class_new(RBinFile *binfile, const char *name,
const char *super, int view) {
RBinObject *o = binfile? binfile->o: NULL;
@ -2534,13 +2608,6 @@ R_API ut64 r_bin_get_vaddr(RBin *bin, ut64 paddr, ut64 vaddr) {
return r_binfile_get_vaddr (bin->cur, paddr, vaddr);
}
static ut64 binobj_a2b(RBinObject *o, ut64 addr) {
if (!o) {
return addr;
}
return o->baddr_shift + addr;
}
R_API ut64 r_bin_a2b(RBin *bin, ut64 addr) {
RBinObject *o = r_bin_cur_object (bin);
return o? o->baddr_shift + addr: addr;
@ -2548,10 +2615,7 @@ R_API ut64 r_bin_a2b(RBin *bin, ut64 addr) {
R_API ut64 r_bin_get_size(RBin *bin) {
RBinObject *o = r_bin_cur_object (bin);
if (o) {
return o->size;
}
return UT64_MAX;
return o? o->size: UT64_MAX;
}
R_API int r_bin_file_delete_all(RBin *bin) {
@ -2635,8 +2699,7 @@ R_API int r_bin_file_set_cur_by_fd(RBin *bin, ut32 bin_fd) {
return r_bin_file_set_cur_binfile (bin, bf);
}
R_API int r_bin_file_set_cur_binfile_obj(RBin *bin, RBinFile *bf,
RBinObject *obj) {
R_API int r_bin_file_set_cur_binfile_obj(RBin *bin, RBinFile *bf, RBinObject *obj) {
RBinPlugin *plugin = NULL;
if (!bin || !bf || !obj) {
return false;
@ -2654,10 +2717,7 @@ R_API int r_bin_file_set_cur_binfile_obj(RBin *bin, RBinFile *bf,
R_API int r_bin_file_set_cur_binfile(RBin *bin, RBinFile *bf) {
RBinObject *obj = bf? bf->o: NULL;
if (!obj) {
return false;
}
return r_bin_file_set_cur_binfile_obj (bin, bf, obj);
return obj? r_bin_file_set_cur_binfile_obj (bin, bf, obj): false;
}
R_API int r_bin_file_set_cur_by_name(RBin *bin, const char *name) {

View File

@ -89,8 +89,6 @@ static void get_method_list_t(mach0_ut p, RBinFile *arch, char *class_name, RBin
static void get_protocol_list_t(mach0_ut p, RBinFile *arch, RBinClass *klass);
static void get_class_ro_t(mach0_ut p, RBinFile *arch, ut32 *is_meta_class, RBinClass *klass);
static void get_class_t(mach0_ut p, RBinFile *arch, RBinClass *klass, bool dupe);
static void __r_bin_class_free(RBinClass *p);
static bool is_thumb(RBinFile *arch) {
struct MACH0_(obj_t) *bin = (struct MACH0_(obj_t) *)arch->o->bin_obj;
if (bin->hdr.cputype == 12) {
@ -981,29 +979,6 @@ static void get_class_t(mach0_ut p, RBinFile *arch, RBinClass *klass, bool dupe)
}
}
///////////////////////////////////////////////////////////////////////////////
static void __r_bin_class_free(RBinClass *p) {
RBinSymbol *symbol = NULL;
RBinField *field = NULL;
RListIter *iter = NULL;
if (!p) {
return;
}
r_list_foreach (p->methods, iter, symbol) {
free (symbol->name);
free (symbol->classname);
R_FREE (symbol);
}
r_list_foreach (p->fields, iter, field) {
free (field->name);
R_FREE (field);
}
r_list_free (p->methods);
r_list_free (p->fields);
r_bin_class_free (p);
}
#if 0
static RList *parse_swift_classes(RBinFile *bf) {
bool is_swift = false;
@ -1086,7 +1061,7 @@ RList *MACH0_(parse_classes)(RBinFile *arch) {
}
// end of seaching of section with name __objc_classlist
if (!ret && !(ret = r_list_newf ((RListFree)__r_bin_class_free))) {
if (!ret && !(ret = r_list_newf ((RListFree)r_bin_class_free))) {
// retain just for debug
// eprintf ("RList<RBinClass> allocation error\n");
goto get_classes_error;
@ -1142,6 +1117,7 @@ RList *MACH0_(parse_classes)(RBinFile *arch) {
get_classes_error:
r_list_free (sctns);
r_list_free (ret);
__r_bin_class_free (klass);
r_bin_class_free (klass);
//__r_bin_class_free (klass);
return NULL;
}

View File

@ -211,6 +211,25 @@ static RList* symbols(RBinFile *arch) {
break;
}
ptr->name = strdup ((char*)symbols[i].name);
if (ptr->name[0] == '_' && strncmp (ptr->name, "imp.", 4)) {
char *dn = r_bin_demangle (arch, ptr->name, ptr->name, ptr->vaddr);
if (dn) {
ptr->dname = dn;
char *p = strchr (dn, '.');
if (p) {
if (IS_UPPER (ptr->name[0])) {
ptr->classname = strdup (ptr->name);
ptr->classname[p - ptr->name] = 0;
} else if (IS_UPPER (p[1])) {
ptr->classname = strdup (p + 1);
p = strchr (ptr->classname, '.');
if (p) {
*p = 0;
}
}
}
}
}
ptr->forwarder = r_str_const ("NONE");
ptr->bind = r_str_const ((symbols[i].type == R_BIN_MACH0_SYMBOL_TYPE_LOCAL)?
"LOCAL": "GLOBAL");

View File

@ -2327,7 +2327,7 @@ static int bin_classes(RCore *r, int mode) {
}
r_list_foreach (c->methods, iter2, sym) {
r_cons_printf ("0x%08"PFMT64x" method %d %s\n",
sym->vaddr, m, sym->name);
sym->vaddr, m, sym->dname? sym->dname: sym->name);
m++;
}
}

View File

@ -382,6 +382,7 @@ typedef struct r_bin_class_t {
typedef struct r_bin_symbol_t {
/* heap-allocated */
char *name;
char *dname;
char *classname;
/* const-unique-strings */
const char *forwarder;
@ -485,8 +486,6 @@ typedef struct r_bin_bind_t {
#ifdef R_API
#define r_bin_class_free(x) { free(x->name);free(x->super);free (x); }
/* bin.c */
R_API void r_bin_load_filter(RBin *bin, ut64 rules);
R_API int r_bin_load(RBin *bin, const char *file, ut64 baseaddr, ut64 loadaddr, int xtr_idx, int fd, int rawstr);
@ -554,6 +553,7 @@ R_API RList* /*<RBinClass>*/r_bin_get_classes(RBin *bin);
R_API RBinClass *r_bin_class_get (RBinFile *binfile, const char *name);
R_API RBinClass *r_bin_class_new (RBinFile *binfile, const char *name, const char *super, int view);
R_API void r_bin_class_free(RBinClass *c);
R_API RBinSymbol *r_bin_class_add_method (RBinFile *binfile, const char *classname, const char *name, int nargs);
R_API void r_bin_class_add_field (RBinFile *binfile, const char *classname, const char *name);