2011-02-23 19:53:56 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2011 nibble<.ds@gmail.com> */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
/* TODO:
|
|
|
|
* dlopen library and show address
|
|
|
|
*/
|
|
|
|
|
2009-03-08 15:49:15 +00:00
|
|
|
#include <r_types.h>
|
2010-01-24 11:40:48 +00:00
|
|
|
#include <r_util.h>
|
2009-03-08 15:49:15 +00:00
|
|
|
#include <r_lib.h>
|
2010-03-10 10:01:38 +00:00
|
|
|
#include <r_list.h>
|
2009-03-08 15:49:15 +00:00
|
|
|
#include <r_bin.h>
|
2010-03-10 10:01:38 +00:00
|
|
|
#include <list.h>
|
2009-03-09 12:03:42 +00:00
|
|
|
#include "../config.h"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-05-25 23:42:22 +00:00
|
|
|
static RBinPlugin *bin_static_plugins[] = { R_BIN_STATIC_PLUGINS };
|
2010-09-24 19:23:13 +00:00
|
|
|
static RBinXtrPlugin *bin_xtr_static_plugins[] = { R_BIN_XTR_STATIC_PLUGINS };
|
2010-02-07 12:17:51 +00:00
|
|
|
|
2010-10-17 18:38:19 +00:00
|
|
|
static void get_strings_range(RBinArch *arch, RList *list, int min, ut64 from, ut64 to, ut64 scnrva) {
|
2009-07-05 14:49:47 +00:00
|
|
|
char str[R_BIN_SIZEOF_STRINGS];
|
2010-03-10 10:01:38 +00:00
|
|
|
int i, matches = 0, ctr = 0;
|
2010-06-23 15:30:16 +00:00
|
|
|
RBinString *ptr = NULL;
|
2009-03-16 23:34:45 +00:00
|
|
|
|
2011-09-02 01:09:26 +00:00
|
|
|
if (to > arch->buf->length)
|
|
|
|
to = arch->buf->length;
|
|
|
|
for (i = from; i < to; i++) {
|
2010-09-24 19:23:13 +00:00
|
|
|
if ((IS_PRINTABLE (arch->buf->buf[i])) && matches < R_BIN_SIZEOF_STRINGS-1) {
|
|
|
|
str[matches] = arch->buf->buf[i];
|
2010-06-20 22:48:06 +00:00
|
|
|
matches++;
|
2011-02-23 19:53:56 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* check if the length fits in our request */
|
|
|
|
if (matches >= min) {
|
|
|
|
if (!(ptr = R_NEW (RBinString))) {
|
|
|
|
eprintf ("Error allocating string\n");
|
|
|
|
break;
|
2009-03-16 23:34:45 +00:00
|
|
|
}
|
2011-02-23 19:53:56 +00:00
|
|
|
str[matches] = '\0';
|
|
|
|
ptr->offset = i-matches;
|
2011-12-01 08:32:16 +00:00
|
|
|
ptr->rva = ptr->offset-from+scnrva;
|
|
|
|
//HACK if (scnrva) ptr->rva = ptr->offset-from+scnrva; else ptr->rva = ptr->offset;
|
2011-06-09 00:12:46 +00:00
|
|
|
ptr->size = matches+1;
|
2011-02-23 19:53:56 +00:00
|
|
|
ptr->ordinal = ctr;
|
|
|
|
// copying so many bytes here..
|
|
|
|
memcpy (ptr->string, str, R_BIN_SIZEOF_STRINGS);
|
|
|
|
ptr->string[R_BIN_SIZEOF_STRINGS-1] = '\0';
|
2011-06-04 03:27:26 +00:00
|
|
|
r_name_filter (ptr->string, R_BIN_SIZEOF_STRINGS-1);
|
2011-02-23 19:53:56 +00:00
|
|
|
r_list_append (list, ptr);
|
|
|
|
ctr++;
|
2009-03-16 23:34:45 +00:00
|
|
|
}
|
2011-02-23 19:53:56 +00:00
|
|
|
matches = 0;
|
2009-03-16 23:34:45 +00:00
|
|
|
}
|
2010-06-23 15:30:16 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
static int is_data_section(RBinArch *a, RBinSection *s) {
|
|
|
|
// XXX: DIRTY HACK! should we check sections srwx to be READ ONLY and NONEXEC?
|
|
|
|
if (strstr (a->info->bclass, "MACH0") && strstr (s->name, "_cstring")) // OSX
|
|
|
|
return 1;
|
|
|
|
if (strstr (a->info->bclass, "ELF") && strstr (s->name, "data")) // LINUX
|
|
|
|
return 1;
|
|
|
|
if (strstr (a->info->bclass, "PE"))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-06-23 15:30:16 +00:00
|
|
|
// TODO: check only in data section. filter chars only in -r mode
|
2011-10-05 00:38:37 +00:00
|
|
|
static RList* get_strings(RBinArch *a, int min) {
|
|
|
|
RBinSection *section;
|
|
|
|
RListIter *iter;
|
2010-06-23 15:30:16 +00:00
|
|
|
RList *ret;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
if (!(ret = r_list_new ())) {
|
|
|
|
eprintf ("Error allocating array\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ret->free = free;
|
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
if (a->sections) {
|
|
|
|
r_list_foreach (a->sections, iter, section) {
|
|
|
|
if (is_data_section (a, section)) {
|
2010-06-23 15:30:16 +00:00
|
|
|
count ++;
|
2011-10-05 00:38:37 +00:00
|
|
|
get_strings_range (a, ret, min,
|
2010-10-17 18:38:19 +00:00
|
|
|
section->offset, section->offset+section->size, section->rva);
|
2010-06-23 15:30:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-10-25 18:30:05 +00:00
|
|
|
if (r_list_empty (a->sections)) //if (count == 0)
|
2011-10-05 00:38:37 +00:00
|
|
|
get_strings_range (a, ret, min, 0, a->size, 0);
|
2009-03-16 23:34:45 +00:00
|
|
|
return ret;
|
2009-03-16 20:07:31 +00:00
|
|
|
}
|
|
|
|
|
2010-10-04 01:46:58 +00:00
|
|
|
static int r_bin_init_items(RBin *bin, int dummy) {
|
2010-11-18 10:41:17 +00:00
|
|
|
int i;
|
2010-10-04 01:46:58 +00:00
|
|
|
struct list_head *pos;
|
2011-10-05 00:38:37 +00:00
|
|
|
RBinArch *a = &bin->curarch;
|
2010-10-04 01:46:58 +00:00
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
a->curplugin = NULL;
|
2010-10-04 01:46:58 +00:00
|
|
|
list_for_each (pos, &bin->bins) {
|
|
|
|
RBinPlugin *h = list_entry (pos, RBinPlugin, list);
|
2011-09-02 14:45:39 +00:00
|
|
|
if ((dummy && !strncmp (h->name, "any", 5)) ||
|
2010-10-04 01:46:58 +00:00
|
|
|
(!dummy && (h->check && h->check (&bin->curarch)))) {
|
|
|
|
bin->curarch.curplugin = h;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-10-05 00:38:37 +00:00
|
|
|
if (!a->curplugin || !a->curplugin->load || !a->curplugin->load (a))
|
2010-10-04 01:46:58 +00:00
|
|
|
return R_FALSE;
|
2011-10-05 00:38:37 +00:00
|
|
|
if (a->curplugin->baddr)
|
|
|
|
a->baddr = a->curplugin->baddr (a);
|
|
|
|
if (a->curplugin->binsym)
|
2010-11-18 10:41:17 +00:00
|
|
|
for (i=0; i<R_BIN_SYM_LAST; i++)
|
2011-10-05 00:38:37 +00:00
|
|
|
a->binsym[i] = a->curplugin->binsym (a, i);
|
|
|
|
if (a->curplugin->entries)
|
|
|
|
a->entries = a->curplugin->entries (a);
|
|
|
|
if (a->curplugin->fields)
|
|
|
|
a->fields = a->curplugin->fields (a);
|
|
|
|
if (a->curplugin->imports)
|
|
|
|
a->imports = a->curplugin->imports (a);
|
|
|
|
if (a->curplugin->info)
|
|
|
|
a->info = a->curplugin->info (a);
|
|
|
|
if (a->curplugin->libs)
|
|
|
|
a->libs = a->curplugin->libs (a);
|
|
|
|
if (a->curplugin->relocs)
|
|
|
|
a->relocs = a->curplugin->relocs (a);
|
|
|
|
if (a->curplugin->sections)
|
|
|
|
a->sections = a->curplugin->sections (a);
|
|
|
|
if (a->curplugin->strings)
|
|
|
|
a->strings = a->curplugin->strings (a);
|
|
|
|
else a->strings = get_strings (a, 4);
|
|
|
|
if (a->curplugin->symbols)
|
|
|
|
a->symbols = a->curplugin->symbols (a);
|
|
|
|
if (a->curplugin->classes)
|
|
|
|
a->classes = a->curplugin->classes (a);
|
2010-10-04 01:46:58 +00:00
|
|
|
return R_TRUE;
|
2010-02-07 12:17:51 +00:00
|
|
|
}
|
|
|
|
|
2010-05-28 00:44:51 +00:00
|
|
|
/* TODO: Free plugins */
|
2010-10-04 01:46:58 +00:00
|
|
|
static void r_bin_free_items(RBin *bin) {
|
2010-11-18 10:41:17 +00:00
|
|
|
int i;
|
2011-10-05 00:38:37 +00:00
|
|
|
RBinArch *a = &bin->curarch;
|
2011-02-23 19:53:56 +00:00
|
|
|
// XXX: drop all those silly conditionals! if it's null is not for freeing
|
2011-10-05 00:38:37 +00:00
|
|
|
if (a->entries) r_list_free (a->entries);
|
|
|
|
if (a->fields) r_list_free (a->fields);
|
|
|
|
if (a->imports) r_list_free (a->imports);
|
|
|
|
if (a->info) free (a->info);
|
|
|
|
if (a->libs) r_list_free (a->libs);
|
|
|
|
if (a->relocs) r_list_free (a->relocs);
|
|
|
|
if (a->sections) r_list_free (a->sections);
|
|
|
|
if (a->strings) r_list_free (a->strings);
|
|
|
|
if (a->symbols) r_list_free (a->symbols);
|
|
|
|
if (a->binsym)
|
2010-11-18 10:41:17 +00:00
|
|
|
for (i=0; i<R_BIN_SYM_LAST; i++)
|
2011-10-05 00:38:37 +00:00
|
|
|
free (a->binsym[i]);
|
|
|
|
if (a->file) free (a->file);
|
|
|
|
if (a->curplugin && a->curplugin->destroy)
|
|
|
|
a->curplugin->destroy (a);
|
2010-09-24 19:23:13 +00:00
|
|
|
}
|
|
|
|
|
2010-10-04 01:46:58 +00:00
|
|
|
static void r_bin_init(RBin *bin) {
|
2010-09-24 19:23:13 +00:00
|
|
|
struct list_head *pos;
|
2010-10-04 01:46:58 +00:00
|
|
|
|
2010-09-24 19:23:13 +00:00
|
|
|
bin->curxtr = NULL;
|
|
|
|
list_for_each (pos, &bin->binxtrs) {
|
|
|
|
RBinXtrPlugin *h = list_entry (pos, RBinXtrPlugin, list);
|
2010-10-04 01:46:58 +00:00
|
|
|
if (h->check && h->check (bin)) {
|
2010-09-24 19:23:13 +00:00
|
|
|
bin->curxtr = h;
|
2010-10-04 01:46:58 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-09-24 19:23:13 +00:00
|
|
|
}
|
2010-10-04 01:46:58 +00:00
|
|
|
if (bin->curxtr && bin->curxtr->load)
|
|
|
|
bin->curxtr->load (bin);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int r_bin_extract(RBin *bin, int idx) {
|
|
|
|
ut8 *buf;
|
2010-09-24 19:23:13 +00:00
|
|
|
if (bin->curxtr && bin->curxtr->extract)
|
2011-02-23 19:53:56 +00:00
|
|
|
return bin->curxtr->extract (bin, idx);
|
2011-11-21 23:59:20 +00:00
|
|
|
//free (bin->curarch.file);
|
2011-02-23 19:53:56 +00:00
|
|
|
bin->curarch.file = strdup (bin->file);
|
|
|
|
if (!(buf = (ut8*)r_file_slurp (bin->file, &bin->curarch.size)))
|
2011-02-24 09:07:29 +00:00
|
|
|
return 0;
|
2011-02-23 19:53:56 +00:00
|
|
|
bin->curarch.buf = r_buf_new ();
|
|
|
|
if (!r_buf_set_bytes (bin->curarch.buf, buf, bin->curarch.size)) {
|
2010-09-24 19:23:13 +00:00
|
|
|
free (buf);
|
2011-02-24 09:07:29 +00:00
|
|
|
return 0;
|
2010-09-24 19:23:13 +00:00
|
|
|
}
|
2011-02-23 19:53:56 +00:00
|
|
|
free (buf);
|
2011-02-24 09:07:29 +00:00
|
|
|
return 1;
|
2010-02-07 12:17:51 +00:00
|
|
|
}
|
|
|
|
|
2010-05-25 23:42:22 +00:00
|
|
|
R_API int r_bin_add(RBin *bin, RBinPlugin *foo) {
|
2009-03-09 01:14:50 +00:00
|
|
|
struct list_head *pos;
|
2009-03-08 15:49:15 +00:00
|
|
|
if (foo->init)
|
2010-02-07 12:17:51 +00:00
|
|
|
foo->init (bin->user);
|
2011-02-23 19:53:56 +00:00
|
|
|
list_for_each_prev (pos, &bin->bins) { // XXX: use r_list here
|
2010-05-25 23:42:22 +00:00
|
|
|
RBinPlugin *h = list_entry (pos, RBinPlugin, list);
|
2010-02-07 12:17:51 +00:00
|
|
|
if (!strcmp (h->name, foo->name))
|
2009-03-08 23:49:15 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
2010-02-07 12:17:51 +00:00
|
|
|
list_add_tail (&(foo->list), &(bin->bins));
|
2009-03-08 15:49:15 +00:00
|
|
|
return R_TRUE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-09-24 19:23:13 +00:00
|
|
|
R_API int r_bin_xtr_add(RBin *bin, RBinXtrPlugin *foo) {
|
|
|
|
struct list_head *pos;
|
2010-10-04 01:46:58 +00:00
|
|
|
|
2010-09-24 19:23:13 +00:00
|
|
|
if (foo->init)
|
|
|
|
foo->init (bin->user);
|
|
|
|
list_for_each_prev (pos, &bin->binxtrs) {
|
|
|
|
RBinXtrPlugin *h = list_entry (pos, RBinXtrPlugin, list);
|
|
|
|
if (!strcmp (h->name, foo->name))
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
list_add_tail (&(foo->list), &(bin->binxtrs));
|
|
|
|
return R_TRUE;
|
2010-07-29 14:04:18 +00:00
|
|
|
}
|
|
|
|
|
2010-02-07 12:17:51 +00:00
|
|
|
R_API void* r_bin_free(RBin *bin) {
|
2011-02-23 19:53:56 +00:00
|
|
|
if (!bin) return NULL;
|
2010-10-04 01:46:58 +00:00
|
|
|
r_bin_free_items (bin);
|
|
|
|
if (bin->curxtr && bin->curxtr->destroy)
|
|
|
|
bin->curxtr->destroy (bin);
|
2010-03-04 00:46:25 +00:00
|
|
|
free (bin);
|
2010-01-08 12:25:03 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-07 12:17:51 +00:00
|
|
|
R_API int r_bin_list(RBin *bin) {
|
2009-09-24 10:29:05 +00:00
|
|
|
struct list_head *pos;
|
2009-07-16 12:17:32 +00:00
|
|
|
|
2009-03-08 15:49:15 +00:00
|
|
|
list_for_each_prev(pos, &bin->bins) {
|
2010-05-25 23:42:22 +00:00
|
|
|
RBinPlugin *h = list_entry (pos, RBinPlugin, list);
|
2010-02-07 12:17:51 +00:00
|
|
|
printf ("bin %-10s %s\n", h->name, h->desc);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2010-09-24 19:23:13 +00:00
|
|
|
list_for_each_prev(pos, &bin->binxtrs) {
|
|
|
|
RBinXtrPlugin *h = list_entry (pos, RBinXtrPlugin, list);
|
|
|
|
printf ("bin-xtr %-10s %s\n", h->name, h->desc);
|
|
|
|
}
|
2010-01-24 11:40:48 +00:00
|
|
|
return R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-09-24 19:23:13 +00:00
|
|
|
R_API int r_bin_load(RBin *bin, const char *file, int dummy) {
|
2010-01-24 14:35:28 +00:00
|
|
|
if (!bin || !file)
|
2010-02-07 12:17:51 +00:00
|
|
|
return R_FALSE;
|
2010-10-04 01:46:58 +00:00
|
|
|
bin->file = r_file_abspath (file);
|
|
|
|
r_bin_init (bin);
|
|
|
|
bin->narch = r_bin_extract (bin, 0);
|
2010-09-24 19:23:13 +00:00
|
|
|
if (bin->narch == 0)
|
|
|
|
return R_FALSE;
|
2010-10-04 01:46:58 +00:00
|
|
|
return r_bin_init_items (bin, dummy);
|
2009-03-08 15:49:15 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-05-25 22:59:10 +00:00
|
|
|
// remove this getters.. we have no threads or mutexes to protect here
|
2010-02-07 12:17:51 +00:00
|
|
|
R_API ut64 r_bin_get_baddr(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.baddr;
|
2009-03-08 15:49:15 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-11-18 10:41:17 +00:00
|
|
|
R_API RBinAddr* r_bin_get_sym(RBin *bin, int sym) {
|
|
|
|
if (sym<0 || sym>=R_BIN_SYM_LAST)
|
|
|
|
return NULL;
|
|
|
|
return bin->curarch.binsym[sym];
|
2010-05-30 04:06:25 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 10:01:38 +00:00
|
|
|
R_API RList* r_bin_get_entries(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.entries;
|
2009-03-08 15:49:15 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-03-10 10:01:38 +00:00
|
|
|
R_API RList* r_bin_get_fields(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.fields;
|
2009-03-08 15:49:15 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-03-10 10:01:38 +00:00
|
|
|
R_API RList* r_bin_get_imports(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.imports;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-02-07 12:17:51 +00:00
|
|
|
R_API RBinInfo* r_bin_get_info(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.info;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 10:01:38 +00:00
|
|
|
R_API RList* r_bin_get_libs(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.libs;
|
2009-04-24 10:12:15 +00:00
|
|
|
}
|
|
|
|
|
2010-09-10 09:11:38 +00:00
|
|
|
R_API RList* r_bin_get_relocs(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.relocs;
|
2010-09-10 09:11:38 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 10:01:38 +00:00
|
|
|
R_API RList* r_bin_get_sections(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.sections;
|
2010-01-24 11:40:48 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-02-23 17:26:02 +00:00
|
|
|
R_API RBinSection* r_bin_get_section_at(RBin *bin, ut64 off, int va) {
|
|
|
|
RBinSection *section;
|
2010-03-10 10:01:38 +00:00
|
|
|
RListIter *iter;
|
2010-02-23 17:26:02 +00:00
|
|
|
ut64 from, to;
|
|
|
|
|
2010-10-04 01:46:58 +00:00
|
|
|
if (bin->curarch.sections)
|
|
|
|
r_list_foreach (bin->curarch.sections, iter, section) {
|
|
|
|
from = va ? bin->curarch.baddr+section->rva : section->offset;
|
|
|
|
to = va ? bin->curarch.baddr+section->rva+section->vsize :
|
2010-02-23 17:26:02 +00:00
|
|
|
section->offset + section->size;
|
|
|
|
if (off >= from && off < to)
|
|
|
|
return section;
|
|
|
|
}
|
|
|
|
return NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 10:01:38 +00:00
|
|
|
R_API RList* r_bin_get_strings(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.strings;
|
2010-02-07 12:17:51 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-03-10 10:01:38 +00:00
|
|
|
R_API RList* r_bin_get_symbols(RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.symbols;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-13 19:25:03 +00:00
|
|
|
R_API int r_bin_is_big_endian (RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return bin->curarch.info->big_endian;
|
2010-03-13 19:25:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_bin_is_stripped (RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return R_BIN_DBG_STRIPPED (bin->curarch.info->dbg_info);
|
2010-03-13 19:25:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_bin_is_static (RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return R_BIN_DBG_STATIC (bin->curarch.info->dbg_info);
|
2010-03-13 19:25:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX Implement in r_bin_meta and deprecate? */
|
|
|
|
R_API int r_bin_has_dbg_linenums (RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return R_BIN_DBG_LINENUMS (bin->curarch.info->dbg_info);
|
2010-03-13 19:25:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_bin_has_dbg_syms (RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return R_BIN_DBG_SYMS (bin->curarch.info->dbg_info);
|
2010-03-13 19:25:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_bin_has_dbg_relocs (RBin *bin) {
|
2010-10-04 01:46:58 +00:00
|
|
|
return R_BIN_DBG_RELOCS (bin->curarch.info->dbg_info);
|
2010-03-13 19:25:03 +00:00
|
|
|
}
|
|
|
|
|
2010-02-07 12:17:51 +00:00
|
|
|
R_API RBin* r_bin_new() {
|
2011-02-23 19:53:56 +00:00
|
|
|
int i;
|
2010-05-28 00:44:51 +00:00
|
|
|
RBinPlugin *static_plugin;
|
2010-09-24 19:23:13 +00:00
|
|
|
RBinXtrPlugin *static_xtr_plugin;
|
2011-02-23 19:53:56 +00:00
|
|
|
RBin *bin = R_NEW (RBin);
|
2010-05-20 15:40:58 +00:00
|
|
|
if (bin) {
|
2010-08-16 12:58:10 +00:00
|
|
|
memset (bin, 0, sizeof (RBin));
|
2010-05-20 15:40:58 +00:00
|
|
|
INIT_LIST_HEAD (&bin->bins);
|
2010-08-16 12:58:10 +00:00
|
|
|
for (i=0; bin_static_plugins[i]; i++) {
|
2010-05-28 00:44:51 +00:00
|
|
|
static_plugin = R_NEW (RBinPlugin);
|
|
|
|
memcpy (static_plugin, bin_static_plugins[i], sizeof (RBinPlugin));
|
|
|
|
r_bin_add (bin, static_plugin);
|
|
|
|
}
|
2010-09-24 19:23:13 +00:00
|
|
|
INIT_LIST_HEAD (&bin->binxtrs);
|
|
|
|
for (i=0; bin_xtr_static_plugins[i]; i++) {
|
|
|
|
static_xtr_plugin = R_NEW (RBinXtrPlugin);
|
|
|
|
memcpy (static_xtr_plugin, bin_xtr_static_plugins[i], sizeof (RBinXtrPlugin));
|
|
|
|
r_bin_xtr_add (bin, static_xtr_plugin);
|
|
|
|
}
|
2010-05-20 15:40:58 +00:00
|
|
|
}
|
2010-01-24 11:40:48 +00:00
|
|
|
return bin;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
// TODO: handle ARCH and BITS
|
2011-09-04 00:23:53 +00:00
|
|
|
/* arch and bits are implicit in the plugin name, do we really need
|
|
|
|
* to overwrite bin->curarch.info? */
|
2011-07-25 19:10:25 +00:00
|
|
|
R_API int r_bin_use_arch(RBin *bin, const char *arch, int bits, const char *name) {
|
|
|
|
struct list_head *pos;
|
|
|
|
|
2011-09-04 00:19:43 +00:00
|
|
|
if (!bin->curarch.info)
|
|
|
|
bin->curarch.info = R_NEW (RBinInfo);
|
|
|
|
memset (bin->curarch.info, 0, sizeof (RBinInfo));
|
|
|
|
strncpy (bin->curarch.info->arch, arch, R_BIN_SIZEOF_STRINGS);
|
|
|
|
bin->curarch.info->bits = bits;
|
2011-08-27 01:31:55 +00:00
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
list_for_each_prev(pos, &bin->bins) {
|
|
|
|
RBinPlugin *h = list_entry (pos, RBinPlugin, list);
|
|
|
|
if (!strcmp (name, h->name)) {
|
|
|
|
bin->curarch.curplugin = h;
|
|
|
|
// TODO: set bits and name
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2011-08-27 01:31:55 +00:00
|
|
|
// DUPDUPDUP
|
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
R_API int r_bin_select(RBin *bin, const char *arch, int bits, const char *name) {
|
2010-09-24 19:23:13 +00:00
|
|
|
int i;
|
2011-08-27 01:31:55 +00:00
|
|
|
for (i=0; i<bin->narch; i++) {
|
2011-07-25 19:10:25 +00:00
|
|
|
r_bin_select_idx (bin, i);
|
2010-10-04 01:46:58 +00:00
|
|
|
if (!bin->curarch.info || !bin->curarch.file ||
|
|
|
|
(arch && !strstr (bin->curarch.info->arch, arch)) ||
|
|
|
|
(bits && bits != bin->curarch.info->bits) ||
|
|
|
|
(name && !strstr (bin->curarch.file, name)))
|
2010-10-01 09:58:11 +00:00
|
|
|
continue;
|
2010-10-01 08:09:50 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
2010-09-24 19:23:13 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
R_API int r_bin_select_idx(RBin *bin, int idx) {
|
2010-10-04 01:46:58 +00:00
|
|
|
r_bin_free_items (bin);
|
|
|
|
if (r_bin_extract (bin, idx))
|
|
|
|
return r_bin_init_items (bin, R_FALSE);
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_bin_list_archs(RBin *bin) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < bin->narch; i++)
|
2011-07-25 19:10:25 +00:00
|
|
|
if (r_bin_select_idx (bin, i) && bin->curarch.info)
|
2011-11-21 23:59:20 +00:00
|
|
|
printf ("%03i 0x%08"PFMT64x" %s_%i %s\n", i,
|
|
|
|
bin->curarch.offset, bin->curarch.info->arch,
|
|
|
|
bin->curarch.info->bits, bin->curarch.info->machine);
|
2010-10-04 01:46:58 +00:00
|
|
|
}
|
|
|
|
|
2010-02-07 12:17:51 +00:00
|
|
|
R_API void r_bin_set_user_ptr(RBin *bin, void *user) {
|
2010-01-24 11:40:48 +00:00
|
|
|
bin->user = user;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2010-10-04 08:55:43 +00:00
|
|
|
|
2011-06-26 18:29:24 +00:00
|
|
|
static int getoffset (RBin *bin, int type, int idx) {
|
|
|
|
RBinArch *a = &bin->curarch;
|
|
|
|
if (a && a->curplugin && a->curplugin->get_offset)
|
|
|
|
return a->curplugin->get_offset (a, type, idx);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_bin_bind (RBin *bin, RBinBind *b) {
|
|
|
|
b->bin = bin;
|
|
|
|
b->get_offset = getoffset;
|
|
|
|
}
|
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
R_API RBuffer *r_bin_create (RBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen) {
|
|
|
|
RBinArch *a = &bin->curarch;
|
2011-07-25 22:30:45 +00:00
|
|
|
if (codelen<0) codelen = 0;
|
|
|
|
if (datalen<0) datalen = 0;
|
2011-07-25 19:10:25 +00:00
|
|
|
if (a && a->curplugin && a->curplugin->create)
|
|
|
|
return a->curplugin->create (bin, code, codelen, data, datalen);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-10-04 08:55:43 +00:00
|
|
|
R_API RBinObj *r_bin_get_object(RBin *bin, int flags) {
|
2010-11-18 10:41:17 +00:00
|
|
|
int i;
|
2010-10-04 08:55:43 +00:00
|
|
|
RBinObj *obj = R_NEW (RBinObj);
|
|
|
|
if (obj) {
|
|
|
|
obj->symbols = r_bin_get_symbols (bin);
|
|
|
|
obj->imports = r_bin_get_imports (bin);
|
|
|
|
obj->entries = r_bin_get_entries (bin);
|
2010-11-18 10:41:17 +00:00
|
|
|
for (i=0; i<R_BIN_SYM_LAST; i++)
|
|
|
|
obj->binsym[i] = r_bin_get_sym (bin, i);
|
2010-10-04 08:55:43 +00:00
|
|
|
obj->baddr = r_bin_get_baddr (bin);
|
2011-11-29 14:29:50 +00:00
|
|
|
obj->info = r_bin_get_info (bin);
|
2010-10-04 08:55:43 +00:00
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_bin_object_free(RBinObj *obj) {
|
|
|
|
// XXX: leak
|
|
|
|
free (obj);
|
|
|
|
}
|
2011-10-05 00:38:37 +00:00
|
|
|
|
|
|
|
R_API RList* /*<RBinClass>*/r_bin_get_classes(RBin *bin) {
|
|
|
|
return bin->curarch.classes;
|
|
|
|
}
|
2011-11-21 23:59:20 +00:00
|
|
|
|
|
|
|
R_API ut64 r_bin_get_offset (RBin *bin) {
|
|
|
|
ut64 offset = bin->curarch.offset;
|
|
|
|
if (offset>0x1000) // XXX HACK
|
|
|
|
offset -= 0x1000;
|
|
|
|
return offset;
|
|
|
|
}
|