diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index 38ee46cbc9..4142871955 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -741,7 +741,25 @@ R_API void r_anal_fcn_fit_overlaps (RAnal *anal, RAnalFunction *fcn) { } } +static int cmpaddr (const void *_a, const void *_b) { + const RAnalBlock *a = _a, *b = _b; + return (a->addr > b->addr); +} + +void r_anal_trim_jmprefs(RAnalFunction *fcn) { + RAnalRef *ref; + RListIter *iter; + r_list_foreach (fcn->refs, iter, ref) { + if (ref->type == R_ANAL_REF_TYPE_CODE && + ref->addr >= fcn->addr && (ref->addr - fcn->addr) < fcn->size) { + r_list_delete(fcn->refs, iter); + } + } +} + R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int reftype) { + int ret; + fcn->size = 0; fcn->type = (reftype==R_ANAL_REF_TYPE_CODE)? R_ANAL_FCN_TYPE_LOC: R_ANAL_FCN_TYPE_FCN; @@ -750,7 +768,34 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 int result = anal->cur->fcn (anal, fcn, addr, buf, len, reftype); if (anal->cur->custom_fn_anal) return result; } - return fcn_recurse (anal, fcn, addr, buf, len, FCN_DEPTH); + ret = fcn_recurse (anal, fcn, addr, buf, len, FCN_DEPTH); + + if (ret == R_ANAL_RET_END && fcn->size) { // cfg analysis completed + RListIter *iter; + RAnalBlock *bb; + ut64 endaddr = fcn->addr; + ut64 overlapped = -1; + RAnalFunction *fcn1 = NULL; + + // set function size as length of continuous sequence of bbs + r_list_sort (fcn->bbs, &cmpaddr); + r_list_foreach (fcn->bbs, iter, bb) { + if (endaddr != bb->addr) break; + endaddr += bb->size; + } + r_anal_fcn_resize(fcn, endaddr - fcn->addr); + + // resize function if overlaps + r_list_foreach (anal->fcns, iter, fcn1) { + if (fcn1->addr >= (fcn->addr) && + fcn1->addr < (fcn->addr + fcn->size)) + if (overlapped > fcn1->addr) + overlapped = fcn1->addr; + } + if (overlapped != -1) r_anal_fcn_resize (fcn, overlapped - fcn->addr); + r_anal_trim_jmprefs(fcn); + } + return ret; } // TODO: need to implement r_anal_fcn_remove(RAnal *anal, RAnalFunction *fcn); diff --git a/libr/core/anal.c b/libr/core/anal.c index d700720883..d884c39c0a 100644 --- a/libr/core/anal.c +++ b/libr/core/anal.c @@ -205,11 +205,6 @@ R_API char *r_core_anal_fcn_autoname(RCore *core, ut64 addr, int dump) { return NULL; } -static int cmpaddr (const void *_a, const void *_b) { - const RAnalBlock *a = _a, *b = _b; - return (a->addr > b->addr); -} - static int iscodesection(RCore *core, ut64 addr) { RIOSection *s = r_io_section_vget (core->io, addr); return (s && s->rwx & R_IO_EXEC)? 1: 0; @@ -233,17 +228,6 @@ static void r_anal_set_stringrefs(RCore *core, RAnalFunction *fcn) { } } -void r_anal_trim_jmprefs(RAnalFunction *fcn) { - RAnalRef *ref; - RListIter *iter; - r_list_foreach (fcn->refs, iter, ref) { - if (ref->type == R_ANAL_REF_TYPE_CODE && - ref->addr >= fcn->addr && (ref->addr - fcn->addr) < fcn->size) { - r_list_delete(fcn->refs, iter); - } - } -} - static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth) { int has_next = r_config_get_i (core->config, "anal.hasnext"); RAnalFunction *fcn; @@ -320,19 +304,6 @@ static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth (fcnlen == R_ANAL_RET_END && fcn->size < 1)) { /* Error analyzing function */ goto error; } else if (fcnlen == R_ANAL_RET_END) { /* Function analysis complete */ - // resize function if overlaps - ut64 overlapped = -1; - RAnalFunction *fcn1 = NULL; - RListIter *iter1; - r_list_foreach (core->anal->fcns, iter1, fcn1) { - if (fcn1->addr >= (fcn->addr) && - fcn1->addr < (fcn->addr + fcn->size)) - if (overlapped > fcn1->addr) - overlapped = fcn1->addr; - } - if (overlapped != -1) r_anal_fcn_resize (fcn, overlapped - fcn->addr); - r_anal_trim_jmprefs(fcn); - f = r_flag_get_i2 (core->flags, fcn->addr); free (fcn->name); if (f) { /* Check if it's already flagged */ @@ -358,7 +329,6 @@ static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth } else { fcn->depth = 256 - fcn->depth; } - r_list_sort (fcn->bbs, &cmpaddr); /* New function: Add initial xref */ if (from != UT64_MAX) {