radare2/libr/core/cbin.c
Ahmed Mohamed Abd El-MAwgood c474aa5a9f Fixing nasty bug in CC implementation (#5650)
That is not the kind of bug I see everyday
1- calling convention db is loaded
2- function cc types is initialized by project file, that string is only
one copy across the whole database for memory efficiency.
3- The db is reloaded due to change in arch or what ever, Old strings
are freed and new one is created with totally new address. Most cases it
just reload the same database.
4- Addresses in function cc types are not updates, they are already
freed at reloading db step

Solution implemented at db reloading step:
1- create new temp db with all possible available calling conventions and
the adresses in memory of these calling conventions
2- once db is reloaded, grab adress of cc from function, match it with
the name in the new temp db, then replace it with the constant value
from the newly loaded db
2016-08-30 15:47:04 +02:00

2499 lines
73 KiB
C

/* radare - LGPL - Copyright 2011-2016 - earada, pancake */
#include <r_core.h>
#define is_in_range(at, from, sz) ((at) >= (from) && (at) < ((from) + (sz)))
#define VA_FALSE 0
#define VA_TRUE 1
#define VA_NOREBASE 2
#define IS_MODE_SET(mode) (mode & R_CORE_BIN_SET)
#define IS_MODE_SIMPLE(mode) (mode & R_CORE_BIN_SIMPLE)
#define IS_MODE_SIMPLEST(mode) (mode & R_CORE_BIN_SIMPLEST)
#define IS_MODE_JSON(mode) (mode & R_CORE_BIN_JSON)
#define IS_MODE_RAD(mode) (mode & R_CORE_BIN_RADARE)
#define IS_MODE_NORMAL(mode) (!mode)
// dup from cmd_info
#define PAIR_WIDTH 9
static void pair(const char *a, const char *b, int mode, bool last) {
if (!b || !(*b)) return;
if (IS_MODE_JSON (mode)) {
const char *lst = last ? "" : ",";
r_cons_printf ("\"%s\":%s%s", a, b, lst);
} else {
char ws[16];
int al = strlen (a);
al = PAIR_WIDTH - al;
if (al < 0) al = 0;
memset (ws, ' ', al);
ws[al] = 0;
r_cons_printf ("%s%s%s\n", a, ws, b);
}
}
static void pair_bool (const char *a, bool t, int mode, bool last) {
pair (a, r_str_bool (t), mode, last);
}
static void pair_int (const char *a, int n, int mode, bool last) {
pair (a, sdb_fmt (0, "%d", n), mode, last);
}
static void pair_str (const char *a, const char *b, int mode, int last) {
if (IS_MODE_JSON (mode)) {
if (!b) b = "";
pair (a, sdb_fmt (0, "\"%s\"", b), mode, last);
} else {
pair (a, b, mode, last);
}
}
#define STR(x) (x)?(x):""
// XXX - this may lead to conflicts with set by name
static int r_core_bin_set_cur(RCore *core, RBinFile *binfile);
static ut64 rva(RBin *bin, ut64 paddr, ut64 vaddr, int va) {
if (va == VA_TRUE) {
return r_bin_get_vaddr (bin, paddr, vaddr);
} else if (va == VA_NOREBASE) {
return vaddr;
} else {
return paddr;
}
}
R_API int r_core_bin_set_by_fd(RCore *core, ut64 bin_fd) {
if (r_bin_file_set_cur_by_fd (core->bin, bin_fd)) {
r_core_bin_set_cur (core, r_core_bin_cur(core));
return true;
}
return false;
}
R_API int r_core_bin_set_by_name(RCore *core, const char * name) {
if (r_bin_file_set_cur_by_name (core->bin, name)) {
r_core_bin_set_cur (core, r_core_bin_cur (core));
return true;
}
return false;
}
R_API int r_core_bin_set_env(RCore *r, RBinFile *binfile) {
RBinObject *binobj = binfile ? binfile->o: NULL;
RBinInfo *info = binobj ? binobj->info: NULL;
if (info) {
int va = info->has_va;
const char * arch = info->arch;
ut16 bits = info->bits;
ut64 baseaddr = r_bin_get_baddr (r->bin);
/* Hack to make baddr work on some corner */
r_config_set_i (r->config, "io.va",
(binobj->info)? binobj->info->has_va: 0);
r_config_set_i (r->config, "bin.baddr", baseaddr);
r_config_set (r->config, "asm.arch", arch);
r_config_set_i (r->config, "asm.bits", bits);
r_config_set (r->config, "anal.arch", arch);
if (info->cpu && *info->cpu) {
r_config_set (r->config, "anal.cpu", info->cpu);
} else {
r_config_set (r->config, "anal.cpu", arch);
}
r_asm_use (r->assembler, arch);
r_core_bin_info (r, R_CORE_BIN_ACC_ALL, R_CORE_BIN_SET,
va, NULL, NULL);
r_core_bin_set_cur (r, binfile);
return true;
}
return false;
}
R_API int r_core_bin_set_cur(RCore *core, RBinFile *binfile) {
if (!core->bin) return false;
if (!binfile) {
// Find first available binfile
ut32 fd = r_core_file_cur_fd (core);
binfile = fd != (ut32) -1 ? r_bin_file_find_by_fd (
core->bin, fd) : NULL;
if (!binfile) return false;
}
r_bin_file_set_cur_binfile (core->bin, binfile);
return true;
}
R_API int r_core_bin_refresh_strings(RCore *r) {
return r_bin_reset_strings (r->bin) ? true: false;
}
R_API RBinFile * r_core_bin_cur(RCore *core) {
RBinFile *binfile = r_bin_cur (core->bin);
return binfile;
}
static bool string_filter(RCore *core, const char *str) {
int i;
/* pointer/rawdata detection */
if (core->bin->strpurge) {
ut8 bo[0x100];
int up = 0;
int lo = 0;
int ot = 0;
int di = 0;
int ln = 0;
int sp = 0;
int nm = 0;
for (i = 0; i<0x100; i++) {
bo[i] = 0;
}
for (i = 0; str[i]; i++) {
if (str[i]>='0' && str[i]<='9')
nm++;
else if (str[i]>='a' && str[i]<='z')
lo++;
else if (str[i]>='A' && str[i]<='Z')
up++;
else ot++;
if (str[i]=='\\') ot++;
if (str[i]==' ') sp++;
bo[(ut8)str[i]] = 1;
ln++;
}
for (i = 0; i<0x100; i++) {
if (bo[i])
di++;
}
if (ln>2 && str[0] != '_') {
if (ln<10) return false;
if (ot >= (nm+up+lo))
return false;
if (lo <3)
return false;
}
}
switch (core->bin->strfilter) {
case 'U': // only uppercase strings
for (i = 0; str[i]; i++) {
char ch = str[i];
if (ch == ' ') continue;
if (ch<'@'|| ch > 'Z') {
/// if (ch<'0' || ch>'9') {
return false;
// }
}
if (ch<0 || !IS_PRINTABLE (ch))
return false;
}
if (str[0] && str[1]) {
for (i = 2; i<6 && str[i]; i++) {
if (str[i] == str[0])
return false;
if (str[i] == str[1])
return false;
}
}
if (str[0] == str[2]) return false; // rm false positives
break;
case 'a': // only alphanumeric - plain ascii
for (i = 0; str[i]; i++) {
char ch = str[i];
if (ch < 1 || !IS_PRINTABLE (ch)) {
return false;
}
}
break;
case 'e': // emails
if (str && *str) {
if (!strstr (str+1, "@"))
return false;
if (!strstr (str+1, "."))
return false;
} else return false;
break;
case 'f': // format-string
if (str && *str) {
if (!strstr (str+1, "%"))
return false;
} else return false;
break;
case 'u': // URLs
if (!strstr (str, "://"))
return false;
break;
case 'i': //IPV4
{
int segment = 0;
int segmentsum = 0;
bool prevd = false;
for (i = 0; str[i]; i++) {
char ch = str[i];
if (ch >= '0' && ch <= '9') {
segmentsum = segmentsum*10 + (ch - '0');
if (segment == 3) {
return true;
}
prevd = true;
} else if (ch == '.') {
if (prevd == true && segmentsum < 256){
segment++;
segmentsum = 0;
} else {
segmentsum = 0;
segment = 0;
}
prevd = false;
} else {
segmentsum = 0;
prevd = false;
segment = 0;
}
}
return false;
}
case 'p': // path
if (str[0] != '/') {
return false;
}
break;
case '8': // utf8
for (i = 0; str[i]; i++) {
char ch = str[i];
if (ch < 0) {
return true;
}
}
return false;
}
return true;
}
static int bin_strings(RCore *r, int mode, int va) {
char *q;
RBinSection *section;
int hasstr, minstr, maxstr, rawstr;
RBinString *string;
RListIter *iter;
RList *list;
RBin *bin = r->bin;
RBinFile *binfile = r_core_bin_cur (r);
RBinPlugin *plugin = r_bin_file_cur_plugin (binfile);
if (!binfile) return false;
minstr = r_config_get_i (r->config, "bin.minstr");
maxstr = r_config_get_i (r->config, "bin.maxstr");
rawstr = r_config_get_i (r->config, "bin.rawstr");
binfile->rawstr = rawstr;
if (!(hasstr = r_config_get_i (r->config, "bin.strings"))) {
return 0;
}
if (!plugin) return 0;
if (plugin->info && plugin->name) {
if (strcmp (plugin->name, "any") == 0 && !rawstr) {
return false;
}
}
bin->minstrlen = minstr;
minstr = bin->minstrlen;
bin->maxstrlen = maxstr;
maxstr = bin->maxstrlen;
if (!(list = r_bin_get_strings (bin))) {
return false;
}
if (IS_MODE_JSON (mode)) r_cons_printf ("[");
if (IS_MODE_RAD (mode)) r_cons_printf ("fs strings");
if (IS_MODE_SET (mode) && r_config_get_i (r->config, "bin.strings")) {
r_flag_space_set (r->flags, "strings");
r_cons_break (NULL, NULL);
}
r_list_foreach (list, iter, string) {
const char *section_name, *type_string;
ut64 paddr, vaddr, addr;
if (!string_filter (r, string->string)) {
continue;
}
paddr = string->paddr;
vaddr = r_bin_get_vaddr (bin, paddr, string->vaddr);
addr = va ? vaddr : paddr;
if (string->length < minstr) continue;
if (maxstr && string->length > maxstr) continue;
section = r_bin_get_section_at (r_bin_cur_object (bin), paddr, 0);
section_name = section ? section->name : "unknown";
type_string = string->type == 'w' ? "wide" : "ascii";
if (IS_MODE_SET (mode)) {
char *f_name, *str;
if (r_cons_singleton()->breaked) break;
r_meta_add (r->anal, R_META_TYPE_STRING, addr,
addr + string->size, string->string);
f_name = strdup (string->string);
r_name_filter (f_name, -1);
if (r->bin->prefix) {
str = r_str_newf ("%s.str.%s", r->bin->prefix, f_name);
} else {
str = r_str_newf ("str.%s", f_name);
}
r_flag_set (r->flags, str, addr, string->size);
free (str);
free (f_name);
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_printf ("0x%"PFMT64x" %d %d %s\n", addr,
string->size, string->length, string->string);
} else if (IS_MODE_SIMPLEST (mode)) {
r_cons_println (string->string);
} else if (IS_MODE_JSON (mode)) {
q = r_base64_encode_dyn (string->string, -1);
r_cons_printf ("%s{\"vaddr\":%"PFMT64d
",\"paddr\":%"PFMT64d",\"ordinal\":%d"
",\"size\":%d,\"length\":%d,\"section\":\"%s\","
"\"type\":\"%s\",\"string\":\"%s\"}",
iter->p ? ",": "",
vaddr, paddr, string->ordinal, string->size,
string->length, section_name, type_string, q);
free (q);
} else if (IS_MODE_RAD (mode)) {
char *f_name, *str;
f_name = strdup (string->string);
r_name_filter (f_name, R_FLAG_NAME_SIZE);
if (r->bin->prefix) {
str = r_str_newf ("%s.str.%s", r->bin->prefix, f_name);
r_cons_printf ("f %s.str.%s %"PFMT64d" @ 0x%08"PFMT64x"\n"
"Cs %"PFMT64d" @ 0x%08"PFMT64x"\n",
r->bin->prefix, f_name, string->size, addr,
string->size, addr);
} else {
str = r_str_newf ("str.%s", f_name);
r_cons_printf ("f str.%s %"PFMT64d" @ 0x%08"PFMT64x"\n"
"Cs %"PFMT64d" @ 0x%08"PFMT64x"\n",
f_name, string->size, addr,
string->size, addr);
}
free (str);
free (f_name);
} else {
r_cons_printf ("vaddr=0x%08"PFMT64x" paddr=0x%08"
PFMT64x" ordinal=%03u sz=%u len=%u "
"section=%s type=%s string=%s\n",
vaddr, paddr, string->ordinal, string->size,
string->length, section_name, type_string,
string->string);
}
}
if (IS_MODE_JSON (mode)) r_cons_printf ("]");
if (IS_MODE_SET (mode)) r_cons_break_end ();
return true;
}
static const char* get_compile_time(Sdb *binFileSdb) {
Sdb *info_ns = sdb_ns(binFileSdb, "info", false);
const char *timeDateStamp_string = sdb_const_get (info_ns,
"image_file_header.TimeDateStamp_string", 0);
return timeDateStamp_string;
}
static int is_executable (RBinObject *obj) {
RListIter *it;
RBinSection* sec;
if (obj) {
if (obj->info && obj->info->arch)
return true;
r_list_foreach (obj->sections, it, sec) {
if (R_BIN_SCN_EXECUTABLE & sec->srwx)
return true;
}
}
return false;
}
#define DBSPATH R2_LIBDIR"/radare2/"R2_VERSION"/fcnsign"
static void sdb_concat_by_path (Sdb *s, const char *path) {
Sdb *db = sdb_new (0, path, 0);
sdb_merge (s, db);
sdb_close (db);
sdb_free (db);
}
R_API void r_core_anal_type_init(RCore *core) {
Sdb *types = core->anal->sdb_types;
sdb_reset (types); // make sure they are empty this is initializing
const char *anal_arch = r_config_get (core->config, "anal.arch");
const char *os = r_config_get (core->config, "asm.os");
int bits = core->assembler->bits;
char *dbpath;
if (r_file_exists (DBSPATH"/types.sdb")) {
sdb_concat_by_path (types, DBSPATH"/types.sdb");
}
dbpath = sdb_fmt (-1, DBSPATH"/types-%s.sdb", anal_arch);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (types, dbpath);
}
dbpath = sdb_fmt (-1, DBSPATH"/types-%s.sdb", os);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (types, dbpath);
}
dbpath = sdb_fmt (-1, DBSPATH"/types-%d.sdb", bits);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (types, dbpath);
}
dbpath = sdb_fmt (-1, DBSPATH"/types-%s-%d.sdb", os, bits);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (types, dbpath);
}
dbpath = sdb_fmt (-1, DBSPATH"/types-%s-%d.sdb", anal_arch, bits);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (types, dbpath);
}
dbpath = sdb_fmt (-1, DBSPATH"/types-%s-%s.sdb", anal_arch, os);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (types, dbpath);
}
dbpath = sdb_fmt (-1, DBSPATH"/types-%s-%s-%d.sdb", anal_arch, os, bits);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (types, dbpath);
}
}
static int save_ptr(void *p, const char *k, const char *v) {
Sdb *sdbs[2];
sdbs[0] = ((Sdb**) p)[0];
sdbs[1] = ((Sdb**) p)[1];
if (!strncmp (v, "cc", strlen("cc") + 1)) {
const char *x = sdb_const_get (sdbs[1], sdb_fmt (-1, "cc.%s.name", k), 0);
char *tmp = sdb_fmt (-1, "0x%08"PFMT64x, (ut64)x);
sdb_set (sdbs[0], tmp, x, 0);
}
return 1;
}
R_API void r_core_anal_cc_init(RCore *core) {
Sdb *sdbs[2];
sdbs[0] = sdb_new0 ();
sdbs[1] = core->anal->sdb_cc;
//save pointers and values stored inside them
//to recover from freeing heeps
const char *defaultcc = sdb_const_get (sdbs[1], "default.cc", 0);
sdb_set (sdbs[0], sdb_fmt (-1, "0x%08"PFMT64x, defaultcc), defaultcc, 0);
sdb_foreach (core->anal->sdb_cc, save_ptr, sdbs);
sdb_reset ( core->anal->sdb_cc);
const char *anal_arch = r_config_get (core->config, "anal.arch");
int bits = core->anal->bits;
if (bits == 16 && !strcmp (anal_arch, "arm")) {
bits = 32;
}
char *dbpath = sdb_fmt (-1, DBSPATH"/cc-%s-%d.sdb", anal_arch, bits);
if (r_file_exists (dbpath)) {
sdb_concat_by_path (core->anal->sdb_cc, dbpath);
}
//restore all freed CC or replace with new default cc
RListIter *it;
RAnalFunction *fcn;
r_list_foreach (core->anal->fcns, it, fcn) {
char *ptr = sdb_fmt (-1, "0x%08"PFMT64x, (ut64)fcn->cc);
const char *cc = sdb_const_get (sdbs[0], ptr, 0);
if (cc) {
fcn->cc = r_anal_cc_to_constant (core->anal, (char *)cc);
}
if (!fcn->cc) {
fcn->cc = r_anal_cc_default (core->anal);
}
}
sdb_close (sdbs[0]);
sdb_free (sdbs[0]);
}
#undef DBSPATH
static int bin_info(RCore *r, int mode) {
int i, j, v;
char str[R_FLAG_NAME_SIZE];
char size_str[32];
char baddr_str[32];
RBinInfo *info = r_bin_get_info (r->bin);
RBinFile *binfile = r_core_bin_cur (r);
RBinObject *obj = r_bin_cur_object (r->bin);
const char *compiled = NULL;
bool havecode;
if (!binfile || !info || !obj) {
if (mode & R_CORE_BIN_JSON) r_cons_printf ("{}");
return false;
}
havecode = is_executable (obj) | (obj->entries != NULL);
compiled = get_compile_time (binfile->sdb);
snprintf (size_str, sizeof (size_str),
"%"PFMT64u, r_bin_get_size (r->bin));
snprintf (baddr_str, sizeof (baddr_str),
"%"PFMT64u, info->baddr);
if (IS_MODE_SET (mode)) {
r_config_set (r->config, "file.type", info->rclass);
r_config_set (r->config, "cfg.bigendian", info->big_endian ? "true" : "false");
if (info->rclass && !strcmp (info->rclass, "fs")) {
r_config_set (r->config, "asm.arch", info->arch);
r_core_cmdf (r, "m /root %s 0", info->arch);
} else {
if (info->lang) {
r_config_set (r->config, "bin.lang", info->lang);
}
r_config_set (r->config, "asm.os", info->os);
r_config_set (r->config, "asm.arch", info->arch);
r_config_set (r->config, "anal.arch", info->arch);
snprintf (str, R_FLAG_NAME_SIZE, "%i", info->bits);
r_config_set (r->config, "asm.bits", str);
r_config_set (r->config, "asm.dwarf",
(R_BIN_DBG_STRIPPED & info->dbg_info) ? "false" : "true");
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_ALIGN);
if (v != -1) r_config_set_i (r->config, "asm.pcalign", v);
}
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_printf ("arch %s\n", info->arch);
r_cons_printf ("bits %d\n", info->bits);
r_cons_printf ("os %s\n", info->os);
r_cons_printf ("endian %s\n", info->big_endian? "big": "little");
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
if (v != -1) r_cons_printf ("minopsz %d\n", v);
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_MAX_OP_SIZE);
if (v != -1) r_cons_printf ("maxopsz %d\n", v);
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_ALIGN);
if (v != -1) r_cons_printf ("pcalign %d\n", v);
} else if (IS_MODE_RAD (mode)) {
if (info->type && !strcmp (info->type, "fs")) {
r_cons_printf ("e file.type=fs\n");
r_cons_printf ("m /root %s 0\n", info->arch);
} else {
r_cons_printf ("e cfg.bigendian=%s\n"
"e asm.bits=%i\n"
"e asm.dwarf=%s\n",
r_str_bool (info->big_endian),
info->bits,
r_str_bool (R_BIN_DBG_STRIPPED &info->dbg_info));
if (info->lang && *info->lang) {
r_cons_printf ("e bin.lang=%s\n", info->lang);
}
if (info->rclass && *info->rclass) {
r_cons_printf ("e file.type=%s\n",
info->rclass);
}
if (info->os) {
r_cons_printf ("e asm.os=%s\n", info->os);
}
if (info->arch) {
r_cons_printf ("e asm.arch=%s\n", info->arch);
}
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_ALIGN);
if (v != -1) r_cons_printf ("e asm.pcalign=%d\n", v);
}
} else {
// XXX: if type is 'fs' show something different?
char *tmp_buf;
if (IS_MODE_JSON (mode)) {
r_cons_printf ("{");
}
pair_bool ("havecode", havecode, mode, false);
pair_bool ("pic", info->has_pi, mode, false);
pair_bool ("canary", info->has_canary, mode, false);
pair_bool ("nx", info->has_nx, mode, false);
pair_bool ("crypto", info->has_crypto, mode, false);
pair_bool ("va", info->has_va, mode, false);
pair_str ("intrp", info->intrp, mode, false);
pair_str ("bintype", info->rclass, mode, false);
pair_str ("class", info->bclass, mode, false);
pair_str ("lang", info->lang, mode, false);
pair_str ("arch", info->arch, mode, false);
pair_int ("bits", info->bits, mode, false);
pair_str ("machine", info->machine, mode, false);
pair_str ("os", info->os, mode, false);
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_MIN_OP_SIZE);
if (v != -1) {
pair_int ("minopsz", v, mode, false);
}
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_MAX_OP_SIZE);
if (v != -1) {
pair_int ("maxopsz", v, mode, false);
}
v = r_anal_archinfo (r->anal, R_ANAL_ARCHINFO_ALIGN);
if (v != -1) {
pair_int ("pcalign", v, mode, false);
}
pair_str ("subsys", info->subsystem, mode, false);
pair_str ("endian", info->big_endian ? "big" : "little", mode, false);
pair_bool ("stripped", R_BIN_DBG_STRIPPED & info->dbg_info, mode, false);
pair_bool ("static", r_bin_is_static (r->bin), mode, false);
pair_bool ("linenum", R_BIN_DBG_LINENUMS & info->dbg_info, mode, false);
pair_bool ("lsyms", R_BIN_DBG_SYMS & info->dbg_info, mode, false);
pair_bool ("relocs", R_BIN_DBG_RELOCS & info->dbg_info, mode, false);
pair_str ("rpath", info->rpath, mode, false);
pair_str ("binsz", size_str, mode, false);
pair_str ("compiled", compiled, mode, false);
tmp_buf = r_str_escape (info->debug_file_name);
pair_str ("dbg_file", tmp_buf, mode, false);
free (tmp_buf);
if (info->claimed_checksum) {
/* checksum specified in header */
pair_str ("hdr.csum", info->claimed_checksum, mode, false);
}
if (info->actual_checksum) {
/* computed checksum */
pair_str ("cmp.csum", info->actual_checksum, mode, false);
}
for (i = 0; info->sum[i].type; i++) {
RBinHash *h = &info->sum[i];
ut64 hash = r_hash_name_to_bits (h->type);
RHash *rh = r_hash_new (true, hash);
int len = r_hash_calculate (rh, hash, (const ut8*)
binfile->buf->buf+h->from, h->to);
if (len < 1) {
eprintf ("Invaild wtf\n");
}
r_hash_free (rh);
r_cons_printf ("%s\t%d-%dc\t", h->type, h->from, h->to+h->from);
for (j = 0; j < h->len; j++) {
r_cons_printf ("%02x", h->buf[j]);
}
r_cons_newline ();
}
pair_str ("guid", info->guid, mode, true);
if (IS_MODE_JSON (mode)) r_cons_printf ("}");
}
r_core_anal_type_init (r);
r_core_anal_cc_init (r);
return true;
}
static int bin_dwarf(RCore *core, int mode) {
RBinDwarfRow *row;
RListIter *iter;
RList *list = NULL;
RBinFile *binfile = r_core_bin_cur (core);
RBinPlugin * plugin = r_bin_file_cur_plugin (binfile);
if (!binfile) return false;
if (plugin && plugin->lines) {
list = plugin->lines (binfile);
} else if (core->bin) {
// TODO: complete and speed-up support for dwarf
if (r_config_get_i (core->config, "bin.dbginfo")) {
RBinDwarfDebugAbbrev *da = NULL;
da = r_bin_dwarf_parse_abbrev (core->bin, mode);
r_bin_dwarf_parse_info (da, core->bin, mode);
r_bin_dwarf_parse_aranges (core->bin, mode);
list = r_bin_dwarf_parse_line (core->bin, mode);
r_bin_dwarf_free_debug_abbrev (da);
free (da);
}
}
if (!list) return false;
r_cons_break (NULL, NULL);
r_list_foreach (list, iter, row) {
if (r_cons_singleton()->breaked) break;
if (mode) {
// TODO: use 'Cl' instead of CC
const char *path = row->file;
char *line = r_file_slurp_line (path, row->line-1, 0);
if (line) {
r_str_filter (line, strlen (line));
line = r_str_replace (line, "\"", "\\\"", 1);
line = r_str_replace (line, "\\\\", "\\", 1);
}
// TODO: implement internal : if ((mode & R_CORE_BIN_SET))
if ((mode & R_CORE_BIN_SET)) {
char *cmt = r_str_newf ("%s:%d %s", row->file, row->line, line?line:"");
r_meta_set_string (core->anal, R_META_TYPE_COMMENT,
row->address, cmt);
free (cmt);
} else {
r_cons_printf ("\"CC %s:%d %s\"@0x%"PFMT64x"\n",
row->file, row->line, line?line:"", row->address);
}
free (line);
} else {
r_cons_printf ("0x%08"PFMT64x"\t%s\t%d\n", row->address, row->file, row->line);
}
}
r_cons_break_end ();
r_list_free (list);
return true;
}
static int bin_pdb(RCore *core, int mode) {
R_PDB pdb = {0};
ut64 baddr = r_bin_get_baddr (core->bin);
pdb.cb_printf = r_cons_printf;
if (!init_pdb_parser (&pdb, core->bin->file)) {
return false;
}
if (!pdb.pdb_parse (&pdb)) {
eprintf ("pdb was not parsed\n");
pdb.finish_pdb_parse (&pdb);
return false;
}
if (mode == R_CORE_BIN_JSON) r_cons_printf("[");
switch (mode) {
case R_CORE_BIN_SET:
mode = 's';
r_core_cmd0 (core, ".iP*");
return true;
case R_CORE_BIN_JSON:
mode = 'j';
break;
case '*':
case 1:
mode = 'r';
break;
default:
mode = 'd'; // default
break;
}
pdb.print_types (&pdb, mode);
if (mode == 'j') r_cons_printf (",");
pdb.print_gvars (&pdb, baddr, mode);
if (mode == 'j') r_cons_printf ("]");
pdb.finish_pdb_parse (&pdb);
return true;
}
static int bin_main(RCore *r, int mode, int va) {
RBinAddr *binmain = r_bin_get_sym (r->bin, R_BIN_SYM_MAIN);
ut64 addr;
if (!binmain) return false;
addr = va ? r_bin_a2b (r->bin, binmain->vaddr) : binmain->paddr;
if (IS_MODE_SET (mode)) {
r_flag_space_set (r->flags, "symbols");
r_flag_set (r->flags, "main", addr, r->blocksize);
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_printf ("%"PFMT64d, addr);
} else if (IS_MODE_RAD (mode)) {
r_cons_printf ("fs symbols\n");
r_cons_printf ("f main @ 0x%08"PFMT64x"\n", addr);
} else if (IS_MODE_JSON (mode)) {
r_cons_printf ("{\"vaddr\":%" PFMT64d
",\"paddr\":%" PFMT64d "}", addr, binmain->paddr);
} else {
r_cons_printf ("[Main]\n");
r_cons_printf ("vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x"\n",
addr, binmain->paddr);
}
return true;
}
static int bin_entry(RCore *r, int mode, ut64 laddr, int va) {
char str[R_FLAG_NAME_SIZE];
RList *entries = r_bin_get_entries (r->bin);
RListIter *iter;
RBinAddr *entry = NULL;
int i = 0;
ut64 baddr = r_bin_get_baddr (r->bin);
if (IS_MODE_RAD (mode)) r_cons_printf ("fs symbols\n");
else if (IS_MODE_JSON (mode)) r_cons_printf ("[");
else if (IS_MODE_NORMAL (mode)) r_cons_printf ("[Entrypoints]\n");
r_list_foreach (entries, iter, entry) {
ut64 paddr = entry->paddr;
ut64 at = rva (r->bin, paddr, entry->vaddr, va);
const char *type = r_bin_entry_type_string (entry->type);
if (!type) type = "unknown";
if (IS_MODE_SET (mode)) {
r_flag_space_set (r->flags, "symbols");
snprintf (str, R_FLAG_NAME_SIZE, "entry%i", i);
r_flag_set (r->flags, str, at, 1);
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_printf ("0x%08"PFMT64x"\n", at);
} else if (IS_MODE_JSON (mode)) {
r_cons_printf ("%s{\"vaddr\":%" PFMT64d ","
"\"paddr\":%" PFMT64d ","
"\"baddr\":%" PFMT64d ","
"\"laddr\":%" PFMT64d ","
"\"type\":\"%s\"}",
iter->p ? "," : "", at, paddr, baddr, laddr, type);
} else if (IS_MODE_RAD (mode)) {
r_cons_printf ("f entry%i 1 @ 0x%08"PFMT64x"\n", i, at);
r_cons_printf ("s entry%i\n", i);
} else {
r_cons_printf (
"vaddr=0x%08"PFMT64x
" paddr=0x%08"PFMT64x
" baddr=0x%08"PFMT64x
" laddr=0x%08"PFMT64x
" type=%s\n",
at, paddr, baddr, laddr, type);
}
i++;
}
if (IS_MODE_SET (mode)) {
if (entry) {
ut64 at = rva (r->bin, entry->paddr, entry->vaddr, va);
r_core_seek (r, at, 0);
}
} else if (IS_MODE_JSON (mode)) {
r_cons_printf ("]");
r_cons_newline ();
} else if (IS_MODE_NORMAL (mode)) {
r_cons_printf ("\n%i entrypoints\n", i);
}
return true;
}
static const char *bin_reloc_type_name(RBinReloc *reloc) {
#define CASE(T) case R_BIN_RELOC_ ## T: return reloc->additive ? "ADD_" #T : "SET_" #T
switch (reloc->type) {
CASE(8);
CASE(16);
CASE(32);
CASE(64);
}
return "UNKNOWN";
#undef CASE
}
static ut8 bin_reloc_size(RBinReloc *reloc) {
#define CASE(T) case R_BIN_RELOC_ ## T: return T / 8
switch (reloc->type) {
CASE(8);
CASE(16);
CASE(32);
CASE(64);
}
return 0;
#undef CASE
}
static char *resolveModuleOrdinal(Sdb *sdb, const char *module, int ordinal) {
Sdb *db = sdb;
char *foo = sdb_get (db, sdb_fmt (0, "%d", ordinal), 0);
return (foo && *foo) ? foo : NULL;
}
static char *get_reloc_name(RBinReloc *reloc, ut64 addr) {
char *reloc_name = NULL;
if (reloc->import) {
reloc_name = r_str_newf ("reloc.%s_%d",
reloc->import->name, (int)(addr & 0xff));
if (!reloc_name) return NULL;
r_str_replace_char (reloc_name, '$', '_');
} else if (reloc->is_ifunc) {
// addend is the function pointer for the resolving ifunc
reloc_name = r_str_newf ("reloc.ifunc_%"PFMT64x, reloc->addend);
} else {
// TODO(eddyb) implement constant relocs.
}
return reloc_name;
}
static void set_bin_relocs (RCore *r, RBinReloc *reloc, ut64 addr, Sdb **db, char **sdb_module) {
int bin_demangle = r_config_get_i (r->config, "bin.demangle");
const char *lang = r_config_get (r->config, "bin.lang");
char *demname = NULL;
bool is_pe = true;
int is_sandbox = r_sandbox_enable (0);
if (reloc->import && reloc->import->name[0]) {
char str[R_FLAG_NAME_SIZE];
RFlagItem *fi;
if (is_pe && !is_sandbox && strstr (reloc->import->name, "Ordinal")) {
const char *TOKEN = ".dll_Ordinal_";
char *module = strdup (reloc->import->name);
char *import = strstr (module, TOKEN);
r_str_case (module, false);
if (import) {
char *filename = NULL;
int ordinal;
*import = 0;
import += strlen (TOKEN);
ordinal = atoi (import);
if (!*sdb_module || strcmp (module, *sdb_module)) {
sdb_free (*db);
*db = NULL;
free (*sdb_module);
*sdb_module = strdup (module);
/* always lowercase */
filename = sdb_fmt (1, "%s.sdb", module);
r_str_case (filename, false);
if (r_file_exists (filename)) {
*db = sdb_new (NULL, filename, 0);
} else {
#if __WINDOWS__
filename = sdb_fmt (1, "share/radare2/"R2_VERSION"/format/dll/%s.sdb", module);
#else
filename = sdb_fmt (1, R2_PREFIX"/share/radare2/" R2_VERSION"/format/dll/%s.sdb", module);
#endif
if (r_file_exists (filename)) {
*db = sdb_new (NULL, filename, 0);
}
}
}
if (*db) {
// ordinal-1 because we enumerate starting at 0
char *symname = resolveModuleOrdinal (*db, module, ordinal-1);
if (symname) {
if (r->bin->prefix) {
reloc->import->name = r_str_newf
("%s.%s.%s", r->bin->prefix, module, symname);
} else {
reloc->import->name = r_str_newf
("%s.%s", module, symname);
}
}
}
}
free (module);
r_anal_hint_set_size (r->anal, reloc->vaddr, 4);
r_meta_add (r->anal, R_META_TYPE_DATA, reloc->vaddr, reloc->vaddr+4, NULL);
}
if (r->bin->prefix) {
snprintf (str, R_FLAG_NAME_SIZE,
"%s.reloc.%s_%d", r->bin->prefix,
reloc->import->name, (int)(addr&0xff));
} else {
snprintf (str, R_FLAG_NAME_SIZE,
"reloc.%s_%d", reloc->import->name,
(int)(addr&0xff));
}
if (bin_demangle) {
demname = r_bin_demangle (r->bin->cur, lang, str);
}
r_name_filter (str, 0);
fi = r_flag_set (r->flags, str, addr, bin_reloc_size (reloc));
if (demname) {
char *realname;
if (r->bin->prefix) {
realname = sdb_fmt (0, "%s.reloc.%s",
r->bin->prefix, demname);
} else {
realname = sdb_fmt (0, "reloc.%s", demname);
}
r_flag_item_set_realname (fi, realname);
}
} else {
char *reloc_name = get_reloc_name (reloc, addr);
if (reloc_name) {
r_flag_set (r->flags, reloc_name, addr, bin_reloc_size (reloc));
free (reloc_name);
}
}
}
static int bin_relocs(RCore *r, int mode, int va) {
int bin_demangle = r_config_get_i (r->config, "bin.demangle");
RList *relocs;
RListIter *iter;
RBinReloc *reloc = NULL;
Sdb *db = NULL;
char *sdb_module = NULL;
int i = 0;
va = VA_TRUE; // XXX relocs always vaddr?
//this has been created for reloc object files
relocs = r_bin_patch_relocs (r->bin);
if (!relocs) {
relocs = r_bin_get_relocs (r->bin);
if (!relocs)
return false;
}
if (IS_MODE_RAD (mode)) {
r_cons_println ("fs relocs");
} else if (IS_MODE_NORMAL (mode)) {
r_cons_println ("[Relocations]");
} else if (IS_MODE_JSON (mode)) {
r_cons_print ("[");
} else if (IS_MODE_SET (mode)) {
r_flag_space_set (r->flags, "relocs");
}
r_list_foreach (relocs, iter, reloc) {
ut64 addr = rva (r->bin, reloc->paddr, reloc->vaddr, va);
if (IS_MODE_SET (mode)) {
set_bin_relocs (r, reloc, addr, &db, &sdb_module);
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_printf ("0x%08"PFMT64x" %s\n", addr, reloc->import ? reloc->import->name : "");
} else if (IS_MODE_RAD (mode)) {
//char *reloc_name = get_reloc_name (reloc, addr);
char *name = reloc->import ? strdup (reloc->import->name): NULL;
if (name && bin_demangle) {
char *mn = r_bin_demangle (r->bin->cur, NULL, name);
if (mn) {
free (name);
name = mn;
}
}
if (name) {
r_cons_printf ("f %s%s%s @ 0x%08"PFMT64x"\n",
r->bin->prefix ? r->bin->prefix : "reloc.",
r->bin->prefix ? "." : "", name, addr);
free (name);
}
} else if (IS_MODE_JSON (mode)) {
const char *comma = iter->p? ",":"";
const char *reloc_name = reloc->import ?
sdb_fmt (0, "\"%s\"", reloc->import->name) :
"null";
r_cons_printf ("%s{\"name\":%s,"
"\"type\":\"%s\","
"\"vaddr\":%"PFMT64d","
"\"paddr\":%"PFMT64d","
"\"is_ifunc\":%s}",
comma, reloc_name,
bin_reloc_type_name (reloc),
reloc->vaddr, reloc->paddr,
r_str_bool (reloc->is_ifunc));
} else if (IS_MODE_NORMAL (mode)) {
char *name = strdup (reloc->import ?
reloc->import->name: "null");
if (bin_demangle) {
char *mn = r_bin_demangle (r->bin->cur, NULL, name);
if (mn && *mn) {
free (name);
name = mn;
}
}
r_cons_printf ("vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x" type=%s",
addr, reloc->paddr, bin_reloc_type_name (reloc));
if (reloc->import && reloc->import->name[0]) {
r_cons_printf (" %s", name);
} else if (reloc->symbol && name && name[0]) {
r_cons_printf (" %s", name);
}
free (name);
if (reloc->addend) {
if (reloc->import && reloc->addend > 0) {
r_cons_printf (" +");
}
if (reloc->addend < 0) {
r_cons_printf (" - 0x%08"PFMT64x, -reloc->addend);
} else {
r_cons_printf (" 0x%08"PFMT64x, reloc->addend);
}
}
if (reloc->is_ifunc) {
r_cons_print (" (ifunc)");
}
r_cons_newline ();
}
i++;
}
if (IS_MODE_JSON (mode)) {
r_cons_print ("]");
}
if (IS_MODE_NORMAL (mode)) {
r_cons_printf ("\n%i relocations\n", i);
}
return true;
}
#define MYDB 1
/* this is a hacky workaround that needs proper refactoring in Rbin to use Sdb */
#if MYDB
static Sdb *mydb = NULL;
static RList *osymbols = NULL;
static RBinSymbol *get_symbol(RBin *bin, RList *symbols, const char *name, ut64 addr) {
RBinSymbol *symbol, *res = NULL;
RListIter *iter;
if (mydb && symbols != osymbols) {
sdb_free (mydb);
mydb = NULL;
osymbols = symbols;
}
if (mydb) {
if (name) {
res = (RBinSymbol*)(void*)(size_t)
sdb_num_get (mydb, name, NULL);
} else {
res = (RBinSymbol*)(void*)(size_t)
sdb_num_get (mydb, sdb_fmt(0, "0x"PFMT64x, addr), NULL);
}
} else {
mydb = sdb_new0 ();
r_list_foreach (symbols, iter, symbol) {
/* ${name}=${ptrToSymbol} */
if (!sdb_num_add (mydb, symbol->name, (ut64)(size_t)symbol, 0)) {
// eprintf ("DUP (%s)\n", symbol->name);
}
/* 0x${vaddr}=${ptrToSymbol} */
if (!sdb_num_add (mydb, sdb_fmt(0, "0x"PFMT64x, symbol->vaddr), (ut64)(size_t)symbol, 0)) {
// eprintf ("DUP (%s)\n", symbol->name);
}
if (name) {
if (!res && !strcmp (symbol->name, name)) {
res = symbol;
}
} else {
if (symbol->vaddr == addr) {
res = symbol;
}
}
}
}
return res;
}
#else
static RList *osymbols = NULL;
static RBinSymbol *get_symbol(RBin *bin, RList *symbols, const char *name, ut64 addr) {
RBinSymbol *symbol;
RListIter *iter;
r_list_foreach (symbols, iter, symbol) {
if (name) {
if (!strcmp (symbol->name, name))
return symbol;
} else {
if (symbol->vaddr == addr) {
return symbol;
}
}
}
return NULL;
}
#endif
/* XXX: This is a hack to get PLT references in rabin2 -i */
/* imp. is a prefix that can be rewritten by the symbol table */
static ut64 impaddr(RBin *bin, int va, const char *name) {
char impname[512];
RList *symbols;
RBinSymbol *s;
if (!name || !*name) {
return false;
}
if (!(symbols = r_bin_get_symbols (bin))) {
return false;
}
// TODO: avoid using snprintf here
snprintf (impname, sizeof (impname), "imp.%s", name);
s = get_symbol (bin, symbols, impname, 0LL);
if (s) {
if (va) {
return r_bin_get_vaddr (bin, s->paddr, s->vaddr);
}
return s->paddr;
}
return 0LL;
}
static int bin_imports(RCore *r, int mode, int va, const char *name) {
int bin_demangle = r_config_get_i (r->config, "bin.demangle");
RBinImport *import;
RListIter *iter;
RList *imports;
char *str;
int i = 0;
imports = r_bin_get_imports (r->bin);
if (IS_MODE_JSON (mode)) {
r_cons_print ("[");
} else if (IS_MODE_RAD (mode)) {
r_cons_println ("fs imports");
} else if (IS_MODE_NORMAL (mode)) {
r_cons_println ("[Imports]");
}
r_list_foreach (imports, iter, import) {
char *symname, *escname;
ut64 addr;
if (name && strcmp (import->name, name)) {
continue;
}
symname = strdup (import->name);
if (bin_demangle) {
char *dname = r_bin_demangle (r->bin->cur, NULL, symname);
if (dname) {
free (symname);
symname = r_str_newf ("sym.imp.%s", dname);
free (dname);
}
}
if (r->bin->prefix) {
char *prname;
prname = r_str_newf ("%s.%s", r->bin->prefix, symname);
free (symname);
symname = prname;
}
escname = r_str_escape (symname);
addr = impaddr (r->bin, va, symname);
if (IS_MODE_SET (mode)) {
// TODO(eddyb) symbols that are imports.
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_println (escname);
} else if (IS_MODE_JSON (mode)) {
str = r_str_utf16_encode (symname, -1);
str = r_str_replace (str, "\"", "\\\"", 1);
addr = impaddr (r->bin, va, symname);
r_cons_printf ("%s{\"ordinal\":%d,"
"\"bind\":\"%s\","
"\"type\":\"%s\",",
iter->p ? "," : "",
import->ordinal,
import->bind,
import->type);
if (import->classname && import->classname[0]) {
r_cons_printf ("\"classname\":\"%s\","
"\"descriptor\":\"%s\",",
import->classname,
import->descriptor);
}
r_cons_printf ("\"name\":\"%s\",\"plt\":%"PFMT64d"}",
str, addr);
free (str);
} else if (IS_MODE_RAD (mode)) {
// TODO(eddyb) symbols that are imports.
} else {
const char *bind = r_str_get (import->bind);
const char *type = r_str_get (import->type);
r_cons_printf ("ordinal=%03d plt=0x%08"PFMT64x" bind=%s type=%s",
import->ordinal, addr, bind, type);
if (import->classname && import->classname[0]) {
r_cons_printf (" classname=%s", import->classname);
}
r_cons_printf (" name=%s", escname);
if (import->descriptor && import->descriptor[0]) {
r_cons_printf (" descriptor=%s", import->descriptor);
}
r_cons_newline ();
}
free (symname);
free (escname);
i++;
}
if (IS_MODE_JSON (mode)) {
r_cons_print ("]");
} else if (IS_MODE_NORMAL (mode)) {
r_cons_printf ("\n%i imports\n", i);
}
#if MYDB
osymbols = NULL;
sdb_free (mydb);
mydb = NULL;
#endif
return true;
}
static const char *getPrefixFor(const char *s) {
if (s) {
if (!strcmp (s, "NOTYPE")) {
return "loc";
} else if (!strcmp (s, "OBJECT")) {
return "obj";
}
}
return "sym";
}
typedef struct {
const char *pfx; // prefix for flags
char *name; // raw symbol name
char *nameflag; // flag name for symbol
char *demname; // demangled raw symbol name
char *demflag; // flag name for demangled symbol
char *classname; // classname
char *classflag; // flag for classname
char *methname; // methods [class]::[method]
char *methflag; // methods flag sym.[class].[method]
} SymName;
static void snInit(RCore *r, SymName *sn, RBinSymbol *sym, const char *lang) {
#define MAXFLAG_LEN 128
int bin_demangle = lang != NULL;
const char *pfx;
if (!r || !sym || !sym->name) return;
pfx = getPrefixFor (sym->type);
sn->name = strdup (sym->name);
sn->nameflag = r_str_newf ("%s.%s", pfx, sym->name);
r_name_filter (sn->nameflag, MAXFLAG_LEN);
if (sym->classname && sym->classname[0]) {
sn->classname = strdup (sym->classname);
sn->classflag = r_str_newf ("sym.%s.%s", sn->classname, sn->name);
r_name_filter (sn->classflag, MAXFLAG_LEN);
sn->methname = r_str_newf ("%s::%s", sn->classname, sym->name);
sn->methflag = r_str_newf ("sym.%s.%s", sn->classname, sn->name);
r_name_filter (sn->methflag, strlen (sn->methflag));
} else {
sn->classname = NULL;
sn->classflag = NULL;
sn->methname = NULL;
sn->methflag = NULL;
}
sn->demname = NULL;
sn->demflag = NULL;
if (bin_demangle && sym->paddr) {
sn->demname = r_bin_demangle (r->bin->cur, lang, sn->name);
if (sn->demname) {
sn->demflag = r_str_newf ("%s.%s", pfx, sn->demname);
r_name_filter (sn->demflag, -1);
}
}
}
static void snFini(SymName *sn) {
R_FREE (sn->name);
R_FREE (sn->nameflag);
R_FREE (sn->demname);
R_FREE (sn->demflag);
R_FREE (sn->classname);
R_FREE (sn->classflag);
R_FREE (sn->methname);
R_FREE (sn->methflag);
}
static bool isAnExport(RBinSymbol *s) {
/* workaround for some bin plugs */
if (!strncmp (s->name, "imp.", 4)) {
return false;
}
return (s->bind && !strcmp (s->bind, "GLOBAL"));
}
static int bin_symbols_internal(RCore *r, int mode, ut64 laddr, int va, ut64 at, const char *name, bool exponly) {
RBinInfo *info = r_bin_get_info (r->bin);
RList *entries = r_bin_get_entries (r->bin);
RBinSymbol *symbol;
RBinAddr *entry;
RListIter *iter;
RList *symbols;
const char *lang;
int lastfs = 's';
int i = 0;
int is_arm, bin_demangle = r_config_get_i (r->config, "bin.demangle");
if (!info) {
return 0;
}
is_arm = info && info->arch && !strncmp (info->arch, "arm", 3);
lang = bin_demangle ? r_config_get (r->config, "bin.lang") : NULL;
symbols = r_bin_get_symbols (r->bin);
r_space_set (&r->anal->meta_spaces, "bin");
if (IS_MODE_JSON (mode)) {
r_cons_printf ("[");
} else if (IS_MODE_SET (mode)) {
r_flag_space_set (r->flags, "symbols");
} else if (!at && exponly) {
if (IS_MODE_RAD (mode)) {
r_cons_printf ("fs exports\n");
} else if (IS_MODE_NORMAL (mode)) {
r_cons_printf ("[Exports]\n");
}
} else if (!at && !exponly) {
if (IS_MODE_RAD (mode)) {
r_cons_printf ("fs symbols\n");
} else if (IS_MODE_NORMAL (mode)) {
r_cons_printf ("[Symbols]\n");
}
}
//handle thumb and arm for entry point since they are not present in symbols
if (is_arm) {
r_list_foreach (entries, iter, entry) {
if (IS_MODE_SET (mode)) {
if (info->bits < 33) { // 16 or 32
int force_bits = 0;
ut64 addr = rva (r->bin, entry->paddr, entry->vaddr, va);
if (entry->paddr & 1 || entry->bits == 16) {
force_bits = 16;
} else if (info->bits == 16 && entry->bits == 32) {
force_bits = 32;
} else if (!(entry->paddr & 1)) {
force_bits = 32;
}
if (force_bits) {
r_anal_hint_set_bits (r->anal, addr, force_bits);
}
}
}
}
}
r_list_foreach (symbols, iter, symbol) {
ut64 addr = rva (r->bin, symbol->paddr, symbol->vaddr, va);
SymName sn;
if (exponly && !isAnExport (symbol)) continue;
if (name && strcmp (symbol->name, name)) continue;
if (at && (symbol->size == 0 || !is_in_range (at, addr, symbol->size))) {
continue;
}
snInit (r, &sn, symbol, lang);
if (IS_MODE_SET (mode)) {
if (is_arm && info->bits < 33) { // 16 or 32
int force_bits = 0;
if (symbol->paddr & 1 || symbol->bits == 16) {
force_bits = 16;
} else if (info->bits == 16 && symbol->bits == 32) {
force_bits = 32;
} else if (!(symbol->paddr & 1) && symbol->bits == 32) {
force_bits = 32;
}
if (force_bits) {
r_anal_hint_set_bits (r->anal, addr, force_bits);
}
}
if (!strncmp (symbol->name, "imp.", 4)) {
if (lastfs != 'i')
r_flag_space_set (r->flags, "imports");
lastfs = 'i';
} else {
if (lastfs != 's')
r_flag_space_set (r->flags, "symbols");
lastfs = 's';
}
/* If that's a Classed symbol (method or so) */
if (sn.classname) {
RFlagItem *fi = NULL;
char *comment = NULL;
fi = r_flag_get (r->flags, sn.methflag);
if (r->bin->prefix) {
char *prname;
prname = r_str_newf ("%s.%s", r->bin->prefix, sn.methflag);
r_name_filter (sn.methflag, -1);
free (sn.methflag);
sn.methflag = prname;
}
if (fi) {
r_flag_item_set_realname (fi, sn.methname);
if ((fi->offset - r->flags->base) == addr) {
comment = fi->comment ? strdup (fi->comment) : NULL;
r_flag_unset (r->flags, fi);
fi = NULL;
}
} else {
fi = r_flag_set (r->flags, sn.methflag, addr, symbol->size);
comment = fi->comment ? strdup (fi->comment) : NULL;
if (comment) {
r_flag_item_set_comment (fi, comment);
R_FREE (comment);
}
}
} else {
const char *fn, *n;
RFlagItem *fi;
n = sn.demname ? sn.demname : sn.name;
fn = sn.demflag ? sn.demflag : sn.nameflag;
char *fnp = (r->bin->prefix) ?
r_str_newf ("%s.%s", r->bin->prefix, fn):
strdup (fn);
fi = r_flag_set (r->flags, fnp, addr, symbol->size);
if (fi) {
r_flag_item_set_realname (fi, n);
} else {
if (fn) eprintf ("[Warning] Can't find flag (%s)\n", fn);
}
free (fnp);
}
if (sn.demname) {
r_meta_add (r->anal, R_META_TYPE_COMMENT,
addr, symbol->size, sn.demname);
}
} else if (IS_MODE_JSON (mode)) {
char *str = r_str_utf16_encode (symbol->name, -1);
str = r_str_replace (str, "\"", "\\\"", 1);
r_cons_printf ("%s{\"name\":\"%s\","
"\"demname\":\"%s\","
"\"flagname\":\"%s\","
"\"size\":%d,"
"\"type\":\"%s\","
"\"vaddr\":%"PFMT64d","
"\"paddr\":%"PFMT64d"}",
iter->p?",":"", str,
sn.demname? sn.demname: "",
sn.nameflag,
(int)symbol->size,
symbol->type,
(ut64)addr, (ut64)symbol->paddr);
free (str);
} else if (IS_MODE_SIMPLE (mode)) {
const char *name = sn.demname? sn.demname: symbol->name;
r_cons_printf ("0x%08"PFMT64x" %d %s\n",
addr, (int)symbol->size, name);
} else if (IS_MODE_RAD (mode)) {
RBinFile *binfile;
RBinPlugin *plugin;
char *name = strdup (sn.demname? sn.demname: symbol->name);
r_name_filter (name, -1);
if (!strncmp (name, "imp.", 4)) {
if (lastfs != 'i')
r_cons_printf ("fs imports\n");
lastfs = 'i';
} else {
if (lastfs != 's') {
r_cons_printf ("fs %s\n",
exponly? "exports": "symbols");
}
lastfs = 's';
}
if (r->bin->prefix) {
r_cons_printf ("f %s.sym.%s %u 0x%08"PFMT64x"\n",
r->bin->prefix, name, symbol->size, addr);
} else {
r_cons_printf ("f sym.%s %u 0x%08"PFMT64x"\n",
name, symbol->size, addr);
}
binfile = r_core_bin_cur (r);
plugin = r_bin_file_cur_plugin (binfile);
if (plugin && plugin->name) {
if (!strncmp (plugin->name, "pe", 2)) {
char *p, *module = strdup (symbol->name);
p = strstr (module, ".dll_");
if (p) {
const char *symname = p + 5;
*p = 0;
if (r->bin->prefix) {
r_cons_printf ("k bin/pe/%s/%d=%s.%s\n",
module, symbol->ordinal, r->bin->prefix, symname);
} else {
r_cons_printf ("k bin/pe/%s/%d=%s\n",
module, symbol->ordinal, symname);
}
}
free (module);
}
}
} else {
const char *bind = symbol->bind;
const char *type = symbol->type;
const char *name = sn.demname? sn.demname: symbol->name;
const char *fwd = symbol->forwarder;
if (!bind) bind = "";
if (!type) type = "";
if (!fwd) fwd = "";
r_cons_printf ("vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x" ord=%03u "
"fwd=%s sz=%u bind=%s type=%s name=%s\n",
addr, symbol->paddr, symbol->ordinal, fwd,
symbol->size, bind, type, name);
}
snFini (&sn);
i++;
}
if (IS_MODE_JSON (mode)) r_cons_printf ("]");
if (IS_MODE_NORMAL (mode) && !at) {
r_cons_printf ("\n%i %s\n", i, exponly ? "exports" : "symbols");
}
r_space_set (&r->anal->meta_spaces, NULL);
return true;
}
static int bin_exports(RCore *r, int mode, ut64 laddr, int va, ut64 at, const char *name) {
return bin_symbols_internal (r, mode, laddr, va, at, name, true);
}
static int bin_symbols(RCore *r, int mode, ut64 laddr, int va, ut64 at, const char *name) {
return bin_symbols_internal (r, mode, laddr, va, at, name, false);
}
static char *build_hash_string(int mode, const char *chksum, ut8 *data, ut32 datalen) {
char *chkstr = NULL, *aux, *ret = NULL;
const char *ptr = chksum;
char tmp[128];
int i;
do {
for (i = 0; *ptr && *ptr != ',' && i < sizeof(tmp) -1; i++)
tmp[i] = *ptr++;
tmp[i] = '\0';
chkstr = r_hash_to_string (NULL, tmp, data, datalen);
if (!chkstr) {
if (*ptr && *ptr == ',') ptr++;
continue;
}
if (IS_MODE_SIMPLE (mode)) {
aux = r_str_newf ("%s ", chkstr);
} else if (IS_MODE_JSON (mode)) {
aux = r_str_newf ("\"%s\":\"%s\",", tmp, chkstr);
} else {
aux = r_str_newf ("%s=%s ", tmp, chkstr);
}
ret = r_str_concat (ret, aux);
free (chkstr);
free (aux);
if (*ptr && *ptr == ',') ptr++;
} while (*ptr);
return ret;
}
static int bin_sections(RCore *r, int mode, ut64 laddr, int va, ut64 at, const char *name, const char *chksum) {
char str[R_FLAG_NAME_SIZE];
RBinSection *section;
RBinInfo *info = NULL;
RList *sections;
RListIter *iter;
int i = 0;
int fd = -1;
sections = r_bin_get_sections (r->bin);
if (IS_MODE_JSON (mode)) r_cons_printf ("[");
else if (IS_MODE_RAD (mode) && !at) r_cons_printf ("fs sections\n");
else if (IS_MODE_NORMAL (mode) && !at) r_cons_printf ("[Sections]\n");
else if (IS_MODE_SET (mode)) {
fd = r_core_file_cur_fd (r);
r_flag_space_set (r->flags, "sections");
}
r_list_foreach (sections, iter, section) {
char perms[] = "-----";
int va_sect = va;
ut64 addr;
if (va && !(section->srwx & R_BIN_SCN_READABLE)) {
va_sect = VA_NOREBASE;
}
addr = rva (r->bin, section->paddr, section->vaddr, va_sect);
if (name && strcmp (section->name, name)) continue;
r_name_filter (section->name, sizeof (section->name));
if (at && (section->size == 0 || !is_in_range (at, addr, section->size))) {
continue;
}
if (section->srwx & R_BIN_SCN_MAP) perms[0] = 'm';
if (section->srwx & R_BIN_SCN_SHAREABLE) perms[1] = 's';
if (section->srwx & R_BIN_SCN_READABLE) perms[2] = 'r';
if (section->srwx & R_BIN_SCN_WRITABLE) perms[3] = 'w';
if (section->srwx & R_BIN_SCN_EXECUTABLE) perms[4] = 'x';
if (IS_MODE_SET (mode)) {
#if LOAD_BSS_MALLOC
if (!strcmp (section->name, ".bss")) {
// check if there's already a file opened there
int loaded = 0;
RListIter *iter;
RIOMap *m;
r_list_foreach (r->io->maps, iter, m) {
if (m->from == addr) {
loaded = 1;
}
}
if (!loaded) {
r_core_cmdf (r, "on malloc://%d 0x%"PFMT64x" # bss\n",
section->vsize, addr);
}
}
#endif
r_name_filter (section->name, 128);
if (section->format) {
r_core_cmdf (r, "%s @ 0x%"PFMT64x, section->format, section->vaddr);
}
if (r->bin->prefix) {
snprintf (str, sizeof(str)-1, "%s.section.%s",
r->bin->prefix, section->name);
} else {
snprintf (str, sizeof(str)-1, "section.%s", section->name);
}
r_flag_set (r->flags, str, addr, section->size);
if (r->bin->prefix) {
snprintf (str, sizeof(str)-1, "%s.section_end.%s",
r->bin->prefix, section->name);
} else {
snprintf (str, sizeof(str)-1, "section_end.%s", section->name);
}
r_flag_set (r->flags, str, addr + section->size, 0);
if (section->arch || section->bits) {
const char *arch = section->arch;
int bits = section->bits;
if (info) {
if (!arch) arch = info->arch;
if (!bits) bits = info->bits;
}
//r_io_section_set_archbits (r->io, addr, arch, bits);
}
if (r->bin->prefix) {
snprintf (str, sizeof (str)-1, "[%i] va=0x%08"PFMT64x" pa=0x%08"
PFMT64x" sz=%" PFMT64d" vsz=%"PFMT64d" rwx=%s %s.%s",
i, addr, section->paddr, section->size, section->vsize,
perms, r->bin->prefix, section->name);
} else {
snprintf (str, sizeof (str)-1, "[%i] va=0x%08"PFMT64x" pa=0x%08"
PFMT64x" sz=%" PFMT64d" vsz=%"PFMT64d" rwx=%s %s",
i, addr, section->paddr, section->size, section->vsize,
perms, section->name);
}
r_meta_add (r->anal, R_META_TYPE_COMMENT, addr, addr, str);
if (section->add)
r_io_section_add (r->io, section->paddr, addr, section->size, section->vsize, section->srwx, section->name, 0, fd);
} else if (IS_MODE_SIMPLE (mode)) {
char *hashstr = NULL;
if (chksum) {
ut8 *data = malloc (section->size);
if (!data) return false;
ut32 datalen = section->size;
r_io_pread (r->io, section->paddr, data, datalen);
hashstr = build_hash_string (mode, chksum,
data, datalen);
free (data);
}
r_cons_printf ("0x%"PFMT64x" 0x%"PFMT64x" %s %s%s%s\n",
addr, addr + section->size,
perms,
hashstr ? hashstr : "", hashstr ? " " : "",
section->name
);
free (hashstr);
} else if (IS_MODE_JSON (mode)) {
char *hashstr = NULL;
if (chksum) {
ut8 *data = malloc (section->size);
if (!data) return false;
ut32 datalen = section->size;
r_io_pread (r->io, section->paddr, data, datalen);
hashstr = build_hash_string (mode, chksum,
data, datalen);
free (data);
}
r_cons_printf ("%s{\"name\":\"%s\","
"\"size\":%"PFMT64d","
"\"vsize\":%"PFMT64d","
"\"flags\":\"%s\","
"%s"
"\"paddr\":%"PFMT64d","
"\"vaddr\":%"PFMT64d"}",
iter->p?",":"",
section->name,
section->size,
section->vsize,
perms,
hashstr ? hashstr : "",
section->paddr,
addr);
free (hashstr);
} else if (IS_MODE_RAD (mode)) {
if (!strcmp (section->name, ".bss")) {
r_cons_printf ("on malloc://%d 0x%"PFMT64x" # bss\n",
section->vsize, addr);
}
if (r->bin->prefix) {
r_cons_printf ("S 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" %s.%s %d\n",
section->paddr, addr, section->size, section->vsize,
r->bin->prefix, section->name, (int)section->srwx);
} else {
r_cons_printf ("S 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08"PFMT64x" %s %d\n",
section->paddr, addr, section->size, section->vsize,
section->name, (int)section->srwx);
}
if (section->arch || section->bits) {
const char *arch = section->arch;
int bits = section->bits;
if (info) {
if (!arch) arch = info->arch;
if (!bits) bits = info->bits;
}
r_cons_printf ("Sa %s %d @ 0x%08"
PFMT64x"\n", arch, bits, addr);
}
if (r->bin->prefix) {
r_cons_printf ("f %s.section.%s %"PFMT64d" 0x%08"PFMT64x"\n",
r->bin->prefix, section->name, section->size, addr);
r_cons_printf ("f %s.section_end.%s 1 0x%08"PFMT64x"\n",
r->bin->prefix, section->name, addr + section->size);
r_cons_printf ("CC [%02i] va=0x%08"PFMT64x" pa=0x%08"PFMT64x" sz=%"PFMT64d" vsz=%"PFMT64d" "
"rwx=%s %s.%s @ 0x%08"PFMT64x"\n",
i, addr, section->paddr, section->size, section->vsize,
perms, r->bin->prefix, section->name, addr);
} else {
r_cons_printf ("f section.%s %"PFMT64d" 0x%08"PFMT64x"\n",
section->name, section->size, addr);
r_cons_printf ("f section_end.%s 1 0x%08"PFMT64x"\n",
section->name, addr + section->size);
r_cons_printf ("CC [%02i] va=0x%08"PFMT64x" pa=0x%08"PFMT64x" sz=%"PFMT64d" vsz=%"PFMT64d" "
"rwx=%s %s @ 0x%08"PFMT64x"\n",
i, addr, section->paddr, section->size, section->vsize,
perms, section->name, addr);
}
} else {
char *hashstr = NULL, str[128];
if (chksum) {
ut8 *data = malloc (section->size);
if (!data) return false;
ut32 datalen = section->size;
// VA READ IS BROKEN?
r_io_pread (r->io, section->paddr, data, datalen);
hashstr = build_hash_string (mode, chksum,
data, datalen);
free (data);
}
if (section->arch || section->bits) {
const char *arch = section->arch;
int bits = section->bits;
if (!arch) arch = info->arch;
if (!bits) bits = info->bits;
snprintf (str, sizeof (str), "arch=%s bits=%d ", arch, bits);
} else str[0] = 0;
r_cons_printf ("idx=%02i vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x" sz=%"PFMT64d" vsz=%"PFMT64d" "
"perm=%s %s%sname=%s\n",
i, addr, section->paddr, section->size, section->vsize,
perms, str, hashstr ?hashstr : "", section->name);
free (hashstr);
}
i++;
}
if (IS_MODE_JSON (mode)) {
r_cons_println ("]");
} else if (IS_MODE_NORMAL (mode) && !at) {
r_cons_printf ("\n%i sections\n", i);
}
return true;
}
static int bin_fields(RCore *r, int mode, int va) {
RList *fields;
RListIter *iter;
RBinField *field;
int i = 0;
RBin *bin = r->bin;
RBinFile *binfile = r_core_bin_cur (r);
ut64 size = binfile ? binfile->size : UT64_MAX;
ut64 baddr = r_bin_get_baddr (r->bin);
if (!(fields = r_bin_get_fields (bin))) {
return false;
}
if (IS_MODE_JSON (mode)) {
r_cons_print ("[");
} else if (IS_MODE_RAD (mode)) {
r_cons_println ("fs header");
} else if (IS_MODE_NORMAL (mode)) {
r_cons_println ("[Header fields]");
}
//why this? there is an overlap in bin_sections with ehdr
//because there can't be two sections with the same name
#if 0
else if (IS_MODE_SET (mode)) {
// XXX: Need more flags??
// this will be set even if the binary does not have an ehdr
int fd = r_core_file_cur_fd(r);
r_io_section_add (r->io, 0, baddr, size, size, 7, "ehdr", 0, fd);
}
#endif
r_list_foreach (fields, iter, field) {
ut64 addr = rva (bin, field->paddr, field->vaddr, va);
if (IS_MODE_RAD (mode)) {
r_name_filter (field->name, -1);
r_cons_printf ("f header.%s @ 0x%08"PFMT64x"\n", field->name, addr);
r_cons_printf ("[%02i] vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x" name=%s\n",
i, addr, field->paddr, field->name);
} else if (IS_MODE_JSON (mode)) {
r_cons_printf ("%s{\"name\":\"%s\","
"\"paddr\":%"PFMT64d"}",
iter->p?",":"",
field->name, addr);
} else if (IS_MODE_NORMAL (mode)) {
r_cons_printf ("idx=%02i vaddr=0x%08"PFMT64x" paddr=0x%08"PFMT64x" name=%s\n",
i, addr, field->paddr, field->name);
}
i++;
}
if (IS_MODE_JSON (mode)) r_cons_printf ("]");
else if (IS_MODE_RAD (mode)) {
/* add program header section */
r_cons_printf ("S 0 0x%"PFMT64x" 0x%"PFMT64x" 0x%"PFMT64x" ehdr rwx\n",
baddr, size, size);
} else if (IS_MODE_NORMAL (mode)) {
r_cons_printf ("\n%i fields\n", i);
}
return true;
}
static int bin_classes(RCore *r, int mode) {
RListIter *iter, *iter2;
RBinSymbol *sym;
RBinClass *c;
char *name;
RList *cs = r_bin_get_classes (r->bin);
if (!cs) {
return false;
}
// XXX: support for classes is broken and needs more love
if (IS_MODE_JSON (mode)) {
r_cons_print ("[");
} else if (IS_MODE_SET (mode)) {
if (!r_config_get_i (r->config, "bin.classes")) {
return false;
}
r_flag_space_set (r->flags, "classes");
} else if (IS_MODE_RAD (mode)) {
r_cons_println ("fs classes");
}
r_list_foreach (cs, iter, c) {
if (!c || !c->name || !c->name[0]) {
continue;
}
name = strdup (c->name);
r_name_filter (name, 0);
if (IS_MODE_SET (mode)) {
const char *classname = sdb_fmt (0, "class.%s", name);
r_flag_set (r->flags, classname, c->addr, 1);
r_list_foreach (c->methods, iter2, sym) {
char *method = sdb_fmt (1, "method.%s.%s", c->name, sym->name);
r_name_filter (method, -1);
r_flag_set (r->flags, method, sym->vaddr, 1);
}
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_printf ("0x%08"PFMT64x" %s%s%s\n",
c->addr, c->name, c->super ? " " : "",
c->super ? c->super : "");
} else if (IS_MODE_RAD (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, sym) {
r_cons_printf ("f method.%s.%s = 0x%"PFMT64x"\n",
c->name, sym->name, sym->vaddr);
}
} else if (IS_MODE_JSON (mode)) {
if (c->super) {
r_cons_printf ("%s{\"classname\":\"%s\",\"addr\":%"PFMT64d",\"index\":%"PFMT64d",\"super\":\"%s\",\"methods\":[",
iter->p ? "," : "", c->name, c->addr,
c->index, c->super);
} else {
r_cons_printf ("%s{\"classname\":\"%s\",\"addr\":%"PFMT64d",\"index\":%"PFMT64d",\"methods\":[",
iter->p ? "," : "", c->name, c->addr,
c->index);
}
r_list_foreach (c->methods, iter2, sym) {
r_cons_printf ("%s{\"name\":\"%s\",\"static\":%s,\"addr\":%"PFMT64d"}",
iter2->p? ",": "", sym->name, (sym->bind && strcmp (sym->bind, "METH"))? "true": "false", sym->vaddr);
}
r_cons_printf ("]}");
} else {
int m = 0;
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);
} else {
r_cons_newline ();
}
r_list_foreach (c->methods, iter2, sym) {
r_cons_printf ("0x%08"PFMT64x" method %d %s\n",
sym->vaddr, m, sym->name);
m++;
}
}
free (name);
}
if (IS_MODE_JSON (mode)) {
r_cons_print ("]");
}
return true;
}
static int bin_size(RCore *r, int mode) {
ut64 size = r_bin_get_size (r->bin);
if (IS_MODE_SIMPLE (mode) || IS_MODE_JSON (mode)) {
r_cons_printf ("%"PFMT64u"\n", size);
} else if (IS_MODE_RAD (mode)) {
r_cons_printf ("f bin_size @ %"PFMT64u"\n", size);
} else if (IS_MODE_SET (mode)) {
r_core_cmdf (r, "f bin_size @ %"PFMT64u"\n", size);
} else {
r_cons_printf ("%"PFMT64u"\n", size);
}
return true;
}
static int bin_libs(RCore *r, int mode) {
RList *libs;
RListIter *iter;
char* lib;
int i = 0;
if (!(libs = r_bin_get_libs (r->bin))) {
return false;
}
if (IS_MODE_JSON (mode)) {
r_cons_print ("[");
} else if (IS_MODE_NORMAL (mode)) {
r_cons_println ("[Linked libraries]");
}
r_list_foreach (libs, iter, lib) {
if (IS_MODE_SET (mode)) {
// Nothing to set.
// TODO: load libraries with iomaps?
} else if (IS_MODE_RAD (mode)) {
r_cons_printf ("CCa entry0 %s\n", lib);
} else if (IS_MODE_JSON (mode)) {
r_cons_printf ("%s\"%s\"", iter->p ? "," : "", lib);
} else {
// simple and normal print mode
r_cons_println (lib);
}
i++;
}
if (IS_MODE_JSON (mode)) {
r_cons_print ("]");
} else if (IS_MODE_NORMAL (mode)) {
if (i == 1) {
r_cons_printf ("\n%i library\n", i);
} else {
r_cons_printf ("\n%i libraries\n", i);
}
}
return true;
}
static void bin_mem_print(RList *mems, int perms, int depth, int mode) {
RBinMem *mem;
RListIter *iter;
if (!mems) {
return;
}
r_list_foreach (mems, iter, mem) {
if (IS_MODE_JSON (mode)) {
r_cons_printf ("{\"name\":\"%s\",\"size\":%d,\"address\":%d,"
"\"flags\":\"%s\"}", mem->name, mem->size,
mem->addr, r_str_rwx_i (mem->perms & perms));
} else if (IS_MODE_SIMPLE (mode)) {
r_cons_printf ("0x%08"PFMT64x"\n", mem->addr);
} else {
r_cons_printf ("0x%08"PFMT64x" +0x%04x %s %*s%-*s\n",
mem->addr, mem->size, r_str_rwx_i (mem->perms & perms),
depth, "", 20-depth, mem->name);
}
if (mem->mirrors) {
if (IS_MODE_JSON (mode)) {
r_cons_printf (",");
}
bin_mem_print (mem->mirrors, mem->perms & perms, depth + 1, mode);
}
if (IS_MODE_JSON(mode)) {
if (iter->n) {
r_cons_printf (",");
}
}
}
}
static int bin_mem(RCore *r, int mode) {
RList *mem = NULL;
if (!r) return false;
if (!IS_MODE_JSON(mode)) {
if (!(IS_MODE_RAD (mode) || IS_MODE_SET (mode))) {
r_cons_println ("[Memory]\n");
}
}
if (!(mem = r_bin_get_mem (r->bin))) {
return false;
}
if (IS_MODE_JSON (mode)) {
r_cons_print ("[");
bin_mem_print (mem, 7, 0, R_CORE_BIN_JSON);
r_cons_println ("]");
return true;
} else if (!(IS_MODE_RAD (mode) || IS_MODE_SET (mode))) {
bin_mem_print (mem, 7, 0, mode);
}
return true;
}
static void bin_pe_versioninfo(RCore *r) {
Sdb *sdb = NULL;
int num_version = 0;
int num_stringtable = 0;
int num_string = 0;
const char *format_version = "bin/cur/info/vs_version_info/VS_VERSIONINFO%d";
const char *format_stringtable = "%s/string_file_info/stringtable%d";
const char *format_string = "%s/string%d";
r_cons_printf ("=== VS_VERSIONINFO ===\n\n");
do {
char path_version[256] = {0};
snprintf (path_version, sizeof (path_version), format_version, num_version);
if (!(sdb = sdb_ns_path (r->sdb, path_version, 0)))
break;
r_cons_printf ("# VS_FIXEDFILEINFO\n\n");
char path_fixedfileinfo[256] = {0};
snprintf (path_fixedfileinfo, sizeof (path_fixedfileinfo), "%s/fixed_file_info", path_version);
if (!(sdb = sdb_ns_path (r->sdb, path_fixedfileinfo, 0)))
break;
r_cons_printf (" Signature: 0x%"PFMT64x"\n", sdb_num_get (sdb, "Signature", 0));
r_cons_printf (" StrucVersion: 0x%"PFMT64x"\n", sdb_num_get (sdb, "StrucVersion", 0));
r_cons_printf (" FileVersion: %"PFMT64d".%"PFMT64d".%"PFMT64d".%"PFMT64d"\n",
sdb_num_get (sdb, "FileVersionMS", 0) >> 16,
sdb_num_get (sdb, "FileVersionMS", 0) & 0xFFFF,
sdb_num_get (sdb, "FileVersionLS", 0) >> 16,
sdb_num_get (sdb, "FileVersionLS", 0) & 0xFFFF);
r_cons_printf (" ProductVersion: %"PFMT64d".%"PFMT64d".%"PFMT64d".%"PFMT64d"\n",
sdb_num_get (sdb, "ProductVersionMS", 0) >> 16,
sdb_num_get (sdb, "ProductVersionMS", 0) & 0xFFFF,
sdb_num_get (sdb, "ProductVersionLS", 0) >> 16,
sdb_num_get (sdb, "ProductVersionLS", 0) & 0xFFFF);
r_cons_printf (" FileFlagsMask: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileFlagsMask", 0));
r_cons_printf (" FileFlags: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileFlags", 0));
r_cons_printf (" FileOS: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileOS", 0));
r_cons_printf (" FileType: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileType", 0));
r_cons_printf (" FileSubType: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileSubType", 0));
#if 0
r_cons_printf (" FileDate: %d.%d.%d.%d\n",
sdb_num_get (sdb, "FileDateMS", 0) >> 16,
sdb_num_get (sdb, "FileDateMS", 0) & 0xFFFF,
sdb_num_get (sdb, "FileDateLS", 0) >> 16,
sdb_num_get (sdb, "FileDateLS", 0) & 0xFFFF);
#endif
r_cons_newline ();
r_cons_println ("# StringTable\n");
for (num_stringtable = 0; sdb; ++num_stringtable) {
char path_stringtable[256] = {0};
snprintf (path_stringtable, sizeof (path_stringtable), format_stringtable, path_version, num_stringtable);
sdb = sdb_ns_path (r->sdb, path_stringtable, 0);
for (num_string = 0; sdb; ++num_string) {
char path_string[256] = {0};
snprintf (path_string, sizeof (path_string), format_string, path_stringtable, num_string);
sdb = sdb_ns_path (r->sdb, path_string, 0);
if (sdb) {
int lenkey = 0;
int lenval = 0;
ut8 *key_utf16 = sdb_decode (sdb_const_get (sdb, "key", 0), &lenkey);
ut8 *val_utf16 = sdb_decode (sdb_const_get (sdb, "value", 0), &lenval);
ut8 *key_utf8 = calloc (lenkey * 2, 1);
ut8 *val_utf8 = calloc (lenval * 2, 1);
if (r_str_utf16_to_utf8 (key_utf8, lenkey * 2, key_utf16, lenkey, true) < 0
|| r_str_utf16_to_utf8 (val_utf8, lenval * 2, val_utf16, lenval, true) < 0) {
eprintf ("Warning: Cannot decode utf16 to utf8\n");
} else {
r_cons_printf (" %s: %s\n", (char*)key_utf8, (char*)val_utf8);
}
free (key_utf8);
free (val_utf8);
free (key_utf16);
free (val_utf16);
}
}
}
++num_version;
} while (sdb);
}
static void bin_elf_versioninfo(RCore *r) {
const char *format = "bin/cur/info/versioninfo/%s%d";
char path[256] = {0};
int num_versym = 0;
int num_verneed = 0;
int num_entry = 0;
Sdb *sdb = NULL;
do {
snprintf (path, sizeof (path), format, "versym", num_versym++);
if (!(sdb = sdb_ns_path (r->sdb, path, 0)))
break;
ut64 addr = sdb_num_get (sdb, "addr", 0);
ut64 offset = sdb_num_get (sdb, "offset", 0);
ut64 link = sdb_num_get (sdb, "link", 0);
ut64 num_entries = sdb_num_get (sdb, "num_entries", 0);
const char *section_name = sdb_const_get (sdb, "section_name", 0);
const char *link_section_name = sdb_const_get (sdb, "link_section_name", 0);
r_cons_printf ("Version symbols section '%s' contains %d entries:\n", section_name, num_entries);
r_cons_printf (" Addr: 0x%08"PFMT64x" Offset: 0x%08"PFMT64x" Link: %x (%s)\n",
(ut64)addr, (ut64)offset, (ut32)link, link_section_name);
do {
int num_val = 0;
char path_entry[256] = {0};
snprintf (path_entry, sizeof (path_entry), "%s/entry%d", path, num_entry++);
if (!(sdb = sdb_ns_path (r->sdb, path_entry, 0)))
break;
r_cons_printf (" 0x%08"PFMT64x": ", sdb_num_get (sdb, "idx", 0));
const char *value = NULL;
do {
char key[32] = {0};
snprintf (key, sizeof (key), "value%d", num_val++);
if ((value = sdb_const_get (sdb, key, 0)))
r_cons_printf ("%s ", value);
} while (value);
r_cons_newline ();
} while (sdb);
r_cons_println ("\n");
} while (sdb);
do {
int num_version = 0;
char path_version[256] = {0};
snprintf (path, sizeof (path), format, "verneed", num_verneed++);
if (!(sdb = sdb_ns_path (r->sdb, path, 0)))
break;
r_cons_printf ("Version need section '%s' contains %d entries:\n",
sdb_const_get (sdb, "section_name", 0), (int)sdb_num_get (sdb, "num_entries", 0));
r_cons_printf (" Addr: 0x%08"PFMT64x, sdb_num_get (sdb, "addr", 0));
r_cons_printf (" Offset: 0x%08"PFMT64x" Link to section: %"PFMT64d" (%s)\n",
sdb_num_get (sdb, "offset", 0), sdb_num_get (sdb, "link", 0),
sdb_const_get (sdb, "link_section_name", 0));
do {
snprintf (path_version, sizeof (path_version), "%s/version%d", path, num_version++);
const char *filename = NULL;
char path_vernaux[256] = {0};
int num_vernaux = 0;
if (!(sdb = sdb_ns_path (r->sdb, path_version, 0)))
break;
r_cons_printf (" 0x%08"PFMT64x": Version: %d",
sdb_num_get (sdb, "idx", 0), (int)sdb_num_get (sdb, "vn_version", 0));
if ((filename = sdb_const_get (sdb, "file_name", 0)))
r_cons_printf (" File: %s", filename);
r_cons_printf (" Cnt: %d\n", (int)sdb_num_get (sdb, "cnt", 0));
do {
snprintf (path_vernaux, sizeof (path_vernaux), "%s/vernaux%d",
path_version, num_vernaux++);
if (!(sdb = sdb_ns_path (r->sdb, path_vernaux, 0)))
break;
r_cons_printf (" 0x%08"PFMT64x": Name: %s",
sdb_num_get (sdb, "idx", 0), sdb_const_get (sdb, "name", 0));
r_cons_printf (" Flags: %s Version: %d\n",
sdb_const_get (sdb, "flags", 0), (int)sdb_num_get (sdb, "version", 0));
} while (sdb);
} while (sdb);
} while (sdb);
}
static void bin_mach0_versioninfo(RCore *r) {
/* TODO */
}
static int bin_versioninfo(RCore *r, int mode) {
const RBinInfo *info = r_bin_get_info (r->bin);
if (!info || !info->rclass) {
return false;
}
if (!strncmp ("pe", info->rclass, 2)) {
bin_pe_versioninfo (r);
} else if (!strncmp ("elf", info->rclass, 3)) {
bin_elf_versioninfo (r);
} else if (!strncmp ("mach0", info->rclass, 5)) {
bin_mach0_versioninfo (r);
} else {
r_cons_println ("Unknown format");
return false;
}
return true;
}
static int bin_signature(RCore *r, int mode) {
RBinFile *cur = r_bin_cur (r->bin);
RBinPlugin *plg = r_bin_file_cur_plugin (cur);
if (plg && plg->signature) {
const char *signature = plg->signature (cur);
r_cons_println (signature);
return true;
}
return false;
}
R_API int r_core_bin_info(RCore *core, int action, int mode, int va, RCoreBinFilter *filter, const char *chksum) {
int ret = true;
const char *name = NULL;
ut64 at = 0, loadaddr = r_bin_get_laddr (core->bin);
if (filter && filter->offset) {
at = filter->offset;
}
if (filter && filter->name) {
name = filter->name;
}
// use our internal values for va
va = va ? VA_TRUE : VA_FALSE;
if ((action & R_CORE_BIN_ACC_STRINGS)) ret &= bin_strings (core, mode, va);
if ((action & R_CORE_BIN_ACC_INFO)) ret &= bin_info (core, mode);
if ((action & R_CORE_BIN_ACC_MAIN)) ret &= bin_main (core, mode, va);
if ((action & R_CORE_BIN_ACC_DWARF)) ret &= bin_dwarf (core, mode);
if ((action & R_CORE_BIN_ACC_PDB)) ret &= bin_pdb (core, mode);
if ((action & R_CORE_BIN_ACC_ENTRIES)) ret &= bin_entry (core, mode, loadaddr, va);
if ((action & R_CORE_BIN_ACC_SECTIONS)) ret &= bin_sections (core, mode, loadaddr, va, at, name, chksum);
if ((action & R_CORE_BIN_ACC_RELOCS)) ret &= bin_relocs (core, mode, va);
if ((action & R_CORE_BIN_ACC_IMPORTS)) ret &= bin_imports (core, mode, va, name);
if ((action & R_CORE_BIN_ACC_EXPORTS)) ret &= bin_exports (core, mode, loadaddr, va, at, name);
if ((action & R_CORE_BIN_ACC_SYMBOLS)) ret &= bin_symbols (core, mode, loadaddr, va, at, name);
if ((action & R_CORE_BIN_ACC_FIELDS)) ret &= bin_fields (core, mode, va);
if ((action & R_CORE_BIN_ACC_LIBS)) ret &= bin_libs (core, mode);
if ((action & R_CORE_BIN_ACC_CLASSES)) ret &= bin_classes (core, mode);
if ((action & R_CORE_BIN_ACC_SIZE)) ret &= bin_size (core, mode);
if ((action & R_CORE_BIN_ACC_MEM)) ret &= bin_mem (core, mode);
if ((action & R_CORE_BIN_ACC_VERSIONINFO)) ret &= bin_versioninfo (core, mode);
if ((action & R_CORE_BIN_ACC_SIGNATURE)) ret &= bin_signature (core, mode);
return ret;
}
R_API int r_core_bin_set_arch_bits(RCore *r, const char *name, const char * arch, ut16 bits) {
RCoreFile *cf = r_core_file_cur (r);
RBinFile *binfile;
if (!name) {
name = (cf && cf->desc) ? cf->desc->name : NULL;
}
if (!name) {
return false;
}
/* Check if the arch name is a valid name */
if (!r_asm_is_valid (r->assembler, arch)) {
return false;
}
/* Find a file with the requested name/arch/bits */
binfile = r_bin_file_find_by_arch_bits (r->bin, arch, bits, name);
if (!binfile) {
return false;
}
if (!r_bin_use_arch (r->bin, arch, bits, name)) {
return false;
}
r_core_bin_set_cur (r, binfile);
return r_core_bin_set_env (r, binfile);
}
R_API int r_core_bin_update_arch_bits(RCore *r) {
RBinFile *binfile = r_core_bin_cur (r);
const char *arch = r->assembler->cur->arch;
ut16 bits = r->assembler->bits;
const char *name = binfile ? binfile->file : NULL;
return r_core_bin_set_arch_bits (r, name, arch, bits);
}
R_API int r_core_bin_raise(RCore *core, ut32 binfile_idx, ut32 binobj_idx) {
RBin *bin = core->bin;
RBinFile *binfile = NULL;
if (binfile_idx == UT32_MAX && binobj_idx == UT32_MAX) {
return false;
}
if (!r_bin_select_by_ids (bin, binfile_idx, binobj_idx)) {
return false;
}
binfile = r_core_bin_cur (core);
if (binfile) {
r_io_raise (core->io, binfile->fd);
}
// it should be 0 to use r_io_use_fd in r_core_block_read
core->switch_file_view = 0;
return binfile && r_core_bin_set_env (core, binfile) && r_core_block_read (core);
}
R_API int r_core_bin_delete(RCore *core, ut32 binfile_idx, ut32 binobj_idx) {
RBin *bin = core->bin;
RBinFile *binfile = NULL;
if (binfile_idx == UT32_MAX && binobj_idx == UT32_MAX) return false;
if (!r_bin_object_delete (bin, binfile_idx, binobj_idx)) return false;
binfile = r_core_bin_cur (core);
if (binfile) {
r_io_raise (core->io, binfile->fd);
}
core->switch_file_view = 0;
return binfile && r_core_bin_set_env (core, binfile) && r_core_block_read (core);
}
static int r_core_bin_file_print(RCore *core, RBinFile *binfile, int mode) {
RListIter *iter;
RBinObject *obj;
const char *name = binfile ? binfile->file : NULL;
(void)r_bin_get_info (core->bin); // XXX is this necssary for proper iniitialization
ut32 id = binfile ? binfile->id : 0;
ut32 fd = binfile ? binfile->fd : 0;
ut32 bin_sz = binfile ? binfile->size : 0;
// TODO: handle mode to print in json and r2 commands
if (!binfile) {
return false;
}
switch (mode) {
case 'j':
r_cons_printf ("{\"name\":\"%s\",\"fd\":%d,\"id\":%d,\"size\":%d,\"objs\":[",
name, fd, id, bin_sz);
r_list_foreach (binfile->objs, iter, obj) {
RBinInfo *info = obj->info;
ut8 bits = info ? info->bits : 0;
const char *arch = info ? info->arch : "unknown";
r_cons_printf ("{\"objid\":%d,\"arch\":\"%s\",\"bits\":%d,\"binoffset\":%"
PFMT64d",\"objsize\":%"PFMT64d"}",
obj->id, arch, bits, obj->boffset, obj->obj_size);
if (iter->n) {
r_cons_print (",");
}
}
r_cons_print ("]}");
break;
default:
r_cons_printf ("binfile fd=%d name=%s id=%d\n", fd, name, id);
r_list_foreach (binfile->objs, iter, obj) {
RBinInfo *info = obj->info;
ut8 bits = info ? info->bits : 0;
const char *arch = info ? info->arch : "unknown";
r_cons_printf ("id=%d arch=%s bits=%d boffset=0x%04"PFMT64x" size=0x%04"PFMT64x"\n",
obj->id, arch, bits, obj->boffset, obj->obj_size );
}
break;
}
return true;
}
R_API int r_core_bin_list(RCore *core, int mode) {
// list all binfiles and there objects and there archs
int count = 0;
RListIter *iter;
RBinFile *binfile = NULL; //, *cur_bf = r_core_bin_cur (core) ;
RBin *bin = core->bin;
const RList *binfiles = bin ? bin->binfiles: NULL;
if (!binfiles) {
return false;
}
if (mode == 'j') {
r_cons_print ("[");
}
r_list_foreach (binfiles, iter, binfile) {
r_core_bin_file_print (core, binfile, mode);
if (iter->n && mode == 'j') {
r_cons_print (",");
}
}
if (mode == 'j') {
r_cons_println ("]");
}
//r_core_file_set_by_file (core, cur_cf);
//r_core_bin_bind (core, cur_bf);
return count;
}