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

Try Catch Improvement #4305

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions do_you_see_this
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello
9 changes: 9 additions & 0 deletions librz/analysis/analysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ static void global_kv_free(HtPPKv *kv) {
rz_analysis_var_global_free(kv->value);
}

static void exception_scope_kv_free(HtUPKv *kv) {
rz_list_free(kv->value);
}

RZ_API RzAnalysis *rz_analysis_new(void) {
int i;
RzAnalysis *analysis = RZ_NEW0(RzAnalysis);
Expand Down Expand Up @@ -102,6 +106,7 @@ RZ_API RzAnalysis *rz_analysis_new(void) {
analysis->cpp_abi = RZ_ANALYSIS_CPP_ABI_ITANIUM;
analysis->opt.depth = 32;
analysis->opt.noncode = false; // do not analyze data by default
analysis->exception_scopes_ht = ht_up_new(NULL, exception_scope_kv_free, NULL);
rz_spaces_init(&analysis->meta_spaces, "CS");
rz_event_hook(analysis->meta_spaces.event, RZ_SPACE_EVENT_UNSET, meta_unset_for, NULL);
rz_event_hook(analysis->meta_spaces.event, RZ_SPACE_EVENT_COUNT, meta_count_for, NULL);
Expand Down Expand Up @@ -192,6 +197,10 @@ RZ_API RzAnalysis *rz_analysis_free(RzAnalysis *a) {
ht_pp_free(a->ht_global_var);
rz_list_free(a->plugins);
rz_analysis_debug_info_free(a->debug_info);
// TODO (Jared): Implement
// free a->exception_scopes_tree
// rz_rbtree_itv_free(&a->exception_scopes_tree);
ht_up_free(a->exception_scopes_ht);
free(a);
return NULL;
}
Expand Down
43 changes: 12 additions & 31 deletions librz/analysis/fcn.c
Original file line number Diff line number Diff line change
Expand Up @@ -773,37 +773,6 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
rz_analysis_block_set_size(bb, newbbsize);
fcn->ninstr++;
}
if (analysis->opt.trycatch) {
const char *name = analysis->coreb.getName(analysis->coreb.core, at);
if (name) {
if (rz_str_startswith(name, "try.") && rz_str_endswith(name, ".from")) {
char *handle = strdup(name);
// handle = rz_str_replace (handle, ".from", ".to", 0);
ut64 from_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
handle = rz_str_replace(handle, ".from", ".catch", 0);
ut64 handle_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
handle = rz_str_replace(handle, ".catch", ".filter", 0);
ut64 filter_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
if (filter_addr) {
rz_analysis_xrefs_set(analysis, op.addr, filter_addr, RZ_ANALYSIS_XREF_TYPE_CALL);
}
bb->jump = at + oplen;
if (from_addr != bb->addr) {
bb->fail = handle_addr;
ret = analyze_function_locally(analysis, fcn, handle_addr);
if (bb->size == 0) {
rz_analysis_function_remove_block(fcn, bb);
}
rz_analysis_block_update_hash(bb);
rz_analysis_block_unref(bb);
bb = fcn_append_basic_block(analysis, fcn, bb->jump);
if (!bb) {
gotoBeach(RZ_ANALYSIS_RET_ERROR);
}
}
}
}
}
idx += oplen;
delay.un_idx = idx;
if (analysis->opt.delay && op.delay > 0 && !delay.pending) {
Expand Down Expand Up @@ -1633,6 +1602,18 @@ RZ_API int rz_analysis_fcn(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 a
RzVector tasks;
rz_vector_init(&tasks, sizeof(RzAnalysisTaskItem), NULL, NULL);
rz_analysis_task_item_new(analysis, &tasks, fcn, NULL, addr, 0);
if (analysis->opt.trycatch) {
RzBinTrycatch *tc;
RzListIter *it;
RzList *scopes = ht_up_find(analysis->exception_scopes_ht, fcn->addr, NULL);
rz_list_foreach (scopes, it, tc) {
if (tc->filter) {
rz_analysis_xrefs_set(analysis, tc->from, tc->filter, RZ_ANALYSIS_XREF_TYPE_CALL);
}
// TODO (Jared): Fix Function
rz_analysis_task_item_new(analysis, &tasks, fcn, NULL, tc->handler, fcn->stack);
}
}
int ret = rz_analysis_run_tasks(&tasks);
rz_vector_fini(&tasks);
return ret;
Expand Down
1 change: 1 addition & 0 deletions librz/bin/p/bin_pe64.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ static bool read_pe64_scope_record(RzBuffer *buf, ut64 base, PE64_SCOPE_RECORD *
rz_buf_read_ble32_offset(buf, &offset, &record->JumpTarget, big_endian);
}

// TODO: (Jared) Analyze this closely
static RzPVector /*<RzBinTrycatch *>*/ *trycatch(RzBinFile *bf) {
ut64 baseAddr = bf->o->opts.baseaddr;
ut64 offset;
Expand Down
95 changes: 80 additions & 15 deletions librz/core/agraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,10 @@ static void create_dummy_nodes(RzAGraph *g) {
dummy->layer = from->layer + i;
dummy->is_reversed = is_reversed(g, e);
dummy->w = 1;
dummy->is_unconditional_jmp = to->is_unconditional_jmp;
dummy->address = to->address;
dummy->jump = to->jump;
dummy->fail = to->fail;
rz_agraph_add_edge_at(g, prev, dummy, nth);
rz_list_append(g->dummy_nodes, dummy);

Expand Down Expand Up @@ -1754,6 +1758,9 @@ static void fix_back_edge_dummy_nodes(RzAGraph *g, RzANode *from, RzANode *to) {
}

static int get_edge_number(const RzAGraph *g, RzANode *src, RzANode *dst, bool outgoing) {
if (g->is_callgraph) {
return 0;
}
RzListIter *itn;
RzGraphNode *gv;
int cur_nth = 0;
Expand All @@ -1768,6 +1775,9 @@ static int get_edge_number(const RzAGraph *g, RzANode *src, RzANode *dst, bool o
? rz_graph_get_neighbours(g->graph, src->gnode)
: rz_graph_innodes(g->graph, dst->gnode);
const int exit_edges = rz_list_length(neighbours);
if (exit_edges == 1) {
return -1;
}
rz_list_foreach (neighbours, itn, gv) {
if (!(v = gv->data)) {
break;
Expand Down Expand Up @@ -2346,6 +2356,7 @@ static int get_bbnodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn) {
RzListIter *iter;
bool emu = rz_config_get_i(core->config, "asm.emu");
bool few = rz_config_get_i(core->config, "graph.few");
bool trycatch = rz_config_get_i(core->config, "graph.trycatch");
int ret = false;
ut64 saved_gp = core->analysis->gp;
ut8 *saved_arena = NULL;
Expand Down Expand Up @@ -2384,6 +2395,9 @@ static int get_bbnodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn) {
char *title = get_title(bb->addr);

RzANode *node = rz_agraph_add_node(g, title, body);
node->address = bb->addr;
node->jump = bb->jump;
node->fail = bb->fail;
if (shortcuts) {
rz_core_agraph_add_shortcut(core, g, node, bb->addr, title);
}
Expand All @@ -2395,6 +2409,15 @@ static int get_bbnodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn) {
core->keep_asmqjmps = true;
}

RzList *exception_scopes = NULL;
if (trycatch) {
// RzInterval itv = { rz_analysis_function_min_addr(fcn),
RzInterval itv = { rz_analysis_function_min_addr(fcn),
rz_analysis_function_max_addr(fcn) - rz_analysis_function_min_addr(fcn) };
// TODO (Jared): Implement exception_scopes_tree
exception_scopes = rz_interval_tree_all_intersect(fcn->analysis->exception_scopes_tree, itv);
}

rz_list_foreach (fcn->bbs, iter, bb) {
if (bb->addr == UT64_MAX) {
continue;
Expand All @@ -2406,6 +2429,28 @@ static int get_bbnodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn) {
char *title = get_title(bb->addr);
RzANode *u = rz_agraph_get_node(g, title);
RzANode *v;

RzListIter *it;
RzBinTrycatch *tc;
rz_list_foreach (exception_scopes, it, tc) {
if (bb->addr == tc->handler) {
continue;
}
if (!rz_itv_overlap2((RzInterval){ bb->addr, bb->size }, tc->from, tc->to - 1)) {
continue;
}
RzAnalysisBlock *catch_bb = rz_analysis_get_block_at(bb->analysis, tc->handler);
if (!catch_bb || catch_bb->addr == bb->jump || catch_bb->addr == bb->fail) {
continue;
}
title = get_title(catch_bb->addr);
v = rz_agraph_get_node(g, title);
free(title);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
free(title);
RZ_FREE(title);

Use RZ_FREE when a pointer is reused.
RZ_FREE will invoke free and also set the freed pointer to NULL.

if (v) {
v->is_unconditional_jmp = true;
rz_agraph_add_edge(g, u, v);
}
}
free(title);
if (bb->jump != UT64_MAX) {
title = get_title(bb->jump);
Expand All @@ -2430,7 +2475,7 @@ static int get_bbnodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn) {
}
}
}

rz_list_free(exception_scopes);
delete_dup_edges(g);
ret = true;

Expand Down Expand Up @@ -2861,6 +2906,14 @@ static int first_x_cmp(const void *_a, const void *_b, void *user) {
return 0;
}

static inline bool is_true_edge(RzANode *src, RzANode *dst) {
return src->jump != UT64_MAX && src->jump == dst->address;
}

static inline bool is_false_edge(RzANode *src, RzANode *dst) {
return src->fail != UT64_MAX && src->fail == dst->address;
}

static void agraph_print_edges(RzAGraph *g) {
if (!g->edgemode) {
return;
Expand All @@ -2869,12 +2922,20 @@ static void agraph_print_edges(RzAGraph *g) {
agraph_print_edges_simple(g);
return;
}

int out_nth, in_nth, bendpoint;
RzListIter *itn, *itm, *ito;
RzCanvasLineStyle style = { 0 };
const RzList *nodes = rz_graph_get_nodes(g->graph);
RzGraphNode *ga;
RzANode *a;
// RzANode *real_parent = a;
// if (a->is_dummy) {
// real_parent = (RzANode *)(((RzGraphNode *)rz_list_first(ga->in_nodes))->data);
// while (real_parent && real_parent->is_dummy) {
// real_parent = (RzANode *)(((RzGraphNode *)rz_list_first((real_parent->gnode)->in_nodes))->data);
// }
// }

RzList *lyr = rz_list_new();
RzList *bckedges = rz_list_new();
Expand Down Expand Up @@ -2938,28 +2999,29 @@ static void agraph_print_edges(RzAGraph *g) {
rz_list_sort(neighbours, first_x_cmp, NULL);
}

RzANode *real_parent = a;
if (a->is_dummy) {
real_parent = (RzANode *)(((RzGraphNode *)rz_list_first(ga->in_nodes))->data);
while (real_parent && real_parent->is_dummy) {
real_parent = (RzANode *)(((RzGraphNode *)rz_list_first((real_parent->gnode)->in_nodes))->data);
}
}

rz_list_foreach (neighbours, itn, gb) {
if (!(b = gb->data)) {
break;
}
out_nth = get_edge_number(g, a, b, true);
in_nth = get_edge_number(g, a, b, false);

bool parent_many = false;
if (a->is_dummy) {
RzANode *in = (RzANode *)(((RzGraphNode *)rz_list_first(ga->in_nodes))->data);
while (in && in->is_dummy) {
in = (RzANode *)(((RzGraphNode *)rz_list_first((in->gnode)->in_nodes))->data);
}
if (in && in->gnode) {
parent_many = rz_list_length(in->gnode->out_nodes) > 2;
} else {
parent_many = false;
}
}

style.dot_style = DOT_STYLE_NORMAL;
if (many || parent_many || g->is_il) {
if (is_true_edge(real_parent, b) && out_nth != -1) {
style.color = LINE_TRUE;
style.dot_style = DOT_STYLE_CONDITIONAL;
} else if (is_false_edge(real_parent, b)) {
style.color = LINE_FALSE;
style.dot_style = DOT_STYLE_CONDITIONAL;
} else if (many || b->is_unconditional_jmp) {
style.color = LINE_UNCJMP;
} else {
switch (out_nth) {
Expand Down Expand Up @@ -3783,6 +3845,9 @@ RZ_API RzANode *rz_agraph_add_node(const RzAGraph *g, const char *title, const c
rz_strf(buf, "agraph.nodes.%s.body", res->title);
sdb_set_owned(g->db, buf, s, 0);
}
res->address = UT64_MAX;
res->jump = UT64_MAX;
res->fail = UT64_MAX;
return res;
}

Expand Down
23 changes: 23 additions & 0 deletions librz/core/canalysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -1487,10 +1487,24 @@ static bool is_skippable_addr(RzCore *core, ut64 addr) {
if (fcn->addr == addr) {
return true;
}
if (ht_up_find(core->analysis->exception_scopes_ht, addr, NULL)) {
return false;
}
const RzList *flags = rz_flag_get_list(core->flags, addr);
return !(flags && rz_list_find(flags, fcn, find_sym_flag, NULL));
}

static bool analyze_exception_source(void *user, const ut64 key, const void *value) {
RzCore *core = user;
const RzList *scopes = value;
RzListIter *it;
RzBinTrycatch *trycatch;
rz_list_foreach (scopes, it, trycatch) {
rz_core_analysis_fcn(core, trycatch->source, UT64_MAX, RZ_ANALYSIS_XREF_TYPE_NULL, core->analysis->opt.depth);
}
return true;
}

// XXX: This function takes sometimes forever
/* analyze a RzAnalysisFunction at the address 'at'.
* If the function has been already analyzed, it adds a
Expand Down Expand Up @@ -4003,8 +4017,17 @@ RZ_API bool rz_core_analysis_everything(RzCore *core, bool experimental, char *d
return false;
}

if (core->analysis->exception_scopes_ht->count) {
notify = "Analyze exception sources as functions";
rz_core_notify_begin(core, "%s", notify);
ht_up_foreach(core->analysis->exception_scopes_ht, analyze_exception_source, core);
rz_core_notify_done(core, "%s", notify);
rz_core_task_yield(&core->tasks);
}

notify = "Analyze function calls";
rz_core_notify_begin(core, "%s", notify);
rz_core_analysis_calls(core, false); // "aac"
(void)rz_core_analysis_calls(core, false); // "aac"
Comment on lines +4030 to 4031
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

rz_core_seek(core, curseek, true);
rz_core_notify_done(core, "%s", notify);
Expand Down
Loading
Loading