Instantiate RArch in anal ##arch

This commit is contained in:
condret 2022-09-25 03:19:52 +02:00
parent 1181497bfc
commit 4e92945241
6 changed files with 167 additions and 12 deletions

View File

@ -94,6 +94,7 @@ R_API RAnal *r_anal_new(void) {
anal->ht_addr_fun = ht_up_new0 ();
anal->ht_name_fun = ht_pp_new0 ();
anal->config = r_arch_config_new ();
anal->arch = r_arch_new ();
anal->esil_goto_limit = R_ANAL_ESIL_GOTO_LIMIT;
anal->opt.nopskip = true; // skip nops in code analysis
anal->opt.hpskip = false; // skip `mov reg,reg` and `lea reg,[reg]`
@ -169,6 +170,7 @@ R_API void r_anal_free(RAnal *a) {
r_th_lock_free (a->lock);
r_interval_tree_fini (&a->meta);
r_unref (a->config);
r_arch_free (a->arch);
free (a->zign_path);
r_list_free (a->plugins);
r_rbtree_free (a->bb_tree, __block_free_rb, NULL);

View File

@ -48,7 +48,7 @@ R_API RArchConfig *r_arch_config_new(void) {
// ac->free = (void (*)(void*))my_ac_free;
ac->syntax = R_ARCH_SYNTAX_INTEL;
r_ref_init (ac, &_ac_free);
ac->big_endian = false;
ac->endian = R_SYS_ENDIAN_NONE;
r_ref (ac);
return (RArchConfig *)ac;
}

View File

@ -40,7 +40,7 @@ R_API RArch *r_arch_new(void) {
return a;
}
static char *_find_bestmatch(RList *plugins, RArchConfig *cfg) {
static ut32 _rate_compat(RArchPlugin *p, RArchConfig *cfg) {
ut32 bits;
switch (cfg->bits) {
case 64:
@ -67,21 +67,26 @@ static char *_find_bestmatch(RList *plugins, RArchConfig *cfg) {
default:
bits = UT32_MAX;
}
ut32 score = 0;
if (!strcmp (p->arch, cfg->arch)) {
score = 50;
}
if (p->bits & bits) {
score += (!!score) * 30;
}
if (p->endian & cfg->endian) {
score += (!!score) * 20;
}
return score;
}
static char *_find_bestmatch(RList *plugins, RArchConfig *cfg) {
ut8 best_score = 0;
char *name = NULL;
RListIter *iter;
RArchPlugin *p;
r_list_foreach (plugins, iter, p) {
ut32 score = 0;
if (!strcmp (p->arch, cfg->arch)) {
score = 50;
}
if (p->bits & bits) {
score += (!!score) * 30;
}
if (p->endian & cfg->endian) {
score += (!!score) * 20;
}
const ut32 score = _rate_compat (p, cfg);
if (score > best_score) {
best_score = score;
name = p->name;
@ -112,6 +117,104 @@ R_API bool r_arch_use(RArch *arch, RArchConfig *config) {
return true;
}
R_API bool r_arch_set_bits(RArch *arch, ut32 bits) {
r_return_val_if_fail (arch && bits, false);
if (!arch->cfg) {
arch->cfg = r_arch_config_new ();
if (!arch->cfg) {
return false;
}
arch->cfg->bits = bits;
if (!r_arch_use (arch, arch->cfg)) {
r_unref (arch->cfg);
arch->cfg = NULL;
return false;
}
}
if (arch->autoselect) {
if (arch->current) {
const ut32 score = _rate_compat (arch->current->p, arch->cfg);
arch->cfg->bits = bits;
if (!score || score > _rate_compat (arch->current->p, arch->cfg)) {
return r_arch_use (arch, arch->cfg);
}
return true;
}
arch->cfg->bits = bits;
return r_arch_use (arch, arch->cfg);
}
arch->cfg->bits = bits;
return true;
}
R_API bool r_arch_set_endian(RArch *arch, ut32 endian) {
r_return_val_if_fail (arch, false);
if (!arch->cfg) {
arch->cfg = r_arch_config_new ();
if (!arch->cfg) {
return false;
}
arch->cfg->endian = endian;
if (!r_arch_use (arch, arch->cfg)) {
r_unref (arch->cfg);
arch->cfg = NULL;
return false;
}
}
if (arch->autoselect) {
if (arch->current) {
const ut32 score = _rate_compat (arch->current->p, arch->cfg);
arch->cfg->endian = endian;
if (!score || score > _rate_compat (arch->current->p, arch->cfg)) {
return r_arch_use (arch, arch->cfg);
}
return true;
}
arch->cfg->endian = endian;
return r_arch_use (arch, arch->cfg);
}
arch->cfg->bits = endian;
return true;
}
R_API bool r_arch_set_arch(RArch *arch, char *archname) {
r_return_val_if_fail (arch && archname, false);
char *_arch = strdup (archname);
if (!_arch) {
return false;
}
if (!arch->cfg) {
arch->cfg = r_arch_config_new ();
if (!arch->cfg) {
free (_arch);
return false;
}
arch->cfg->arch = _arch;
if (!r_arch_use (arch, arch->cfg)) {
r_unref (arch->cfg);
arch->cfg = NULL;
return false;
}
}
if (arch->autoselect) {
if (arch->current) {
const ut32 score = _rate_compat (arch->current->p, arch->cfg);
free (arch->cfg->arch);
arch->cfg->arch = _arch;
if (!score || score > _rate_compat (arch->current->p, arch->cfg)) {
return r_arch_use (arch, arch->cfg);
}
return true;
}
free (arch->cfg->arch);
arch->cfg->arch = _arch;
return r_arch_use (arch, arch->cfg);
}
free (arch->cfg->arch);
arch->cfg->arch = _arch;
return true;
}
R_API bool r_arch_add(RArch *a, RArchPlugin *ap) {
r_return_val_if_fail (a && ap->name && ap->arch, false);
return !!r_list_append (a->plugins, ap);
@ -149,5 +252,8 @@ R_API void r_arch_free(RArch *a) {
r_return_if_fail (a);
ht_pp_free (a->decoders);
r_list_free (a->plugins);
if (a->cfg) {
r_unref (a->cfg);
}
free (a);
}

View File

@ -493,6 +493,44 @@ static bool cb_analarch(void *user, void *data) {
return false;
}
static void update_archdecoder_options(RCore *core, RConfigNode *node) {
r_return_if_fail (core && core->anal && core->anal->arch && node);
r_config_node_purge_options (node);
RListIter *it;
RArchPlugin *p;
r_list_foreach (core->anal->arch->plugins, it, p) {
if (p->name) {
SETOPTIONS (node, p->name, NULL);
}
}
}
static bool cb_archdecoder(void *user, void *data) {
RCore *core = (RCore*) user;
r_return_val_if_fail (core && core->anal && core->anal->arch, false);
RConfigNode *node = (RConfigNode*) data;
if (*node->value == '?') {
update_archdecoder_options (core, node);
print_node_options (node);
return false;
}
if (*node->value) {
if (r_arch_use_decoder (core->anal->arch, node->value)) {
return true;
}
R_LOG_ERROR ("arch.decoder: cannot find '%s'", node->value);
}
return false;
}
static bool cb_archautoselect(void *user, void *data) {
RCore *core = (RCore*) user;
r_return_val_if_fail (core && core->anal && core->anal->arch, false);
RConfigNode *node = (RConfigNode*) data;
core->anal->arch->autoselect = node->i_value;
return true;
}
#if 0
static bool cb_analcpu(void *user, void *data) {
RCore *core = (RCore *) user;
@ -3395,6 +3433,10 @@ R_API int r_core_config_init(RCore *core) {
SETCB ("anal.recont", "false", &cb_analrecont, "end block after splitting a basic block instead of error"); // testing
SETCB ("anal.jmp.indir", "false", &cb_analijmp, "follow the indirect jumps in function analysis"); // testing
SETI ("anal.ptrdepth", 3, "maximum number of nested pointers to follow in analysis");
n = NODECB ("arch.decoder", "null", &cb_archdecoder);
SETDESC (n, "select the instruction decoder to use");
update_archdecoder_options (core, n);
SETCB ("arch.autoselect", "false", &cb_archautoselect, "automagically select matching decoder on arch related config changes (has no effect atm)");
SETICB ("asm.lines.maxref", 0, &cb_analmaxrefs, "maximum number of reflines to be analyzed and displayed in asm.lines with pd");
SETCB ("anal.jmp.tbl", "true", &cb_anal_jmptbl, "analyze jump tables in switch statements");

View File

@ -626,6 +626,7 @@ typedef struct r_anal_t {
struct r_anal_esil_t *esil;
struct r_anal_plugin_t *cur;
struct r_anal_esil_plugin_t *esil_cur; // ???
RArch *arch;
RAnalRange *limit; // anal.from, anal.to
RList *plugins; // anal plugins
RList *esil_plugins;

View File

@ -334,6 +334,7 @@ typedef struct r_arch_t {
RArchDecoder *current; //currently used decoder
HtPP *decoders; //as decoders instantiated plugins
RArchConfig *cfg; //config
bool autoselect;
} RArch;
typedef struct r_arch_plugin_t {
@ -372,6 +373,9 @@ R_API bool r_arch_set_reg_profile(RArch *arch, const char *dname, struct r_reg_t
// arch.c
R_API RArch *r_arch_new(void);
R_API bool r_arch_use(RArch *arch, RArchConfig *config);
R_API bool r_arch_set_bits(RArch *arch, ut32 bits);
R_API bool r_arch_set_endian(RArch *arch, ut32 endian);
R_API bool r_arch_set_arch(RArch *arch, char *archname);
R_API bool r_arch_add(RArch *arch, RArchPlugin *ap);
R_API bool r_arch_del(RArch *arch, const char *name);
R_API void r_arch_free(RArch *arch);