2019-05-27 16:18:01 +00:00
|
|
|
/* radare2 - LGPL - Copyright 2009-2019 - pancake, nibble, dso */
|
2018-03-04 22:52:45 +00:00
|
|
|
|
|
|
|
#include <r_bin.h>
|
|
|
|
#include <r_util.h>
|
2018-11-05 10:25:31 +00:00
|
|
|
#include "i/private.h"
|
2018-03-04 22:52:45 +00:00
|
|
|
|
2019-06-16 16:36:33 +00:00
|
|
|
R_API void r_bin_mem_free(void *data) {
|
2018-11-07 09:52:32 +00:00
|
|
|
RBinMem *mem = (RBinMem *)data;
|
|
|
|
if (mem && mem->mirrors) {
|
2019-06-16 16:36:33 +00:00
|
|
|
mem->mirrors->free = r_bin_mem_free;
|
2018-11-07 09:52:32 +00:00
|
|
|
r_list_free (mem->mirrors);
|
|
|
|
mem->mirrors = NULL;
|
|
|
|
}
|
|
|
|
free (mem);
|
|
|
|
}
|
|
|
|
|
2019-09-26 09:36:20 +00:00
|
|
|
static int reloc_cmp(const void *a, const RBNode *b, void *user) {
|
2019-01-21 10:40:24 +00:00
|
|
|
const RBinReloc *ar = (const RBinReloc *)a;
|
|
|
|
const RBinReloc *br = container_of (b, const RBinReloc, vrb);
|
|
|
|
if (ar->vaddr > br->vaddr) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (ar->vaddr < br->vaddr) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-12-04 09:10:33 +00:00
|
|
|
static void reloc_free(RBNode *rbn, void *user) {
|
2019-01-21 10:40:24 +00:00
|
|
|
free (container_of (rbn, RBinReloc, vrb));
|
|
|
|
}
|
|
|
|
|
2018-11-07 09:52:32 +00:00
|
|
|
static void object_delete_items(RBinObject *o) {
|
|
|
|
ut32 i = 0;
|
|
|
|
r_return_if_fail (o);
|
|
|
|
sdb_free (o->addr2klassmethod);
|
|
|
|
r_list_free (o->entries);
|
|
|
|
r_list_free (o->fields);
|
|
|
|
r_list_free (o->imports);
|
|
|
|
r_list_free (o->libs);
|
2019-12-04 09:10:33 +00:00
|
|
|
r_rbtree_free (o->relocs, reloc_free, NULL);
|
2018-11-07 09:52:32 +00:00
|
|
|
r_list_free (o->sections);
|
|
|
|
r_list_free (o->strings);
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_free (o->strings_db);
|
2018-11-07 09:52:32 +00:00
|
|
|
r_list_free (o->symbols);
|
|
|
|
r_list_free (o->classes);
|
2019-05-08 15:05:55 +00:00
|
|
|
ht_pp_free (o->classes_ht);
|
2019-06-07 01:50:22 +00:00
|
|
|
ht_pp_free (o->methods_ht);
|
2018-11-07 09:52:32 +00:00
|
|
|
r_list_free (o->lines);
|
|
|
|
sdb_free (o->kv);
|
|
|
|
r_list_free (o->mem);
|
|
|
|
for (i = 0; i < R_BIN_SYM_LAST; i++) {
|
|
|
|
free (o->binsym[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-05 10:25:31 +00:00
|
|
|
R_IPI void r_bin_object_free(void /*RBinObject*/ *o_) {
|
2018-03-04 22:52:45 +00:00
|
|
|
RBinObject *o = o_;
|
2019-06-16 16:36:33 +00:00
|
|
|
if (o) {
|
|
|
|
free (o->regstate);
|
|
|
|
r_bin_info_free (o->info);
|
|
|
|
object_delete_items (o);
|
|
|
|
free (o);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-07 09:52:32 +00:00
|
|
|
static char *swiftField(const char *dn, const char *cn) {
|
|
|
|
if (!dn || !cn) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static RList *classes_from_symbols(RBinFile *bf) {
|
|
|
|
RBinSymbol *sym;
|
|
|
|
RListIter *iter;
|
2019-06-07 12:06:37 +00:00
|
|
|
r_list_foreach (bf->o->symbols, iter, sym) {
|
2018-11-07 09:52:32 +00:00
|
|
|
if (sym->name[0] != '_') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const char *cn = sym->classname;
|
|
|
|
if (cn) {
|
2019-06-07 01:50:22 +00:00
|
|
|
RBinClass *c = r_bin_file_add_class (bf, sym->classname, NULL, 0);
|
2018-11-07 09:52:32 +00:00
|
|
|
if (!c) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// swift specific
|
|
|
|
char *dn = sym->dname;
|
|
|
|
char *fn = swiftField (dn, cn);
|
|
|
|
if (fn) {
|
|
|
|
// eprintf ("FIELD %s %s\n", cn, fn);
|
2019-09-16 17:35:19 +00:00
|
|
|
RBinField *f = r_bin_field_new (sym->paddr, sym->vaddr, sym->size, fn, NULL, NULL, false);
|
2018-11-07 09:52:32 +00:00
|
|
|
r_list_append (c->fields, f);
|
|
|
|
free (fn);
|
|
|
|
} else {
|
|
|
|
char *mn = strstr (dn, "..");
|
2019-05-27 16:18:01 +00:00
|
|
|
if (!mn) {
|
|
|
|
mn = strstr (dn, cn);
|
2018-11-07 09:52:32 +00:00
|
|
|
if (mn && mn[strlen (cn)] == '.') {
|
|
|
|
mn += strlen (cn) + 1;
|
|
|
|
// eprintf ("METHOD %s %s\n", sym->classname, mn);
|
|
|
|
r_list_append (c->methods, sym);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-07 12:06:37 +00:00
|
|
|
return bf->o->classes;
|
2018-11-07 09:52:32 +00:00
|
|
|
}
|
|
|
|
|
2019-06-18 05:19:47 +00:00
|
|
|
// TODO: kill offset and sz, because those should be inferred from binfile->buf
|
2019-05-27 16:18:01 +00:00
|
|
|
R_IPI RBinObject *r_bin_object_new(RBinFile *bf, RBinPlugin *plugin, ut64 baseaddr, ut64 loadaddr, ut64 offset, ut64 sz) {
|
|
|
|
r_return_val_if_fail (bf && plugin, NULL);
|
|
|
|
ut64 bytes_sz = r_buf_size (bf->buf);
|
|
|
|
Sdb *sdb = bf->sdb;
|
2018-03-04 22:52:45 +00:00
|
|
|
RBinObject *o = R_NEW0 (RBinObject);
|
|
|
|
if (!o) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-12-03 00:19:59 +00:00
|
|
|
o->obj_size = (bytes_sz >= sz + offset)? sz: 0;
|
2018-03-04 22:52:45 +00:00
|
|
|
o->boffset = offset;
|
2018-11-14 09:47:28 +00:00
|
|
|
o->strings_db = ht_up_new0 ();
|
2018-09-09 01:38:59 +00:00
|
|
|
o->regstate = NULL;
|
2019-06-16 16:36:33 +00:00
|
|
|
o->kv = sdb_new0 (); // XXX bf->sdb bf->o->sdb wtf
|
2018-03-04 22:52:45 +00:00
|
|
|
o->baddr = baseaddr;
|
2019-06-07 12:06:37 +00:00
|
|
|
o->classes = r_list_newf ((RListFree)r_bin_class_free);
|
2019-06-07 01:50:22 +00:00
|
|
|
o->classes_ht = ht_pp_new0 ();
|
|
|
|
o->methods_ht = ht_pp_new0 ();
|
2018-03-04 22:52:45 +00:00
|
|
|
o->baddr_shift = 0;
|
|
|
|
o->plugin = plugin;
|
|
|
|
o->loadaddr = loadaddr != UT64_MAX ? loadaddr : 0;
|
|
|
|
|
2018-12-03 00:19:59 +00:00
|
|
|
if (plugin && plugin->load_buffer) {
|
2019-05-27 16:18:01 +00:00
|
|
|
if (!plugin->load_buffer (bf, &o->bin_obj, bf->buf, loadaddr, sdb)) {
|
|
|
|
if (bf->rbin->verbose) {
|
|
|
|
eprintf ("Error in r_bin_object_new: load_buffer failed for %s plugin\n", plugin->name);
|
|
|
|
}
|
2018-04-03 18:23:26 +00:00
|
|
|
sdb_free (o->kv);
|
|
|
|
free (o);
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-03-04 22:52:45 +00:00
|
|
|
} else {
|
2018-11-07 09:52:32 +00:00
|
|
|
R_LOG_WARN ("Plugin %s should implement load_buffer method.\n", plugin->name);
|
2018-03-04 22:52:45 +00:00
|
|
|
sdb_free (o->kv);
|
|
|
|
free (o);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-06-18 05:19:47 +00:00
|
|
|
// XXX - object size can't be set here and needs to be set where where
|
2018-11-07 09:52:32 +00:00
|
|
|
// the object is created from. The reason for this is to prevent
|
2018-03-04 22:52:45 +00:00
|
|
|
// mis-reporting when the file is loaded from impartial bytes or is
|
2018-11-07 09:52:32 +00:00
|
|
|
// extracted from a set of bytes in the file
|
2019-06-16 21:35:12 +00:00
|
|
|
r_bin_file_set_obj (bf->rbin, bf, o);
|
2019-06-10 09:25:34 +00:00
|
|
|
r_bin_set_baddr (bf->rbin, o->baddr);
|
2020-05-08 10:20:37 +00:00
|
|
|
r_bin_object_set_items (bf, o);
|
2018-03-04 22:52:45 +00:00
|
|
|
|
2019-05-27 16:18:01 +00:00
|
|
|
bf->sdb_info = o->kv;
|
|
|
|
sdb = bf->rbin->sdb;
|
|
|
|
if (sdb) {
|
|
|
|
Sdb *bdb = bf->sdb; // sdb_new0 ();
|
|
|
|
sdb_ns_set (bdb, "info", o->kv);
|
|
|
|
sdb_ns_set (bdb, "addrinfo", bf->sdb_addrinfo);
|
|
|
|
o->kv = bdb;
|
|
|
|
// bf->sdb = o->kv;
|
|
|
|
// bf->sdb_info = o->kv;
|
|
|
|
// sdb_ns_set (bf->sdb, "info", o->kv);
|
|
|
|
//sdb_ns (sdb, sdb_fmt ("fd.%d", bf->fd), 1);
|
|
|
|
sdb_set (bf->sdb, "archs", "0:0:x86:32", 0); // x86??
|
|
|
|
/* NOTE */
|
|
|
|
/* Those refs++ are necessary because sdb_ns() doesnt rerefs all
|
|
|
|
* sub-namespaces */
|
|
|
|
/* And if any namespace is referenced backwards it gets
|
|
|
|
* double-freed */
|
|
|
|
// bf->sdb_info = sdb_ns (bf->sdb, "info", 1);
|
|
|
|
// bf->sdb_addrinfo = sdb_ns (bf->sdb, "addrinfo", 1);
|
|
|
|
// bf->sdb_addrinfo->refs++;
|
|
|
|
sdb_ns_set (sdb, "cur", bdb); // bf->sdb);
|
|
|
|
const char *fdns = sdb_fmt ("fd.%d", bf->fd);
|
|
|
|
sdb_ns_set (sdb, fdns, bdb); // bf->sdb);
|
|
|
|
bf->sdb->refs++;
|
|
|
|
}
|
2018-03-04 22:52:45 +00:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2018-10-27 03:01:09 +00:00
|
|
|
static void filter_classes(RBinFile *bf, RList *list) {
|
|
|
|
Sdb *db = sdb_new0 ();
|
2019-05-09 09:08:58 +00:00
|
|
|
HtPP *ht = ht_pp_new0 ();
|
2018-10-27 03:01:09 +00:00
|
|
|
RListIter *iter, *iter2;
|
|
|
|
RBinClass *cls;
|
|
|
|
RBinSymbol *sym;
|
|
|
|
r_list_foreach (list, iter, cls) {
|
|
|
|
if (!cls->name) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int namepad_len = strlen (cls->name) + 32;
|
|
|
|
char *namepad = malloc (namepad_len + 1);
|
|
|
|
if (namepad) {
|
2018-11-11 23:04:41 +00:00
|
|
|
char *p;
|
2018-10-27 03:01:09 +00:00
|
|
|
strcpy (namepad, cls->name);
|
2018-11-11 23:04:41 +00:00
|
|
|
p = r_bin_filter_name (bf, db, cls->index, namepad);
|
|
|
|
if (p) {
|
|
|
|
namepad = p;
|
|
|
|
}
|
2018-10-27 03:01:09 +00:00
|
|
|
free (cls->name);
|
|
|
|
cls->name = namepad;
|
|
|
|
r_list_foreach (cls->methods, iter2, sym) {
|
|
|
|
if (sym->name) {
|
2019-05-09 09:08:58 +00:00
|
|
|
r_bin_filter_sym (bf, ht, sym->vaddr, sym);
|
2018-10-27 03:01:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
eprintf ("Cannot alloc %d byte(s)\n", namepad_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sdb_free (db);
|
2019-05-09 09:08:58 +00:00
|
|
|
ht_pp_free (ht);
|
2018-10-27 03:01:09 +00:00
|
|
|
}
|
|
|
|
|
2019-01-21 10:40:24 +00:00
|
|
|
static RBNode *list2rbtree(RList *relocs) {
|
|
|
|
RListIter *it;
|
|
|
|
RBinReloc *reloc;
|
|
|
|
RBNode *res = NULL;
|
|
|
|
|
|
|
|
r_list_foreach (relocs, it, reloc) {
|
2019-09-26 09:36:20 +00:00
|
|
|
r_rbtree_insert (&res, reloc, &reloc->vrb, reloc_cmp, NULL);
|
2019-01-21 10:40:24 +00:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2020-02-16 14:43:31 +00:00
|
|
|
static void r_bin_object_rebuild_classes_ht(RBinObject *o) {
|
|
|
|
ht_pp_free (o->classes_ht);
|
|
|
|
ht_pp_free (o->methods_ht);
|
|
|
|
o->classes_ht = ht_pp_new0 ();
|
|
|
|
o->methods_ht = ht_pp_new0 ();
|
|
|
|
|
|
|
|
RListIter *it, *it2;
|
|
|
|
RBinClass *klass;
|
|
|
|
RBinSymbol *method;
|
|
|
|
r_list_foreach (o->classes, it, klass) {
|
2020-02-21 10:05:55 +00:00
|
|
|
if (klass->name) {
|
|
|
|
ht_pp_insert (o->classes_ht, klass->name, klass);
|
2020-02-16 14:43:31 +00:00
|
|
|
|
2020-02-21 10:05:55 +00:00
|
|
|
r_list_foreach (klass->methods, it2, method) {
|
|
|
|
const char *name = sdb_fmt ("%s::%s", klass->name, method->name);
|
|
|
|
ht_pp_insert (o->methods_ht, name, method);
|
|
|
|
}
|
2020-02-16 14:43:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-10 09:25:34 +00:00
|
|
|
R_API int r_bin_object_set_items(RBinFile *bf, RBinObject *o) {
|
|
|
|
r_return_val_if_fail (bf && o && o->plugin, false);
|
2018-10-20 23:27:15 +00:00
|
|
|
|
2019-06-16 16:36:33 +00:00
|
|
|
int i;
|
|
|
|
bool isSwift = false;
|
2019-06-10 09:25:34 +00:00
|
|
|
RBin *bin = bf->rbin;
|
|
|
|
RBinPlugin *p = o->plugin;
|
|
|
|
int minlen = (bf->rbin->minstrlen > 0) ? bf->rbin->minstrlen : p->minstrlen;
|
|
|
|
bf->o = o;
|
2018-03-15 10:46:07 +00:00
|
|
|
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->file_type) {
|
|
|
|
int type = p->file_type (bf);
|
2018-03-15 10:46:07 +00:00
|
|
|
if (type == R_BIN_TYPE_CORE) {
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->regstate) {
|
|
|
|
o->regstate = p->regstate (bf);
|
2018-03-15 10:46:07 +00:00
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->maps) {
|
|
|
|
o->maps = p->maps (bf);
|
2018-03-15 10:46:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->boffset) {
|
|
|
|
o->boffset = p->boffset (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
// XXX: no way to get info from xtr pluginz?
|
|
|
|
// Note, object size can not be set from here due to potential
|
|
|
|
// inconsistencies
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->size) {
|
|
|
|
o->size = p->size (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
2018-10-27 03:01:09 +00:00
|
|
|
// XXX this is expensive because is O(n^n)
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->binsym) {
|
2018-03-04 22:52:45 +00:00
|
|
|
for (i = 0; i < R_BIN_SYM_LAST; i++) {
|
2019-06-10 09:25:34 +00:00
|
|
|
o->binsym[i] = p->binsym (bf, i);
|
2018-03-04 22:52:45 +00:00
|
|
|
if (o->binsym[i]) {
|
|
|
|
o->binsym[i]->paddr += o->loadaddr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->entries) {
|
|
|
|
o->entries = p->entries (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
REBASE_PADDR (o, o->entries, RBinAddr);
|
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->fields) {
|
|
|
|
o->fields = p->fields (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
if (o->fields) {
|
|
|
|
o->fields->free = r_bin_field_free;
|
|
|
|
REBASE_PADDR (o, o->fields, RBinField);
|
|
|
|
}
|
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->imports) {
|
2018-03-04 22:52:45 +00:00
|
|
|
r_list_free (o->imports);
|
2019-06-10 09:25:34 +00:00
|
|
|
o->imports = p->imports (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
if (o->imports) {
|
|
|
|
o->imports->free = r_bin_import_free;
|
|
|
|
}
|
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->symbols) {
|
|
|
|
o->symbols = p->symbols (bf); // 5s
|
2018-11-07 09:52:32 +00:00
|
|
|
if (o->symbols) {
|
|
|
|
o->symbols->free = r_bin_symbol_free;
|
|
|
|
REBASE_PADDR (o, o->symbols, RBinSymbol);
|
|
|
|
if (bin->filter) {
|
2019-06-10 09:25:34 +00:00
|
|
|
r_bin_filter_symbols (bf, o->symbols); // 5s
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
o->info = p->info? p->info (bf): NULL;
|
|
|
|
if (p->libs) {
|
|
|
|
o->libs = p->libs (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->sections) {
|
2018-03-04 22:52:45 +00:00
|
|
|
// XXX sections are populated by call to size
|
|
|
|
if (!o->sections) {
|
2019-06-10 09:25:34 +00:00
|
|
|
o->sections = p->sections (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
REBASE_PADDR (o, o->sections, RBinSection);
|
|
|
|
if (bin->filter) {
|
2019-06-10 09:25:34 +00:00
|
|
|
r_bin_filter_sections (bf, o->sections);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bin->filter_rules & (R_BIN_REQ_RELOCS | R_BIN_REQ_IMPORTS)) {
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->relocs) {
|
|
|
|
RList *l = p->relocs (bf);
|
2019-02-06 13:21:57 +00:00
|
|
|
if (l) {
|
|
|
|
REBASE_PADDR (o, l, RBinReloc);
|
|
|
|
o->relocs = list2rbtree (l);
|
|
|
|
l->free = NULL;
|
2019-10-24 12:33:54 +00:00
|
|
|
r_list_free (l);
|
2019-02-06 13:21:57 +00:00
|
|
|
}
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bin->filter_rules & R_BIN_REQ_STRINGS) {
|
2019-06-16 16:36:33 +00:00
|
|
|
o->strings = p->strings
|
|
|
|
? p->strings (bf)
|
|
|
|
: r_bin_file_get_strings (bf, minlen, 0, bf->rawstr);
|
2018-03-04 22:52:45 +00:00
|
|
|
if (bin->debase64) {
|
|
|
|
r_bin_object_filter_strings (o);
|
|
|
|
}
|
|
|
|
REBASE_PADDR (o, o->strings, RBinString);
|
|
|
|
}
|
|
|
|
if (bin->filter_rules & R_BIN_REQ_CLASSES) {
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->classes) {
|
|
|
|
RList *classes = p->classes (bf);
|
2019-06-08 23:19:49 +00:00
|
|
|
if (classes) {
|
|
|
|
// XXX we should probably merge them instead
|
|
|
|
r_list_free (o->classes);
|
|
|
|
o->classes = classes;
|
2020-02-16 14:43:31 +00:00
|
|
|
r_bin_object_rebuild_classes_ht (o);
|
2019-06-08 23:19:49 +00:00
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
isSwift = r_bin_lang_swift (bf);
|
2018-10-27 03:01:09 +00:00
|
|
|
if (isSwift) {
|
2019-06-10 09:25:34 +00:00
|
|
|
o->classes = classes_from_symbols (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
} else {
|
2019-06-10 09:25:34 +00:00
|
|
|
RList *classes = classes_from_symbols (bf);
|
2019-06-08 23:19:49 +00:00
|
|
|
if (classes) {
|
|
|
|
o->classes = classes;
|
|
|
|
}
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
if (bin->filter) {
|
2019-06-10 09:25:34 +00:00
|
|
|
filter_classes (bf, o->classes);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
2018-03-23 12:51:47 +00:00
|
|
|
// cache addr=class+method
|
2018-05-14 15:35:51 +00:00
|
|
|
if (o->classes) {
|
|
|
|
RList *klasses = o->classes;
|
2018-03-23 12:57:49 +00:00
|
|
|
RListIter *iter, *iter2;
|
|
|
|
RBinClass *klass;
|
|
|
|
RBinSymbol *method;
|
|
|
|
if (!o->addr2klassmethod) {
|
|
|
|
// this is slow. must be optimized, but at least its cached
|
|
|
|
o->addr2klassmethod = sdb_new0 ();
|
|
|
|
r_list_foreach (klasses, iter, klass) {
|
|
|
|
r_list_foreach (klass->methods, iter2, method) {
|
2018-04-10 21:52:47 +00:00
|
|
|
char *km = sdb_fmt ("method.%s.%s", klass->name, method->name);
|
|
|
|
char *at = sdb_fmt ("0x%08"PFMT64x, method->vaddr);
|
2018-03-23 12:57:49 +00:00
|
|
|
sdb_set (o->addr2klassmethod, at, km, 0);
|
|
|
|
}
|
2018-03-23 12:51:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->lines) {
|
|
|
|
o->lines = p->lines (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->get_sdb) {
|
|
|
|
Sdb* new_kv = p->get_sdb (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
if (new_kv != o->kv) {
|
|
|
|
sdb_free (o->kv);
|
|
|
|
}
|
|
|
|
o->kv = new_kv;
|
|
|
|
}
|
2019-06-10 09:25:34 +00:00
|
|
|
if (p->mem) {
|
|
|
|
o->mem = p->mem (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
2019-06-16 16:36:33 +00:00
|
|
|
if (bin->filter_rules & (R_BIN_REQ_INFO | R_BIN_REQ_SYMBOLS | R_BIN_REQ_IMPORTS)) {
|
|
|
|
o->lang = isSwift? R_BIN_NM_SWIFT: r_bin_load_languages (bf);
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-21 10:40:24 +00:00
|
|
|
R_IPI RBNode *r_bin_object_patch_relocs(RBin *bin, RBinObject *o) {
|
|
|
|
r_return_val_if_fail (bin && o, NULL);
|
|
|
|
|
|
|
|
static bool first = true;
|
|
|
|
// r_bin_object_set_items set o->relocs but there we don't have access
|
2019-06-02 21:35:38 +00:00
|
|
|
// to io so we need to be run from bin_relocs, free the previous reloc and get
|
2019-01-21 10:40:24 +00:00
|
|
|
// the patched ones
|
|
|
|
if (first && o->plugin && o->plugin->patch_relocs) {
|
|
|
|
RList *tmp = o->plugin->patch_relocs (bin);
|
|
|
|
first = false;
|
|
|
|
if (!tmp) {
|
|
|
|
return o->relocs;
|
|
|
|
}
|
2019-12-04 09:10:33 +00:00
|
|
|
r_rbtree_free (o->relocs, reloc_free, NULL);
|
2019-01-21 10:40:24 +00:00
|
|
|
REBASE_PADDR (o, tmp, RBinReloc);
|
|
|
|
o->relocs = list2rbtree (tmp);
|
|
|
|
first = false;
|
2020-09-08 07:52:35 +00:00
|
|
|
bin->is_reloc_patched = true;
|
2019-01-21 10:40:24 +00:00
|
|
|
}
|
|
|
|
return o->relocs;
|
|
|
|
}
|
|
|
|
|
2018-11-05 10:25:31 +00:00
|
|
|
R_IPI RBinObject *r_bin_object_get_cur(RBin *bin) {
|
2018-11-07 22:57:24 +00:00
|
|
|
r_return_val_if_fail (bin && bin->cur, NULL);
|
|
|
|
return bin->cur->o;
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
|
2019-06-02 21:35:38 +00:00
|
|
|
R_IPI RBinObject *r_bin_object_find_by_arch_bits(RBinFile *bf, const char *arch, int bits, const char *name) {
|
2019-06-04 01:35:01 +00:00
|
|
|
r_return_val_if_fail (bf && arch && name, NULL);
|
2019-07-05 16:43:15 +00:00
|
|
|
if (bf->o) {
|
|
|
|
RBinInfo *info = bf->o->info;
|
|
|
|
if (info && info->arch && info->file &&
|
|
|
|
(bits == info->bits) &&
|
|
|
|
!strcmp (info->arch, arch) &&
|
|
|
|
!strcmp (info->file, name)) {
|
|
|
|
return bf->o;
|
|
|
|
}
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
2018-10-30 08:07:58 +00:00
|
|
|
return NULL;
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
|
2019-06-05 23:23:59 +00:00
|
|
|
R_API bool r_bin_object_delete(RBin *bin, ut32 bf_id) {
|
2018-10-20 23:27:15 +00:00
|
|
|
r_return_val_if_fail (bin, false);
|
|
|
|
|
2019-06-16 16:36:33 +00:00
|
|
|
bool res = false;
|
2019-06-05 23:23:59 +00:00
|
|
|
RBinFile *bf = r_bin_file_find_by_id (bin, bf_id);
|
2019-06-02 21:35:38 +00:00
|
|
|
if (bf) {
|
2019-06-05 23:23:59 +00:00
|
|
|
if (bin->cur == bf) {
|
|
|
|
bin->cur = NULL;
|
|
|
|
}
|
|
|
|
// wtf
|
|
|
|
if (!bf->o) {
|
|
|
|
r_list_delete_data (bin->binfiles, bf);
|
|
|
|
}
|
2018-03-04 22:52:45 +00:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2018-11-05 10:25:31 +00:00
|
|
|
R_IPI void r_bin_object_filter_strings(RBinObject *bo) {
|
2019-07-02 23:21:41 +00:00
|
|
|
r_return_if_fail (bo && bo->strings);
|
2018-10-20 23:27:15 +00:00
|
|
|
|
2018-03-04 22:52:45 +00:00
|
|
|
RList *strings = bo->strings;
|
|
|
|
RBinString *ptr;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (strings, iter, ptr) {
|
|
|
|
char *dec = (char *)r_base64_decode_dyn (ptr->string, -1);
|
|
|
|
if (dec) {
|
|
|
|
char *s = ptr->string;
|
|
|
|
for (;;) {
|
|
|
|
char *dec2 = (char *)r_base64_decode_dyn (s, -1);
|
|
|
|
if (!dec2) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!r_str_is_printable (dec2)) {
|
|
|
|
free (dec2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free (dec);
|
|
|
|
s = dec = dec2;
|
|
|
|
}
|
|
|
|
if (r_str_is_printable (dec) && strlen (dec) > 3) {
|
|
|
|
free (ptr->string);
|
|
|
|
ptr->string = dec;
|
|
|
|
ptr->type = R_STRING_TYPE_BASE64;
|
|
|
|
} else {
|
|
|
|
free (dec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|