mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-01 00:51:19 +00:00
2891 lines
101 KiB
C
2891 lines
101 KiB
C
/* radare - LGPL - Copyright 2009-2018 - pancake */
|
|
|
|
#include <r_core.h>
|
|
|
|
#define NODECB(w,x,y) r_config_set_cb (cfg,w,x,y)
|
|
#define NODEICB(w,x,y) r_config_set_i_cb (cfg,w,x,y)
|
|
#define SETDESC(x,y) r_config_node_desc (x,y)
|
|
#define SETOPTIONS(x, ...) set_options (x, __VA_ARGS__)
|
|
#define SETI(x,y,z) SETDESC (r_config_set_i (cfg,x,y), z)
|
|
#define SETICB(w,x,y,z) SETDESC (NODEICB (w,x,y), z)
|
|
#define SETPREF(x,y,z) SETDESC (r_config_set (cfg,x,y), z)
|
|
#define SETCB(w,x,y,z) SETDESC (NODECB (w,x,y), z)
|
|
|
|
static void set_options(RConfigNode *node, ...) {
|
|
va_list argp;
|
|
char *option = NULL;
|
|
va_start (argp, node);
|
|
option = va_arg (argp, char *);
|
|
while (option) {
|
|
r_list_append (node->options, option);
|
|
option = va_arg (argp, char *);
|
|
}
|
|
va_end (argp);
|
|
}
|
|
|
|
static bool isGdbPlugin(RCore *core) {
|
|
if (core->io && core->io->desc && core->io->desc->plugin) {
|
|
if (core->io->desc->plugin->name && !strcmp (core->io->desc->plugin->name, "gdb")) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void print_node_options(RConfigNode *node) {
|
|
RListIter *iter;
|
|
char *option;
|
|
r_list_foreach (node->options, iter, option) {
|
|
r_cons_printf ("%s\n", option);
|
|
}
|
|
}
|
|
|
|
/* TODO: use loop here */
|
|
/*------------------------------------------------------------------------------------------*/
|
|
|
|
static int compareName(const RAnalFunction *a, const RAnalFunction *b) {
|
|
return a && b && a->name && b->name && strcmp (a->name, b->name);
|
|
}
|
|
|
|
static int compareNameLen(const RAnalFunction *a, const RAnalFunction *b) {
|
|
return a && b && a->name && b->name && strlen (a->name) > strlen (b->name);
|
|
}
|
|
|
|
static int compareAddress(const RAnalFunction *a, const RAnalFunction *b) {
|
|
return a && b && a->addr && b->addr && a->addr > b->addr;
|
|
}
|
|
|
|
static int compareType(const RAnalFunction *a, const RAnalFunction *b) {
|
|
return a && b && a->diff->type && b->diff->type && a->diff->type > b->diff->type;
|
|
}
|
|
|
|
static int compareSize(const RAnalFunction *a, const RAnalFunction *b) {
|
|
// return a && b && a->_size < b->_size;
|
|
return a && b && r_anal_fcn_realsize (a) > r_anal_fcn_realsize (b);
|
|
}
|
|
|
|
static int compareDist(const RAnalFunction *a, const RAnalFunction *b) {
|
|
return a && b && a->diff->dist && b->diff->dist && a->diff->dist > b->diff->dist;
|
|
}
|
|
|
|
static int cb_diff_sort(void *_core, void *_node) {
|
|
RConfigNode *node = _node;
|
|
const char *column = node->value;
|
|
RCore *core = _core;
|
|
if (column && strcmp (column, "?")) {
|
|
if (!strcmp (column, "name")) {
|
|
core->anal->columnSort = (RListComparator)compareName;
|
|
} else if (!strcmp (column, "namelen")) {
|
|
core->anal->columnSort = (RListComparator)compareNameLen;
|
|
} else if (!strcmp (column, "addr")) {
|
|
core->anal->columnSort = (RListComparator)compareAddress;
|
|
} else if (!strcmp (column, "type")) {
|
|
core->anal->columnSort = (RListComparator)compareType;
|
|
} else if (!strcmp (column, "size")) {
|
|
core->anal->columnSort = (RListComparator)compareSize;
|
|
} else if (!strcmp (column, "dist")) {
|
|
core->anal->columnSort = (RListComparator)compareDist;
|
|
} else {
|
|
goto fail;
|
|
}
|
|
return true;
|
|
}
|
|
fail:
|
|
eprintf ("e diff.sort = [name, namelen, addr, type, size, dist]\n");
|
|
return false;
|
|
}
|
|
|
|
static const char *has_esil(RCore *core, const char *name) {
|
|
RListIter *iter;
|
|
RAnalPlugin *h;
|
|
if (!core || !core->anal || !name) {
|
|
return NULL;
|
|
}
|
|
RAnal *a = core->anal;
|
|
r_list_foreach (a->plugins, iter, h) {
|
|
if (!strcmp (name, h->name)) {
|
|
return h->esil? "Ae": "A_";
|
|
}
|
|
}
|
|
return "__";
|
|
}
|
|
|
|
// copypasta from binr/rasm2/rasm2.c
|
|
static void rasm2_list(RCore *core, const char *arch, int fmt) {
|
|
int i;
|
|
const char *feat2, *feat;
|
|
RAsm *a = core->assembler;
|
|
char bits[32];
|
|
RAsmPlugin *h;
|
|
RListIter *iter;
|
|
if (fmt == 'j') {
|
|
r_cons_print ("{");
|
|
}
|
|
r_list_foreach (a->plugins, iter, h) {
|
|
if (arch && *arch) {
|
|
if (h->cpus && !strcmp (arch, h->name)) {
|
|
char *c = strdup (h->cpus);
|
|
int n = r_str_split (c, ',');
|
|
for (i = 0; i < n; i++) {
|
|
r_cons_println (r_str_word_get0 (c, i));
|
|
}
|
|
free (c);
|
|
break;
|
|
}
|
|
} else {
|
|
bits[0] = 0;
|
|
/* The underscore makes it easier to distinguish the
|
|
* columns */
|
|
if (h->bits&8) strcat (bits, "_8");
|
|
if (h->bits&16) strcat (bits, "_16");
|
|
if (h->bits&32) strcat (bits, "_32");
|
|
if (h->bits&64) strcat (bits, "_64");
|
|
if (!*bits) strcat (bits, "_0");
|
|
feat = "__";
|
|
if (h->assemble && h->disassemble) feat = "ad";
|
|
if (h->assemble && !h->disassemble) feat = "a_";
|
|
if (!h->assemble && h->disassemble) feat = "_d";
|
|
feat2 = has_esil (core, h->name);
|
|
if (fmt == 'q') {
|
|
r_cons_println (h->name);
|
|
} else if (fmt == 'j') {
|
|
const char *str_bits = "32, 64";
|
|
const char *license = "GPL";
|
|
r_cons_printf ("\"%s\":{\"bits\":[%s],\"license\":\"%s\",\"description\":\"%s\",\"features\":\"%s\"}%s",
|
|
h->name, str_bits, license, h->desc, feat, iter->n? ",": "");
|
|
} else {
|
|
r_cons_printf ("%s%s %-9s %-11s %-7s %s\n",
|
|
feat, feat2, bits, h->name,
|
|
h->license?h->license:"unknown", h->desc);
|
|
}
|
|
}
|
|
}
|
|
if (fmt == 'j') {
|
|
r_cons_print ("}\n");
|
|
}
|
|
}
|
|
|
|
static inline void __setsegoff(RConfig *cfg, const char *asmarch, int asmbits) {
|
|
int autoseg = (!strncmp (asmarch, "x86", 3) && asmbits == 16);
|
|
r_config_set (cfg, "asm.segoff", r_str_bool (autoseg));
|
|
}
|
|
|
|
static int cb_debug_hitinfo(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->dbg->hitinfo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analarmthumb(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.armthumb = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analeobjmp(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.eobjmp = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analafterjmp(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.afterjmp = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analstrings(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (node->i_value) {
|
|
r_config_set (core->config, "bin.strings", "false");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_analsleep(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->sleep = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analmaxrefs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->maxreflines = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analnopskip (void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.nopskip = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analhpskip (void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.hpskip = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analbbsplit (void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.bbsplit = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
/* obey section permissions */
|
|
static int cb_analnoncode(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.noncode = !!node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static void update_analarch_options(RCore *core, RConfigNode *node) {
|
|
RAnalPlugin *h;
|
|
RListIter *it;
|
|
if (core && core->anal && node) {
|
|
r_list_purge (node->options);
|
|
r_list_foreach (core->anal->plugins, it, h) {
|
|
SETOPTIONS (node, h->name, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int cb_analarch(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (*node->value == '?') {
|
|
update_analarch_options (core, node);
|
|
print_node_options (node);
|
|
return false;
|
|
}
|
|
if (*node->value) {
|
|
if (r_anal_use (core->anal, node->value)) {
|
|
return true;
|
|
}
|
|
const char *aa = r_config_get (core->config, "asm.arch");
|
|
if (!aa || strcmp (aa, node->value)) {
|
|
eprintf ("anal.arch: cannot find '%s'\n", node->value);
|
|
} else {
|
|
r_config_set (core->config, "anal.arch", "null");
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static int cb_analcpu(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_anal_set_cpu (core->anal, node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_analsplit(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->split = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_analrecont(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.recont = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_asmminvalsub(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->parser->minval = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrrainbow(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->print->flags |= R_PRINT_FLAGS_RAINBOW;
|
|
} else {
|
|
core->print->flags &= (~R_PRINT_FLAGS_RAINBOW);
|
|
}
|
|
r_print_set_flags (core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static int cb_asmsecsub(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->print->flags |= R_PRINT_FLAGS_SECSUB;
|
|
} else {
|
|
core->print->flags &= (~R_PRINT_FLAGS_SECSUB);
|
|
}
|
|
r_print_set_flags (core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static int cb_asmassembler(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_asm_use_assembler (core->assembler, node->value);
|
|
return true;
|
|
}
|
|
|
|
static void update_asmcpu_options(RCore *core, RConfigNode *node) {
|
|
RAsmPlugin *h;
|
|
RListIter *iter;
|
|
if (!core || !core->assembler) {
|
|
return;
|
|
}
|
|
const char *arch = r_config_get (core->config, "asm.arch");
|
|
if (!arch || !*arch) {
|
|
return;
|
|
}
|
|
r_list_purge (node->options);
|
|
r_list_foreach (core->assembler->plugins, iter, h) {
|
|
if (h->cpus && !strcmp (arch, h->name)) {
|
|
char *c = strdup (h->cpus);
|
|
int i, n = r_str_split (c, ',');
|
|
for (i = 0; i < n; i++) {
|
|
SETOPTIONS (node, r_str_word_get0 (c, i), NULL);
|
|
}
|
|
free (c);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int cb_asmcpu(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (*node->value == '?') {
|
|
update_asmcpu_options (core, node);
|
|
/* print verbose help instead of plain option listing */
|
|
rasm2_list (core, r_config_get (core->config, "asm.arch"), node->value[1]);
|
|
return 0;
|
|
}
|
|
r_asm_set_cpu (core->assembler, node->value);
|
|
r_config_set (core->config, "anal.cpu", node->value);
|
|
return true;
|
|
}
|
|
|
|
static void update_asmarch_options(RCore *core, RConfigNode *node) {
|
|
RAsmPlugin *h;
|
|
RListIter *iter;
|
|
if (core && node && core->assembler) {
|
|
r_list_purge (node->options);
|
|
r_list_foreach (core->assembler->plugins, iter, h) {
|
|
SETOPTIONS (node, h->name, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int cb_asmarch(void *user, void *data) {
|
|
char asmparser[32];
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
const char *asmos = NULL;
|
|
int bits = R_SYS_BITS;
|
|
if (!*node->value || !core || !core->assembler) {
|
|
return false;
|
|
}
|
|
asmos = r_config_get (core->config, "asm.os");
|
|
if (core && core->anal && core->anal->bits) {
|
|
bits = core->anal->bits;
|
|
}
|
|
if (node->value[0] == '?') {
|
|
if (strlen (node->value) > 1 && node->value[1] == '?') {
|
|
update_asmarch_options (core, node);
|
|
/* print more verbose help instead of plain option values */
|
|
rasm2_list (core, NULL, node->value[1]);
|
|
return false;
|
|
} else {
|
|
print_node_options (node);
|
|
return false;
|
|
}
|
|
}
|
|
r_egg_setup (core->egg, node->value, bits, 0, R_SYS_OS);
|
|
|
|
if (!r_asm_use (core->assembler, node->value)) {
|
|
eprintf ("asm.arch: cannot find (%s)\n", node->value);
|
|
return false;
|
|
}
|
|
//we should strdup here otherwise will crash if any r_config_set
|
|
//free the old value
|
|
char *asm_cpu = strdup (r_config_get (core->config, "asm.cpu"));
|
|
if (core->assembler->cur) {
|
|
const char *newAsmCPU = core->assembler->cur->cpus;
|
|
if (newAsmCPU) {
|
|
if (*newAsmCPU) {
|
|
char *nac = strdup (newAsmCPU);
|
|
char *comma = strchr (nac, ',');
|
|
if (comma) {
|
|
*comma = 0;
|
|
r_config_set (core->config, "asm.cpu", nac);
|
|
}
|
|
free (nac);
|
|
} else {
|
|
r_config_set (core->config, "asm.cpu", "");
|
|
}
|
|
}
|
|
bits = core->assembler->cur->bits;
|
|
if (8 & bits) {
|
|
bits = 8;
|
|
} else if (16 & bits) {
|
|
bits = 16;
|
|
} else if (32 & bits) {
|
|
bits = 32;
|
|
} else {
|
|
bits = 64;
|
|
}
|
|
}
|
|
snprintf (asmparser, sizeof (asmparser), "%s.pseudo", node->value);
|
|
r_config_set (core->config, "asm.parser", asmparser);
|
|
if (core->assembler->cur && core->anal &&
|
|
!(core->assembler->cur->bits & core->anal->bits)) {
|
|
r_config_set_i (core->config, "asm.bits", bits);
|
|
}
|
|
|
|
//r_debug_set_arch (core->dbg, r_sys_arch_id (node->value), bits);
|
|
r_debug_set_arch (core->dbg, node->value, bits);
|
|
if (!r_config_set (core->config, "anal.arch", node->value)) {
|
|
char *p, *s = strdup (node->value);
|
|
if (s) {
|
|
p = strchr (s, '.');
|
|
if (p) {
|
|
*p = 0;
|
|
}
|
|
if (!r_config_set (core->config, "anal.arch", s)) {
|
|
/* fall back to the anal.null plugin */
|
|
r_config_set (core->config, "anal.arch", "null");
|
|
}
|
|
free (s);
|
|
}
|
|
}
|
|
// set pcalign
|
|
{
|
|
int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
|
|
if (v != -1) {
|
|
r_config_set_i (core->config, "asm.pcalign", v);
|
|
} else {
|
|
r_config_set_i (core->config, "asm.pcalign", 0);
|
|
}
|
|
}
|
|
if (core->anal) {
|
|
if (!r_syscall_setup (core->anal->syscall, node->value, asmos, core->anal->bits)) {
|
|
//eprintf ("asm.arch: Cannot setup syscall '%s/%s' from '%s'\n",
|
|
// node->value, asmos, R2_LIBDIR"/radare2/"R2_VERSION"/syscall");
|
|
}
|
|
}
|
|
//if (!strcmp (node->value, "bf"))
|
|
// r_config_set (core->config, "dbg.backend", "bf");
|
|
__setsegoff (core->config, node->value, core->assembler->bits);
|
|
|
|
// set a default endianness
|
|
int bigbin = r_bin_is_big_endian (core->bin);
|
|
if (bigbin == -1 /* error: no endianness detected in binary */) {
|
|
// try to set RAsm to LE
|
|
r_asm_set_big_endian (core->assembler, false);
|
|
// set endian of display to LE
|
|
core->print->big_endian = false;
|
|
} else {
|
|
// try to set endian of RAsm to match binary
|
|
r_asm_set_big_endian (core->assembler, bigbin);
|
|
// set endian of display to match binary
|
|
core->print->big_endian = bigbin;
|
|
}
|
|
r_asm_set_cpu (core->assembler, asm_cpu);
|
|
free (asm_cpu);
|
|
RConfigNode *asmcpu = r_config_node_get (core->config, "asm.cpu");
|
|
if (asmcpu) {
|
|
update_asmcpu_options (core, asmcpu);
|
|
}
|
|
/* reload types and cc info */
|
|
// changing asm.arch changes anal.arch
|
|
// changing anal.arch sets types db
|
|
// so ressetting is redundant and may lead to bugs
|
|
// 1 case this is usefull is when sdb_types is null
|
|
if (!core->anal || !core->anal->sdb_types) {
|
|
r_core_anal_type_init (core);
|
|
}
|
|
r_core_anal_cc_init (core);
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbgbpsize(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->dbg->bpsize = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbgbtdepth(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->dbg->btdepth = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_asmbits(void *user, void *data) {
|
|
const char *asmos, *asmarch;
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
int ret = 0, bits;
|
|
if (!core) {
|
|
eprintf ("user can't be NULL\n");
|
|
return false;
|
|
}
|
|
|
|
bits = node->i_value;
|
|
|
|
if (bits > 0) {
|
|
ret = r_asm_set_bits (core->assembler, bits);
|
|
if (!ret) {
|
|
RAsmPlugin *h = core->assembler->cur;
|
|
if (h) {
|
|
eprintf ("Cannot set bits %d to '%s'\n", bits, h->name);
|
|
} else {
|
|
eprintf ("e asm.bits: Cannot set value, no plugins defined yet\n");
|
|
ret = true;
|
|
}
|
|
}
|
|
if (!r_anal_set_bits (core->anal, bits)) {
|
|
eprintf ("asm.arch: Cannot setup '%d' bits analysis engine\n", bits);
|
|
}
|
|
core->print->bits = bits;
|
|
}
|
|
if (core->dbg && core->anal && core->anal->cur) {
|
|
r_debug_set_arch (core->dbg, core->anal->cur->arch, bits);
|
|
bool load_from_debug = r_config_get_i (core->config, "cfg.debug");
|
|
if (load_from_debug) {
|
|
if (core->dbg->h && core->dbg->h->reg_profile) {
|
|
// XXX. that should depend on the plugin, not the host os
|
|
#if __WINDOWS__
|
|
#if !defined(__MINGW64__) && !defined(_WIN64)
|
|
core->dbg->bits = R_SYS_BITS_32;
|
|
#else
|
|
core->dbg->bits = R_SYS_BITS_64;
|
|
#endif
|
|
#endif
|
|
char *rp = core->dbg->h->reg_profile (core->dbg);
|
|
r_reg_set_profile_string (core->dbg->reg, rp);
|
|
r_reg_set_profile_string (core->anal->reg, rp);
|
|
free (rp);
|
|
}
|
|
} else {
|
|
(void)r_anal_set_reg_profile (core->anal);
|
|
}
|
|
}
|
|
|
|
asmos = r_config_get (core->config, "asm.os");
|
|
asmarch = r_config_get (core->config, "asm.arch");
|
|
if (core->anal) {
|
|
if (!r_syscall_setup (core->anal->syscall, asmarch, asmos, bits)) {
|
|
//eprintf ("asm.arch: Cannot setup syscall '%s/%s' from '%s'\n",
|
|
// node->value, asmos, R2_LIBDIR"/radare2/"R2_VERSION"/syscall");
|
|
}
|
|
__setsegoff (core->config, asmarch, core->anal->bits);
|
|
if (core->dbg) {
|
|
r_bp_use (core->dbg->bp, asmarch, core->anal->bits);
|
|
r_config_set_i (core->config, "dbg.bpsize", r_bp_size (core->dbg->bp));
|
|
}
|
|
}
|
|
/* set pcalign */
|
|
{
|
|
int v = r_anal_archinfo (core->anal, R_ANAL_ARCHINFO_ALIGN);
|
|
r_config_set_i (core->config, "asm.pcalign", (v != -1)? v: 0);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void update_asmfeatures_options(RCore *core, RConfigNode *node) {
|
|
int i, argc;
|
|
char *features;
|
|
|
|
if (core && core->assembler && core->assembler->cur) {
|
|
if (core->assembler->cur->features) {
|
|
features = strdup (core->assembler->cur->features);
|
|
argc = r_str_split (features, ',');
|
|
for (i = 0; i < argc; i++) {
|
|
const char *feature = r_str_word_get0 (features, i);
|
|
SETOPTIONS (node, feature, NULL);
|
|
}
|
|
free (features);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int cb_asmfeatures(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (*node->value == '?') {
|
|
update_asmfeatures_options (core, node);
|
|
print_node_options (node);
|
|
return 0;
|
|
}
|
|
free (core->assembler->features);
|
|
core->assembler->features = NULL;
|
|
if (node->value[0]) {
|
|
core->assembler->features = strdup (node->value);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int cb_asmlineswidth(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->anal->lineswidth = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_emustr(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
r_config_set (core->config, "asm.emu", "true");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_emuskip(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (*node->value == '?') {
|
|
if (strlen (node->value) > 1 && node->value[1] == '?') {
|
|
r_cons_printf ("Concatenation of meta types encoded as characters:\n" \
|
|
"'d': data\n'c': code\n's': string\n'f': format\n'm': magic\n" \
|
|
"'h': hide\n'C': comment\n'r': run\n" \
|
|
"(default is 'ds' to skip data and strings)\n");
|
|
} else {
|
|
print_node_options (node);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_asm_armimm(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->assembler->immdisp = node->i_value ? true : false;
|
|
return true;
|
|
}
|
|
|
|
static int cb_asm_invhex(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->assembler->invhex = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_asm_pcalign(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
int align = node->i_value;
|
|
if (align < 0) {
|
|
align = 0;
|
|
}
|
|
core->assembler->pcalign = align;
|
|
core->anal->pcalign = align;
|
|
return true;
|
|
}
|
|
|
|
static int cb_asmos(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
int asmbits = r_config_get_i (core->config, "asm.bits");
|
|
RConfigNode *asmarch, *node = (RConfigNode*) data;
|
|
|
|
if (*node->value == '?') {
|
|
print_node_options (node);
|
|
return 0;
|
|
}
|
|
if (!node->value[0]) {
|
|
free (node->value);
|
|
node->value = strdup (R_SYS_OS);
|
|
}
|
|
asmarch = r_config_node_get (core->config, "asm.arch");
|
|
if (asmarch) {
|
|
r_syscall_setup (core->anal->syscall, asmarch->value,
|
|
node->value, core->anal->bits);
|
|
__setsegoff (core->config, asmarch->value, asmbits);
|
|
}
|
|
r_anal_set_os (core->anal, node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_asmparser(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
return r_parse_use (core->parser, node->value);
|
|
}
|
|
|
|
static int cb_asmstrenc (void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
print_node_options (node);
|
|
r_cons_printf (" -- if string's 2nd & 4th bytes are 0 then utf16le else "
|
|
"if 2nd - 4th & 6th bytes are 0 & no char > 0x10ffff then utf32le else "
|
|
"if utf8 char detected then utf8 else latin1\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_binfilter(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->bin->filter = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
/* BinDemangleCmd */
|
|
static int cb_bdc(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->bin->demanglercmd = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_useldr(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->bin->use_ldr = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_usextr(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->bin->use_xtr = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_strpurge(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (*node->value == '?') {
|
|
r_cons_printf (
|
|
"There can be multiple entries separated by commas. No whitespace before/after entries.\n"
|
|
"Possible entries:\n"
|
|
" true : use the false_positive() classifier in cbin.c\n"
|
|
" addr : purge string at addr\n"
|
|
" addr1-addr2 : purge all strings in the range addr1-addr2 inclusive\n"
|
|
" !addr : prevent purge of string at addr by prev entries\n"
|
|
" !addr1-addr2 : prevent purge of strings in range addr1-addr2 inclusive by prev entries\n"
|
|
"Neither !true nor !false is supported.\n"
|
|
"\n"
|
|
"Example usage: e bin.strpurge=true,0-0xff,!0x1a\n"
|
|
" -- purge strings using the false_positive() classifier in cbin.c and also strings \n"
|
|
" with addresses in the range 0-0xff, but not the string at 0x1a.\n");
|
|
return false;
|
|
}
|
|
free (core->bin->strpurge);
|
|
core->bin->strpurge = !*node->value || !strcmp (node->value, "false")
|
|
? NULL : strdup (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_midflags (void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
print_node_options (node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_strfilter(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (node->value[0] == '?') {
|
|
if (strlen (node->value) > 1 && node->value[1] == '?') {
|
|
r_cons_printf ("Valid values for bin.strfilter:\n"
|
|
"a only alphanumeric printable\n"
|
|
"8 only strings with utf8 chars\n"
|
|
"p file/directory paths\n"
|
|
"e email-like addresses\n"
|
|
"u urls\n"
|
|
"i IPv4 address-like strings\n"
|
|
"U only uppercase strings\n"
|
|
"f format-strings\n");
|
|
} else {
|
|
print_node_options (node);
|
|
}
|
|
return false;
|
|
} else {
|
|
core->bin->strfilter = node->value[0];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_binforce(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
r_bin_force_plugin (core->bin, node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_asmsyntax(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (*node->value == '?') {
|
|
print_node_options (node);
|
|
return false;
|
|
} else {
|
|
int syntax = r_asm_syntax_from_string (node->value);
|
|
if (syntax == -1) {
|
|
return false;
|
|
}
|
|
r_asm_set_syntax (core->assembler, syntax);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dirzigns(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
free (core->anal->zign_path);
|
|
core->anal->zign_path = strdup (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_bigendian(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
// Try to set endian based on preference, restrict by RAsmPlugin
|
|
bool isbig = r_asm_set_big_endian (core->assembler, node->i_value);
|
|
// Set anal endianness the same as asm
|
|
r_anal_set_big_endian (core->anal, isbig);
|
|
// the big endian should also be assigned to dbg->bp->endian
|
|
if (core->dbg && core->dbg->bp) {
|
|
core->dbg->bp->endian = isbig;
|
|
}
|
|
// Set printing endian to user's choice
|
|
core->print->big_endian = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_cfgdatefmt(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
snprintf (core->print->datefmt, 32, "%s", node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_timezone(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->print->datezone = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_cfglog(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->cfglog = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_cfgdebug(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (!core) {
|
|
return false;
|
|
}
|
|
if (core->io) {
|
|
core->io->debug = node->i_value;
|
|
}
|
|
if (core->dbg && node->i_value) {
|
|
const char *dbgbackend = r_config_get (core->config, "dbg.backend");
|
|
core->bin->is_debugger = true;
|
|
r_debug_use (core->dbg, dbgbackend);
|
|
if (!strcmp (r_config_get (core->config, "cmd.prompt"), "")) {
|
|
r_config_set (core->config, "cmd.prompt", ".dr*");
|
|
}
|
|
if (!strcmp (dbgbackend, "bf")) {
|
|
r_config_set (core->config, "asm.arch", "bf");
|
|
}
|
|
if (core->file) {
|
|
r_debug_select (core->dbg, r_io_fd_get_pid (core->io, core->file->fd),
|
|
r_io_fd_get_tid (core->io, core->file->fd));
|
|
}
|
|
} else {
|
|
r_debug_use (core->dbg, NULL);
|
|
core->bin->is_debugger = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dirsrc(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
RCore *core = (RCore *)user;
|
|
free (core->bin->srcdir);
|
|
core->bin->srcdir = strdup (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_cfgsanbox(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
int ret = r_sandbox_enable (node->i_value);
|
|
if (node->i_value != ret) {
|
|
eprintf ("Cannot disable sandbox\n");
|
|
}
|
|
return (!node->i_value && ret)? 0: 1;
|
|
}
|
|
|
|
static int cb_str_escbslash(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->print->esc_bslash = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_cfg_fortunes(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
RConfigNode *node = (RConfigNode *)data;
|
|
// TODO CN_BOOL option does not receive the right hand side of assignment as an argument
|
|
if (node->value[0] == '?') {
|
|
r_core_fortune_list (core);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_cfg_fortunes_type(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *)data;
|
|
if (node->value[0] == '?') {
|
|
r_core_fortune_list_types ();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_cmdlog(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
R_FREE (core->cmdlog);
|
|
core->cmdlog = strdup (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_cmdrepeat(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->cmdrepeat = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrnull(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->cons->null = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_color(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->print->flags |= R_PRINT_FLAGS_COLOR;
|
|
} else {
|
|
//c:core->print->flags ^= R_PRINT_FLAGS_COLOR;
|
|
core->print->flags &= (~R_PRINT_FLAGS_COLOR);
|
|
}
|
|
r_cons_singleton ()->use_color = node->i_value? 1: 0;
|
|
r_print_set_flags (core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static int cb_decoff(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->print->flags |= R_PRINT_FLAGS_ADDRDEC;
|
|
} else {
|
|
core->print->flags &= (~R_PRINT_FLAGS_ADDRDEC);
|
|
}
|
|
r_print_set_flags (core->print, core->print->flags);
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbgbep(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (*node->value == '?') {
|
|
print_node_options (node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_btalgo(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (*node->value == '?') {
|
|
print_node_options (node);
|
|
return false;
|
|
}
|
|
free (core->dbg->btalgo);
|
|
core->dbg->btalgo = strdup (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_libs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
free (core->dbg->glob_libs);
|
|
core->dbg->glob_libs = strdup (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_unlibs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
free (core->dbg->glob_unlibs);
|
|
core->dbg->glob_unlibs = strdup (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_forks(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->dbg->trace_forks = node->i_value;
|
|
if (core->io->debug) {
|
|
r_debug_attach (core->dbg, core->dbg->pid);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_gdb_page_size(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (node->i_value < 64) { // 64 is hardcoded min packet size
|
|
return false;
|
|
}
|
|
if (isGdbPlugin (core)) {
|
|
char cmd[64];
|
|
snprintf (cmd, sizeof (cmd), "page_size %"PFMT64d, node->i_value);
|
|
free (r_io_system (core->io, cmd));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_gdb_retries(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (node->i_value <= 0) {
|
|
return false;
|
|
}
|
|
if (isGdbPlugin (core)) {
|
|
char cmd[64];
|
|
snprintf (cmd, sizeof (cmd), "retries %"PFMT64d, node->i_value);
|
|
free (r_io_system (core->io, cmd));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_execs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->dbg->trace_execs = node->i_value;
|
|
if (core->io->debug) {
|
|
r_debug_attach (core->dbg, core->dbg->pid);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_clone(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->dbg->trace_clone = node->i_value;
|
|
if (core->io->debug) {
|
|
r_debug_attach (core->dbg, core->dbg->pid);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_follow_child(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->dbg->follow_child = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_aftersc(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->dbg->trace_aftersyscall = node->i_value;
|
|
if (core->io->debug) {
|
|
r_debug_attach (core->dbg, core->dbg->pid);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_runprofile(void *user, void *data) {
|
|
RCore *r = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
free ((void*)r->io->runprofile);
|
|
if (!node || !*(node->value)) {
|
|
r->io->runprofile = NULL;
|
|
} else {
|
|
r->io->runprofile = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbg_args(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (!node || !*(node->value)) {
|
|
core->io->args = NULL;
|
|
} else {
|
|
core->io->args = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbgstatus(void *user, void *data) {
|
|
RCore *r = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (r_config_get_i (r->config, "cfg.debug")) {
|
|
if (node->i_value) {
|
|
r_config_set (r->config, "cmd.prompt",
|
|
".dr*; drd; sr PC;pi 1;s-");
|
|
} else {
|
|
r_config_set (r->config, "cmd.prompt", ".dr*");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbgbackend(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (!strcmp (node->value, "?")) {
|
|
r_debug_plugin_list (core->dbg, 'q');
|
|
return false;
|
|
}
|
|
if (!strcmp (node->value, "bf")) {
|
|
r_config_set (core->config, "asm.arch", "bf");
|
|
}
|
|
r_debug_use (core->dbg, node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_gotolimit(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (r_sandbox_enable (0)) {
|
|
eprintf ("Cannot change gotolimit\n");
|
|
return false;
|
|
}
|
|
if (core->anal->esil) {
|
|
core->anal->esil_goto_limit = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_esilverbose (void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (core->anal->esil) {
|
|
core->anal->esil->verbose = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_esilstackdepth (void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (node->i_value < 3) {
|
|
eprintf ("esil.stack.depth must be greater than 2\n");
|
|
node->i_value = 32;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_fixrows(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton ()->fix_rows = (int)node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_fixcolumns(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton ()->fix_columns = atoi (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_rows(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton ()->force_rows = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_hexcompact(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->print->flags |= R_PRINT_FLAGS_COMPACT;
|
|
} else {
|
|
core->print->flags &= (~R_PRINT_FLAGS_COMPACT);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_hexpairs(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->print->pairs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_hexcomments(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->print->flags |= R_PRINT_FLAGS_COMMENT;
|
|
} else {
|
|
core->print->flags &= ~R_PRINT_FLAGS_COMMENT;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_iopcache(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if ((bool)node->i_value) {
|
|
if (core) {
|
|
r_config_set_i (core->config, "io.pcache.read", true);
|
|
r_config_set_i (core->config, "io.pcache.write", true);
|
|
}
|
|
} else {
|
|
if (core && core->io) {
|
|
r_io_desc_cache_fini_all (core->io);
|
|
r_config_set_i (core->config, "io.pcache.read", false);
|
|
r_config_set_i (core->config, "io.pcache.write", false);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_iopcacheread(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if ((bool)node->i_value) {
|
|
if (core && core->io) {
|
|
core->io->p_cache |= 1;
|
|
}
|
|
} else {
|
|
if (core && core->io && core->io->p_cache) {
|
|
core->io->p_cache &= 2;
|
|
if (!(core->io->p_cache & 2)) {
|
|
r_io_desc_cache_fini_all (core->io);
|
|
r_config_set_i (core->config, "io.pcache", false);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_iopcachewrite(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if ((bool)node->i_value) {
|
|
if (core && core->io) {
|
|
core->io->p_cache |= 2;
|
|
}
|
|
} else {
|
|
if (core && core->io && core->io->p_cache) {
|
|
core->io->p_cache &= 1;
|
|
if (!(core->io->p_cache & 1)) {
|
|
r_io_desc_cache_fini_all (core->io);
|
|
r_config_set_i (core->config, "io.pcache", false);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
R_API bool r_core_esil_cmd(RAnalEsil *esil, const char *cmd, ut64 a1, ut64 a2) {
|
|
if (cmd && *cmd) {
|
|
RCore *core = esil->anal->user;
|
|
r_core_cmdf (core, "%s %"PFMT64d" %" PFMT64d, cmd, a1, a2);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static int cb_cmd_esil_ioer(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core && core->anal && core->anal->esil) {
|
|
core->anal->esil->cmd = r_core_esil_cmd;
|
|
free (core->anal->esil->cmd_ioer);
|
|
core->anal->esil->cmd_ioer = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_cmd_esil_todo(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core && core->anal && core->anal->esil) {
|
|
core->anal->esil->cmd = r_core_esil_cmd;
|
|
free (core->anal->esil->cmd_todo);
|
|
core->anal->esil->cmd_todo = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_cmd_esil_intr(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core && core->anal && core->anal->esil) {
|
|
core->anal->esil->cmd = r_core_esil_cmd;
|
|
free (core->anal->esil->cmd_intr);
|
|
core->anal->esil->cmd_intr = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_mdevrange(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core && core->anal && core->anal->esil) {
|
|
core->anal->esil->cmd = r_core_esil_cmd;
|
|
free (core->anal->esil->mdev_range);
|
|
core->anal->esil->mdev_range = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_cmd_esil_mdev(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core && core->anal && core->anal->esil) {
|
|
core->anal->esil->cmd = r_core_esil_cmd;
|
|
free (core->anal->esil->cmd_mdev);
|
|
core->anal->esil->cmd_mdev = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_cmd_esil_trap(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core && core->anal && core->anal->esil) {
|
|
core->anal->esil->cmd = r_core_esil_cmd;
|
|
core->anal->esil->cmd_trap = strdup (node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_fsview(void *user, void *data) {
|
|
int type = R_FS_VIEW_NORMAL;
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (*node->value == '?') {
|
|
print_node_options (node);
|
|
return false;
|
|
}
|
|
if (!strcmp (node->value, "all")) {
|
|
type = R_FS_VIEW_ALL;
|
|
}
|
|
if (!strstr (node->value, "del")) {
|
|
type |= R_FS_VIEW_DELETED;
|
|
}
|
|
if (!strstr (node->value, "spe")) {
|
|
type |= R_FS_VIEW_SPECIAL;
|
|
}
|
|
r_fs_view (core->fs, type);
|
|
return true;
|
|
}
|
|
|
|
static int cb_cmddepth(void *user, void *data) {
|
|
int c = R_MAX (((RConfigNode*)data)->i_value, 0);
|
|
((RCore *)user)->cmd_depth = c;
|
|
return true;
|
|
}
|
|
|
|
static int cb_hexcols(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
int c = R_MIN (1024, R_MAX (((RConfigNode*)data)->i_value, 0));
|
|
if (c < 0) {
|
|
c = 0;
|
|
}
|
|
core->print->cols = c & ~1;
|
|
core->dbg->regcols = c/4;
|
|
return true;
|
|
}
|
|
|
|
static int cb_hexstride(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
((RCore *)user)->print->stride = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_search_kwidx(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->search->n_kws = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_iobuffer(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
ut64 from, to;
|
|
from = r_config_get_i (core->config, "io.buffer.from");
|
|
to = r_config_get_i (core->config, "io.buffer.to");
|
|
if (from>=to) {
|
|
eprintf ("ERROR: io.buffer.from >= io.buffer.to"
|
|
" (0x%"PFMT64x" >= 0x%"PFMT64x")\n", from, to);
|
|
} else {
|
|
r_io_buffer_load (core->io, from, (int)(to-from));
|
|
}
|
|
} else {
|
|
r_io_buffer_close (core->io);
|
|
}
|
|
r_core_block_read (core);
|
|
return true;
|
|
}
|
|
|
|
static int cb_io_cache_mode(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
RConfigNode *node = (RConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->io->cachemode = true;
|
|
} else {
|
|
core->io->cachemode = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_io_cache_read(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
RConfigNode *node = (RConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->io->cached |= R_IO_READ;
|
|
} else {
|
|
core->io->cached &= ~R_IO_READ;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_io_cache_write(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
RConfigNode *node = (RConfigNode *)data;
|
|
if (node->i_value) {
|
|
core->io->cached |= R_IO_WRITE;
|
|
} else {
|
|
core->io->cached &= ~R_IO_WRITE;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_io_cache(void *user, void *data) {
|
|
(void)cb_io_cache_read (user, data);
|
|
(void)cb_io_cache_write (user, data);
|
|
return true;
|
|
}
|
|
|
|
static int cb_ioaslr(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value != core->io->aslr) {
|
|
core->io->aslr = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_iova(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value != core->io->va) {
|
|
core->io->va = node->i_value;
|
|
/* ugly fix for r2 -d ... "r2 is going to die soon ..." */
|
|
if (core->io->desc) {
|
|
r_core_block_read (core);
|
|
}
|
|
#if 0
|
|
/* reload symbol information */
|
|
if (r_list_length (r_bin_get_sections (core->bin)) > 0) {
|
|
r_core_cmd0 (core, ".ia*");
|
|
}
|
|
#endif
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_ioff(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->io->ff = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_io_oxff(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->io->Oxff = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_filepath(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
char *pikaboo = strstr (node->value, "://");
|
|
if (pikaboo) {
|
|
if (pikaboo[3] == '/') {
|
|
r_config_set (core->config, "file.lastpath", node->value);
|
|
char *ovalue = node->value;
|
|
node->value = strdup (pikaboo + 3);
|
|
free (ovalue);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
r_config_set (core->config, "file.lastpath", node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_ioautofd(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->io->autofd = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scr_color_grep(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
|
|
/* Let cons know we have a new pager. */
|
|
core->cons->grep_color = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_pager(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
|
|
/* Let cons know we have a new pager. */
|
|
core->cons->pager = node->value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_breaklines(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton ()->break_lines = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_fps(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton ()->fps = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_rgbcolors(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
RCore *core = (RCore *) user;
|
|
if (node->i_value) {
|
|
r_cons_singleton()->truecolor =
|
|
(r_config_get_i (core->config, "scr.truecolor"))?2:1;
|
|
} else {
|
|
r_cons_singleton()->truecolor = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrbreakword(void* user, void* data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (*node->value) {
|
|
r_cons_breakword (node->value);
|
|
} else {
|
|
r_cons_breakword (NULL);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrcolumns(void* user, void* data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
RCore *core = (RCore*) user;
|
|
int n = atoi (node->value);
|
|
core->cons->force_columns = n;
|
|
core->dbg->regcols = n / 20;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrfgets(void* user, void* data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->cons->user_fgets = node->i_value
|
|
? NULL : (void *)r_core_fgets;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrhtml(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton ()->is_html = node->i_value;
|
|
// TODO: control error and restore old value (return false?) show errormsg?
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrhighlight(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_highlight (node->value);
|
|
return true;
|
|
}
|
|
|
|
#if __WINDOWS__ && !__CYGWIN__
|
|
static int scr_ansicon(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton()->ansicon = node->i_value;
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
static int cb_screcho(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton()->echo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrlinesleep(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton()->linesleep = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrpagesize(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton()->pagesize= node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrflush(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton()->flush = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_exectrap(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
RCore *core = (RCore*) user;
|
|
if (core->anal && core->anal->esil) {
|
|
core->anal->esil->exectrap = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_iotrap(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
RCore *core = (RCore*) user;
|
|
if (core->anal && core->anal->esil) {
|
|
core->anal->esil->iotrap = node->i_value;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrint(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value && r_sandbox_enable (0)) {
|
|
return false;
|
|
}
|
|
r_cons_singleton()->is_interactive = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrnkey(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (!strcmp (node->value, "help") || *node->value == '?') {
|
|
print_node_options (node);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrprompt(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_line_singleton()->echo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_scrrows(void* user, void* data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
int n = atoi (node->value);
|
|
((RCore *)user)->cons->force_rows = n;
|
|
return true;
|
|
}
|
|
|
|
static int cb_contiguous(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->search->contiguous = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_searchalign(void *user, void *data) {
|
|
RCore *core = (RCore *)user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->search->align = node->i_value;
|
|
core->print->addrmod = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_segoff(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->print->flags |= R_PRINT_FLAGS_SEGOFF;
|
|
} else {
|
|
core->print->flags &= (((ut32)-1) & (~R_PRINT_FLAGS_SEGOFF));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_stopthreads(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->dbg->stop_all_threads = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_swstep(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->dbg->swstep = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_consbreak(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->dbg->consbreak = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_teefile(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
r_cons_singleton()->teefile = node->value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_trace(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->dbg->trace->enabled = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_tracetag(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->dbg->trace->tag = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_truecolor(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (r_cons_singleton()->truecolor)
|
|
r_cons_singleton()->truecolor = (node->i_value)? 2: 1;
|
|
return true;
|
|
}
|
|
|
|
static int cb_utf8(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->cons->use_utf8 = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_utf8_curvy(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->cons->use_utf8_curvy = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_zoombyte(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
switch (*node->value) {
|
|
case 'p': case 'f': case 's': case '0':
|
|
case 'F': case 'e': case 'h':
|
|
core->print->zoom->mode = *node->value;
|
|
break;
|
|
default:
|
|
r_cons_printf ("p\nf\ns\n0\nF\ne\nh\n");
|
|
// eprintf ("Invalid zoom.byte value. See pz? for help\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_binverbose(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->bin->verbose = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_rawstr(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->bin->rawstr = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_debase64(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
core->bin->debase64 = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_binstrings(void *user, void *data) {
|
|
const ut32 req = R_BIN_REQ_STRINGS;
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (node->i_value) {
|
|
core->bin->filter_rules |= req;
|
|
} else {
|
|
core->bin->filter_rules &= ~req;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_bindbginfo(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (!core || !core->bin) {
|
|
return false;
|
|
}
|
|
core->bin->want_dbginfo = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_binprefix(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (!core || !core->bin) {
|
|
return false;
|
|
}
|
|
if (node->value && *node->value) {
|
|
if (!strcmp (node->value, "auto")) {
|
|
if (!core->bin->file) {
|
|
return false;
|
|
}
|
|
char *name = (char *)r_file_basename (core->bin->file);
|
|
if (name) {
|
|
r_name_filter (name, strlen (name));
|
|
r_str_filter (name, strlen (name));
|
|
core->bin->prefix = strdup (name);
|
|
free (name);
|
|
}
|
|
} else {
|
|
core->bin->prefix = node->value;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_binmaxstrbuf(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core->bin) {
|
|
int v = node->i_value;
|
|
ut64 old_v = core->bin->maxstrbuf;
|
|
if (v < 1) {
|
|
v = 4; // HACK
|
|
}
|
|
core->bin->maxstrbuf = v;
|
|
if (v>old_v) {
|
|
r_core_bin_refresh_strings (core);
|
|
}
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_binmaxstr(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core->bin) {
|
|
int v = node->i_value;
|
|
if (v<1) v = 4; // HACK
|
|
core->bin->maxstrlen = v;
|
|
// TODO: Do not refresh if nothing changed (minstrlen ?)
|
|
r_core_bin_refresh_strings (core);
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_binminstr(void *user, void *data) {
|
|
RCore *core = (RCore *) user;
|
|
RConfigNode *node = (RConfigNode *) data;
|
|
if (core->bin) {
|
|
int v = node->i_value;
|
|
if (v<1) v = 4; // HACK
|
|
core->bin->minstrlen = v;
|
|
// TODO: Do not refresh if nothing changed (minstrlen ?)
|
|
r_core_bin_refresh_strings (core);
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_searchin(void *user, void *data) {
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
if (node->value[0] == '?') {
|
|
if (strlen (node->value) > 1 && node->value[1] == '?') {
|
|
r_cons_printf ("Valid values for search.in (depends on .from/.to and io.va):\n"
|
|
"raw search in raw io (ignoring bounds)\n"
|
|
"block search in the current block\n"
|
|
"io.map search in current map\n"
|
|
"io.maps search in all maps\n"
|
|
"io.section search in current mapped section\n"
|
|
"io.sections search in all mapped sections\n"
|
|
"io.sections.write search in all writable marked sections\n"
|
|
"io.sections.exec search in all executable marked sections\n"
|
|
"dbg.stack search in the stack\n"
|
|
"dbg.heap search in the heap\n"
|
|
"dbg.map search in current memory map\n"
|
|
"dbg.maps search in all memory maps\n"
|
|
"dbg.maps.exec search in all executable marked memory maps\n"
|
|
"dbg.maps.write search in all writable marked memory maps\n"
|
|
"anal.fcn search in the current function\n"
|
|
"anal.bb search in the current basic-block\n");
|
|
} else {
|
|
print_node_options (node);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int __dbg_swstep_getter(void *user, RConfigNode *node) {
|
|
RCore *core = (RCore*)user;
|
|
node->i_value = core->dbg->swstep;
|
|
return true;
|
|
}
|
|
|
|
static int cb_dirpfx(RCore *core, RConfigNode *node) {
|
|
r_sys_prefix (node->value);
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_gp(RCore *core, RConfigNode *node) {
|
|
core->anal->gp = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_from(RCore *core, RConfigNode *node) {
|
|
if (r_config_get_i (core->config, "anal.limits")) {
|
|
r_anal_set_limits (core->anal,
|
|
r_config_get_i (core->config, "anal.from"),
|
|
r_config_get_i (core->config, "anal.to"));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_limits(void *user, RConfigNode *node) {
|
|
RCore *core = (RCore*)user;
|
|
if (node->i_value) {
|
|
r_anal_set_limits (core->anal,
|
|
r_config_get_i (core->config, "anal.from"),
|
|
r_config_get_i (core->config, "anal.to"));
|
|
} else {
|
|
r_anal_unset_limits (core->anal);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int cb_anal_rnr(void *user, RConfigNode *node) {
|
|
RCore *core = (RCore*)user;
|
|
core->anal->recursive_noreturn = node->i_value;
|
|
return 1;
|
|
}
|
|
|
|
static int cb_anal_jmptbl(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.jmptbl = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_cjmpref(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.cjmpref = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_jmpref(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.jmpref = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_jmpabove(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.jmpabove = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_followdatarefs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.followdatarefs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_searchstringrefs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.searchstringrefs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_pushret(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.pushret = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_brokenrefs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.followbrokenfcnsrefs = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_bbs_alignment(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.bbs_alignment = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_anal_bb_max_size(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->anal->opt.bb_max_size = node->i_value;
|
|
return true;
|
|
}
|
|
|
|
static int cb_linesto(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
ut64 from = (ut64)r_config_get_i (core->config, "lines.from");
|
|
int io_sz = r_io_size (core->io);
|
|
ut64 to = r_num_math (core->num, node->value);
|
|
if (to == 0) {
|
|
core->print->lines_cache_sz = -1; //r_core_lines_initcache (core, from, to);
|
|
return false;
|
|
}
|
|
if (to > from+io_sz) {
|
|
eprintf ("ERROR: \"lines.to\" can't exceed addr 0x%08"PFMT64x
|
|
" 0x%08"PFMT64x" %d\n", from, to, io_sz);
|
|
return true;
|
|
}
|
|
if (to > from) {
|
|
core->print->lines_cache_sz = r_core_lines_initcache (core, from, to);
|
|
//if (core->print->lines_cache_sz == -1) { eprintf ("ERROR: Can't allocate memory\n"); }
|
|
} else {
|
|
eprintf ("Invalid range 0x%08"PFMT64x" .. 0x%08"PFMT64x"\n", from, to);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_linesabs(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
core->print->lines_abs = node->i_value;
|
|
if (core->print->lines_abs && core->print->lines_cache_sz <= 0) {
|
|
ut64 from = (ut64)r_config_get_i (core->config, "lines.from");
|
|
ut64 to = (ut64)r_config_get_i (core->config, "lines.to");
|
|
core->print->lines_cache_sz = r_core_lines_initcache (core, from, to);
|
|
if (core->print->lines_cache_sz == -1) {
|
|
eprintf ("ERROR: \"lines.from\" and \"lines.to\" must be set\n");
|
|
} else {
|
|
eprintf ("Found %d lines\n", core->print->lines_cache_sz-1);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_malloc(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
|
|
if (node->value) {
|
|
if (!strcmp ("jemalloc", node->value) || !strcmp ("glibc", node->value)) {
|
|
if (core->dbg) {
|
|
core->dbg->malloc = data;
|
|
}
|
|
}
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int cb_dbgsnap(void *user, void *data) {
|
|
RCore *core = (RCore*) user;
|
|
RConfigNode *node = (RConfigNode*) data;
|
|
|
|
if (node->value){
|
|
r_debug_session_path (core->dbg, node->value);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static char *getViewerPath() {
|
|
int i;
|
|
const char *viewers[] = {
|
|
"open",
|
|
"geeqie",
|
|
"gqview",
|
|
"eog",
|
|
"xdg-open",
|
|
NULL
|
|
};
|
|
for (i = 0; viewers[i]; i++) {
|
|
char *dotPath = r_file_path (viewers[i]);
|
|
if (dotPath && strcmp (dotPath, viewers[i])) {
|
|
return dotPath;
|
|
}
|
|
free (dotPath);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#define SLURP_LIMIT (10*1024*1024)
|
|
R_API int r_core_config_init(RCore *core) {
|
|
int i;
|
|
char buf[128], *p, *tmpdir;
|
|
RConfigNode *n;
|
|
RConfig *cfg = core->config = r_config_new (core);
|
|
if (!cfg) {
|
|
return 0;
|
|
}
|
|
cfg->cb_printf = r_cons_printf;
|
|
cfg->num = core->num;
|
|
/* dir.prefix is used in other modules, set it first */
|
|
{
|
|
char *pfx = r_sys_getenv("R2_PREFIX");
|
|
if (!pfx) {
|
|
pfx = strdup (R2_PREFIX);
|
|
}
|
|
SETCB ("dir.prefix", pfx, (RConfigCallback)&cb_dirpfx, "Default prefix r2 was compiled for");
|
|
free (pfx);
|
|
}
|
|
/* pdb */
|
|
SETPREF ("pdb.useragent", "Microsoft-Symbol-Server/6.11.0001.402", "User agent for Microsoft symbol server");
|
|
SETPREF ("pdb.server", "https://msdl.microsoft.com/download/symbols", "Base URL for Microsoft symbol server");
|
|
SETI ("pdb.extract", 1, "Avoid extract of the pdb file, just download");
|
|
SETI ("pdb.autoload", false, "Automatically load the required pdb files for loaded DLLs");
|
|
|
|
/* anal */
|
|
SETPREF ("anal.fcnprefix", "fcn", "Prefix new function names with this");
|
|
SETPREF ("anal.a2f", "false", "Use the new WIP analysis algorithm (core/p/a2f), anal.depth ignored atm");
|
|
SETICB ("anal.gp", 0, (RConfigCallback)&cb_anal_gp, "Set the value of the GP register (MIPS)");
|
|
SETCB ("anal.limits", "false", (RConfigCallback)&cb_anal_limits, "Restrict analysis to address range [anal.from:anal.to]");
|
|
SETCB ("anal.rnr", "false", (RConfigCallback)&cb_anal_rnr, "Recursive no return checks (EXPERIMENTAL)");
|
|
SETCB ("anal.limits", "false", (RConfigCallback)&cb_anal_limits, "Restrict analysis to address range [anal.from:anal.to]");
|
|
SETICB ("anal.from", -1, (RConfigCallback)&cb_anal_from, "Lower limit on the address range for analysis");
|
|
SETICB ("anal.to", -1, (RConfigCallback)&cb_anal_from, "Upper limit on the address range for analysis");
|
|
n = NODECB ("anal.in", "io.maps", &cb_searchin);
|
|
SETDESC (n, "Specify search boundaries for analysis");
|
|
SETOPTIONS (n, "raw", "block", "io.map", "io.maps",
|
|
"io.sections", "io.sections.write", "io.sections.exec", "io.sections.readonly",
|
|
"dbg.stack", "dbg.heap", "dbg.map",
|
|
"dbg.maps", "dbg.maps.exec", "dbg.maps.write", "dbg.maps.readonly",
|
|
"anal.fcn", "anal.bb", NULL);
|
|
SETI ("anal.timeout", 0, "Stop analyzing after a couple of seconds");
|
|
|
|
SETCB ("anal.armthumb", "false", &cb_analarmthumb, "aae computes arm/thumb changes (lot of false positives ahead)");
|
|
SETCB ("anal.eobjmp", "false", &cb_analeobjmp, "jmp is end of block mode (option)");
|
|
SETCB ("anal.afterjmp", "true", &cb_analafterjmp, "Continue analysis after jmp/ujmp");
|
|
SETI ("anal.depth", 16, "Max depth at code analysis"); // XXX: warn if depth is > 50 .. can be problematic
|
|
SETICB ("anal.sleep", 0, &cb_analsleep, "Sleep N usecs every so often during analysis. Avoid 100% CPU usage");
|
|
SETPREF ("anal.calls", "false", "Make basic af analysis walk into calls");
|
|
SETPREF ("anal.autoname", "true", "Automatically set a name for the functions, may result in some false positives");
|
|
SETPREF ("anal.hasnext", "false", "Continue analysis after each function");
|
|
SETPREF ("anal.esil", "false", "Use the new ESIL code analysis");
|
|
SETCB ("anal.strings", "false", &cb_analstrings, "Identify and register strings during analysis (aar only)");
|
|
SETPREF ("anal.vars", "true", "Analyze local variables and arguments");
|
|
SETPREF ("anal.vinfun", "true", "Search values in functions (aav) (false by default to only find on non-code)");
|
|
SETPREF ("anal.vinfunrange", "false", "Search values outside function ranges (requires anal.vinfun=false)\n");
|
|
SETCB ("anal.nopskip", "true", &cb_analnopskip, "Skip nops at the beginning of functions");
|
|
SETCB ("anal.hpskip", "false", &cb_analhpskip, "Skip `mov reg, reg` and `lea reg, [reg] at the beginning of functions");
|
|
SETCB ("anal.noncode", "false", &cb_analnoncode, "Analyze data as code");
|
|
n = NODECB ("anal.arch", R_SYS_ARCH, &cb_analarch);
|
|
SETDESC (n, "Select the architecture to use");
|
|
update_analarch_options (core, n);
|
|
SETCB ("anal.cpu", R_SYS_ARCH, &cb_analcpu, "Specify the anal.cpu to use");
|
|
SETPREF ("anal.prelude", "", "Specify an hexpair to find preludes in code");
|
|
SETCB ("anal.split", "true", &cb_analsplit, "Split functions into basic blocks in analysis");
|
|
SETCB ("anal.recont", "false", &cb_analrecont, "End block after splitting a basic block instead of error"); // testing
|
|
SETI ("anal.ptrdepth", 3, "Maximum number of nested pointers to follow in analysis");
|
|
SETICB ("anal.maxreflines", 0, &cb_analmaxrefs, "Maximum number of reflines to be analyzed and displayed in asm.lines with pd");
|
|
|
|
SETCB ("anal.jmptbl", "false", &cb_anal_jmptbl, "Analyze jump tables in switch statements");
|
|
|
|
SETCB ("anal.cjmpref", "false", &cb_anal_cjmpref, "Create references for conditional jumps");
|
|
SETCB ("anal.jmpref", "true", &cb_anal_jmpref, "Create references for unconditional jumps");
|
|
|
|
SETCB ("anal.jmpabove", "true", &cb_anal_jmpabove, "Jump above function pointer");
|
|
SETCB ("anal.datarefs", "false", &cb_anal_followdatarefs, "Follow data references for code coverage");
|
|
SETCB ("anal.brokenrefs", "false", &cb_anal_brokenrefs, "Follow function references as well if function analysis was failed");
|
|
|
|
SETCB ("anal.refstr", "false", &cb_anal_searchstringrefs, "Search string references in data references");
|
|
SETCB ("anal.bb.split", "true", &cb_analbbsplit, "Use the experimental basic block split for JMPs");
|
|
SETCB ("anal.bb.align", "0x10", &cb_anal_bbs_alignment, "Possible space between basic blocks");
|
|
SETCB ("anal.bb.maxsize", "1024", &cb_anal_bb_max_size, "Maximum basic block size");
|
|
SETCB ("anal.pushret", "false", &cb_anal_pushret, "Analyze push+ret as jmp");
|
|
|
|
#if __linux__ && __GNU_LIBRARY__ && __GLIBC__ && __GLIBC_MINOR__
|
|
SETCB("dbg.malloc", "glibc", &cb_malloc, "Choose malloc structure parser");
|
|
#else
|
|
SETCB("dbg.malloc", "jemalloc", &cb_malloc, "Choose malloc structure parser");
|
|
#endif
|
|
|
|
SETPREF ("esil.prestep", "true", "Step before esil evaluation in `de` commands");
|
|
SETPREF ("esil.fillstack", "", "Initialize ESIL stack with (random, debrujn, sequence, zeros, ...)");
|
|
SETICB ("esil.verbose", 0, &cb_esilverbose, "Show ESIL verbose level (0, 1, 2)");
|
|
SETICB ("esil.gotolimit", core->anal->esil_goto_limit, &cb_gotolimit, "Maximum number of gotos per ESIL expression");
|
|
SETICB ("esil.stack.depth", 32, &cb_esilstackdepth, "Number of elements that can be pushed on the esilstack");
|
|
SETI ("esil.stack.size", 0xf0000, "Number of elements that can be pushed on the esilstack");
|
|
SETI ("esil.stack.addr", 0x100000, "Number of elements that can be pushed on the esilstack");
|
|
SETPREF ("esil.stack.pattern", "0", "Specify fill pattern to initialize the stack (0, w, d, i)");
|
|
|
|
/* asm */
|
|
//asm.os needs to be first, since other asm.* depend on it
|
|
SETICB ("asm.armimm", false, &cb_asm_armimm, "Display # for immediates in ARM");
|
|
n = NODECB ("asm.os", R_SYS_OS, &cb_asmos);
|
|
SETDESC (n, "Select operating system (kernel)");
|
|
SETOPTIONS (n, "ios", "dos", "darwin", "linux", "freebsd", "openbsd", "netbsd", "windows", NULL);
|
|
SETI ("asm.maxrefs", 5, "Maximum number of xrefs to be displayed as list (use columns above)");
|
|
SETCB ("asm.invhex", "false", &cb_asm_invhex, "Show invalid instructions as hexadecimal numbers");
|
|
SETPREF ("asm.bytes", "true", "Display the bytes of each instruction");
|
|
SETPREF ("asm.flagsinbytes", "false", "Display flags inside the bytes space");
|
|
n = NODEICB ("asm.midflags", 2, &cb_midflags);
|
|
SETDESC (n, "Realign disassembly if there is a flag in the middle of an instruction");
|
|
SETPREF ("asm.midcursor", "false", "Cursor in visual disasm mode breaks the instruction");
|
|
SETOPTIONS (n, "0 = do not show flag", "1 = show without realign", "2 = realign at middle flag",
|
|
"3 = realign at middle flag if sym.*", NULL);
|
|
SETPREF ("asm.cmtflgrefs", "true", "Show comment flags associated to branch reference");
|
|
SETPREF ("asm.cmtright", "true", "Show comments at right of disassembly if they fit in screen");
|
|
SETI ("asm.cmtcol", 71, "Column to align comments");
|
|
SETICB ("asm.pcalign", 0, &cb_asm_pcalign, "Only recognize as valid instructions aligned to this value");
|
|
SETPREF ("asm.calls", "true", "Show callee function related info as comments in disasm");
|
|
SETPREF ("asm.bbline", "false", "Show empty line after every basic block");
|
|
SETPREF ("asm.comments", "true", "Show comments in disassembly view");
|
|
SETPREF ("asm.jmphints", "true", "Show jump hints [numbers] in disasm");
|
|
SETPREF ("asm.jmpsub", "false", "Always substitute jump, call and branch targets in disassembly");
|
|
SETPREF ("asm.leahints", "false", "Show LEA hints [numbers] in disasm");
|
|
SETPREF ("asm.slow", "true", "Perform slow analysis operations in disasm");
|
|
SETPREF ("asm.decode", "false", "Use code analysis as a disassembler");
|
|
SETPREF ("asm.flgoff", "false", "Show offset in flags");
|
|
SETPREF ("asm.immstr", "false", "Show immediates values as strings");
|
|
SETPREF ("asm.immtrim", "false", "Remove all offsets and constants from disassembly");
|
|
SETPREF ("asm.indent", "false", "Indent disassembly based on reflines depth");
|
|
SETI ("asm.indentspace", 2, "How many spaces to indent the code");
|
|
SETPREF ("asm.dwarf", "false", "Show dwarf comment at disassembly");
|
|
SETPREF ("asm.dwarf.abspath", "false", "Show absolute path in asm.dwarf");
|
|
SETPREF ("asm.dwarf.file", "true", "Show filename of asm.dwarf in pd");
|
|
SETPREF ("asm.esil", "false", "Show ESIL instead of mnemonic");
|
|
SETPREF ("asm.nodup", "false", "Do not show dupped instructions (collapse disasm)");
|
|
SETPREF ("asm.emu", "false", "Run ESIL emulation analysis on disasm");
|
|
SETPREF ("asm.emustack", "false", "Create a temporary fake stack when emulating in disasm (asm.emu)");
|
|
SETCB ("asm.emustr", "false", &cb_emustr, "Show only strings if any in the asm.emu output");
|
|
SETPREF ("asm.emuwrite", "false", "Allow asm.emu to modify memory (WARNING)");
|
|
n = NODECB ("asm.emuskip", "ds", &cb_emuskip);
|
|
SETDESC (n, "Skip metadata of given types in asm.emu");
|
|
SETOPTIONS (n, "d", "c", "s", "f", "m", "h", "C", "r", NULL);
|
|
SETPREF ("asm.filter", "true", "Replace numeric values by flags (e.g. 0x4003e0 -> sym.imp.printf)");
|
|
SETPREF ("asm.fcnlines", "true", "Show function boundary lines");
|
|
SETPREF ("asm.flags", "true", "Show flags");
|
|
SETPREF ("asm.lbytes", "true", "Align disasm bytes to left");
|
|
SETPREF ("asm.lines", "true", "Show ASCII-art lines at disassembly");
|
|
SETPREF ("asm.lines.call", "false", "Enable call lines");
|
|
SETPREF ("asm.lines.ret", "false", "Show separator lines after ret");
|
|
SETPREF ("asm.linesout", "true", "Show out of block lines");
|
|
SETPREF ("asm.linesright", "false", "Show lines before opcode instead of offset");
|
|
SETPREF ("asm.lineswide", "false", "Put a space between lines");
|
|
SETICB ("asm.lineswidth", 7, &cb_asmlineswidth, "Number of columns for program flow arrows");
|
|
SETICB ("asm.minvalsub", 0x100, &cb_asmminvalsub, "Minimum value to substitute in instructions (asm.varsub)");
|
|
SETPREF ("asm.middle", "false", "Allow disassembling jumps in the middle of an instruction");
|
|
SETPREF ("asm.noisy", "true", "Show comments considered noisy but possibly useful");
|
|
SETPREF ("asm.offset", "true", "Show offsets at disassembly");
|
|
SETCB ("scr.rainbow", "false", &cb_scrrainbow, "Shows rainbow colors depending of address");
|
|
SETPREF ("asm.reloff", "false", "Show relative offsets instead of absolute address in disasm");
|
|
SETPREF ("asm.reloff.flags", "false", "Show relative offsets to flags (not only functions)");
|
|
SETPREF ("asm.section", "false", "Show section name before offset");
|
|
SETI ("asm.section.col", 20, "Columns width to show asm.section");
|
|
SETCB ("asm.section.sub", "false", &cb_asmsecsub, "Show offsets in disasm prefixed with section/map name");
|
|
SETPREF ("asm.pseudo", "false", "Enable pseudo syntax");
|
|
SETPREF ("asm.size", "false", "Show size of opcodes in disassembly (pd)");
|
|
SETPREF ("asm.stackptr", "false", "Show stack pointer at disassembly");
|
|
SETPREF ("asm.cyclespace", "false", "Indent instructions depending on CPU-cycles");
|
|
SETPREF ("asm.cycles", "false", "Show CPU-cycles taken by instruction at disassembly");
|
|
SETI ("asm.tabs", 0, "Use tabs in disassembly");
|
|
SETPREF ("asm.tabsonce", "false", "Only tabulate the opcode, not the arguments");
|
|
SETI ("asm.tabsoff", 0, "tabulate spaces after the offset");
|
|
SETPREF ("asm.trace", "false", "Show execution traces for each opcode");
|
|
SETPREF ("asm.tracespace", "false", "Indent disassembly with trace.count information");
|
|
SETPREF ("asm.ucase", "false", "Use uppercase syntax at disassembly");
|
|
SETPREF ("asm.capitalize", "false", "Use camelcase at disassembly");
|
|
SETPREF ("asm.vars", "true", "Show local function variables in disassembly");
|
|
SETPREF ("asm.varxs", "false", "Show accesses of local variables");
|
|
SETPREF ("asm.varsub", "true", "Substitute variables in disassembly");
|
|
SETPREF ("asm.varsum", "false", "Show variables summary instead of full list in disasm");
|
|
SETPREF ("asm.varsub_only", "true", "Substitute the entire variable expression with the local variable name (e.g. [local10h] instead of [ebp+local10h])");
|
|
SETPREF ("asm.relsub", "true", "Substitute pc relative expressions in disasm");
|
|
SETPREF ("asm.cmtfold", "false", "Fold comments, toggle with Vz");
|
|
SETPREF ("asm.family", "false", "Show family name in disasm");
|
|
SETPREF ("asm.symbol", "false", "Show symbol+delta instead of absolute offset");
|
|
SETPREF ("asm.anal", "false", "Analyze code and refs while disassembling (see anal.strings)");
|
|
SETI ("asm.shortcut", 1, "Shortcut position (-1, 0, 1)");
|
|
SETI ("asm.symbol.col", 40, "Columns width to show asm.section");
|
|
SETCB ("asm.assembler", "", &cb_asmassembler, "Set the plugin name to use when assembling");
|
|
SETPREF ("asm.minicols", "false", "Only show the instruction in the column disasm");
|
|
RConfigNode *asmcpu = NODECB ("asm.cpu", R_SYS_ARCH, &cb_asmcpu);
|
|
SETDESC (asmcpu, "Set the kind of asm.arch cpu");
|
|
RConfigNode *asmarch = NODECB ("asm.arch", R_SYS_ARCH, &cb_asmarch);
|
|
SETDESC (asmarch, "Set the arch to be used by asm");
|
|
/* we need to have both asm.arch and asm.cpu defined before updating options */
|
|
update_asmarch_options (core, asmarch);
|
|
update_asmcpu_options (core, asmcpu);
|
|
n = NODECB ("asm.features", "", &cb_asmfeatures);
|
|
SETDESC (n, "Specify supported features by the target CPU");
|
|
update_asmfeatures_options (core, n);
|
|
SETCB ("asm.parser", "x86.pseudo", &cb_asmparser, "Set the asm parser to use");
|
|
SETCB ("asm.segoff", "false", &cb_segoff, "Show segmented address in prompt (x86-16)");
|
|
SETCB ("asm.decoff", "false", &cb_decoff, "Show segmented address in prompt (x86-16)");
|
|
n = NODECB ("asm.syntax", "intel", &cb_asmsyntax);
|
|
SETDESC (n, "Select assembly syntax");
|
|
SETOPTIONS (n, "att", "intel", "masm", "jz", "regnum", NULL);
|
|
SETI ("asm.nbytes", 6, "Number of bytes for each opcode at disassembly");
|
|
SETPREF ("asm.bytespace", "false", "Separate hexadecimal bytes with a whitespace");
|
|
#if R_SYS_BITS == R_SYS_BITS_64
|
|
SETICB ("asm.bits", 64, &cb_asmbits, "Word size in bits at assembler");
|
|
#else
|
|
SETICB ("asm.bits", 32, &cb_asmbits, "Word size in bits at assembler");
|
|
#endif
|
|
SETPREF ("asm.functions", "true", "Show functions in disassembly");
|
|
SETPREF ("asm.fcncalls", "true", "Show functions calls");
|
|
SETPREF ("asm.xrefs", "true", "Show xrefs in disassembly");
|
|
SETPREF ("asm.demangle", "true", "Show demangled symbols in disasm");
|
|
SETPREF ("asm.describe", "false", "Show opcode description");
|
|
SETPREF ("asm.hints", "false", "Show hints for magic numbers in disasm");
|
|
SETPREF ("asm.marks", "true", "Show marks before the disassembly");
|
|
SETPREF ("asm.cmtrefs", "false", "Show flag and comments from refs in disasm");
|
|
SETPREF ("asm.cmtpatch", "false", "Show patch comments in disasm");
|
|
SETPREF ("asm.cmtoff", "nodup", "Show offset comment in disasm (true, false, nodup)");
|
|
SETPREF ("asm.payloads", "false", "Show payload bytes in disasm");
|
|
SETPREF ("asm.asciidot", "false", "Enable a char filter for string comments that passes through chars in the "
|
|
"range 0x20-0x7e and turns the rest into dots (except some control chars)");
|
|
n = NODECB ("asm.strenc", "guess", &cb_asmstrenc);
|
|
SETDESC (n, "Assumed string encoding for disasm");
|
|
SETOPTIONS (n, "latin1", "utf8", "utf16le", "utf32le", "guess", NULL);
|
|
SETCB ("bin.usextr", "true", &cb_usextr, "Use extract plugins when loading files");
|
|
SETCB ("bin.useldr", "true", &cb_useldr, "Use loader plugins when loading files");
|
|
SETCB ("bin.strpurge", "", &cb_strpurge, "Purge strings (e bin.strpurge=? provides more detail)");
|
|
SETPREF ("bin.b64str", "false", "Try to debase64 the strings");
|
|
SETPREF ("bin.libs", "false", "Try to load libraries after loading main binary");
|
|
n = NODECB ("bin.strfilter", "", &cb_strfilter);
|
|
SETDESC (n, "Filter strings");
|
|
SETOPTIONS (n, "a", "8", "p", "e", "u", "i", "U", "f", NULL);
|
|
SETCB ("bin.filter", "true", &cb_binfilter, "Filter symbol names to fix dupped names");
|
|
SETCB ("bin.force", "", &cb_binforce, "Force that rbin plugin");
|
|
SETPREF ("bin.lang", "", "Language for bin.demangle");
|
|
SETPREF ("bin.demangle", "true", "Import demangled symbols from RBin");
|
|
SETCB ("bin.demanglecmd", "false", &cb_bdc, "run xcrun swift-demangle and similar if available (SLOW)");
|
|
|
|
/* bin */
|
|
SETI ("bin.baddr", -1, "Base address of the binary");
|
|
SETI ("bin.laddr", 0, "Base address for loading library ('*.so')");
|
|
SETCB ("bin.dbginfo", "true", &cb_bindbginfo, "Load debug information at startup if available");
|
|
SETPREF ("bin.relocs", "true", "Load relocs information at startup if available");
|
|
SETICB ("bin.minstr", 0, &cb_binminstr, "Minimum string length for r_bin");
|
|
SETICB ("bin.maxstr", 0, &cb_binmaxstr, "Maximum string length for r_bin");
|
|
SETICB ("bin.maxstrbuf", 1024*1024*10, & cb_binmaxstrbuf, "Maximum size of range to load strings from");
|
|
SETCB ("bin.prefix", NULL, &cb_binprefix, "Prefix all symbols/sections/relocs with a specific string");
|
|
SETCB ("bin.rawstr", "false", &cb_rawstr, "Load strings from raw binaries");
|
|
SETCB ("bin.strings", "true", &cb_binstrings, "Load strings from rbin on startup");
|
|
SETCB ("bin.debase64", "false", &cb_debase64, "Try to debase64 all strings");
|
|
SETPREF ("bin.classes", "true", "Load classes from rbin on startup");
|
|
SETCB ("bin.verbose", "true", &cb_binverbose, "Show RBin warnings when loading binaries");
|
|
|
|
/* prj */
|
|
SETPREF ("prj.name", "", "Name of current project");
|
|
SETPREF ("prj.files", "false", "Save the target binary inside the project directory");
|
|
SETPREF ("prj.git", "false", "Every project is a git repo and saving is committing");
|
|
SETPREF ("prj.zip", "false", "Use ZIP format for project files");
|
|
SETPREF ("prj.gpg", "false", "TODO: Encrypt project with GnuPGv2");
|
|
SETPREF ("prj.simple", "false", "Use simple project saving style (funcions, comments, options)");
|
|
|
|
/* cfg */
|
|
SETPREF ("cfg.plugins", "true", "Load plugins at startup");
|
|
SETCB ("time.fmt", "%Y-%m-%d %H:%M:%S %z", &cb_cfgdatefmt, "Date format (%Y-%m-%d %H:%M:%S %z)");
|
|
SETICB ("time.zone", 0, &cb_timezone, "Time zone, in hours relative to GMT: +2, -1,..");
|
|
SETCB ("cfg.log", "false", &cb_cfglog, "Log changes using the T api needed for realtime syncing");
|
|
SETPREF ("cfg.newtab", "false", "Show descriptions in command completion");
|
|
SETCB ("cfg.debug", "false", &cb_cfgdebug, "Debugger mode");
|
|
p = r_sys_getenv ("EDITOR");
|
|
#if __WINDOWS__ && !__CYGWIN__
|
|
r_config_set (cfg, "cfg.editor", p? p: "notepad");
|
|
#else
|
|
r_config_set (cfg, "cfg.editor", p? p: "vi");
|
|
#endif
|
|
free (p);
|
|
r_config_desc (cfg, "cfg.editor", "Select default editor program");
|
|
SETPREF ("cfg.user", r_sys_whoami (buf), "Set current username/pid");
|
|
SETCB ("cfg.fortunes", "true", &cb_cfg_fortunes, "If enabled show tips at start");
|
|
SETCB ("cfg.fortunes.type", "tips,fun", &cb_cfg_fortunes_type, "Type of fortunes to show (tips, fun, nsfw, creepy)");
|
|
SETPREF ("cfg.fortunes.clippy", "false", "Use ?E instead of ?e");
|
|
SETPREF ("cfg.fortunes.tts", "false", "Speak out the fortune");
|
|
SETI ("cfg.hashlimit", SLURP_LIMIT, "If the file is bigger than hashlimit, do not compute hashes");
|
|
SETPREF ("cfg.prefixdump", "dump", "Filename prefix for automated dumps");
|
|
SETCB ("cfg.sandbox", "false", &cb_cfgsanbox, "Sandbox mode disables systems and open on upper directories");
|
|
SETPREF ("cfg.wseek", "false", "Seek after write");
|
|
SETCB ("cfg.bigendian", "false", &cb_bigendian, "Use little (false) or big (true) endianness");
|
|
|
|
// zign
|
|
SETPREF ("zign.prefix", "sign", "Default prefix for zignatures matches");
|
|
SETI ("zign.maxsz", 500, "Maximum zignature length");
|
|
SETI ("zign.minsz", 16, "Minimum zignature length for matching");
|
|
SETI ("zign.mincc", 10, "Minimum cyclomatic complexity for matching");
|
|
SETPREF ("zign.graph", "true", "Use graph metrics for matching");
|
|
SETPREF ("zign.bytes", "true", "Use bytes patterns for matching");
|
|
SETPREF ("zign.offset", "true", "Use original offset for matching");
|
|
SETPREF ("zign.refs", "true", "Use references for matching");
|
|
SETPREF ("zign.autoload", "false", "Autoload all zignatures located in ~/.config/radare2/zigns");
|
|
|
|
/* diff */
|
|
SETCB ("diff.sort", "addr", &cb_diff_sort, "Specify function diff sorting column see (e diff.sort=?)");
|
|
SETI ("diff.from", 0, "Set source diffing address for px (uses cc command)");
|
|
SETI ("diff.to", 0, "Set destination diffing address for px (uses cc command)");
|
|
SETPREF ("diff.bare", "false", "Never show function names in diff output");
|
|
SETPREF ("diff.levenstein", "false", "Use faster (and buggy) levenstein algorithm for buffer distance diffing");
|
|
|
|
/* dir */
|
|
SETCB ("dir.dbgsnap", ".", &cb_dbgsnap, "Path to session dump files");
|
|
{
|
|
char *path = r_str_newf ("%s/" R_MAGIC_PATH, r_config_get (core->config, "dir.prefix"));
|
|
SETPREF ("dir.magic", path, "Path to r_magic files");
|
|
free (path);
|
|
}
|
|
#if __WINDOWS__
|
|
SETPREF ("dir.plugins", "plugins", "Path to plugin files to be loaded at startup");
|
|
#else
|
|
SETPREF ("dir.plugins", R2_LIBDIR"/radare2/"R2_VERSION"/", "Path to plugin files to be loaded at startup");
|
|
#endif
|
|
SETCB ("dir.source", "", &cb_dirsrc, "Path to find source files");
|
|
SETPREF ("dir.types", "/usr/include", "Default path to look for cparse type files");
|
|
#if __ANDROID__
|
|
SETPREF ("dir.projects", "/data/data/org.radare.radare2installer/radare2/projects", "Default path for projects");
|
|
#elif __WINDOWS__
|
|
SETPREF ("dir.projects", "~\\"R2_HOMEDIR"\\projects", "Default path for projects");
|
|
#else
|
|
SETPREF ("dir.projects", "~/"R2_HOMEDIR"/projects", "Default path for projects");
|
|
#endif
|
|
SETCB ("dir.zigns", "~/"R2_HOMEDIR"/zigns", &cb_dirzigns, "Default path for zignatures (see zo command)");
|
|
SETPREF ("stack.bytes", "true", "Show bytes instead of words in stack");
|
|
SETPREF ("stack.anotated", "false", "Show anotated hexdump in visual debug");
|
|
SETI ("stack.size", 64, "Size in bytes of stack hexdump in visual debug");
|
|
SETI ("stack.delta", 0, "Delta for the stack dump");
|
|
|
|
SETCB ("dbg.libs", "", &cb_dbg_libs, "If set stop when loading matching libname");
|
|
SETI ("dbg.hwbp", 0, "Set HW or SW breakpoints");
|
|
SETCB ("dbg.unlibs", "", &cb_dbg_unlibs, "If set stop when unloading matching libname");
|
|
SETPREF ("dbg.slow", "false", "Show stack and regs in visual mode in a slow but verbose mode");
|
|
|
|
SETPREF ("dbg.bpinmaps", "true", "Force breakpoints to be inside a valid map");
|
|
SETCB ("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
|
|
n = NODECB ("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
|
|
SETDESC (n, "Select backtrace algorithm");
|
|
SETOPTIONS (n, "default", "fuzzy", "anal", NULL);
|
|
SETCB ("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
|
|
SETCB ("dbg.clone", "false", &cb_dbg_clone, "Stop execution if new thread is created");
|
|
SETCB ("dbg.aftersyscall", "true", &cb_dbg_aftersc, "Stop execution before the syscall is executed (see dcs)");
|
|
SETCB ("dbg.execs", "false", &cb_dbg_execs, "Stop execution if new thread is created");
|
|
SETCB ("dbg.profile", "", &cb_runprofile, "Path to RRunProfile file");
|
|
SETCB ("dbg.args", "", &cb_dbg_args, "Set the args of the program to debug");
|
|
SETCB ("dbg.follow.child", "false", &cb_dbg_follow_child, "Continue tracing the child process on fork. By default the parent process is traced");
|
|
/* debug */
|
|
SETCB ("dbg.status", "false", &cb_dbgstatus, "Set cmd.prompt to '.dr*' or '.dr*;drd;sr PC;pi 1;s-'");
|
|
#if DEBUGGER
|
|
SETCB ("dbg.backend", "native", &cb_dbgbackend, "Select the debugger backend");
|
|
#else
|
|
SETCB ("dbg.backend", "esil", &cb_dbgbackend, "Select the debugger backend");
|
|
#endif
|
|
n = NODECB ("dbg.bep", "loader", &cb_dbgbep);
|
|
SETDESC (n, "Break on entrypoint");
|
|
SETOPTIONS (n, "loader", "entry", "constructor", "main", NULL);
|
|
if (core->cons->rows > 30) { // HACKY
|
|
r_config_set_i (cfg, "dbg.follow", 64);
|
|
} else {
|
|
r_config_set_i (cfg, "dbg.follow", 32);
|
|
}
|
|
r_config_desc (cfg, "dbg.follow", "Follow program counter when pc > core->offset + dbg.follow");
|
|
SETCB ("dbg.swstep", "false", &cb_swstep, "Force use of software steps (code analysis+breakpoint)");
|
|
SETPREF ("dbg.trace.inrange", "false", "While tracing, avoid following calls outside specified range");
|
|
SETPREF ("dbg.trace.libs", "true", "Trace library code too");
|
|
SETPREF ("dbg.exitkills", "true", "Kill process on exit");
|
|
SETPREF ("dbg.exe.path", NULL, "Path to binary being debugged");
|
|
SETICB ("dbg.gdb.page_size", 4096, &cb_dbg_gdb_page_size, "Page size on gdb target (useful for QEMU)");
|
|
SETICB ("dbg.gdb.retries", 10, &cb_dbg_gdb_retries, "Number of retries before gdb packet read times out");
|
|
SETCB ("dbg.consbreak", "false", &cb_consbreak, "SIGINT handle for attached processes");
|
|
|
|
r_config_set_getter (cfg, "dbg.swstep", (RConfigCallback)__dbg_swstep_getter);
|
|
|
|
// TODO: This should be specified at first by the debug backend when attaching
|
|
#if __arm__ || __mips__
|
|
SETICB ("dbg.bpsize", 4, &cb_dbgbpsize, "Size of software breakpoints");
|
|
#else
|
|
SETICB ("dbg.bpsize", 1, &cb_dbgbpsize, "Size of software breakpoints");
|
|
#endif
|
|
SETPREF ("dbg.bpsysign", "false", "Ignore system breakpoints");
|
|
SETICB ("dbg.btdepth", 128, &cb_dbgbtdepth, "Depth of backtrace");
|
|
SETCB ("dbg.trace", "false", &cb_trace, "Trace program execution (see asm.trace)");
|
|
SETICB ("dbg.trace.tag", 0, &cb_tracetag, "Trace tag");
|
|
|
|
/* cmd */
|
|
char *xdotPath = r_file_path ("xdot");
|
|
if (r_file_exists (xdotPath)) {
|
|
r_config_set (cfg, "cmd.graph", "ag $$ > a.dot;!xdot a.dot");
|
|
} else {
|
|
char *dotPath = r_file_path ("dot");
|
|
if (r_file_exists (dotPath)) {
|
|
R_FREE (dotPath);
|
|
char *viewer = getViewerPath();
|
|
if (viewer) {
|
|
char *cmd = r_str_newf ("ag $$>a.dot;!dot -Tgif -oa.gif a.dot;!%s a.gif", viewer);
|
|
r_config_set (cfg, "cmd.graph", cmd);
|
|
free (viewer);
|
|
free (cmd);
|
|
} else {
|
|
r_config_set (cfg, "cmd.graph", "?e cannot find a valid picture viewer");
|
|
}
|
|
} else {
|
|
r_config_set (cfg, "cmd.graph", "agf");
|
|
}
|
|
free (dotPath);
|
|
}
|
|
free (xdotPath);
|
|
r_config_desc (cfg, "cmd.graph", "Command executed by 'agv' command to view graphs");
|
|
SETPREF ("cmd.xterm", "xterm -bg black -fg gray -e", "xterm command to spawn with V@");
|
|
SETICB ("cmd.depth", 10, &cb_cmddepth, "Maximum command depth");
|
|
SETPREF ("cmd.bp", "", "Run when a breakpoint is hit");
|
|
SETICB ("cmd.hitinfo", 1, &cb_debug_hitinfo, "Show info when a tracepoint/breakpoint is hit");
|
|
SETPREF ("cmd.times", "", "Run when a command is repeated (number prefix)");
|
|
SETPREF ("cmd.stack", "", "Command to display the stack in visual debug mode");
|
|
SETPREF ("cmd.cprompt", "", "Column visual prompt commands");
|
|
SETPREF ("cmd.gprompt", "", "Graph visual prompt commands");
|
|
SETPREF ("cmd.hit", "", "Run when a search hit is found");
|
|
SETPREF ("cmd.open", "", "Run when file is opened");
|
|
SETCB ("cmd.log", "", &cb_cmdlog, "Every time a new T log is added run this command");
|
|
SETPREF ("cmd.prompt", "", "Prompt commands");
|
|
SETCB ("cmd.repeat", "false", &cb_cmdrepeat, "Empty command an alias for '..' (repeat last command)");
|
|
SETPREF ("cmd.fcn.new", "", "Run when new function is analyzed");
|
|
SETPREF ("cmd.fcn.delete", "", "Run when a function is deleted");
|
|
SETPREF ("cmd.fcn.rename", "", "Run when a function is renamed");
|
|
SETPREF ("cmd.visual", "", "Replace current print mode");
|
|
SETPREF ("cmd.vprompt", "", "Visual prompt commands");
|
|
|
|
SETCB ("cmd.esil.mdev", "", &cb_cmd_esil_mdev, "Command to run when memory device address is accessed");
|
|
SETCB ("cmd.esil.intr", "", &cb_cmd_esil_intr, "Command to run when an esil interrupt happens");
|
|
SETCB ("cmd.esil.trap", "", &cb_cmd_esil_trap, "Command to run when an esil trap happens");
|
|
SETCB ("cmd.esil.todo", "", &cb_cmd_esil_todo, "Command to run when the esil instruction contains TODO");
|
|
SETCB ("cmd.esil.ioer", "", &cb_cmd_esil_ioer, "Command to run when esil fails to IO (invalid read/write)");
|
|
|
|
/* filesystem */
|
|
n = NODECB ("fs.view", "normal", &cb_fsview);
|
|
SETDESC (n, "Set visibility options for filesystems");
|
|
SETOPTIONS (n, "all", "deleted", "special", NULL);
|
|
|
|
/* hexdump */
|
|
SETPREF ("hex.header", "true", "Show header in hexdumps");
|
|
SETCB ("hex.pairs", "true", &cb_hexpairs, "Show bytes paired in 'px' hexdump");
|
|
SETCB ("hex.compact", "false", &cb_hexcompact, "Show smallest 16 byte col hexdump (60 columns)");
|
|
SETI ("hex.flagsz", 0, "If non zero, overrides the flag size in pxa");
|
|
SETICB ("hex.cols", 16, &cb_hexcols, "Number of columns in hexdump");
|
|
SETI ("hex.pcols", 40, "Number of pixel columns for prc");
|
|
SETI ("hex.depth", 5, "Maximal level of recurrence while telescoping memory");
|
|
SETPREF ("hex.onechar", "false", "Number of columns in hexdump");
|
|
SETICB ("hex.stride", 0, &cb_hexstride, "Line stride in hexdump (default is 0)");
|
|
SETCB ("hex.comments", "true", &cb_hexcomments, "Show comments in 'px' hexdump");
|
|
|
|
/* http */
|
|
SETPREF ("http.log", "true", "Show HTTP requests processed");
|
|
SETPREF ("http.logfile", "", "Specify a log file instead of stderr for http requests");
|
|
SETPREF ("http.cors", "false", "Enable CORS");
|
|
SETPREF ("http.referer", "", "CSFR protection if set");
|
|
SETPREF ("http.dirlist", "false", "Enable directory listing");
|
|
SETPREF ("http.allow", "", "Only accept clients from the comma separated IP list");
|
|
#if __WINDOWS__
|
|
r_config_set (cfg, "http.browser", "start");
|
|
#else
|
|
if (r_file_exists ("/usr/bin/openURL")) { // iOS ericautils
|
|
r_config_set (cfg, "http.browser", "/usr/bin/openURL");
|
|
} else if (r_file_exists ("/system/bin/toolbox")) {
|
|
r_config_set (cfg, "http.browser",
|
|
"LD_LIBRARY_PATH=/system/lib am start -a android.intent.action.VIEW -d");
|
|
} else if (r_file_exists ("/usr/bin/xdg-open")) {
|
|
r_config_set (cfg, "http.browser", "xdg-open");
|
|
} else if (r_file_exists ("/usr/bin/open")) {
|
|
r_config_set (cfg, "http.browser", "open");
|
|
} else {
|
|
r_config_set (cfg, "http.browser", "firefox");
|
|
}
|
|
r_config_desc (cfg, "http.browser", "Command to open HTTP URLs");
|
|
#endif
|
|
SETI ("http.maxsize", 0, "Maximum file size for upload");
|
|
SETPREF ("http.bind", "localhost", "Server address");
|
|
SETPREF ("http.homeroot", "~/.config/radare2/www", "http home root directory");
|
|
#if __ANDROID__
|
|
SETPREF ("http.root", "/data/data/org.radare.radare2installer/www", "http root directory");
|
|
#elif __WINDOWS__
|
|
SETPREF ("http.root", "www", "http root directory");
|
|
#else
|
|
SETPREF ("http.root", R2_WWWROOT, "http root directory");
|
|
#endif
|
|
SETPREF ("http.port", "9090", "HTTP server port");
|
|
SETPREF ("http.maxport", "9999", "Last HTTP server port");
|
|
SETPREF ("http.ui", "m", "Default webui (enyo, m, p, t)");
|
|
SETPREF ("http.sandbox", "true", "Sandbox the HTTP server");
|
|
SETI ("http.timeout", 3, "Disconnect clients after N seconds of inactivity");
|
|
SETI ("http.dietime", 0, "Kill server after N seconds with no client");
|
|
SETPREF ("http.verbose", "true", "Output server logs to stdout");
|
|
SETPREF ("http.upget", "false", "/up/ answers GET requests, in addition to POST");
|
|
SETPREF ("http.upload", "false", "Enable file uploads to /up/<filename>");
|
|
SETPREF ("http.uri", "", "Address of HTTP proxy");
|
|
tmpdir = r_file_tmpdir ();
|
|
r_config_set (cfg, "http.uproot", tmpdir);
|
|
free (tmpdir);
|
|
r_config_desc (cfg, "http.uproot", "Path where files are uploaded");
|
|
|
|
/* graph */
|
|
SETPREF ("graph.comments", "true", "Show disasm comments in graph");
|
|
SETPREF ("graph.cmtright", "false", "Show comments at right");
|
|
SETPREF ("graph.format", "dot", "Specify output format for graphs (dot, gml, gmlfcn)");
|
|
SETPREF ("graph.refs", "false", "Graph references in callgraphs (.agc*;aggi)");
|
|
SETI ("graph.edges", 2, "0=no edges, 1=simple edges, 2=avoid collisions");
|
|
SETI ("graph.layout", 0, "Graph layout (0=vertical, 1=horizontal)");
|
|
SETI ("graph.linemode", 1, "Graph edges (0=diagonal, 1=square)");
|
|
SETPREF ("graph.font", "Courier", "Font for dot graphs");
|
|
SETPREF ("graph.offset", "false", "Show offsets in graphs");
|
|
SETPREF ("graph.web", "false", "Display graph in web browser (VV)");
|
|
SETI ("graph.from", UT64_MAX, "");
|
|
SETI ("graph.to", UT64_MAX, "");
|
|
SETI ("graph.scroll", 5, "Scroll speed in ascii-art graph");
|
|
SETPREF ("graph.invscroll", "false", "Invert scroll direction in ascii-art graph");
|
|
SETPREF ("graph.title", "", "Title of the graph");
|
|
SETPREF ("graph.gv.node", "", "Graphviz node style. (color=gray, style=filled shape=box)");
|
|
SETPREF ("graph.gv.edge", "", "Graphviz edge style. (arrowhead=\"vee\")");
|
|
SETPREF ("graph.gv.spline", "", "Graphviz spline style. (splines=\"ortho\")");
|
|
SETPREF ("graph.gv.graph", "", "Graphviz global style attributes. (bgcolor=white)");
|
|
SETPREF ("graph.gv.current", "false", "Highlight the current node in graphviz graph.");
|
|
SETPREF ("graph.nodejmps", "true", "Enables shortcuts for every node.");
|
|
/* hud */
|
|
SETPREF ("hud.path", "", "Set a custom path for the HUD file");
|
|
|
|
SETCB ("esil.exectrap", "false", &cb_exectrap, "trap when executing code in non-executable memory");
|
|
SETCB ("esil.iotrap", "true", &cb_iotrap, "invalid read or writes produce a trap exception");
|
|
SETPREF ("esil.romem", "false", "Set memory as read-only for ESIL");
|
|
SETPREF ("esil.stats", "false", "Statistics from ESIL emulation stored in sdb");
|
|
SETPREF ("esil.nonull", "false", "Prevent memory read, memory write at null pointer");
|
|
SETCB ("esil.mdev.range", "", &cb_mdevrange, "Specify a range of memory to be handled by cmd.esil.mdev");
|
|
|
|
/* scr */
|
|
#if __EMSCRIPTEN__
|
|
r_config_set_cb (cfg, "scr.fgets", "true", cb_scrfgets);
|
|
#else
|
|
r_config_set_cb (cfg, "scr.fgets", "false", cb_scrfgets);
|
|
#endif
|
|
r_config_desc (cfg, "scr.fgets", "Use fgets() instead of dietline for prompt input");
|
|
SETCB ("scr.echo", "false", &cb_screcho, "Show rcons output in realtime to stderr and buffer");
|
|
SETICB ("scr.linesleep", 0, &cb_scrlinesleep, "Flush sleeping some ms in every line");
|
|
SETICB ("scr.pagesize", 1, &cb_scrpagesize, "Flush in pages when scr.linesleep is != 0");
|
|
SETCB ("scr.flush", "false", &cb_scrflush, "Force flush to console in realtime (breaks scripting)");
|
|
/* TODO: rename to asm.color.ops ? */
|
|
SETPREF ("scr.zoneflags", "true", "Show zoneflags in visual mode before the title (see fz?)");
|
|
SETPREF ("scr.color.ops", "true", "Colorize numbers and registers in opcodes");
|
|
SETPREF ("scr.color.bytes", "true", "Colorize bytes that represent the opcodes of the instruction");
|
|
#if __WINDOWS__ && !__CYGWIN__
|
|
SETCB ("scr.ansicon", r_str_bool (r_cons_singleton()->ansicon),
|
|
&scr_ansicon, "Use ANSICON mode or not on Windows");
|
|
#endif
|
|
#if __ANDROID__
|
|
SETPREF ("scr.responsive", "true", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
|
|
#else
|
|
SETPREF ("scr.responsive", "false", "Auto-adjust Visual depending on screen (e.g. unset asm.bytes)");
|
|
#endif
|
|
SETPREF ("scr.wheelnkey", "false", "Use sn/sp and scr.nkey on wheel instead of scroll");
|
|
SETPREF ("scr.wheel", "true", "Mouse wheel in Visual; temporaryly disable/reenable by right click/Enter)");
|
|
SETPREF ("scr.atport", "false", "V@ starts a background http server and spawns an r2 -C");
|
|
SETI ("scr.wheelspeed", 4, "Mouse wheel speed");
|
|
// DEPRECATED: USES hex.cols now SETI ("scr.colpos", 80, "Column position of cmd.cprompt in visual");
|
|
SETCB ("scr.breakword", "", &cb_scrbreakword, "Emulate console break (^C) when a word is printed (useful for pD)");
|
|
SETCB ("scr.breaklines", "false", &cb_breaklines, "Break lines in Visual instead of truncating them");
|
|
SETICB ("scr.columns", 0, &cb_scrcolumns, "Force console column count (width)");
|
|
SETCB ("scr.rows", "0", &cb_scrrows, "Force console row count (height) ");
|
|
SETICB ("scr.rows", 0, &cb_rows, "Force console row count (height) (duplicate?)");
|
|
SETCB ("scr.fps", "false", &cb_fps, "Show FPS in Visual");
|
|
SETICB ("scr.fix.rows", 0, &cb_fixrows, "Workaround for Linux TTY");
|
|
SETICB ("scr.fix.columns", 0, &cb_fixcolumns, "Workaround for Prompt iOS SSH client");
|
|
SETCB ("scr.highlight", "", &cb_scrhighlight, "Highlight that word at RCons level");
|
|
SETCB ("scr.interactive", "true", &cb_scrint, "Start in interactive mode");
|
|
SETI ("scr.feedback", 1, "Set visual feedback level (1=arrow on jump, 2=every key (useful for videos))");
|
|
SETCB ("scr.html", "false", &cb_scrhtml, "Disassembly uses HTML syntax");
|
|
n = NODECB ("scr.nkey", "flag", &cb_scrnkey);
|
|
SETDESC (n, "Select visual seek mode (affects n/N visual commands)");
|
|
SETOPTIONS (n, "fun", "hit", "flag", NULL);
|
|
SETCB ("scr.pager", "", &cb_pager, "Select pager program (when output overflows the window)");
|
|
SETPREF ("scr.randpal", "false", "Random color palete or just get the next one from 'eco'");
|
|
SETCB ("scr.color.grep", "false", &cb_scr_color_grep, "Enable colors when using ~grep");
|
|
SETPREF ("scr.pipecolor", "false", "Enable colors when using pipes");
|
|
SETPREF ("scr.promptfile", "false", "Show user prompt file (used by r2 -q)");
|
|
SETPREF ("scr.promptflag", "false", "Show flag name in the prompt");
|
|
SETPREF ("scr.promptsect", "false", "Show section name in the prompt");
|
|
SETPREF ("scr.tts", "false", "Use tts if available by a command (see ic)");
|
|
SETCB ("scr.prompt", "true", &cb_scrprompt, "Show user prompt (used by r2 -q)");
|
|
SETCB ("scr.tee", "", &cb_teefile, "Pipe output to file of this name");
|
|
SETPREF ("scr.seek", "", "Seek to the specified address on startup");
|
|
#if __WINDOWS__ && !__CYGWIN__
|
|
r_config_set_cb (cfg, "scr.rgbcolor", "false", &cb_rgbcolors);
|
|
#else
|
|
r_config_set_cb (cfg, "scr.rgbcolor", "true", &cb_rgbcolors);
|
|
#endif
|
|
r_config_desc (cfg, "scr.rgbcolor", "Use RGB colors (not available on Windows)");
|
|
SETCB ("scr.truecolor", "false", &cb_truecolor, "Manage color palette (0: ansi 16, 1: 256, 2: 16M)");
|
|
SETCB ("scr.color", (core->print->flags&R_PRINT_FLAGS_COLOR)?"true":"false", &cb_color, "Enable colors");
|
|
SETCB ("scr.null", "false", &cb_scrnull, "Show no output");
|
|
SETCB ("scr.utf8", r_cons_is_utf8()?"true":"false",
|
|
&cb_utf8, "Show UTF-8 characters instead of ANSI");
|
|
SETCB ("scr.utf8.curvy", "false", &cb_utf8_curvy, "Show curved UTF-8 corners (requires scr.utf8)");
|
|
SETPREF ("scr.histsave", "true", "Always save history on exit");
|
|
|
|
/* str */
|
|
SETCB ("str.escbslash", "false", &cb_str_escbslash, "Escape the backslash (iz and Cs-based output only)");
|
|
|
|
/* search */
|
|
SETCB ("search.contiguous", "true", &cb_contiguous, "Accept contiguous/adjacent search hits");
|
|
SETICB ("search.align", 0, &cb_searchalign, "Only catch aligned search hits");
|
|
SETI ("search.chunk", 0, "Chunk size for /+ (default size is asm.bits/8");
|
|
SETI ("search.esilcombo", 8, "Stop search after N consecutive hits");
|
|
SETI ("search.distance", 0, "Search string distance");
|
|
SETPREF ("search.flags", "true", "All search results are flagged, otherwise only printed");
|
|
SETPREF ("search.overlap", "false", "Look for overlapped search hits");
|
|
SETI ("search.maxhits", 0, "Maximum number of hits (0: no limit)");
|
|
SETI ("search.from", -1, "Search start address");
|
|
n = NODECB ("search.in", "io.maps", &cb_searchin);
|
|
SETDESC (n, "Specify search boundaries");
|
|
SETOPTIONS (n, "raw", "block", "io.map", "io.maps",
|
|
"io.sections", "io.sections.write", "io.sections.exec", "io.sections.readonly",
|
|
"dbg.stack", "dbg.heap", "dbg.map",
|
|
"dbg.maps", "dbg.maps.exec", "dbg.maps.write", "dbg.maps.readonly",
|
|
"anal.fcn", "anal.bb", NULL);
|
|
SETICB ("search.kwidx", 0, &cb_search_kwidx, "Store last search index count");
|
|
SETPREF ("search.prefix", "hit", "Prefix name in search hits label");
|
|
SETPREF ("search.show", "true", "Show search results");
|
|
SETI ("search.to", -1, "Search end address");
|
|
|
|
/* rop */
|
|
SETI ("rop.len", 5, "Maximum ROP gadget length");
|
|
SETPREF ("rop.db", "true", "Store rop search results in sdb");
|
|
SETPREF ("rop.subchains", "false", "Display every length gadget from rop.len=X to 2 in /Rl");
|
|
SETPREF ("rop.conditional", "false", "Include conditional jump, calls and returns in ropsearch");
|
|
SETPREF ("rop.nx", "false", "Include NX/XN/XD sections in ropsearch");
|
|
SETPREF ("rop.comments", "false", "Display comments in rop search output");
|
|
|
|
/* io */
|
|
SETCB ("io.buffer", "false", &cb_iobuffer, "Load and use buffer cache if enabled");
|
|
SETI ("io.buffer.from", 0, "Lower address of buffered cache");
|
|
SETI ("io.buffer.to", 0, "Higher address of buffered cache");
|
|
SETCB ("io.cache", "false", &cb_io_cache, "Change both of io.cache.{read,write}");
|
|
SETCB ("io.cache.auto", "false", &cb_io_cache_mode, "Automatic cache all reads in the IO backend");
|
|
SETCB ("io.cache.read", "false", &cb_io_cache_read, "Enable read cache for vaddr (or paddr when io.va=0)");
|
|
SETCB ("io.cache.write", "false", &cb_io_cache_write, "Enable write cache for vaddr (or paddr when io.va=0)");
|
|
SETCB ("io.pcache", "false", &cb_iopcache, "io.cache for p-level");
|
|
SETCB ("io.pcache.write", "false", &cb_iopcachewrite, "Enable write-cache");
|
|
SETCB ("io.pcache.read", "false", &cb_iopcacheread, "Enable read-cache");
|
|
SETCB ("io.ff", "true", &cb_ioff, "Fill invalid buffers with 0xff instead of returning error");
|
|
SETPREF("io.exec", "true", "See !!r2 -h~-x");
|
|
SETICB ("io.0xff", 0xff, &cb_io_oxff, "Use this value instead of 0xff to fill unallocated areas");
|
|
SETCB ("io.aslr", "false", &cb_ioaslr, "Disable ASLR for spawn and such");
|
|
SETCB ("io.va", "true", &cb_iova, "Use virtual address layout");
|
|
SETCB ("io.autofd", "true", &cb_ioautofd, "Change fd when opening a new file");
|
|
|
|
/* file */
|
|
SETPREF ("file.desc", "", "User defined file description (used by projects)");
|
|
SETPREF ("file.md5", "", "MD5 sum of current file");
|
|
SETPREF ("file.info", "true", "RBin info loaded");
|
|
SETPREF ("file.offset", "", "Offset where the file will be mapped at");
|
|
SETCB ("file.path", "", &cb_filepath, "Path of current file");
|
|
SETPREF ("file.lastpath", "", "Path of current file");
|
|
SETPREF ("file.sha1", "", "SHA1 hash of current file");
|
|
SETPREF ("file.type", "", "Type of current file");
|
|
SETI ("file.loadalign", 1024, "Alignment of load addresses");
|
|
SETI ("file.openmany", 1, "Maximum number of files opened at once");
|
|
SETPREF ("file.nowarn", "true", "Suppress file loading warning messages");
|
|
SETPREF ("file.location", "", "Is the file 'local', 'remote', or 'memory'");
|
|
/* magic */
|
|
SETI ("magic.depth", 100, "Recursivity depth in magic description strings");
|
|
|
|
/* rap */
|
|
SETPREF ("rap.loop", "true", "Run rap as a forever-listening daemon");
|
|
|
|
/* nkeys */
|
|
SETPREF ("key.s", "", "override step into action");
|
|
SETPREF ("key.S", "", "override step over action");
|
|
for (i = 1; i < 13; i++) {
|
|
snprintf (buf, sizeof (buf), "key.f%d", i);
|
|
snprintf (buf + 10, sizeof (buf) - 10,
|
|
"Run this when F%d key is pressed in visual mode", i);
|
|
switch (i) {
|
|
default: p = ""; break;
|
|
}
|
|
r_config_set (cfg, buf, p);
|
|
r_config_desc (cfg, buf, buf+10);
|
|
}
|
|
|
|
/* zoom */
|
|
SETCB ("zoom.byte", "h", &cb_zoombyte, "Zoom callback to calculate each byte (See pz? for help)");
|
|
SETI ("zoom.from", 0, "Zoom start address");
|
|
SETI ("zoom.maxsz", 512, "Zoom max size of block");
|
|
SETI ("zoom.to", 0, "Zoom end address");
|
|
n = NODECB ("zoom.in", "io.map", &cb_searchin);
|
|
SETDESC (n, "Specify boundaries for zoom");
|
|
SETOPTIONS (n, "raw", "block", "io.map", "io.maps",
|
|
"io.sections", "io.sections.write", "io.sections.exec", "io.sections.readonly",
|
|
"dbg.stack", "dbg.heap", "dbg.map",
|
|
"dbg.maps", "dbg.maps.exec", "dbg.maps.write", "dbg.maps.readonly",
|
|
"anal.fcn", "anal.bb", NULL);
|
|
/* lines */
|
|
SETI ("lines.from", 0, "Start address for line seek");
|
|
SETCB ("lines.to", "$s", &cb_linesto, "End address for line seek");
|
|
SETCB ("lines.abs", "false", &cb_linesabs, "Enable absolute line numbers");
|
|
|
|
r_config_lock (cfg, true);
|
|
return true;
|
|
}
|