Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extracting types handling into RzType (librz/type) #896

Merged
merged 25 commits into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 78 additions & 34 deletions librz/analysis/analysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,13 @@ RZ_API RzAnalysis *rz_analysis_new(void) {
rz_event_hook(analysis->zign_spaces.event, RZ_SPACE_EVENT_RENAME, zign_rename_for, NULL);
rz_analysis_hint_storage_init(analysis);
rz_interval_tree_init(&analysis->meta, rz_meta_item_free);
analysis->sdb_types = sdb_ns(analysis->sdb, "types", 1);
analysis->typedb = rz_type_db_new();
analysis->sdb_fmts = sdb_ns(analysis->sdb, "spec", 1);
analysis->sdb_cc = sdb_ns(analysis->sdb, "cc", 1);
analysis->sdb_zigns = sdb_ns(analysis->sdb, "zigns", 1);
analysis->sdb_classes = sdb_ns(analysis->sdb, "classes", 1);
analysis->sdb_classes_attrs = sdb_ns(analysis->sdb_classes, "attrs", 1);
analysis->sdb_noret = sdb_ns(analysis->sdb, "noreturn", 1);
analysis->zign_path = strdup("");
analysis->cb_printf = (PrintfCallback)printf;
(void)rz_analysis_pin_init(analysis);
Expand Down Expand Up @@ -239,39 +240,35 @@ RZ_API bool rz_analysis_set_reg_profile(RzAnalysis *analysis) {
return ret;
}

RZ_API bool rz_analysis_set_triplet(RzAnalysis *analysis, const char *os, const char *arch, int bits) {
static bool analysis_set_os(RzAnalysis *analysis, const char *os) {
rz_return_val_if_fail(analysis, false);
if (!os || !*os) {
os = RZ_SYS_OS;
}
free(analysis->os);
analysis->os = strdup(os);
rz_type_db_set_os(analysis->typedb, os);
return true;
}

RZ_API bool rz_analysis_set_triplet(RzAnalysis *analysis, const char *os, const char *arch, int bits) {
rz_return_val_if_fail(analysis, false);
if (!arch || !*arch) {
arch = analysis->cur ? analysis->cur->arch : RZ_SYS_ARCH;
}
if (bits < 1) {
bits = analysis->bits;
}
free(analysis->os);
analysis->os = strdup(os);
analysis_set_os(analysis, os);
rz_analysis_set_bits(analysis, bits);
return rz_analysis_use(analysis, arch);
}

// copypasta from core/cbin.c
static void sdb_concat_by_path(Sdb *s, const char *path) {
Sdb *db = sdb_new(0, path, 0);
sdb_merge(s, db);
sdb_close(db);
sdb_free(db);
}

RZ_API bool rz_analysis_set_os(RzAnalysis *analysis, const char *os) {
Sdb *types = analysis->sdb_types;
const char *dir_prefix = rz_sys_prefix(NULL);
const char *dbpath = sdb_fmt(RZ_JOIN_3_PATHS("%s", RZ_SDB_FCNSIGN, "types-%s.sdb"),
dir_prefix, os);
if (rz_file_exists(dbpath)) {
sdb_concat_by_path(types, dbpath);
}
rz_type_db_load_sdb(analysis->typedb, dbpath);
return rz_analysis_set_triplet(analysis, os, NULL, -1);
}

Expand All @@ -284,6 +281,7 @@ RZ_API bool rz_analysis_set_bits(RzAnalysis *analysis, int bits) {
case 64:
if (analysis->bits != bits) {
analysis->bits = bits;
rz_type_db_set_bits(analysis->typedb, bits);
rz_analysis_set_reg_profile(analysis);
}
return true;
Expand All @@ -298,13 +296,15 @@ RZ_API void rz_analysis_set_cpu(RzAnalysis *analysis, const char *cpu) {
if (v != -1) {
analysis->pcalign = v;
}
rz_type_db_set_cpu(analysis->typedb, cpu);
}

RZ_API int rz_analysis_set_big_endian(RzAnalysis *analysis, int bigend) {
analysis->big_endian = bigend;
if (analysis->reg) {
analysis->reg->big_endian = bigend;
}
rz_type_db_set_endian(analysis->typedb, bigend);
return true;
}

Expand Down Expand Up @@ -408,13 +408,14 @@ RZ_API void rz_analysis_purge(RzAnalysis *analysis) {
rz_analysis_hint_clear(analysis);
rz_interval_tree_fini(&analysis->meta);
rz_interval_tree_init(&analysis->meta, rz_meta_item_free);
sdb_reset(analysis->sdb_types);
rz_type_db_purge(analysis->typedb);
sdb_reset(analysis->sdb_zigns);
sdb_reset(analysis->sdb_classes);
sdb_reset(analysis->sdb_classes_attrs);
rz_analysis_pin_fini(analysis);
rz_analysis_pin_init(analysis);
sdb_reset(analysis->sdb_cc);
sdb_reset(analysis->sdb_noret);
rz_list_free(analysis->fcns);
analysis->fcns = rz_list_newf(rz_analysis_function_free);
rz_analysis_purge_imports(analysis);
Expand All @@ -439,10 +440,10 @@ RZ_API int rz_analysis_archinfo(RzAnalysis *analysis, int query) {

RZ_API bool rz_analysis_noreturn_add(RzAnalysis *analysis, const char *name, ut64 addr) {
const char *tmp_name = NULL;
Sdb *TDB = analysis->sdb_types;
Sdb *NDB = analysis->sdb_noret;
char *fnl_name = NULL;
if (addr != UT64_MAX) {
if (sdb_bool_set(TDB, K_NORET_ADDR(addr), true, 0)) {
if (sdb_bool_set(NDB, K_NORET_ADDR(addr), true, 0)) {
RzAnalysisFunction *fcn = rz_analysis_get_function_at(analysis, addr);
if (fcn) {
fcn->is_noreturn = true;
Expand All @@ -464,12 +465,12 @@ RZ_API bool rz_analysis_noreturn_add(RzAnalysis *analysis, const char *name, ut6
fcn->is_noreturn = true;
}
}
if (rz_type_func_exist(TDB, tmp_name)) {
if (rz_type_func_exist(analysis->typedb, tmp_name)) {
fnl_name = strdup(tmp_name);
} else if (!(fnl_name = rz_type_func_guess(TDB, (char *)tmp_name))) {
} else if (!(fnl_name = rz_type_func_guess(analysis->typedb, (char *)tmp_name))) {
if (addr == UT64_MAX) {
if (name) {
sdb_bool_set(TDB, K_NORET_FUNC(name), true, 0);
sdb_bool_set(NDB, K_NORET_FUNC(name), true, 0);
} else {
eprintf("Can't find prototype for: %s\n", tmp_name);
}
Expand All @@ -479,19 +480,19 @@ RZ_API bool rz_analysis_noreturn_add(RzAnalysis *analysis, const char *name, ut6
//return false;
}
if (fnl_name) {
sdb_bool_set(TDB, K_NORET_FUNC(fnl_name), true, 0);
sdb_bool_set(NDB, K_NORET_FUNC(fnl_name), true, 0);
free(fnl_name);
}
return true;
}

RZ_API bool rz_analysis_noreturn_drop(RzAnalysis *analysis, const char *expr) {
Sdb *TDB = analysis->sdb_types;
Sdb *NDB = analysis->sdb_noret;
expr = rz_str_trim_head_ro(expr);
const char *fcnname = NULL;
if (!strncmp(expr, "0x", 2)) {
ut64 n = rz_num_math(NULL, expr);
sdb_unset(TDB, K_NORET_ADDR(n), 0);
sdb_unset(NDB, K_NORET_ADDR(n), 0);
RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(analysis, n, -1);
if (!fcn) {
// eprintf ("can't find function at 0x%"PFMT64x"\n", n);
Expand All @@ -501,15 +502,15 @@ RZ_API bool rz_analysis_noreturn_drop(RzAnalysis *analysis, const char *expr) {
} else {
fcnname = expr;
}
sdb_unset(TDB, K_NORET_FUNC(fcnname), 0);
sdb_unset(NDB, K_NORET_FUNC(fcnname), 0);
#if 0
char *tmp;
// unnsecessary checks, imho the noreturn db should be pretty simple to allow forward and custom declarations without having to define the function prototype before
if (rz_type_func_exist (TDB, fcnname)) {
sdb_unset (TDB, K_NORET_FUNC (fcnname), 0);
if (rz_type_func_exist (NDB, fcnname)) {
sdb_unset (NDB, K_NORET_FUNC (fcnname), 0);
return true;
} else if ((tmp = rz_type_func_guess (TDB, (char *)fcnname))) {
sdb_unset (TDB, K_NORET_FUNC (fcnname), 0);
} else if ((tmp = rz_type_func_guess (NDB, (char *)fcnname))) {
sdb_unset (NDB, K_NORET_FUNC (fcnname), 0);
free (tmp);
return true;
}
Expand All @@ -518,13 +519,18 @@ RZ_API bool rz_analysis_noreturn_drop(RzAnalysis *analysis, const char *expr) {
return false;
}

static bool rz_analysis_is_noreturn(RzAnalysis *analysis, const char *name) {
return rz_type_func_is_noreturn(analysis->typedb, name) ||
sdb_bool_get(analysis->sdb_noret, K_NORET_FUNC(name), NULL);
}

static bool rz_analysis_noreturn_at_name(RzAnalysis *analysis, const char *name) {
if (sdb_bool_get(analysis->sdb_types, K_NORET_FUNC(name), NULL)) {
if (rz_analysis_is_noreturn(analysis, name)) {
return true;
}
char *tmp = rz_type_func_guess(analysis->sdb_types, (char *)name);
char *tmp = rz_type_func_guess(analysis->typedb, (char *)name);
if (tmp) {
if (sdb_bool_get(analysis->sdb_types, K_NORET_FUNC(tmp), NULL)) {
if (rz_analysis_is_noreturn(analysis, tmp)) {
free(tmp);
return true;
}
Expand All @@ -537,7 +543,7 @@ static bool rz_analysis_noreturn_at_name(RzAnalysis *analysis, const char *name)
}

RZ_API bool rz_analysis_noreturn_at_addr(RzAnalysis *analysis, ut64 addr) {
return sdb_bool_get(analysis->sdb_types, K_NORET_ADDR(addr), NULL);
return sdb_bool_get(analysis->sdb_noret, K_NORET_ADDR(addr), NULL);
}

static bool noreturn_recurse(RzAnalysis *analysis, ut64 addr) {
Expand Down Expand Up @@ -602,6 +608,44 @@ RZ_API bool rz_analysis_noreturn_at(RzAnalysis *analysis, ut64 addr) {
return false;
}

RZ_API RzList *rz_analysis_noreturn_functions(RzAnalysis *analysis) {
rz_return_val_if_fail(analysis, NULL);
// At first we read all noreturn functions from the Types DB
RzList *noretl = rz_type_noreturn_functions(analysis->typedb);
// Then we propagate all noreturn functions that were inferred by
// the analysis process
SdbKv *kv;
SdbListIter *iter;
SdbList *l = sdb_foreach_list(analysis->sdb_noret, true);
ls_foreach (l, iter, kv) {
const char *k = sdbkv_key(kv);
if (!strncmp(k, "func.", 5) && strstr(k, ".noreturn")) {
char *s = strdup(k + 5);
char *d = strchr(s, '.');
if (d) {
*d = 0;
}
rz_list_append(noretl, strdup(s));
free(s);
}
if (!strncmp(k, "addr.", 5)) {
char *off;
if (!(off = strdup(k + 5))) {
break;
}
char *ptr = strstr(off, ".noreturn");
if (ptr) {
*ptr = 0;
char *addr = rz_str_newf("0x%s", off);
rz_list_append(noretl, addr);
}
free(off);
}
}
ls_free(l);
return noretl;
}

RZ_API void rz_analysis_bind(RzAnalysis *analysis, RzAnalysisBind *b) {
if (b) {
b->analysis = analysis;
Expand Down
20 changes: 0 additions & 20 deletions librz/analysis/base_types.h

This file was deleted.

17 changes: 15 additions & 2 deletions librz/analysis/cc.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,20 @@ RZ_API void rz_analysis_set_syscc_default(RzAnalysis *analysis, const char *cc)

RZ_API const char *rz_analysis_cc_func(RzAnalysis *analysis, const char *func_name) {
rz_return_val_if_fail(analysis && func_name, NULL);
const char *query = sdb_fmt("func.%s.cc", func_name);
const char *cc = sdb_const_get(analysis->sdb_types, query, 0);
const char *cc = rz_type_func_cc(analysis->typedb, func_name);
return cc ? cc : rz_analysis_cc_default(analysis);
}

RZ_API RzList *rz_analysis_calling_conventions(RzAnalysis *analysis) {
RzList *ccl = rz_list_new();
SdbKv *kv;
SdbListIter *iter;
SdbList *l = sdb_foreach_list(analysis->sdb_cc, true);
ls_foreach (l, iter, kv) {
if (!strcmp(sdbkv_value(kv), "cc")) {
rz_list_append(ccl, strdup(sdbkv_key(kv)));
}
}
ls_free(l);
return ccl;
}
Loading