mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-27 23:20:40 +00:00
Instantiate RArch in anal ##arch
This commit is contained in:
parent
1181497bfc
commit
4e92945241
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
128
libr/arch/arch.c
128
libr/arch/arch.c
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user