mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-14 08:49:50 +00:00
c474aa5a9f
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
2499 lines
73 KiB
C
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;
|
|
}
|