Refactor RAnal Basic Blocks and Functions (#15169) ##anal
Basic Blocks are now global instead of owned by a single function.
This commit is contained in:
parent
5bb7e28ad4
commit
14215350af
|
@ -28,14 +28,14 @@ plugins: ${LIBSO} ${LIBAR}
|
|||
include ${STATIC_ANAL_PLUGINS}
|
||||
|
||||
STATIC_OBJS=$(addprefix $(LTOP)/anal/p/,$(STATIC_OBJ))
|
||||
OBJLIBS=meta.o reflines.o op.o fcn.o bb.o var.o
|
||||
OBJLIBS=meta.o reflines.o op.o fcn.o bb.o var.o block.o
|
||||
OBJLIBS+=cond.o value.o cc.o class.o diff.o type.o
|
||||
OBJLIBS+=hint.o anal.o data.o xrefs.o esil.o sign.o
|
||||
OBJLIBS+=anal_ex.o switch.o state.o cycles.o esil_dfg.o
|
||||
OBJLIBS+=esil_sources.o esil_interrupt.o esil_cfg.o
|
||||
OBJLIBS+=esil_stats.o esil_trace.o flirt.o labels.o
|
||||
OBJLIBS+=esil2reil.o pin.o session.o vtable.o rtti.o
|
||||
OBJLIBS+=rtti_msvc.o rtti_itanium.o jmptbl.o
|
||||
OBJLIBS+=rtti_msvc.o rtti_itanium.o jmptbl.o function.o
|
||||
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/xtensa-modules.o
|
||||
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/xtensa-isa.o
|
||||
ASMOBJS+=$(LTOP)/asm/arch/xtensa/gnu/elf32-xtensa.o
|
||||
|
|
|
@ -126,10 +126,11 @@ R_API RAnal *r_anal_new(void) {
|
|||
free (anal);
|
||||
return NULL;
|
||||
}
|
||||
anal->bb_tree = NULL;
|
||||
anal->ht_addr_fun = ht_up_new0 ();
|
||||
anal->ht_name_fun = ht_pp_new0 ();
|
||||
anal->os = strdup (R_SYS_OS);
|
||||
anal->reflines = NULL;
|
||||
anal->esil_goto_limit = R_ANAL_ESIL_GOTO_LIMIT;
|
||||
anal->limit = NULL;
|
||||
anal->opt.nopskip = true; // skip nops in code analysis
|
||||
anal->opt.hpskip = false; // skip `mov reg,reg` and `lea reg,[reg]`
|
||||
anal->gp = 0LL;
|
||||
|
@ -169,8 +170,7 @@ R_API RAnal *r_anal_new(void) {
|
|||
anal->stackptr = 0;
|
||||
anal->rb_hints_ranges = NULL;
|
||||
anal->lineswidth = 0;
|
||||
anal->fcns = r_anal_fcn_list_new ();
|
||||
anal->fcn_tree = NULL;
|
||||
anal->fcns = r_list_newf (r_anal_function_free);
|
||||
anal->fcn_addr_tree = NULL;
|
||||
anal->refs = r_anal_ref_list_new ();
|
||||
anal->leaddrs = NULL;
|
||||
|
@ -192,18 +192,22 @@ R_API void r_anal_plugin_free (RAnalPlugin *p) {
|
|||
}
|
||||
}
|
||||
|
||||
void __block_free_rb(RBNode *node, void *user);
|
||||
|
||||
R_API RAnal *r_anal_free(RAnal *a) {
|
||||
if (!a) {
|
||||
return NULL;
|
||||
}
|
||||
/* TODO: Free anals here */
|
||||
r_list_free (a->fcns);
|
||||
ht_up_free (a->ht_addr_fun);
|
||||
ht_pp_free (a->ht_name_fun);
|
||||
set_u_free (a->visited);
|
||||
free (a->cpu);
|
||||
free (a->os);
|
||||
free (a->zign_path);
|
||||
r_list_free (a->plugins);
|
||||
a->fcns->free = r_anal_fcn_free;
|
||||
r_list_free (a->fcns);
|
||||
r_rbtree_free (a->bb_tree, __block_free_rb, NULL);
|
||||
r_spaces_fini (&a->meta_spaces);
|
||||
r_spaces_fini (&a->zign_spaces);
|
||||
r_anal_pin_fini (a);
|
||||
|
@ -489,8 +493,7 @@ R_API int r_anal_purge (RAnal *anal) {
|
|||
sdb_reset (anal->sdb_classes);
|
||||
sdb_reset (anal->sdb_classes_attrs);
|
||||
r_list_free (anal->fcns);
|
||||
anal->fcns = r_anal_fcn_list_new ();
|
||||
anal->fcn_tree = NULL;
|
||||
anal->fcns = r_list_newf (r_anal_function_free);
|
||||
anal->fcn_addr_tree = NULL;
|
||||
r_list_free (anal->refs);
|
||||
anal->refs = r_anal_ref_list_new ();
|
||||
|
@ -707,7 +710,7 @@ R_API bool r_anal_noreturn_at(RAnal *anal, ut64 addr) {
|
|||
return true;
|
||||
}
|
||||
/* XXX this is very slow */
|
||||
RAnalFunction *f = r_anal_get_fcn_at (anal, addr, 0);
|
||||
RAnalFunction *f = r_anal_get_function_at (anal, addr);
|
||||
if (f) {
|
||||
if (r_anal_noreturn_at_name (anal, f->name)) {
|
||||
return true;
|
||||
|
|
|
@ -139,18 +139,17 @@ R_API RAnalBlock * r_anal_ex_get_bb(RAnal *anal, RAnalState *state, ut64 addr) {
|
|||
if (!op || !r_anal_state_addr_is_valid (state, addr)) {
|
||||
return NULL;
|
||||
}
|
||||
current_bb = r_anal_bb_new ();
|
||||
current_bb = r_anal_ex_op_to_bb (anal, state, op);
|
||||
if (!current_bb) {
|
||||
return NULL;
|
||||
}
|
||||
r_anal_ex_op_to_bb (anal, state, current_bb, op);
|
||||
if (!current_bb->op_bytes) {
|
||||
current_bb->op_sz = state->current_op->size;
|
||||
current_bb->op_bytes = malloc (current_bb->op_sz);
|
||||
if (current_bb->op_bytes) {
|
||||
int buf_len = r_anal_state_get_len (state, addr);
|
||||
if (current_bb->op_sz > buf_len) {
|
||||
r_anal_bb_free (current_bb);
|
||||
r_anal_block_unref (current_bb);
|
||||
return NULL;
|
||||
}
|
||||
memcpy (current_bb->op_bytes,
|
||||
|
@ -175,16 +174,17 @@ R_API RList* r_anal_ex_perform_analysis(RAnal *anal, RAnalState *state, ut64 add
|
|||
R_API RList* r_anal_ex_analysis_driver(RAnal *anal, RAnalState *state, ut64 addr ) {
|
||||
ut64 consumed_iter = 0;
|
||||
ut64 bytes_consumed = 0, len = r_anal_state_get_len (state, addr);
|
||||
RAnalBlock *pcurrent_bb = state->current_bb, *past_bb = NULL;
|
||||
RAnalBlock *past_bb = NULL;
|
||||
RAnalOp *pcurrent_op = state->current_op;
|
||||
ut64 backup_addr = state->current_addr;
|
||||
state->current_addr = addr;
|
||||
RList *bb_list = r_anal_bb_list_new ();
|
||||
bb_list->free = NULL; // avoid dblfree
|
||||
RList *bb_list = r_list_newf ((RListFree)r_anal_block_unref);
|
||||
|
||||
if (state->done) {
|
||||
return bb_list;
|
||||
}
|
||||
|
||||
RAnalBlock *prev_current_bb = state->current_bb;
|
||||
state->current_bb = NULL;
|
||||
state->current_op = NULL;
|
||||
|
||||
|
@ -194,9 +194,14 @@ R_API RList* r_anal_ex_analysis_driver(RAnal *anal, RAnalState *state, ut64 addr
|
|||
// check state for bb
|
||||
if (state->current_bb) {
|
||||
// TODO something special should happen here.
|
||||
r_anal_block_ref (state->current_bb);
|
||||
r_anal_ex_perform_revisit_bb_cb (anal, state, state->current_addr);
|
||||
consumed_iter += state->current_bb->op_sz;
|
||||
bytes_consumed += state->current_bb->op_sz;
|
||||
if (state->current_bb) {
|
||||
r_anal_block_unref (state->current_bb);
|
||||
state->current_bb = NULL;
|
||||
}
|
||||
if (state->done) {
|
||||
break;
|
||||
}
|
||||
|
@ -225,7 +230,10 @@ R_API RList* r_anal_ex_analysis_driver(RAnal *anal, RAnalState *state, ut64 addr
|
|||
//state->current_bb is shared in two list and one ht!!!
|
||||
//source of UAF this should be rewritten to avoid such errors
|
||||
r_anal_state_insert_bb (state, state->current_bb);
|
||||
|
||||
r_anal_block_ref (state->current_bb);
|
||||
r_list_append (bb_list, state->current_bb);
|
||||
|
||||
r_anal_ex_perform_post_anal_bb_cb (anal, state, state->current_addr);
|
||||
if (state->done) {
|
||||
break;
|
||||
|
@ -233,36 +241,42 @@ R_API RList* r_anal_ex_analysis_driver(RAnal *anal, RAnalState *state, ut64 addr
|
|||
if (state->current_bb) {
|
||||
bytes_consumed += state->current_bb->op_sz;
|
||||
consumed_iter += state->current_bb->op_sz;
|
||||
r_anal_block_unref (state->current_bb);
|
||||
state->current_bb = NULL;
|
||||
}
|
||||
state->current_addr = state->next_addr;
|
||||
r_anal_op_free (state->current_op);
|
||||
state->current_op = NULL;
|
||||
state->current_bb = NULL;
|
||||
if (!consumed_iter) {
|
||||
eprintf ("No bytes consumed, bailing!\n");
|
||||
break;
|
||||
}
|
||||
consumed_iter = 0;
|
||||
}
|
||||
|
||||
if (state->current_bb) {
|
||||
r_anal_block_unref (state->current_bb);
|
||||
}
|
||||
r_anal_op_free (state->current_op);
|
||||
r_anal_ex_perform_post_anal (anal, state, addr);
|
||||
state->current_op = pcurrent_op;
|
||||
state->current_bb = pcurrent_bb;
|
||||
state->current_bb = prev_current_bb;
|
||||
state->current_addr = backup_addr;
|
||||
return bb_list;
|
||||
}
|
||||
|
||||
R_API void r_anal_ex_op_to_bb(RAnal *anal, RAnalState *state, RAnalBlock *bb, RAnalOp *op) {
|
||||
//ut64 cnd_jmp = (R_ANAL_EX_COND_OP | R_ANAL_EX_CODEOP_JMP);
|
||||
bb->addr = op->addr;
|
||||
bb->size = op->size;
|
||||
bb->type2 = op->type2;
|
||||
bb->type = r_anal_ex_map_anal_ex_to_anal_bb_type ( op->type2 );
|
||||
bb->fail = op->fail;
|
||||
bb->jump = op->jump;
|
||||
|
||||
bb->conditional = R_ANAL_EX_COND_OP & op->type2 ? R_ANAL_OP_TYPE_COND : 0;
|
||||
r_anal_ex_clone_op_switch_to_bb (bb, op);
|
||||
R_API RAnalBlock *r_anal_ex_op_to_bb(RAnal *anal, RAnalState *state, RAnalOp *op) {
|
||||
RAnalBlock *block = r_anal_create_block (anal, op->addr, op->size);
|
||||
if (!block) {
|
||||
return NULL;
|
||||
}
|
||||
block->type2 = op->type2;
|
||||
block->type = r_anal_ex_map_anal_ex_to_anal_bb_type ( op->type2 );
|
||||
block->fail = op->fail;
|
||||
block->jump = op->jump;
|
||||
block->conditional = R_ANAL_EX_COND_OP & op->type2 ? R_ANAL_OP_TYPE_COND : 0;
|
||||
r_anal_ex_clone_op_switch_to_bb (block, op);
|
||||
return block;
|
||||
}
|
||||
|
||||
R_API ut64 r_anal_ex_map_anal_ex_to_anal_bb_type (ut64 ranal2_op_type) {
|
||||
|
|
|
@ -5,73 +5,42 @@
|
|||
#include <r_list.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define DFLT_NINSTR 3
|
||||
typedef struct {
|
||||
ut64 addr;
|
||||
RAnalBlock *ret;
|
||||
} BBFromOffsetJmpmidCtx;
|
||||
|
||||
R_API RAnalBlock *r_anal_bb_new() {
|
||||
RAnalBlock *bb = R_NEW0 (RAnalBlock);
|
||||
if (bb) {
|
||||
bb->addr = UT64_MAX;
|
||||
bb->jump = UT64_MAX;
|
||||
bb->fail = UT64_MAX;
|
||||
bb->type = R_ANAL_BB_TYPE_NULL;
|
||||
bb->op_pos = R_NEWS0 (ut16, DFLT_NINSTR);
|
||||
bb->op_pos_size = DFLT_NINSTR;
|
||||
bb->stackptr = 0;
|
||||
bb->parent_stackptr = INT_MAX;
|
||||
bb->cmpval = UT64_MAX;
|
||||
static bool bb_from_offset_jmpmid_cb(RAnalBlock *block, void *user) {
|
||||
BBFromOffsetJmpmidCtx *ctx = user;
|
||||
// If an instruction starts exactly at the search addr, return that block immediately
|
||||
if (r_anal_bb_op_starts_at (block, ctx->addr)) {
|
||||
ctx->ret = block;
|
||||
return false;
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
R_API void r_anal_bb_free(RAnalBlock *bb) {
|
||||
if (bb) {
|
||||
r_anal_cond_free (bb->cond);
|
||||
free (bb->fingerprint);
|
||||
r_anal_diff_free (bb->diff);
|
||||
free (bb->op_bytes);
|
||||
r_anal_switch_op_free (bb->switch_op);
|
||||
free (bb->label);
|
||||
free (bb->op_pos);
|
||||
free (bb->parent_reg_arena);
|
||||
free (bb);
|
||||
// else search the closest one
|
||||
if (!ctx->ret || ctx->ret->addr < block->addr) {
|
||||
ctx->ret = block;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RList *r_anal_bb_list_new() {
|
||||
return r_list_newf ((RListFree)r_anal_bb_free);
|
||||
}
|
||||
|
||||
R_API inline int r_anal_bb_is_in_offset (RAnalBlock *bb, ut64 off) {
|
||||
return (off >= bb->addr && off < bb->addr + bb->size);
|
||||
static bool bb_from_offset_first_cb(RAnalBlock *block, void *user) {
|
||||
RAnalBlock **ret = user;
|
||||
*ret = block;
|
||||
return false;
|
||||
}
|
||||
|
||||
R_API RAnalBlock *r_anal_bb_from_offset(RAnal *anal, ut64 off) {
|
||||
RListIter *iter, *iter2;
|
||||
RAnalFunction *fcn;
|
||||
RAnalBlock *bb;
|
||||
const bool x86 = anal->cur->arch && !strcmp (anal->cur->arch, "x86");
|
||||
if (anal->opt.jmpmid && x86) {
|
||||
RAnalBlock *nearest_bb = NULL;
|
||||
r_list_foreach (anal->fcns, iter, fcn) {
|
||||
r_list_foreach (fcn->bbs, iter2, bb) {
|
||||
if (r_anal_bb_op_starts_at (bb, off)) {
|
||||
return bb;
|
||||
} else if (r_anal_bb_is_in_offset (bb, off)
|
||||
&& (!nearest_bb || nearest_bb->addr < bb->addr)) {
|
||||
nearest_bb = bb;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nearest_bb;
|
||||
BBFromOffsetJmpmidCtx ctx = { off, NULL };
|
||||
r_anal_blocks_foreach_in (anal, off, bb_from_offset_jmpmid_cb, &ctx);
|
||||
return ctx.ret;
|
||||
}
|
||||
r_list_foreach (anal->fcns, iter, fcn) {
|
||||
r_list_foreach (fcn->bbs, iter2, bb) {
|
||||
if (r_anal_bb_is_in_offset (bb, off)) {
|
||||
return bb;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
RAnalBlock *ret = NULL;
|
||||
r_anal_blocks_foreach_in (anal, off, bb_from_offset_first_cb, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API RAnalBlock *r_anal_bb_get_jumpbb(RAnalFunction *fcn, RAnalBlock *bb) {
|
||||
|
@ -156,7 +125,7 @@ R_API ut64 r_anal_bb_opaddr_at(RAnalBlock *bb, ut64 off) {
|
|||
ut16 delta, delta_off, last_delta;
|
||||
int i;
|
||||
|
||||
if (!r_anal_bb_is_in_offset (bb, off)) {
|
||||
if (!r_anal_block_contains (bb, off)) {
|
||||
return UT64_MAX;
|
||||
}
|
||||
last_delta = 0;
|
||||
|
@ -176,7 +145,7 @@ R_API ut64 r_anal_bb_opaddr_at(RAnalBlock *bb, ut64 off) {
|
|||
R_API bool r_anal_bb_op_starts_at(RAnalBlock *bb, ut64 addr) {
|
||||
int i;
|
||||
|
||||
if (!r_anal_bb_is_in_offset (bb, addr)) {
|
||||
if (!r_anal_block_contains (bb, addr)) {
|
||||
return false;
|
||||
}
|
||||
ut16 off = addr - bb->addr;
|
||||
|
|
|
@ -0,0 +1,462 @@
|
|||
/* radare - LGPL - Copyright 2019 - pancake, thestr4ng3r */
|
||||
|
||||
#include <r_anal.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define unwrap(rbnode) container_of (rbnode, RAnalBlock, _rb)
|
||||
|
||||
static void __max_end(RBNode *node) {
|
||||
RAnalBlock *block = unwrap (node);
|
||||
block->_max_end = block->addr + block->size;
|
||||
int i;
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (node->child[i]) {
|
||||
ut64 end = unwrap (node->child[i])->_max_end;
|
||||
if (end > block->_max_end) {
|
||||
block->_max_end = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __bb_addr_cmp(const void *incoming, const RBNode *in_tree, void *user) {
|
||||
ut64 incoming_addr = *(ut64 *)incoming;
|
||||
const RAnalBlock *in_tree_block = container_of (in_tree, const RAnalBlock, _rb);
|
||||
if (incoming_addr < in_tree_block->addr) {
|
||||
return -1;
|
||||
}
|
||||
if (incoming_addr > in_tree_block->addr) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define D if (anal && anal->verbose)
|
||||
|
||||
R_API void r_anal_block_ref(RAnalBlock *bb) {
|
||||
assert (bb->ref > 0); // 0-refd must already be freed.
|
||||
bb->ref++;
|
||||
}
|
||||
|
||||
|
||||
#define DFLT_NINSTR 3
|
||||
|
||||
static RAnalBlock *block_new(RAnal *a, ut64 addr, ut64 size) {
|
||||
RAnalBlock *block = R_NEW0 (RAnalBlock);
|
||||
if (!block) {
|
||||
return NULL;
|
||||
}
|
||||
block->addr = addr;
|
||||
block->size = size;
|
||||
block->anal = a;
|
||||
block->ref = 1;
|
||||
block->jump = UT64_MAX;
|
||||
block->fail = UT64_MAX;
|
||||
block->type = R_ANAL_BB_TYPE_NULL;
|
||||
block->op_pos = R_NEWS0 (ut16, DFLT_NINSTR);
|
||||
block->op_pos_size = DFLT_NINSTR;
|
||||
block->stackptr = 0;
|
||||
block->parent_stackptr = INT_MAX;
|
||||
block->cmpval = UT64_MAX;
|
||||
block->fcns = r_list_new ();
|
||||
return block;
|
||||
}
|
||||
|
||||
static void block_free(RAnalBlock *block) {
|
||||
if (!block) {
|
||||
return;
|
||||
}
|
||||
r_anal_cond_free (block->cond);
|
||||
free (block->fingerprint);
|
||||
r_anal_diff_free (block->diff);
|
||||
free (block->op_bytes);
|
||||
r_anal_switch_op_free (block->switch_op);
|
||||
r_list_free (block->fcns);
|
||||
free (block->label);
|
||||
free (block->op_pos);
|
||||
free (block->parent_reg_arena);
|
||||
free (block);
|
||||
}
|
||||
|
||||
void __block_free_rb(RBNode *node, void *user) {
|
||||
RAnalBlock *block = unwrap (node);
|
||||
block_free (block);
|
||||
}
|
||||
|
||||
R_API RAnalBlock *r_anal_get_block_at(RAnal *anal, ut64 addr) {
|
||||
RBNode *node = r_rbtree_find (anal->bb_tree, &addr, __bb_addr_cmp, NULL);
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
return unwrap (node);
|
||||
}
|
||||
|
||||
// This is a special case of what r_interval_node_all_in() does
|
||||
static bool all_in(RAnalBlock *node, ut64 addr, RAnalBlockCb cb, void *user) {
|
||||
while (node && addr < node->addr) {
|
||||
// less than the current node, but might still be contained further down
|
||||
node = unwrap (node->_rb.child[0]);
|
||||
}
|
||||
if (!node) {
|
||||
return true;
|
||||
}
|
||||
if (addr >= node->_max_end) {
|
||||
return true;
|
||||
}
|
||||
if (addr < node->addr + node->size) {
|
||||
if (!cb (node, user)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// This can be done more efficiently by building the stack manually
|
||||
if (!all_in (unwrap (node->_rb.child[0]), addr, cb, user)) {
|
||||
return false;
|
||||
}
|
||||
if (!all_in (unwrap (node->_rb.child[1]), addr, cb, user)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API bool r_anal_blocks_foreach_in(RAnal *anal, ut64 addr, RAnalBlockCb cb, void *user) {
|
||||
return all_in (anal->bb_tree ? unwrap (anal->bb_tree) : NULL, addr, cb, user);
|
||||
}
|
||||
|
||||
static bool block_list_cb(RAnalBlock *block, void *user) {
|
||||
RList *list = user;
|
||||
r_anal_block_ref (block);
|
||||
r_list_push (list, block);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RList *r_anal_get_blocks_in(RAnal *anal, ut64 addr) {
|
||||
RList *list = r_list_newf ((RListFree)r_anal_block_unref);
|
||||
if (!list) {
|
||||
return NULL;
|
||||
}
|
||||
r_anal_blocks_foreach_in (anal, addr, block_list_cb, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
static void all_intersect(RAnalBlock *node, ut64 addr, ut64 size, RAnalBlockCb cb, void *user) {
|
||||
ut64 end = addr + size;
|
||||
while (node && end <= node->addr) {
|
||||
// less than the current node, but might still be contained further down
|
||||
node = unwrap (node->_rb.child[0]);
|
||||
}
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
if (addr >= node->_max_end) {
|
||||
return;
|
||||
}
|
||||
if (addr < node->addr + node->size) {
|
||||
cb (node, user);
|
||||
}
|
||||
// This can be done more efficiently by building the stack manually
|
||||
all_intersect (unwrap (node->_rb.child[0]), addr, size, cb, user);
|
||||
all_intersect (unwrap (node->_rb.child[1]), addr, size, cb, user);
|
||||
}
|
||||
|
||||
R_API void r_anal_blocks_foreach_intersect(RAnal *anal, ut64 addr, ut64 size, RAnalBlockCb cb, void *user) {
|
||||
all_intersect (anal->bb_tree ? unwrap (anal->bb_tree) : NULL, addr, size, cb, user);
|
||||
}
|
||||
|
||||
R_API RList *r_anal_get_blocks_intersect(RAnal *anal, ut64 addr, ut64 size) {
|
||||
RList *list = r_list_newf ((RListFree)r_anal_block_unref);
|
||||
if (!list) {
|
||||
return NULL;
|
||||
}
|
||||
r_anal_blocks_foreach_intersect (anal, addr, size, block_list_cb, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
R_API RAnalBlock *r_anal_create_block(RAnal *anal, ut64 addr, ut64 size) {
|
||||
if (r_anal_get_block_at (anal, addr)) {
|
||||
return NULL;
|
||||
}
|
||||
RAnalBlock *block = block_new (anal, addr, size);
|
||||
if (!block) {
|
||||
return NULL;
|
||||
}
|
||||
r_rbtree_aug_insert (&anal->bb_tree, &block->addr, &block->_rb, __bb_addr_cmp, NULL, __max_end);
|
||||
return block;
|
||||
}
|
||||
|
||||
R_API void r_anal_delete_block(RAnalBlock *bb) {
|
||||
r_anal_block_ref (bb);
|
||||
while (!r_list_empty (bb->fcns)) {
|
||||
r_anal_function_remove_block (r_list_first (bb->fcns), bb);
|
||||
}
|
||||
r_anal_block_unref (bb);
|
||||
}
|
||||
|
||||
R_API void r_anal_block_set_size(RAnalBlock *block, ut64 size) {
|
||||
if (block->size == size) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the block's function's cached ranges
|
||||
RAnalFunction *fcn;
|
||||
RListIter *iter;
|
||||
r_list_foreach (block->fcns, iter, fcn) {
|
||||
if (fcn->meta._min != UT64_MAX && fcn->meta._max == block->addr + block->size) {
|
||||
fcn->meta._max = block->addr + size;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the actual resize
|
||||
block->size = size;
|
||||
r_rbtree_aug_update_sum (block->anal->bb_tree, &block->addr, &block->_rb, __bb_addr_cmp, NULL, __max_end);
|
||||
}
|
||||
|
||||
R_API bool r_anal_block_relocate(RAnalBlock *block, ut64 addr, ut64 size) {
|
||||
if (block->addr == addr) {
|
||||
r_anal_block_set_size (block, size);
|
||||
return true;
|
||||
}
|
||||
if (r_anal_get_block_at (block->anal, addr)) {
|
||||
// Two blocks at the same addr is illegle you know...
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the block's function's cached ranges
|
||||
RAnalFunction *fcn;
|
||||
RListIter *iter;
|
||||
r_list_foreach (block->fcns, iter, fcn) {
|
||||
if (fcn->meta._min != UT64_MAX) {
|
||||
if (addr + size > fcn->meta._max) {
|
||||
// we extend after the maximum, so we are the maximum afterwards.
|
||||
fcn->meta._max = addr + size;
|
||||
} else if (block->addr + block->size == fcn->meta._max && addr + size != block->addr + block->size) {
|
||||
// we were the maximum before and may not be it afterwards, not trivial to recalculate.
|
||||
fcn->meta._min = UT64_MAX;
|
||||
continue;
|
||||
}
|
||||
if (block->addr < fcn->meta._min) {
|
||||
// less than the minimum, we know that we are the minimum afterwards.
|
||||
fcn->meta._min = addr;
|
||||
} else if (block->addr == fcn->meta._min && addr != block->addr) {
|
||||
// we were the minimum before and may not be it afterwards, not trivial to recalculate.
|
||||
fcn->meta._min = UT64_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_rbtree_aug_delete (&block->anal->bb_tree, &block->addr, __bb_addr_cmp, NULL, NULL, NULL, __max_end);
|
||||
block->addr = addr;
|
||||
block->size = size;
|
||||
r_rbtree_aug_insert (&block->anal->bb_tree, &block->addr, &block->_rb, __bb_addr_cmp, NULL, __max_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RAnalBlock *r_anal_block_split(RAnalBlock *bbi, ut64 addr) {
|
||||
RAnal *anal = bbi->anal;
|
||||
r_return_val_if_fail (bbi && addr >= bbi->addr && addr < bbi->addr + bbi->size && addr != UT64_MAX, 0);
|
||||
if (addr == bbi->addr) {
|
||||
r_anal_block_ref (bbi); // ref to be consistent with splitted return refcount
|
||||
return bbi;
|
||||
}
|
||||
|
||||
if (r_anal_get_block_at (bbi->anal, addr)) {
|
||||
// can't have two bbs at the same addr
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// create the second block
|
||||
RAnalBlock *bb = block_new (anal, addr, bbi->addr + bbi->size - addr);
|
||||
if (!bb) {
|
||||
return NULL;
|
||||
}
|
||||
bb->jump = bbi->jump;
|
||||
bb->fail = bbi->fail;
|
||||
bb->conditional = bbi->conditional;
|
||||
bb->parent_stackptr = bbi->stackptr;
|
||||
|
||||
// resize the first block
|
||||
r_anal_block_set_size (bbi, addr - bbi->addr);
|
||||
bbi->jump = addr;
|
||||
bbi->fail = UT64_MAX;
|
||||
bbi->conditional = false;
|
||||
|
||||
// insert the second block into the tree
|
||||
r_rbtree_aug_insert (&anal->bb_tree, &bb->addr, &bb->_rb, __bb_addr_cmp, NULL, __max_end);
|
||||
|
||||
// insert the second block into all functions of the first
|
||||
RListIter *iter;
|
||||
RAnalFunction *fcn;
|
||||
r_list_foreach (bbi->fcns, iter, fcn) {
|
||||
r_anal_function_add_block (fcn, bb);
|
||||
}
|
||||
|
||||
// recalculate offset of instructions in both bb and bbi
|
||||
int i;
|
||||
i = 0;
|
||||
while (i < bbi->ninstr && r_anal_bb_offset_inst (bbi, i) < bbi->size) {
|
||||
i++;
|
||||
}
|
||||
int new_bbi_instr = i;
|
||||
if (bb->addr - bbi->addr == r_anal_bb_offset_inst (bbi, i)) {
|
||||
bb->ninstr = 0;
|
||||
while (i < bbi->ninstr) {
|
||||
ut16 off_op = r_anal_bb_offset_inst (bbi, i);
|
||||
if (off_op >= bbi->size + bb->size) {
|
||||
break;
|
||||
}
|
||||
r_anal_bb_set_offset (bb, bb->ninstr, off_op - bbi->size);
|
||||
bb->ninstr++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
bbi->ninstr = new_bbi_instr;
|
||||
return bb;
|
||||
}
|
||||
|
||||
R_API bool r_anal_block_merge(RAnalBlock *a, RAnalBlock *b) {
|
||||
if (a->addr + a->size != b->addr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if function lists are identical
|
||||
if (r_list_length (a->fcns) != r_list_length (b->fcns)) {
|
||||
return false;
|
||||
}
|
||||
RAnalFunction *fcn;
|
||||
RListIter *iter;
|
||||
r_list_foreach (a->fcns, iter, fcn) {
|
||||
if (!r_list_contains (b->fcns, fcn)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep a ref to b, but remove all references of b from its functions
|
||||
r_anal_block_ref (b);
|
||||
while (!r_list_empty (b->fcns)) {
|
||||
r_anal_function_remove_block (r_list_first (b->fcns), b);
|
||||
}
|
||||
|
||||
// merge ops from b into a
|
||||
size_t i;
|
||||
for (i = 0; i < b->ninstr; i++) {
|
||||
r_anal_bb_set_offset (a, a->ninstr++, a->size + r_anal_bb_offset_inst (b, i));
|
||||
}
|
||||
|
||||
// merge everything else into a
|
||||
a->size += b->size;
|
||||
a->jump = b->jump;
|
||||
a->fail = b->fail;
|
||||
|
||||
// kill b completely
|
||||
r_rbtree_aug_delete (&a->anal->bb_tree, &b->addr, __bb_addr_cmp, NULL, __block_free_rb, NULL, __max_end);
|
||||
|
||||
// invalidate ranges of a's functions
|
||||
r_list_foreach (a->fcns, iter, fcn) {
|
||||
fcn->meta._min = UT64_MAX;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_anal_block_unref(RAnalBlock *bb) {
|
||||
assert (bb->ref > 0);
|
||||
bb->ref--;
|
||||
assert (bb->ref >= r_list_length (bb->fcns)); // all of the block's functions must hold a reference to it
|
||||
if (bb->ref < 1) {
|
||||
RAnal *anal = bb->anal;
|
||||
assert (!bb->fcns || r_list_empty (bb->fcns));
|
||||
r_rbtree_aug_delete (&anal->bb_tree, &bb->addr, __bb_addr_cmp, NULL, __block_free_rb, NULL, __max_end);
|
||||
}
|
||||
}
|
||||
|
||||
typedef bool (*RAnalBlockCb)(RAnalBlock *block, void *user);
|
||||
typedef bool (*RAnalAddrCb)(ut64 addr, void *user);
|
||||
|
||||
R_API bool r_anal_block_successor_addrs_foreach(RAnalBlock *block, RAnalAddrCb cb, void *user) {
|
||||
#define CB_ADDR(addr) do { \
|
||||
if (addr == UT64_MAX) { \
|
||||
break; \
|
||||
} \
|
||||
if (!cb (addr, user)) { \
|
||||
return false; \
|
||||
} \
|
||||
} while(0);
|
||||
|
||||
CB_ADDR (block->jump);
|
||||
CB_ADDR (block->fail);
|
||||
if (block->switch_op && block->switch_op->cases) {
|
||||
RListIter *iter;
|
||||
RAnalCaseOp *caseop;
|
||||
r_list_foreach (block->switch_op->cases, iter, caseop) {
|
||||
CB_ADDR (caseop->jump);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#undef CB_ADDR
|
||||
}
|
||||
|
||||
typedef struct r_anal_block_recurse_context_t {
|
||||
RAnal *anal;
|
||||
RPVector/*<RAnalBlock>*/ to_visit;
|
||||
HtUP *visited;
|
||||
} RAnalBlockRecurseContext;
|
||||
|
||||
static bool block_recurse_successor_cb(ut64 addr, void *user) {
|
||||
RAnalBlockRecurseContext *ctx = user;
|
||||
if (ht_up_find_kv (ctx->visited, addr, NULL)) {
|
||||
// already visited
|
||||
return true;
|
||||
}
|
||||
ht_up_insert (ctx->visited, addr, NULL);
|
||||
RAnalBlock *block = r_anal_get_block_at (ctx->anal, addr);
|
||||
if (!block) {
|
||||
return true;
|
||||
}
|
||||
r_pvector_push (&ctx->to_visit, block);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API bool r_anal_block_recurse(RAnalBlock *block, RAnalBlockCb cb, void *user) {
|
||||
bool breaked = false;
|
||||
RAnalBlockRecurseContext ctx;
|
||||
ctx.anal = block->anal;
|
||||
r_pvector_init (&ctx.to_visit, NULL);
|
||||
ctx.visited = ht_up_new0 ();
|
||||
if (!ctx.visited) {
|
||||
goto beach;
|
||||
}
|
||||
|
||||
ht_up_insert (ctx.visited, block->addr, NULL);
|
||||
r_pvector_push (&ctx.to_visit, block);
|
||||
|
||||
while (!r_pvector_empty (&ctx.to_visit)) {
|
||||
RAnalBlock *cur = r_pvector_pop (&ctx.to_visit);
|
||||
breaked = !cb (cur, user);
|
||||
if (breaked) {
|
||||
break;
|
||||
}
|
||||
r_anal_block_successor_addrs_foreach (cur, block_recurse_successor_cb, &ctx);
|
||||
}
|
||||
|
||||
beach:
|
||||
ht_up_free (ctx.visited);
|
||||
r_pvector_clear (&ctx.to_visit);
|
||||
return !breaked;
|
||||
}
|
||||
|
||||
static bool recurse_list_cb(RAnalBlock *block, void *user) {
|
||||
RList *list = user;
|
||||
r_anal_block_ref (block);
|
||||
r_list_push (list, block);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RList *r_anal_block_recurse_list(RAnalBlock *block) {
|
||||
RList *ret = r_list_newf ((RListFree)r_anal_block_unref);
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
r_anal_block_recurse (block, recurse_list_cb, ret);
|
||||
return ret;
|
||||
}
|
|
@ -50,7 +50,6 @@ static const char *attr_type_id(RAnalClassAttrType attr_type) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
R_API void r_anal_class_create(RAnal *anal, const char *name) {
|
||||
char *name_sanitized = r_str_sanitize_sdb_key (name);
|
||||
if (!name_sanitized) {
|
||||
|
|
|
@ -201,8 +201,8 @@ R_API int r_anal_diff_fcn(RAnal *anal, RList *fcns, RList *fcns2) {
|
|||
R_FREE (fcn2->fingerprint);
|
||||
fcn->diff->addr = fcn2->addr;
|
||||
fcn2->diff->addr = fcn->addr;
|
||||
fcn->diff->size = r_anal_fcn_size (fcn2);
|
||||
fcn2->diff->size = r_anal_fcn_size (fcn);
|
||||
fcn->diff->size = r_anal_function_linear_size (fcn2);
|
||||
fcn2->diff->size = r_anal_function_linear_size (fcn);
|
||||
R_FREE (fcn->diff->name);
|
||||
if (fcn2->name) {
|
||||
fcn->diff->name = strdup (fcn2->name);
|
||||
|
@ -231,8 +231,8 @@ R_API int r_anal_diff_fcn(RAnal *anal, RList *fcns, RList *fcns2) {
|
|||
ot = 0;
|
||||
mfcn = mfcn2 = NULL;
|
||||
r_list_foreach (fcns2, iter2, fcn2) {
|
||||
int fcn_size = r_anal_fcn_size (fcn);
|
||||
int fcn2_size = r_anal_fcn_size (fcn2);
|
||||
ut64 fcn_size = r_anal_function_linear_size (fcn);
|
||||
ut64 fcn2_size = r_anal_function_linear_size (fcn2);
|
||||
if (fcn_size > fcn2_size) {
|
||||
maxsize = fcn_size;
|
||||
minsize = fcn2_size;
|
||||
|
@ -272,8 +272,8 @@ R_API int r_anal_diff_fcn(RAnal *anal, RList *fcns, RList *fcns2) {
|
|||
R_FREE (mfcn2->fingerprint);
|
||||
mfcn->diff->addr = mfcn2->addr;
|
||||
mfcn2->diff->addr = mfcn->addr;
|
||||
mfcn->diff->size = r_anal_fcn_size (mfcn2);
|
||||
mfcn2->diff->size = r_anal_fcn_size (mfcn);
|
||||
mfcn->diff->size = r_anal_function_linear_size (mfcn2);
|
||||
mfcn2->diff->size = r_anal_function_linear_size (mfcn);
|
||||
R_FREE (mfcn->diff->name);
|
||||
if (mfcn2->name) {
|
||||
mfcn->diff->name = strdup (mfcn2->name);
|
||||
|
|
923
libr/anal/fcn.c
923
libr/anal/fcn.c
File diff suppressed because it is too large
Load Diff
|
@ -557,7 +557,7 @@ static int module_match_buffer(RAnal *anal, const RFlirtModule *module,
|
|||
// Once the first module function is found, we need to go through the module->public_functions
|
||||
// list to identify the others. See flirt doc for more information
|
||||
|
||||
next_module_function = r_anal_get_fcn_at ((RAnal *) anal, address + flirt_func->offset, 0);
|
||||
next_module_function = r_anal_get_function_at ((RAnal *) anal, address + flirt_func->offset);
|
||||
if (next_module_function) {
|
||||
char *name;
|
||||
int name_offs = 0;
|
||||
|
@ -576,7 +576,7 @@ static int module_match_buffer(RAnal *anal, const RFlirtModule *module,
|
|||
next_flirt_func_it = next_flirt_func_it->n;
|
||||
}
|
||||
// resize function if needed
|
||||
next_module_function_size = r_anal_fcn_size (next_module_function);
|
||||
next_module_function_size = r_anal_function_linear_size (next_module_function);
|
||||
if (next_module_function_size < flirt_fcn_size) {
|
||||
RListIter *iter;
|
||||
RListIter *iter_tmp;
|
||||
|
@ -592,7 +592,7 @@ static int module_match_buffer(RAnal *anal, const RFlirtModule *module,
|
|||
}
|
||||
}
|
||||
r_anal_fcn_resize (anal, next_module_function, flirt_fcn_size);
|
||||
next_module_function_size = r_anal_fcn_size (next_module_function);
|
||||
next_module_function_size = r_anal_function_linear_size (next_module_function);
|
||||
r_anal_trim_jmprefs ((RAnal *)anal, next_module_function);
|
||||
}
|
||||
|
||||
|
@ -675,7 +675,7 @@ static int node_match_functions(RAnal *anal, const RFlirtNode *root_node) {
|
|||
continue;
|
||||
}
|
||||
|
||||
int func_size = r_anal_fcn_size (func);
|
||||
int func_size = r_anal_function_linear_size (func);
|
||||
func_buf = malloc (func_size);
|
||||
if (!anal->iob.read_at (anal->iob.io, func->addr, func_buf, func_size)) {
|
||||
eprintf ("Couldn't read function\n");
|
||||
|
|
|
@ -0,0 +1,334 @@
|
|||
/* radare - LGPL - Copyright 2019 - pancake, thestr4ng3r */
|
||||
|
||||
#include <r_anal.h>
|
||||
|
||||
#define D if (anal->verbose)
|
||||
#define ADDR_FCN_CONTAINER(x) container_of ((RBNode*)(x), RAnalFunction, addr_rb)
|
||||
|
||||
static int _fcn_addr_tree_cmp(const void *a_, const RBNode *b_, void *user) {
|
||||
const RAnalFunction *a = (const RAnalFunction *)a_;
|
||||
const RAnalFunction *b = ADDR_FCN_CONTAINER (b_);
|
||||
ut64 from0 = a->addr, from1 = b->addr;
|
||||
if (from0 != from1) {
|
||||
return from0 < from1 ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool _fcn_tree_delete(RAnal *anal, RAnalFunction *fcn) {
|
||||
r_return_val_if_fail (anal && fcn, false);
|
||||
return !!r_rbtree_delete (&anal->fcn_addr_tree, fcn, _fcn_addr_tree_cmp, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void _fcn_tree_insert(RAnal *anal, RAnalFunction *fcn) {
|
||||
r_rbtree_insert (&anal->fcn_addr_tree, fcn, &(fcn->addr_rb), _fcn_addr_tree_cmp, NULL);
|
||||
}
|
||||
|
||||
static bool get_functions_block_cb(RAnalBlock *block, void *user) {
|
||||
RList *list = user;
|
||||
RListIter *iter;
|
||||
RAnalFunction *fcn;
|
||||
r_list_foreach (block->fcns, iter, fcn) {
|
||||
if (r_list_contains (list, fcn)) {
|
||||
continue;
|
||||
}
|
||||
r_list_push (list, fcn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RList *r_anal_get_functions_in(RAnal *anal, ut64 addr) {
|
||||
RList *list = r_list_new ();
|
||||
if (!list) {
|
||||
return NULL;
|
||||
}
|
||||
r_anal_blocks_foreach_in (anal, addr, get_functions_block_cb, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
static bool __fcn_exists(RAnal *anal, const char *name, ut64 addr) {
|
||||
// check if name is already registered
|
||||
bool found = false;
|
||||
if (addr == UT64_MAX) {
|
||||
eprintf ("Invalid function address (-1) '%s'\n", name);
|
||||
return true;
|
||||
}
|
||||
if (!name) {
|
||||
eprintf ("TODO: Empty function name, we must auto generate one\n");
|
||||
return true;
|
||||
}
|
||||
RAnalFunction *f = ht_pp_find (anal->ht_name_fun, name, &found);
|
||||
if (f && found) {
|
||||
eprintf ("Invalid function name '%s' at 0x%08"PFMT64x"\n", name, addr);
|
||||
return true;
|
||||
}
|
||||
// check if there's a function already in the given address
|
||||
found = false;
|
||||
f = ht_up_find (anal->ht_addr_fun, addr, &found);
|
||||
if (f && found) {
|
||||
eprintf ("Function already defined in 0x%08"PFMT64x"\n", addr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
R_API RAnalFunction *r_anal_function_new(RAnal *anal) {
|
||||
RAnalFunction *fcn = R_NEW0 (RAnalFunction);
|
||||
if (!fcn) {
|
||||
return NULL;
|
||||
}
|
||||
fcn->anal = anal;
|
||||
/* Function qualifier: static/volatile/inline/naked/virtual */
|
||||
fcn->fmod = R_ANAL_FQUALIFIER_NONE;
|
||||
/* Function calling convention: cdecl/stdcall/fastcall/etc */
|
||||
/* Function attributes: weak/noreturn/format/etc */
|
||||
fcn->addr = UT64_MAX;
|
||||
fcn->cc = r_str_constpool_get (&anal->constpool, r_anal_cc_default (anal));
|
||||
fcn->bits = anal->bits;
|
||||
fcn->bbs = r_list_new ();
|
||||
fcn->diff = r_anal_diff_new ();
|
||||
fcn->has_changed = true;
|
||||
fcn->bp_frame = true;
|
||||
fcn->is_noreturn = false;
|
||||
fcn->meta._min = UT64_MAX;
|
||||
return fcn;
|
||||
}
|
||||
|
||||
R_API void r_anal_function_free(void *_fcn) {
|
||||
RAnalFunction *fcn = _fcn;
|
||||
if (!_fcn) {
|
||||
return;
|
||||
}
|
||||
|
||||
RAnalBlock *block;
|
||||
RListIter *iter;
|
||||
r_list_foreach (fcn->bbs, iter, block) {
|
||||
r_list_delete_data (block->fcns, fcn);
|
||||
r_anal_block_unref (block);
|
||||
}
|
||||
r_list_free (fcn->bbs);
|
||||
|
||||
RAnal *anal = fcn->anal;
|
||||
ht_up_delete (anal->ht_addr_fun, fcn->addr);
|
||||
ht_pp_delete (anal->ht_name_fun, fcn->name);
|
||||
_fcn_tree_delete (anal, fcn);
|
||||
|
||||
free (fcn->name);
|
||||
free (fcn->attr);
|
||||
r_list_free (fcn->fcn_locs);
|
||||
fcn->bbs = NULL;
|
||||
free (fcn->fingerprint);
|
||||
r_anal_diff_free (fcn->diff);
|
||||
free (fcn->args);
|
||||
free (fcn);
|
||||
}
|
||||
|
||||
R_API bool r_anal_add_function(RAnal *anal, RAnalFunction *fcn) {
|
||||
if (__fcn_exists (anal, fcn->name, fcn->addr)) {
|
||||
return false;
|
||||
}
|
||||
if (anal->cb.on_fcn_new) {
|
||||
anal->cb.on_fcn_new (anal, anal->user, fcn);
|
||||
}
|
||||
if (anal->flg_fcn_set) {
|
||||
anal->flg_fcn_set (anal->flb.f, fcn->name, fcn->addr, r_anal_function_size_from_entry (fcn));
|
||||
}
|
||||
_fcn_tree_insert (anal, fcn);
|
||||
r_list_append (anal->fcns, fcn);
|
||||
ht_pp_insert (anal->ht_name_fun, fcn->name, fcn);
|
||||
ht_up_insert (anal->ht_addr_fun, fcn->addr, fcn);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RAnalFunction *r_anal_create_function(RAnal *anal, const char *name, ut64 addr, int type, RAnalDiff *diff) {
|
||||
RAnalFunction *fcn = r_anal_function_new (anal);
|
||||
if (!fcn) {
|
||||
return NULL;
|
||||
}
|
||||
fcn->addr = addr;
|
||||
fcn->type = type;
|
||||
fcn->cc = r_str_constpool_get (&anal->constpool, r_anal_cc_default (anal));
|
||||
fcn->bits = anal->bits;
|
||||
if (name) {
|
||||
free (fcn->name);
|
||||
fcn->name = strdup (name);
|
||||
} else {
|
||||
const char *fcnprefix = anal->coreb.cfgGet ? anal->coreb.cfgGet (anal->coreb.core, "anal.fcnprefix") : NULL;
|
||||
if (!fcnprefix) {
|
||||
fcnprefix = "fcn";
|
||||
}
|
||||
fcn->name = r_str_newf ("%s.%08"PFMT64x, fcnprefix, fcn->addr);
|
||||
}
|
||||
if (diff) {
|
||||
fcn->diff->type = diff->type;
|
||||
fcn->diff->addr = diff->addr;
|
||||
R_FREE (fcn->diff->name);
|
||||
if (diff->name) {
|
||||
fcn->diff->name = strdup (diff->name);
|
||||
}
|
||||
}
|
||||
if (!r_anal_add_function (anal, fcn)) {
|
||||
r_anal_function_free (fcn);
|
||||
return NULL;
|
||||
}
|
||||
return fcn;
|
||||
}
|
||||
|
||||
R_API bool r_anal_function_delete(RAnalFunction *fcn) {
|
||||
return r_list_delete_data (fcn->anal->fcns, fcn);
|
||||
}
|
||||
|
||||
R_API RAnalFunction *r_anal_get_function_at(RAnal *anal, ut64 addr) {
|
||||
bool found = false;
|
||||
RAnalFunction *f = ht_up_find (anal->ht_addr_fun, addr, &found);
|
||||
if (f && found) {
|
||||
return f;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API bool r_anal_function_relocate(RAnalFunction *fcn, ut64 addr) {
|
||||
if (fcn->addr == addr) {
|
||||
return true;
|
||||
}
|
||||
if (r_anal_get_function_at (fcn->anal, addr)) {
|
||||
return false;
|
||||
}
|
||||
_fcn_tree_delete (fcn->anal, fcn);
|
||||
fcn->addr = addr;
|
||||
_fcn_tree_insert (fcn->anal, fcn);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API bool r_anal_function_rename(RAnalFunction *fcn, const char *name) {
|
||||
RAnal *anal = fcn->anal;
|
||||
RAnalFunction *existing = ht_pp_find (anal->ht_name_fun, name, NULL);
|
||||
if (existing) {
|
||||
if (existing == fcn) {
|
||||
// fcn->name == name, nothing to do
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
char *newname = strdup (name);
|
||||
if (!newname) {
|
||||
return false;
|
||||
}
|
||||
bool in_tree = ht_pp_delete (anal->ht_name_fun, fcn->name);
|
||||
free (fcn->name);
|
||||
fcn->name = newname;
|
||||
if (in_tree) {
|
||||
// only re-insert if it really was in the tree before
|
||||
ht_pp_insert (anal->ht_name_fun, fcn->name, fcn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_anal_function_add_block(RAnalFunction *fcn, RAnalBlock *bb) {
|
||||
if (r_list_contains (bb->fcns, fcn)) {
|
||||
return;
|
||||
}
|
||||
r_list_append (bb->fcns, fcn); // associate the given fcn with this bb
|
||||
r_anal_block_ref (bb);
|
||||
r_list_append (fcn->bbs, bb);
|
||||
|
||||
if (fcn->meta._min != UT64_MAX) {
|
||||
if (bb->addr + bb->size > fcn->meta._max) {
|
||||
fcn->meta._max = bb->addr + bb->size;
|
||||
}
|
||||
if (bb->addr < fcn->meta._min) {
|
||||
fcn->meta._min = bb->addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (fcn->anal->cb.on_fcn_bb_new) {
|
||||
fcn->anal->cb.on_fcn_bb_new (fcn->anal, fcn->anal->user, fcn, bb);
|
||||
}
|
||||
}
|
||||
|
||||
R_API void r_anal_function_remove_block(RAnalFunction *fcn, RAnalBlock *bb) {
|
||||
r_list_delete_data (bb->fcns, fcn);
|
||||
|
||||
if (fcn->meta._min != UT64_MAX
|
||||
&& (fcn->meta._min == bb->addr || fcn->meta._max == bb->addr + bb->size)) {
|
||||
// If a block is removed at the beginning or end, updating min/max is not trivial anymore, just invalidate
|
||||
fcn->meta._min = UT64_MAX;
|
||||
}
|
||||
|
||||
r_list_delete_data (fcn->bbs, bb);
|
||||
r_anal_block_unref (bb);
|
||||
}
|
||||
|
||||
static void ensure_fcn_range(RAnalFunction *fcn) {
|
||||
if (fcn->meta._min != UT64_MAX) { // recalculate only if invalid
|
||||
return;
|
||||
}
|
||||
ut64 minval = UT64_MAX;
|
||||
ut64 maxval = UT64_MIN;
|
||||
RAnalBlock *block;
|
||||
RListIter *iter;
|
||||
r_list_foreach (fcn->bbs, iter, block) {
|
||||
if (block->addr < minval) {
|
||||
minval = block->addr;
|
||||
}
|
||||
if (block->addr + block->size > maxval) {
|
||||
maxval = block->addr + block->size;
|
||||
}
|
||||
}
|
||||
fcn->meta._min = minval;
|
||||
fcn->meta._max = minval == UT64_MAX ? UT64_MAX : maxval;
|
||||
}
|
||||
|
||||
R_API ut64 r_anal_function_linear_size(RAnalFunction *fcn) {
|
||||
ensure_fcn_range (fcn);
|
||||
return fcn->meta._max - fcn->meta._min;
|
||||
}
|
||||
|
||||
R_API ut64 r_anal_function_min_addr(RAnalFunction *fcn) {
|
||||
ensure_fcn_range (fcn);
|
||||
return fcn->meta._min;
|
||||
}
|
||||
|
||||
R_API ut64 r_anal_function_max_addr(RAnalFunction *fcn) {
|
||||
ensure_fcn_range (fcn);
|
||||
return fcn->meta._max;
|
||||
}
|
||||
|
||||
R_API ut64 r_anal_function_size_from_entry(RAnalFunction *fcn) {
|
||||
ensure_fcn_range (fcn);
|
||||
return fcn->meta._min == UT64_MAX ? 0 : fcn->meta._max - fcn->addr;
|
||||
}
|
||||
|
||||
R_API ut64 r_anal_function_realsize(const RAnalFunction *fcn) {
|
||||
RListIter *iter, *fiter;
|
||||
RAnalBlock *bb;
|
||||
RAnalFunction *f;
|
||||
ut64 sz = 0;
|
||||
if (!sz) {
|
||||
r_list_foreach (fcn->bbs, iter, bb) {
|
||||
sz += bb->size;
|
||||
}
|
||||
r_list_foreach (fcn->fcn_locs, fiter, f) {
|
||||
r_list_foreach (f->bbs, iter, bb) {
|
||||
sz += bb->size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
static bool fcn_in_cb(RAnalBlock *block, void *user) {
|
||||
RListIter *iter;
|
||||
RAnalFunction *fcn;
|
||||
r_list_foreach (block->fcns, iter, fcn) {
|
||||
if (fcn == user) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API bool r_anal_function_contains(RAnalFunction *fcn, ut64 addr) {
|
||||
// fcn_in_cb breaks with false if it finds the fcn
|
||||
return !r_anal_blocks_foreach_in (fcn->anal, addr, fcn_in_cb, fcn);
|
||||
}
|
|
@ -2,6 +2,8 @@ r_anal_sources = [
|
|||
'anal.c',
|
||||
'anal_ex.c',
|
||||
'bb.c',
|
||||
'block.c',
|
||||
'function.c',
|
||||
'jmptbl.c',
|
||||
'cc.c',
|
||||
'class.c',
|
||||
|
|
|
@ -792,7 +792,7 @@ static int meta_print_item(void *user, const char *k, const char *v) {
|
|||
if (!meta_deserialize (ui->anal, &it, k, v)) {
|
||||
return 1;
|
||||
}
|
||||
if (ui->fcn && !r_anal_fcn_in (ui->fcn, it.from)) {
|
||||
if (ui->fcn && !r_anal_function_contains (ui->fcn, it.from)) {
|
||||
goto beach;
|
||||
}
|
||||
if (!it.str) {
|
||||
|
@ -963,7 +963,7 @@ static int get_meta_size(void *user, const char *k, const char *v) {
|
|||
if (!meta_deserialize (ui->anal, &it, k, v)) {
|
||||
return -1;
|
||||
}
|
||||
if (ui->fcn && !r_anal_fcn_in (ui->fcn, it.from)) {
|
||||
if (ui->fcn && !r_anal_function_contains (ui->fcn, it.from)) {
|
||||
goto beach;
|
||||
}
|
||||
if (!it.str) {
|
||||
|
|
|
@ -213,6 +213,7 @@ static int handle_bb_cf_recursive_descent(RAnal *anal, RAnalState *state) {
|
|||
jmp_list = r_anal_ex_perform_analysis ( anal, state, bb->jump );
|
||||
if (jmp_list) {
|
||||
bb->jumpbb = (RAnalBlock *)r_list_get_n (jmp_list, 0);
|
||||
r_list_free (jmp_list);
|
||||
}
|
||||
if (bb->jumpbb) {
|
||||
bb->jump = bb->jumpbb->addr;
|
||||
|
@ -241,6 +242,7 @@ static int handle_bb_cf_recursive_descent(RAnal *anal, RAnalState *state) {
|
|||
jmp_list = r_anal_ex_perform_analysis ( anal, state, bb->jump );
|
||||
if (jmp_list) {
|
||||
bb->jumpbb = (RAnalBlock *)r_list_get_n (jmp_list, 0);
|
||||
r_list_free (jmp_list);
|
||||
}
|
||||
if (bb->jumpbb) {
|
||||
bb->jump = bb->jumpbb->addr;
|
||||
|
@ -260,6 +262,7 @@ static int handle_bb_cf_recursive_descent(RAnal *anal, RAnalState *state) {
|
|||
jmp_list = r_anal_ex_perform_analysis ( anal, state, bb->fail );
|
||||
if (jmp_list) {
|
||||
bb->failbb = (RAnalBlock *)r_list_get_n (jmp_list, 0);
|
||||
r_list_free (jmp_list);
|
||||
}
|
||||
if (bb->failbb) {
|
||||
bb->fail = bb->failbb->addr;
|
||||
|
@ -299,6 +302,7 @@ static int handle_bb_cf_recursive_descent(RAnal *anal, RAnalState *state) {
|
|||
jmp_list = r_anal_ex_perform_analysis (anal, state, caseop->jump );
|
||||
if (jmp_list) {
|
||||
caseop->jumpbb = (RAnalBlock *)r_list_get_n (jmp_list, 0);
|
||||
r_list_free (jmp_list);
|
||||
}
|
||||
if (state->done == 1) {
|
||||
IFDBG eprintf (" Looks like this jmp (bb @ 0x%04"PFMT64x") found a return.\n", addr);
|
||||
|
@ -466,7 +470,6 @@ static int analyze_from_code_buffer(RAnal *anal, RAnalFunction *fcn, ut64 addr,
|
|||
|
||||
fcn->name = r_str_newf ("sym.%08"PFMT64x, addr);
|
||||
fcn->dsc = strdup ("unknown");
|
||||
r_anal_fcn_set_size (NULL, fcn, code_length);
|
||||
fcn->type = R_ANAL_FCN_TYPE_FCN;
|
||||
fcn->addr = addr;
|
||||
state = r_anal_state_new (addr, (ut8*) code_buf, code_length);
|
||||
|
@ -478,12 +481,11 @@ static int analyze_from_code_buffer(RAnal *anal, RAnalFunction *fcn, ut64 addr,
|
|||
r_list_foreach (fcn->bbs, bb_iter, bb) {
|
||||
actual_size += bb->size;
|
||||
}
|
||||
r_anal_fcn_set_size (NULL, fcn, state->bytes_consumed);
|
||||
r_list_free (nodes->cfg_node_addrs);
|
||||
free (nodes);
|
||||
//leak to avoid UAF is the easy solution otherwise a whole rewrite is needed
|
||||
//r_anal_state_free (state);
|
||||
if (r_anal_fcn_size (fcn) != code_length) {
|
||||
if (r_anal_function_linear_size (fcn) != code_length) {
|
||||
return R_ANAL_RET_ERROR;
|
||||
#if 0
|
||||
eprintf ("WARNING Analysis of %s Incorrect: Code Length: 0x%"PFMT64x", Function size reported 0x%x\n", fcn->name, code_length, r_anal_fcn_size(fcn));
|
||||
|
@ -491,6 +493,7 @@ static int analyze_from_code_buffer(RAnal *anal, RAnalFunction *fcn, ut64 addr,
|
|||
r_anal_fcn_set_size (fcn, code_length);
|
||||
#endif
|
||||
}
|
||||
r_anal_state_free (state);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -501,7 +504,6 @@ static int analyze_from_code_attr (RAnal *anal, RAnalFunction *fcn, RBinJavaFiel
|
|||
if (!code_attr) {
|
||||
fcn->name = strdup ("sym.UNKNOWN");
|
||||
fcn->dsc = strdup ("unknown");
|
||||
r_anal_fcn_set_size (NULL, fcn, 1); // code_length);
|
||||
fcn->type = R_ANAL_FCN_TYPE_FCN;
|
||||
fcn->addr = 0;
|
||||
return R_ANAL_RET_ERROR;
|
||||
|
@ -539,13 +541,13 @@ static int analyze_from_code_attr (RAnal *anal, RAnalFunction *fcn, RBinJavaFiel
|
|||
|
||||
static int analyze_method(RAnal *anal, RAnalFunction *fcn, RAnalState *state) {
|
||||
// deallocate niceties
|
||||
r_list_free (fcn->bbs);
|
||||
fcn->bbs = r_anal_bb_list_new ();
|
||||
while (!r_list_empty (fcn->bbs)) {
|
||||
r_anal_function_remove_block (fcn, r_list_first (fcn->bbs));
|
||||
}
|
||||
java_new_method (fcn->addr);
|
||||
state->current_fcn = fcn;
|
||||
// Not a resource leak. Basic blocks should be stored in the state->fcn
|
||||
// TODO: ? RList *bbs =
|
||||
r_anal_ex_perform_analysis (anal, state, fcn->addr);
|
||||
RList *bbs = r_anal_ex_perform_analysis (anal, state, fcn->addr);
|
||||
r_list_free (bbs);
|
||||
return state->anal_ret_val;
|
||||
}
|
||||
|
||||
|
@ -584,8 +586,7 @@ static int java_analyze_fns_from_buffer( RAnal *anal, ut64 start, ut64 end, int
|
|||
|
||||
while (offset < buf_len) {
|
||||
ut64 length = buf_len - offset;
|
||||
|
||||
RAnalFunction *fcn = r_anal_fcn_new ();
|
||||
RAnalFunction *fcn = r_anal_function_new (anal);
|
||||
fcn->cc = r_str_constpool_get (&anal->constpool, r_anal_cc_default (anal));
|
||||
result = analyze_from_code_buffer ( anal, fcn, addr, buffer+offset, length );
|
||||
if (result == R_ANAL_RET_ERROR) {
|
||||
|
@ -593,10 +594,8 @@ static int java_analyze_fns_from_buffer( RAnal *anal, ut64 start, ut64 end, int
|
|||
// XXX - TO Stop or not to Stop ??
|
||||
break;
|
||||
}
|
||||
//r_listrange_add (anal->fcnstore, fcn);
|
||||
r_anal_fcn_tree_insert (anal, fcn);
|
||||
r_list_append (anal->fcns, fcn);
|
||||
offset += r_anal_fcn_size (fcn);
|
||||
r_anal_add_function (anal, fcn);
|
||||
offset += r_anal_function_linear_size (fcn);
|
||||
if (!analyze_all) {
|
||||
break;
|
||||
}
|
||||
|
@ -634,7 +633,7 @@ static int java_analyze_fns( RAnal *anal, ut64 start, ut64 end, int reftype, int
|
|||
if ((method && analyze_all) ||
|
||||
(check_addr_less_start (method, end) ||
|
||||
check_addr_in_code (method, end))) {
|
||||
RAnalFunction *fcn = r_anal_fcn_new ();
|
||||
RAnalFunction *fcn = r_anal_function_new (anal);
|
||||
fcn->cc = r_str_constpool_get (&anal->constpool, r_anal_cc_default (anal));
|
||||
java_set_function_prototype (anal, fcn, method);
|
||||
result = analyze_from_code_attr (anal, fcn, method, loadaddr);
|
||||
|
@ -644,9 +643,7 @@ static int java_analyze_fns( RAnal *anal, ut64 start, ut64 end, int reftype, int
|
|||
// XXX - TO Stop or not to Stop ??
|
||||
}
|
||||
//r_listrange_add (anal->fcnstore, fcn);
|
||||
r_anal_fcn_update_tinyrange_bbs (fcn);
|
||||
r_anal_fcn_tree_insert (anal, fcn);
|
||||
r_list_append (anal->fcns, fcn);
|
||||
r_anal_add_function (anal, fcn);
|
||||
}
|
||||
} // End of methods loop
|
||||
}// end of bin_objs list loop
|
||||
|
|
|
@ -1875,7 +1875,7 @@ static bool fcnMetricsCmp(RSignItem *it, RAnalFunction *fcn) {
|
|||
if (graph->ebbs != -1 && graph->ebbs != ebbs) {
|
||||
return false;
|
||||
}
|
||||
if (graph->bbsum > 0 && matchCount (graph->bbsum, r_anal_fcn_size (fcn))) {
|
||||
if (graph->bbsum > 0 && matchCount (graph->bbsum, r_anal_function_linear_size (fcn))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#define IFINT if(0)
|
||||
|
||||
static void kv_anal_bb_free(HtUPKv *kv) {
|
||||
r_anal_bb_free (kv->value);
|
||||
r_anal_block_unref (kv->value);
|
||||
}
|
||||
|
||||
R_API RAnalState * r_anal_state_new(ut64 start, ut8* buffer, ut64 len) {
|
||||
|
@ -31,7 +31,7 @@ R_API RAnalState * r_anal_state_new(ut64 start, ut8* buffer, ut64 len) {
|
|||
state->current_fcn = NULL;
|
||||
state->ht = ht_up_new (NULL, (HtUPKvFreeFunc)kv_anal_bb_free, NULL);
|
||||
state->ht_sz = 512;
|
||||
state->bbs = r_list_newf ((RListFree)r_anal_bb_free);
|
||||
state->bbs = r_list_newf ((RListFree)r_anal_block_unref);
|
||||
state->max_depth = 50;
|
||||
state->current_depth = 0;
|
||||
return state;
|
||||
|
@ -46,9 +46,11 @@ R_API void r_anal_state_insert_bb(RAnalState* state, RAnalBlock *bb) {
|
|||
return;
|
||||
}
|
||||
if (!r_anal_state_search_bb (state, bb->addr) && state->current_fcn) {
|
||||
r_list_append (state->current_fcn->bbs, bb);
|
||||
r_anal_function_add_block (state->current_fcn, bb);
|
||||
state->bytes_consumed += state->current_bb->op_sz;
|
||||
r_anal_block_ref (bb);
|
||||
if (!ht_up_insert (state->ht, bb->addr, bb)) {
|
||||
r_anal_block_unref (bb);
|
||||
eprintf ("Inserted bb 0x%04"PFMT64x" failure\n", bb->addr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2322,7 +2322,7 @@ static int get_bbnodes(RAGraph *g, RCore *core, RAnalFunction *fcn) {
|
|||
if (!curbb) {
|
||||
curbb = bb;
|
||||
}
|
||||
if (r_anal_bb_is_in_offset (bb, core->offset)) {
|
||||
if (r_anal_block_contains (bb, core->offset)) {
|
||||
curbb = bb;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -691,7 +691,7 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
|
|||
if (!jmp_op) {
|
||||
break;
|
||||
}
|
||||
if ((jmp_op->type == R_ANAL_OP_TYPE_RET && r_anal_bb_is_in_offset (jmpbb, jmp_addr))
|
||||
if ((jmp_op->type == R_ANAL_OP_TYPE_RET && r_anal_block_contains (jmpbb, jmp_addr))
|
||||
|| jmp_op->type == R_ANAL_OP_TYPE_CJMP) {
|
||||
jmp = true;
|
||||
r_anal_op_free (jmp_op);
|
||||
|
|
|
@ -30,15 +30,25 @@ typedef struct fcn {
|
|||
ut64 ends;
|
||||
} fcn_t;
|
||||
|
||||
static bool __is_data_block_cb(RAnalBlock *block, void *user) {
|
||||
bool *block_exists = user;
|
||||
*block_exists = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int __isdata(RCore *core, ut64 addr) {
|
||||
if (!r_io_is_valid_offset (core->io, addr, false)) {
|
||||
// eprintf ("Warning: Invalid memory address at 0x%08"PFMT64x"\n", addr);
|
||||
return 4;
|
||||
}
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
||||
if (fcn) {
|
||||
return r_anal_fcn_size (fcn);
|
||||
|
||||
bool block_exists = false;
|
||||
// This will just set block_exists = true if there is any basic block at this addr
|
||||
r_anal_blocks_foreach_in (core->anal, addr, __is_data_block_cb, &block_exists);
|
||||
if (block_exists) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
RList *list = r_meta_find_list_in (core->anal, addr, -1, 4);
|
||||
RListIter *iter;
|
||||
RAnalMetaItem *meta;
|
||||
|
@ -207,7 +217,7 @@ static void createFunction(RCore *core, fcn_t* fcn, const char *name) {
|
|||
pfx = "fcn";
|
||||
}
|
||||
|
||||
RAnalFunction *f = r_anal_fcn_new ();
|
||||
RAnalFunction *f = r_anal_function_new (core->anal);
|
||||
if (!f) {
|
||||
eprintf ("Failed to create new function\n");
|
||||
return;
|
||||
|
@ -217,7 +227,6 @@ static void createFunction(RCore *core, fcn_t* fcn, const char *name) {
|
|||
f->addr = fcn->addr;
|
||||
f->bits = core->anal->bits;
|
||||
f->cc = r_str_constpool_get (&core->anal->constpool, r_anal_cc_default (core->anal));
|
||||
r_anal_fcn_set_size (NULL, f, fcn->size);
|
||||
f->type = R_ANAL_FCN_TYPE_FCN;
|
||||
|
||||
r_list_foreach (fcn->bbs, fcn_iter, cur) {
|
||||
|
@ -226,10 +235,9 @@ static void createFunction(RCore *core, fcn_t* fcn, const char *name) {
|
|||
}
|
||||
r_anal_fcn_add_bb (core->anal, f, cur->start, (cur->end - cur->start), cur->jump, cur->fail, 0, NULL);
|
||||
}
|
||||
if (!r_anal_fcn_insert (core->anal, f)) {
|
||||
if (!r_anal_add_function (core->anal, f)) {
|
||||
// eprintf ("Failed to insert function\n");
|
||||
r_anal_fcn_free (f);
|
||||
//TODO free not added function
|
||||
r_anal_function_free (f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,10 +35,9 @@ static void loganal(ut64 from, ut64 to, int depth) {
|
|||
eprintf ("0x%08"PFMT64x" > 0x%08"PFMT64x" %d\r", from, to, depth);
|
||||
}
|
||||
|
||||
static int cmpsize (const void *_a, const void *_b) {
|
||||
const RAnalFunction *a = _a, *b = _b;
|
||||
ut64 as = r_anal_fcn_size (a);
|
||||
ut64 bs = r_anal_fcn_size (b);
|
||||
static int cmpsize (const void *a, const void *b) {
|
||||
ut64 as = r_anal_function_linear_size ((RAnalFunction *) a);
|
||||
ut64 bs = r_anal_function_linear_size ((RAnalFunction *) b);
|
||||
return (as> bs)? 1: (as< bs)? -1: 0;
|
||||
}
|
||||
|
||||
|
@ -731,15 +730,15 @@ static void set_fcn_name_from_flag(RAnalFunction *fcn, RFlagItem *f, const char
|
|||
bool nameChanged = false;
|
||||
if (f && f->name) {
|
||||
if (!strncmp (fcn->name, "loc.", 4) || !strncmp (fcn->name, "fcn.", 4)) {
|
||||
r_anal_fcn_rename (fcn, f->name);
|
||||
r_anal_function_rename (fcn, f->name);
|
||||
nameChanged = true;
|
||||
} else if (strncmp (f->name, "sect", 4)) {
|
||||
r_anal_fcn_rename (fcn, f->name);
|
||||
r_anal_function_rename (fcn, f->name);
|
||||
nameChanged = true;
|
||||
}
|
||||
}
|
||||
if (!nameChanged) {
|
||||
r_anal_fcn_rename (fcn, sdb_fmt ("%s.%08" PFMT64x, fcnpfx, fcn->addr));
|
||||
r_anal_function_rename (fcn, sdb_fmt ("%s.%08" PFMT64x, fcnpfx, fcn->addr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,7 +753,7 @@ static int __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
|||
int i, nexti = 0;
|
||||
ut64 *next = NULL;
|
||||
int fcnlen;
|
||||
RAnalFunction *fcn = r_anal_fcn_new ();
|
||||
RAnalFunction *fcn = r_anal_function_new (core->anal);
|
||||
const char *fcnpfx = r_config_get (core->config, "anal.fcnprefix");
|
||||
if (!fcnpfx) {
|
||||
fcnpfx = "fcn";
|
||||
|
@ -772,7 +771,6 @@ static int __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
|||
fcn->bits = core->anal->bits;
|
||||
}
|
||||
fcn->addr = at;
|
||||
r_anal_fcn_set_size (NULL, fcn, 0);
|
||||
fcn->name = getFunctionName (core, at);
|
||||
|
||||
if (!fcn->name) {
|
||||
|
@ -781,7 +779,7 @@ static int __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
|||
r_anal_fcn_invalidate_read_ahead_cache ();
|
||||
do {
|
||||
RFlagItem *f;
|
||||
int delta = r_anal_fcn_size (fcn);
|
||||
ut64 delta = r_anal_function_linear_size (fcn);
|
||||
if (!r_io_is_valid_offset (core->io, at + delta, !core->anal->opt.noncode)) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -812,7 +810,7 @@ static int __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
|||
set_fcn_name_from_flag (fcn, f, fcnpfx);
|
||||
|
||||
if (fcnlen == R_ANAL_RET_ERROR ||
|
||||
(fcnlen == R_ANAL_RET_END && r_anal_fcn_size (fcn) < 1)) { /* Error analyzing function */
|
||||
(fcnlen == R_ANAL_RET_END && !r_anal_function_realsize (fcn))) { /* Error analyzing function */
|
||||
if (core->anal->opt.followbrokenfcnsrefs) {
|
||||
r_anal_analyze_fcn_refs (core, fcn, depth);
|
||||
}
|
||||
|
@ -832,7 +830,7 @@ static int __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
|||
autoname_imp_trampoline (core, fcn);
|
||||
/* Add flag */
|
||||
r_flag_space_push (core->flags, R_FLAGS_FS_FUNCTIONS);
|
||||
r_flag_set (core->flags, fcn->name, fcn->addr, r_anal_fcn_size (fcn));
|
||||
r_flag_set (core->flags, fcn->name, fcn->addr, r_anal_function_linear_size (fcn));
|
||||
r_flag_space_pop (core->flags);
|
||||
}
|
||||
|
||||
|
@ -850,9 +848,9 @@ static int __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
|||
r_anal_xrefs_set (core->anal, from, fcn->addr, reftype);
|
||||
}
|
||||
// XXX: this is wrong. See CID 1134565
|
||||
r_anal_fcn_insert (core->anal, fcn);
|
||||
r_anal_add_function (core->anal, fcn);
|
||||
if (has_next) {
|
||||
ut64 addr = fcn->addr + r_anal_fcn_size (fcn);
|
||||
ut64 addr = r_anal_function_max_addr (fcn);
|
||||
RIOMap *map = r_io_map_get (core->io, addr);
|
||||
// only get next if found on an executable section
|
||||
if (!map || (map && map->perm & R_PERM_X)) {
|
||||
|
@ -862,7 +860,7 @@ static int __core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dep
|
|||
}
|
||||
}
|
||||
if (i == nexti) {
|
||||
ut64 at = fcn->addr + r_anal_fcn_size (fcn);
|
||||
ut64 at = r_anal_function_max_addr (fcn);
|
||||
while (true) {
|
||||
RAnalMetaItem *mi = r_meta_find (core->anal, at, R_META_TYPE_ANY, 0);
|
||||
if (!mi) {
|
||||
|
@ -909,8 +907,8 @@ error:
|
|||
core->anal->leaddrs = NULL;
|
||||
// ugly hack to free fcn
|
||||
if (fcn) {
|
||||
if (!r_anal_fcn_size (fcn) || fcn->addr == UT64_MAX) {
|
||||
r_anal_fcn_free (fcn);
|
||||
if (!r_anal_function_realsize (fcn) || fcn->addr == UT64_MAX) {
|
||||
r_anal_function_free (fcn);
|
||||
fcn = NULL;
|
||||
} else {
|
||||
// TODO: mark this function as not properly analyzed
|
||||
|
@ -922,13 +920,13 @@ error:
|
|||
at);
|
||||
/* Add flag */
|
||||
r_flag_space_push (core->flags, R_FLAGS_FS_FUNCTIONS);
|
||||
r_flag_set (core->flags, fcn->name, at, r_anal_fcn_size (fcn));
|
||||
r_flag_set (core->flags, fcn->name, at, r_anal_function_linear_size (fcn));
|
||||
r_flag_space_pop (core->flags);
|
||||
}
|
||||
r_anal_fcn_insert (core->anal, fcn);
|
||||
r_anal_add_function (core->anal, fcn);
|
||||
}
|
||||
if (fcn && has_next) {
|
||||
ut64 newaddr = fcn->addr + r_anal_fcn_size (fcn);
|
||||
ut64 newaddr = r_anal_function_max_addr (fcn);
|
||||
RIOMap *map = r_io_map_get (core->io, newaddr);
|
||||
if (!map || (map && (map->perm & R_PERM_X))) {
|
||||
next = next_append (next, &nexti, newaddr);
|
||||
|
@ -1262,7 +1260,7 @@ static char *palColorFor(const char *k) {
|
|||
static void core_anal_color_curr_node(RCore *core, RAnalBlock *bbi) {
|
||||
bool color_current = r_config_get_i (core->config, "graph.gv.current");
|
||||
char *pal_curr = palColorFor ("graph.current");
|
||||
bool current = r_anal_bb_is_in_offset (bbi, core->offset);
|
||||
bool current = r_anal_block_contains (bbi, core->offset);
|
||||
|
||||
if (current && color_current) {
|
||||
r_cons_printf ("\t\"0x%08"PFMT64x"\" ", bbi->addr);
|
||||
|
@ -1590,7 +1588,7 @@ static int core_anal_graph_construct_nodes (RCore *core, RAnalFunction *fcn, int
|
|||
top += 250;
|
||||
}
|
||||
} else if (!is_json && !is_keva) {
|
||||
bool current = r_anal_bb_is_in_offset (bbi, core->offset);
|
||||
bool current = r_anal_block_contains (bbi, core->offset);
|
||||
const char *label_color = bbi->traced
|
||||
? pal_traced
|
||||
: (current && color_current)
|
||||
|
@ -1658,7 +1656,7 @@ static int core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts, PJ *
|
|||
if (fcn->nargs > 0) {
|
||||
sdb_num_set (DB, "nargs", fcn->nargs, 0);
|
||||
}
|
||||
sdb_num_set (DB, "size", r_anal_fcn_size (fcn), 0);
|
||||
sdb_num_set (DB, "size", r_anal_function_linear_size (fcn), 0);
|
||||
if (fcn->maxstack > 0) {
|
||||
sdb_num_set (DB, "stack", fcn->maxstack, 0);
|
||||
}
|
||||
|
@ -1680,7 +1678,7 @@ static int core_anal_graph_nodes(RCore *core, RAnalFunction *fcn, int opts, PJ *
|
|||
r_anal_var_count (core->anal, fcn, 'r', 0) +
|
||||
r_anal_var_count (core->anal, fcn, 's', 0) +
|
||||
r_anal_var_count (core->anal, fcn, 'b', 0));
|
||||
pj_kn (pj, "size", r_anal_fcn_size (fcn));
|
||||
pj_kn (pj, "size", r_anal_function_linear_size (fcn));
|
||||
pj_ki (pj, "stack", fcn->maxstack);
|
||||
pj_ks (pj, "type", r_anal_fcn_type_tostring (fcn->type));
|
||||
if (fcn->dsc) {
|
||||
|
@ -1780,7 +1778,7 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
|||
/* update the flags after running the analysis function of the plugin */
|
||||
r_flag_space_push (core->flags, R_FLAGS_FS_FUNCTIONS);
|
||||
r_list_foreach (core->anal->fcns, iter, fcn) {
|
||||
r_flag_set (core->flags, fcn->name, fcn->addr, r_anal_fcn_size (fcn));
|
||||
r_flag_set (core->flags, fcn->name, fcn->addr, r_anal_function_linear_size (fcn));
|
||||
}
|
||||
r_flag_space_pop (core->flags);
|
||||
return result;
|
||||
|
@ -1810,7 +1808,7 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
|||
|
||||
return 0; // already analyzed function
|
||||
}
|
||||
if (r_anal_fcn_is_in_offset (fcn, from)) { // inner function
|
||||
if (r_anal_function_contains (fcn, from)) { // inner function
|
||||
RList *l = r_anal_xrefs_get (core->anal, from);
|
||||
if (l && !r_list_empty (l)) {
|
||||
r_list_free (l);
|
||||
|
@ -1843,16 +1841,14 @@ R_API int r_core_anal_fcn_clean(RCore *core, ut64 addr) {
|
|||
|
||||
if (!addr) {
|
||||
r_list_purge (core->anal->fcns);
|
||||
core->anal->fcn_tree = NULL;
|
||||
core->anal->fcn_addr_tree = NULL;
|
||||
if (!(core->anal->fcns = r_anal_fcn_list_new ())) {
|
||||
if (!(core->anal->fcns = r_list_new ())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
r_list_foreach_safe (core->anal->fcns, iter, iter_tmp, fcni) {
|
||||
if (r_anal_fcn_in (fcni, addr)) {
|
||||
r_anal_fcn_tree_delete (core->anal, fcni);
|
||||
r_list_delete (core->anal->fcns, iter);
|
||||
if (r_anal_function_contains (fcni, addr)) {
|
||||
r_anal_function_delete (fcni);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2245,12 +2241,12 @@ repeat:
|
|||
r_cons_printf ("%s{\"name\":\"%s\", "
|
||||
"\"size\":%d,\"imports\":[",
|
||||
first ? "," : "", fcni->name,
|
||||
r_anal_fcn_size (fcni));
|
||||
r_anal_function_linear_size (fcni));
|
||||
} else {
|
||||
r_cons_printf ("%s{\"name\":\"0x%08" PFMT64x
|
||||
"\", \"size\":%d,\"imports\":[",
|
||||
first ? "," : "", fcni->addr,
|
||||
r_anal_fcn_size (fcni));
|
||||
r_anal_function_linear_size (fcni));
|
||||
}
|
||||
first = 1;
|
||||
break;
|
||||
|
@ -2371,15 +2367,15 @@ static void fcn_list_bbs(RAnalFunction *fcn) {
|
|||
}
|
||||
}
|
||||
|
||||
R_API int r_core_anal_fcn_list_size(RCore *core) {
|
||||
R_API ut64 r_core_anal_fcn_list_size(RCore *core) {
|
||||
RAnalFunction *fcn;
|
||||
RListIter *iter;
|
||||
ut32 total = 0;
|
||||
ut64 total = 0;
|
||||
|
||||
r_list_foreach (core->anal->fcns, iter, fcn) {
|
||||
total += r_anal_fcn_size (fcn);
|
||||
total += r_anal_function_realsize (fcn);
|
||||
}
|
||||
r_cons_printf ("%d\n", total);
|
||||
r_cons_printf ("%"PFMT64u"\n", total);
|
||||
return total;
|
||||
}
|
||||
|
||||
|
@ -2410,23 +2406,6 @@ static int fcnlist_gather_metadata(RAnal *anal, RList *fcns) {
|
|||
xrefs = r_anal_xrefs_get (anal, fcn->addr);
|
||||
fcn->meta.numrefs = xrefs? xrefs->length: 0;
|
||||
r_list_free (xrefs);
|
||||
|
||||
// Determine the bounds of the functions address space
|
||||
ut64 min = UT64_MAX;
|
||||
ut64 max = UT64_MIN;
|
||||
|
||||
RListIter *bbsiter;
|
||||
RAnalBlock *bbi;
|
||||
r_list_foreach (fcn->bbs, bbsiter, bbi) {
|
||||
if (max < bbi->addr + bbi->size) {
|
||||
max = bbi->addr + bbi->size;
|
||||
}
|
||||
if (min > bbi->addr) {
|
||||
min = bbi->addr;
|
||||
}
|
||||
}
|
||||
fcn->meta.min = min;
|
||||
fcn->meta.max = max;
|
||||
}
|
||||
// TODO: Determine sgnc, sgec
|
||||
return 0;
|
||||
|
@ -2471,14 +2450,14 @@ static int fcn_print_verbose(RCore *core, RAnalFunction *fcn, bool use_color) {
|
|||
|
||||
r_cons_printf (FCN_LIST_VERBOSE_ENTRY, color,
|
||||
addrwidth, fcn->addr,
|
||||
r_anal_fcn_realsize (fcn),
|
||||
r_anal_function_realsize (fcn),
|
||||
r_list_length (fcn->bbs),
|
||||
r_anal_fcn_count_edges (fcn, &ebbs),
|
||||
r_anal_fcn_cc (core->anal, fcn),
|
||||
r_anal_fcn_cost (core->anal, fcn),
|
||||
addrwidth, fcn->meta.min,
|
||||
r_anal_fcn_size (fcn),
|
||||
addrwidth, fcn->meta.max,
|
||||
addrwidth, r_anal_function_min_addr (fcn),
|
||||
r_anal_function_linear_size (fcn),
|
||||
addrwidth, r_anal_function_max_addr (fcn),
|
||||
fcn->meta.numcallrefs,
|
||||
r_anal_var_count (core->anal, fcn, 's', 0) +
|
||||
r_anal_var_count (core->anal, fcn, 'b', 0) +
|
||||
|
@ -2546,12 +2525,12 @@ static void __fcn_print_default(RCore *core, RAnalFunction *fcn, bool quiet) {
|
|||
r_cons_printf ("0x%08"PFMT64x" ", fcn->addr);
|
||||
} else {
|
||||
char *msg, *name = r_core_anal_fcn_name (core, fcn);
|
||||
int realsize = r_anal_fcn_realsize (fcn);
|
||||
int size = r_anal_fcn_size (fcn);
|
||||
ut64 realsize = r_anal_function_realsize (fcn);
|
||||
ut64 size = r_anal_function_linear_size (fcn);
|
||||
if (realsize == size) {
|
||||
msg = r_str_newf ("%-12d", size);
|
||||
msg = r_str_newf ("%-12"PFMT64u, size);
|
||||
} else {
|
||||
msg = r_str_newf ("%-4d -> %-4d", size, realsize);
|
||||
msg = r_str_newf ("%-4"PFMT64u" -> %-4"PFMT64u, size, realsize);
|
||||
}
|
||||
r_cons_printf ("0x%08"PFMT64x" %4d %4s %s\n",
|
||||
fcn->addr, r_list_length (fcn->bbs), msg, name);
|
||||
|
@ -2677,9 +2656,9 @@ static int fcn_print_json(RCore *core, RAnalFunction *fcn, PJ *pj) {
|
|||
if (name) {
|
||||
pj_ks (pj, "name", name);
|
||||
}
|
||||
pj_ki (pj, "size", r_anal_fcn_size (fcn));
|
||||
pj_kn (pj, "size", r_anal_function_linear_size (fcn));
|
||||
pj_ks (pj, "is-pure", r_str_bool (r_anal_fcn_get_purity (core->anal, fcn)));
|
||||
pj_ki (pj, "realsz", r_anal_fcn_realsize (fcn));
|
||||
pj_kn (pj, "realsz", r_anal_function_realsize (fcn));
|
||||
pj_ki (pj, "stackframe", fcn->maxstack);
|
||||
if (fcn->cc) {
|
||||
pj_ks (pj, "calltype", fcn->cc); // calling conventions
|
||||
|
@ -2700,8 +2679,8 @@ static int fcn_print_json(RCore *core, RAnalFunction *fcn, PJ *pj) {
|
|||
}
|
||||
|
||||
}
|
||||
pj_ki (pj, "minbound", fcn->meta.min);
|
||||
pj_ki (pj, "maxbound", fcn->meta.max);
|
||||
pj_ki (pj, "minbound", r_anal_function_min_addr (fcn));
|
||||
pj_ki (pj, "maxbound", r_anal_function_max_addr (fcn));
|
||||
|
||||
int outdegree = 0;
|
||||
refs = r_anal_fcn_get_refs (core->anal, fcn);
|
||||
|
@ -2824,7 +2803,7 @@ static int fcn_list_verbose_json(RCore *core, RList *fcns) {
|
|||
static int fcn_print_detail(RCore *core, RAnalFunction *fcn) {
|
||||
const char *defaultCC = r_anal_cc_default (core->anal);
|
||||
char *name = r_core_anal_fcn_name (core, fcn);
|
||||
r_cons_printf ("\"f %s %d 0x%08"PFMT64x"\"\n", name, r_anal_fcn_size (fcn), fcn->addr);
|
||||
r_cons_printf ("\"f %s %"PFMT64u" 0x%08"PFMT64x"\"\n", name, r_anal_function_linear_size (fcn), fcn->addr);
|
||||
r_cons_printf ("\"af+ 0x%08"PFMT64x" %s %c %c\"\n",
|
||||
fcn->addr, name, //r_anal_fcn_size (fcn), name,
|
||||
fcn->type == R_ANAL_FCN_TYPE_LOC?'l':
|
||||
|
@ -2886,7 +2865,7 @@ static bool is_fcn_traced(RDebugTrace *traced, RAnalFunction *fcn) {
|
|||
|
||||
r_list_foreach (traced->traces, iter, trace) {
|
||||
if (!trace->tag || (tag & trace->tag)) {
|
||||
if (r_anal_fcn_in (fcn, trace->addr)) {
|
||||
if (r_anal_function_contains (fcn, trace->addr)) {
|
||||
r_cons_printf ("\ntraced: %d\n", trace->times);
|
||||
return true;
|
||||
}
|
||||
|
@ -2902,10 +2881,10 @@ static int fcn_print_legacy(RCore *core, RAnalFunction *fcn) {
|
|||
int ebbs = 0;
|
||||
char *name = r_core_anal_fcn_name (core, fcn);
|
||||
|
||||
r_cons_printf ("#\noffset: 0x%08"PFMT64x"\nname: %s\nsize: %"PFMT64d,
|
||||
fcn->addr, name, (ut64)r_anal_fcn_size (fcn));
|
||||
r_cons_printf ("#\noffset: 0x%08"PFMT64x"\nname: %s\nsize: %"PFMT64u,
|
||||
fcn->addr, name, r_anal_function_linear_size (fcn));
|
||||
r_cons_printf ("\nis-pure: %s", r_str_bool (r_anal_fcn_get_purity (core->anal, fcn)));
|
||||
r_cons_printf ("\nrealsz: %d", r_anal_fcn_realsize (fcn));
|
||||
r_cons_printf ("\nrealsz: %d", r_anal_function_realsize (fcn));
|
||||
r_cons_printf ("\nstackframe: %d", fcn->maxstack);
|
||||
if (fcn->cc) {
|
||||
r_cons_printf ("\ncall-convention: %s", fcn->cc);
|
||||
|
@ -3018,7 +2997,7 @@ static int fcn_list_table(RCore *core, const char *q, int fmt) {
|
|||
r_table_add_column (t, typeNumber, "cc", 0);
|
||||
r_list_foreach (core->anal->fcns, iter, fcn) {
|
||||
const char *fcnAddr = sdb_fmt ("0x%08"PFMT64x, fcn->addr);
|
||||
const char *fcnSize = sdb_fmt ("%d", r_anal_fcn_size (fcn));
|
||||
const char *fcnSize = sdb_fmt ("%"PFMT64u, r_anal_function_linear_size (fcn));
|
||||
const char *nbbs = sdb_fmt ("%d", r_list_length (fcn->bbs)); // r_anal_fcn_size (fcn));
|
||||
RList *xrefs = r_anal_fcn_get_xrefs (core->anal, fcn);
|
||||
char xref[128], ccstr[128];
|
||||
|
@ -3063,7 +3042,7 @@ R_API int r_core_anal_fcn_list(RCore *core, const char *input, const char *rad)
|
|||
return 0;
|
||||
}
|
||||
if (*rad == '.') {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, core->offset, 0);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->offset);
|
||||
__fcn_print_default (core, fcn, false);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3086,7 +3065,7 @@ R_API int r_core_anal_fcn_list(RCore *core, const char *input, const char *rad)
|
|||
RListIter *iter;
|
||||
RAnalFunction *fcn;
|
||||
r_list_foreach (core->anal->fcns, iter, fcn) {
|
||||
if (!input || r_anal_fcn_in (fcn, addr) || (!strcmp (name, fcn->name))) {
|
||||
if (!input || r_anal_function_contains (fcn, addr) || (!strcmp (name, fcn->name))) {
|
||||
r_list_append (fcns, fcn);
|
||||
}
|
||||
}
|
||||
|
@ -3109,7 +3088,7 @@ R_API int r_core_anal_fcn_list(RCore *core, const char *input, const char *rad)
|
|||
return -1;
|
||||
}
|
||||
ls_foreach (fcns, iter, fcn) {
|
||||
RInterval inter = (RInterval) {fcn->addr, r_anal_fcn_size (fcn)};
|
||||
RInterval inter = {r_anal_function_min_addr (fcn), r_anal_function_linear_size (fcn) };
|
||||
RListInfo *info = r_listinfo_new (r_core_anal_fcn_name (core, fcn), inter, inter, -1, sdb_itoa (fcn->bits, temp, 10));
|
||||
if (!info) {
|
||||
break;
|
||||
|
@ -3172,7 +3151,6 @@ R_API int r_core_anal_fcn_list(RCore *core, const char *input, const char *rad)
|
|||
fcn_list_default (core, fcns, false);
|
||||
break;
|
||||
}
|
||||
|
||||
r_list_free (fcns);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3189,15 +3167,12 @@ static RList *recurse(RCore *core, RAnalBlock *from, RAnalBlock *dest) {
|
|||
}
|
||||
|
||||
static RList *recurse_bb(RCore *core, ut64 addr, RAnalBlock *dest) {
|
||||
RAnalBlock *bb;
|
||||
RList *ret;
|
||||
bb = r_anal_bb_from_offset (core->anal, addr);
|
||||
RAnalBlock *bb = r_anal_bb_from_offset (core->anal, addr);
|
||||
if (bb == dest) {
|
||||
eprintf ("path found!");
|
||||
return NULL;
|
||||
}
|
||||
ret = recurse (core, bb, dest);
|
||||
return ret;
|
||||
return recurse (core, bb, dest);
|
||||
}
|
||||
|
||||
// TODO: move this logic into the main anal loop
|
||||
|
@ -3272,7 +3247,7 @@ static bool anal_path_exists(RCore *core, ut64 from, ut64 to, RList *bbs, int de
|
|||
ht_up_update (state, from, bb);
|
||||
|
||||
// try to find the target in the current function
|
||||
if (r_anal_bb_is_in_offset (bb, to) ||
|
||||
if (r_anal_block_contains (bb, to) ||
|
||||
((!ht_up_find (avoid, bb->jump, NULL) &&
|
||||
!ht_up_find (state, bb->jump, NULL) &&
|
||||
anal_path_exists (core, bb->jump, to, bbs, depth - 1, state, avoid))) ||
|
||||
|
@ -3292,7 +3267,7 @@ static bool anal_path_exists(RCore *core, ut64 from, ut64 to, RList *bbs, int de
|
|||
if (refs) {
|
||||
r_list_foreach (refs, iter, refi) {
|
||||
if (refi->type == R_ANAL_REF_TYPE_CALL) {
|
||||
if (r_anal_bb_is_in_offset (bb, refi->at)) {
|
||||
if (r_anal_block_contains (bb, refi->at)) {
|
||||
if ((refi->at != refi->addr) && !ht_up_find (state, refi->addr, NULL) && anal_path_exists (core, refi->addr, to, bbs, depth - 1, state, avoid)) {
|
||||
r_list_prepend (bbs, bb);
|
||||
r_list_free (refs);
|
||||
|
@ -4100,7 +4075,7 @@ R_API RCoreAnalStats* r_core_anal_get_stats(RCore *core, ut64 from, ut64 to, ut6
|
|||
}
|
||||
piece = (F->addr - from) / step;
|
||||
as->block[piece].functions++;
|
||||
int last_piece = R_MIN ((F->addr + F->_size - 1) / step, blocks - 1);
|
||||
ut64 last_piece = R_MIN ((F->addr + r_anal_function_linear_size (F) - 1) / step, blocks - 1);
|
||||
for (; piece <= last_piece; piece++) {
|
||||
as->block[piece].in_functions++;
|
||||
}
|
||||
|
@ -4336,7 +4311,7 @@ R_API void r_core_anal_undefine(RCore *core, ut64 off) {
|
|||
if (!strncmp (f->name, "fcn.", 4)) {
|
||||
r_flag_unset_name (core->flags, f->name);
|
||||
}
|
||||
r_meta_del (core->anal, R_META_TYPE_ANY, off, r_anal_fcn_size (f));
|
||||
r_meta_del (core->anal, R_META_TYPE_ANY, r_anal_function_min_addr (f), r_anal_function_linear_size (f));
|
||||
}
|
||||
r_anal_fcn_del_locs (core->anal, off);
|
||||
r_anal_fcn_del (core->anal, off);
|
||||
|
@ -4350,9 +4325,8 @@ R_API void r_core_anal_fcn_merge(RCore *core, ut64 addr, ut64 addr2) {
|
|||
ut64 max = 0;
|
||||
int first = 1;
|
||||
RAnalBlock *bb;
|
||||
RAnalFunction *f1 = r_anal_get_fcn_at (core->anal, addr, 0);
|
||||
RAnalFunction *f2 = r_anal_get_fcn_at (core->anal, addr2, 0);
|
||||
RAnalFunction *f3 = NULL;
|
||||
RAnalFunction *f1 = r_anal_get_function_at (core->anal, addr);
|
||||
RAnalFunction *f2 = r_anal_get_function_at (core->anal, addr2);
|
||||
if (!f1 || !f2) {
|
||||
eprintf ("Cannot find function\n");
|
||||
return;
|
||||
|
@ -4391,21 +4365,12 @@ R_API void r_core_anal_fcn_merge(RCore *core, ut64 addr, ut64 addr2) {
|
|||
max = bb->addr + bb->size;
|
||||
}
|
||||
}
|
||||
r_anal_fcn_bbadd (f1, bb);
|
||||
r_anal_function_add_block (f1, bb);
|
||||
}
|
||||
// TODO: import data/code/refs
|
||||
r_anal_function_delete (f2);
|
||||
// update size
|
||||
f1->addr = R_MIN (addr, addr2);
|
||||
r_anal_fcn_set_size (core->anal, f1, max - min);
|
||||
// resize
|
||||
f2->bbs = NULL;
|
||||
r_anal_fcn_tree_delete (core->anal, f2);
|
||||
r_list_foreach (core->anal->fcns, iter, f2) {
|
||||
if (f2 == f3) {
|
||||
r_list_delete (core->anal->fcns, iter);
|
||||
f3->bbs = NULL;
|
||||
}
|
||||
}
|
||||
r_anal_function_relocate (f2, R_MIN (addr, addr2));
|
||||
}
|
||||
|
||||
static bool esil_anal_stop = false;
|
||||
|
@ -4578,7 +4543,7 @@ static void getpcfromstack(RCore *core, RAnalEsil *esil) {
|
|||
return;
|
||||
}
|
||||
|
||||
size = r_anal_fcn_size (fcn);
|
||||
size = r_anal_function_linear_size (fcn);
|
||||
if (size <= 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -4699,7 +4664,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
|
|||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
if (fcn) {
|
||||
addr = fcn->addr;
|
||||
end = fcn->addr + r_anal_fcn_size (fcn);
|
||||
end = r_anal_function_max_addr (fcn);
|
||||
end_address_set = true;
|
||||
}
|
||||
}
|
||||
|
@ -4817,7 +4782,7 @@ repeat:
|
|||
}
|
||||
// if (op.type & 0x80000000 || op.type == 0) {
|
||||
if (op.type == R_ANAL_OP_TYPE_ILL || op.type == R_ANAL_OP_TYPE_UNK) {
|
||||
// i +=2;
|
||||
// i += 2
|
||||
r_anal_op_fini (&op);
|
||||
continue;
|
||||
}
|
||||
|
@ -5435,7 +5400,7 @@ static bool is_noreturn_function(RCore *core, RAnalFunction *f) {
|
|||
r_anal_op_free (op);
|
||||
return false;
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
if (!r_anal_fcn_in (f, op->jump)) {
|
||||
if (!r_anal_function_contains (f, op->jump)) {
|
||||
r_anal_op_free (op);
|
||||
return false;
|
||||
}
|
||||
|
@ -5499,7 +5464,7 @@ R_API void r_core_anal_propagate_noreturn(RCore *core) {
|
|||
// big depth results on infinite loops :( but this is a different issue
|
||||
r_core_anal_fcn (core, addr, UT64_MAX, R_ANAL_REF_TYPE_NULL, 3);
|
||||
|
||||
f = r_anal_get_fcn_at (core->anal, addr, 0);
|
||||
f = r_anal_get_function_at (core->anal, addr);
|
||||
if (!f || (f->type != R_ANAL_FCN_TYPE_FCN && f->type != R_ANAL_FCN_TYPE_SYM)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ R_API void r_core_print_func_args(RCore *core) {
|
|||
if (pcv == UT64_MAX) {
|
||||
pcv = op->ptr;
|
||||
}
|
||||
fcn = r_anal_get_fcn_at (core->anal, pcv, 0);
|
||||
fcn = r_anal_get_function_at (core->anal, pcv);
|
||||
if (fcn) {
|
||||
fcn_name = fcn->name;
|
||||
} else {
|
||||
|
|
|
@ -58,7 +58,7 @@ static int compareType(const RAnalFunction *a, const RAnalFunction *b) {
|
|||
|
||||
static int compareSize(const RAnalFunction *a, const RAnalFunction *b) {
|
||||
// return a && b && a->_size < b->_size;
|
||||
return a && b && r_anal_fcn_realsize (a) > r_anal_fcn_realsize (b);
|
||||
return a && b && r_anal_function_realsize (a) > r_anal_function_realsize (b);
|
||||
}
|
||||
|
||||
static int compareDist(const RAnalFunction *a, const RAnalFunction *b) {
|
||||
|
|
|
@ -3891,7 +3891,7 @@ R_API int r_core_cmd_foreach3(RCore *core, const char *cmd, char *each) { // "@@
|
|||
}
|
||||
if (!filter || r_str_glob (fcn->name, filter)) {
|
||||
r_core_seek (core, fcn->addr, 1);
|
||||
r_core_block_size (core, r_anal_fcn_size (fcn));
|
||||
r_core_block_size (core, r_anal_function_linear_size (fcn));
|
||||
r_core_cmd0 (core, cmd);
|
||||
}
|
||||
}
|
||||
|
@ -4029,7 +4029,7 @@ R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
|
|||
{
|
||||
RListIter *iter;
|
||||
RAnalBlock *bb;
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, core->offset, 0);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->offset);
|
||||
int bs = core->blocksize;
|
||||
if (fcn) {
|
||||
r_list_sort (fcn->bbs, bb_cmp);
|
||||
|
@ -4076,7 +4076,7 @@ R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
|
|||
RListIter *iter;
|
||||
RAnalBlock *bb;
|
||||
int i;
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, core->offset, 0);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->offset);
|
||||
if (fcn) {
|
||||
r_list_sort (fcn->bbs, bb_cmp);
|
||||
r_list_foreach (fcn->bbs, iter, bb) {
|
||||
|
|
|
@ -308,7 +308,6 @@ static const char *help_msg_af[] = {
|
|||
"afC[lc]", " ([addr])@[addr]", "calculate the Cycles (afC) or Cyclomatic Complexity (afCc)",
|
||||
"afc", "[?] type @[addr]", "set calling convention for function",
|
||||
"afd", "[addr]","show function + delta for given offset",
|
||||
"aff", "", "re-adjust function boundaries to fit",
|
||||
"afF", "[1|0|]", "fold/unfold/toggle",
|
||||
"afi", " [addr|fcn.name]", "show function(s) information (verbose afl)",
|
||||
"afj", " [tableaddr] [count]", "analyze function jumptable",
|
||||
|
@ -755,10 +754,9 @@ static int cmpname (const void *_a, const void *_b) {
|
|||
return (int)strcmp (a->name, b->name);
|
||||
}
|
||||
|
||||
static int cmpsize (const void *_a, const void *_b) {
|
||||
const RAnalFunction *a = _a, *b = _b;
|
||||
int sa = (int)r_anal_fcn_size (a);
|
||||
int sb = (int)r_anal_fcn_size (b);
|
||||
static int cmpsize (const void *a, const void *b) {
|
||||
ut64 sa = (int) r_anal_function_linear_size ((RAnalFunction *) a);
|
||||
ut64 sb = (int) r_anal_function_linear_size ((RAnalFunction *) b);
|
||||
return (sa > sb)? -1: (sa < sb)? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -931,7 +929,7 @@ static void flag_every_function(RCore *core) {
|
|||
r_flag_space_push (core->flags, R_FLAGS_FS_FUNCTIONS);
|
||||
r_list_foreach (core->anal->fcns, iter, fcn) {
|
||||
r_flag_set (core->flags, fcn->name,
|
||||
fcn->addr, r_anal_fcn_size (fcn));
|
||||
fcn->addr, r_anal_function_size_from_entry (fcn));
|
||||
}
|
||||
r_flag_space_pop (core->flags);
|
||||
}
|
||||
|
@ -1038,7 +1036,7 @@ static int cmd_an(RCore *core, bool use_json, const char *name)
|
|||
eprintf ("Cannot find function\n");
|
||||
}
|
||||
} else if (tgt_addr != UT64_MAX) {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, tgt_addr, R_ANAL_FCN_TYPE_NULL);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, tgt_addr);
|
||||
RFlagItem *f = r_flag_get_i (core->flags, tgt_addr);
|
||||
if (fcn) {
|
||||
if (name) {
|
||||
|
@ -2054,7 +2052,9 @@ static bool anal_fcn_list_bb(RCore *core, const char *input, bool one) {
|
|||
if (mode == '*') {
|
||||
r_cons_printf ("fs blocks\n");
|
||||
}
|
||||
r_list_sort (fcn->bbs, bb_cmp);
|
||||
if (fcn->bbs) {
|
||||
r_list_sort (fcn->bbs, bb_cmp);
|
||||
}
|
||||
if (mode == '=') { // afb
|
||||
RList *flist = r_list_newf ((RListFree) r_listinfo_free);
|
||||
if (!flist) {
|
||||
|
@ -2082,161 +2082,163 @@ static bool anal_fcn_list_bb(RCore *core, const char *input, bool one) {
|
|||
t = r_table_new ();
|
||||
r_table_set_columnsf (t, "xdxx", "addr", "size", "jump", "fail");
|
||||
}
|
||||
r_list_foreach (fcn->bbs, iter, b) {
|
||||
if (one) {
|
||||
if (bbaddr != UT64_MAX && (bbaddr < b->addr || bbaddr >= (b->addr + b->size))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
switch (mode) {
|
||||
case 't':
|
||||
r_table_add_rowf (t, "xdxx", b->addr, b->size, b->jump, b->fail);
|
||||
break;
|
||||
case 'r':
|
||||
if (b->jump == UT64_MAX) {
|
||||
ut64 retaddr = r_anal_bb_opaddr_i (b, b->ninstr - 1);
|
||||
if (retaddr == UT64_MAX) {
|
||||
break;
|
||||
if (fcn->bbs) {
|
||||
r_list_foreach (fcn->bbs, iter, b) {
|
||||
if (one) {
|
||||
if (bbaddr != UT64_MAX && (bbaddr < b->addr || bbaddr >= (b->addr + b->size))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
switch (mode) {
|
||||
case 't':
|
||||
r_table_add_rowf (t, "xdxx", b->addr, b->size, b->jump, b->fail);
|
||||
break;
|
||||
case 'r':
|
||||
if (b->jump == UT64_MAX) {
|
||||
ut64 retaddr = r_anal_bb_opaddr_i (b, b->ninstr - 1);
|
||||
if (retaddr == UT64_MAX) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp (input, "*")) {
|
||||
r_cons_printf ("db 0x%08"PFMT64x"\n", retaddr);
|
||||
} else if (!strcmp (input, "-*")) {
|
||||
r_cons_printf ("db-0x%08"PFMT64x"\n", retaddr);
|
||||
} else {
|
||||
r_cons_printf ("0x%08"PFMT64x"\n", retaddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
r_cons_printf ("f bb.%05" PFMT64x " = 0x%08" PFMT64x "\n",
|
||||
b->addr & 0xFFFFF, b->addr);
|
||||
break;
|
||||
case 'q':
|
||||
r_cons_printf ("0x%08" PFMT64x "\n", b->addr);
|
||||
break;
|
||||
case 'j':
|
||||
//r_cons_printf ("%" PFMT64u "%s", b->addr, iter->n? ",": "");
|
||||
{
|
||||
RListIter *iter2;
|
||||
RAnalBlock *b2;
|
||||
int inputs = 0;
|
||||
int outputs = 0;
|
||||
r_list_foreach (fcn->bbs, iter2, b2) {
|
||||
if (b2->jump == b->addr) {
|
||||
inputs++;
|
||||
}
|
||||
if (b2->fail == b->addr) {
|
||||
inputs++;
|
||||
}
|
||||
}
|
||||
if (b->jump != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
pj_o (pj);
|
||||
|
||||
if (b->jump != UT64_MAX) {
|
||||
pj_kn (pj, "jump", b->jump);
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
pj_kn (pj, "fail", b->fail);
|
||||
}
|
||||
if (b->switch_op) {
|
||||
pj_k (pj, "switch_op");
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "addr", b->switch_op->addr);
|
||||
pj_kn (pj, "min_val", b->switch_op->min_val);
|
||||
pj_kn (pj, "def_val", b->switch_op->def_val);
|
||||
pj_kn (pj, "max_val", b->switch_op->max_val);
|
||||
pj_k (pj, "cases");
|
||||
pj_a (pj);
|
||||
{
|
||||
RListIter *case_op_iter;
|
||||
RAnalCaseOp *case_op;
|
||||
r_list_foreach (b->switch_op->cases, case_op_iter, case_op) {
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "addr", case_op->addr);
|
||||
pj_kn (pj, "jump", case_op->jump);
|
||||
pj_kn (pj, "value", case_op->value);
|
||||
pj_kn (pj, "cond", case_op->cond);
|
||||
pj_kn (pj, "bb_ref_to", case_op->bb_ref_to);
|
||||
pj_kn (pj, "bb_ref_from", case_op->bb_ref_from);
|
||||
pj_end (pj);
|
||||
if (!strcmp (input, "*")) {
|
||||
r_cons_printf ("db 0x%08"PFMT64x"\n", retaddr);
|
||||
} else if (!strcmp (input, "-*")) {
|
||||
r_cons_printf ("db-0x%08"PFMT64x"\n", retaddr);
|
||||
} else {
|
||||
r_cons_printf ("0x%08"PFMT64x"\n", retaddr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
r_cons_printf ("f bb.%05" PFMT64x " = 0x%08" PFMT64x "\n",
|
||||
b->addr & 0xFFFFF, b->addr);
|
||||
break;
|
||||
case 'q':
|
||||
r_cons_printf ("0x%08" PFMT64x "\n", b->addr);
|
||||
break;
|
||||
case 'j':
|
||||
//r_cons_printf ("%" PFMT64u "%s", b->addr, iter->n? ",": "");
|
||||
{
|
||||
RListIter *iter2;
|
||||
RAnalBlock *b2;
|
||||
int inputs = 0;
|
||||
int outputs = 0;
|
||||
r_list_foreach (fcn->bbs, iter2, b2) {
|
||||
if (b2->jump == b->addr) {
|
||||
inputs++;
|
||||
}
|
||||
if (b2->fail == b->addr) {
|
||||
inputs++;
|
||||
}
|
||||
}
|
||||
if (b->jump != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
pj_o (pj);
|
||||
|
||||
if (b->jump != UT64_MAX) {
|
||||
pj_kn (pj, "jump", b->jump);
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
pj_kn (pj, "fail", b->fail);
|
||||
}
|
||||
if (b->switch_op) {
|
||||
pj_k (pj, "switch_op");
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "addr", b->switch_op->addr);
|
||||
pj_kn (pj, "min_val", b->switch_op->min_val);
|
||||
pj_kn (pj, "def_val", b->switch_op->def_val);
|
||||
pj_kn (pj, "max_val", b->switch_op->max_val);
|
||||
pj_k (pj, "cases");
|
||||
pj_a (pj);
|
||||
{
|
||||
RListIter *case_op_iter;
|
||||
RAnalCaseOp *case_op;
|
||||
r_list_foreach (b->switch_op->cases, case_op_iter, case_op) {
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "addr", case_op->addr);
|
||||
pj_kn (pj, "jump", case_op->jump);
|
||||
pj_kn (pj, "value", case_op->value);
|
||||
pj_kn (pj, "cond", case_op->cond);
|
||||
pj_kn (pj, "bb_ref_to", case_op->bb_ref_to);
|
||||
pj_kn (pj, "bb_ref_from", case_op->bb_ref_from);
|
||||
pj_end (pj);
|
||||
}
|
||||
}
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_kn (pj, "addr", b->addr);
|
||||
pj_ki (pj, "size", b->size);
|
||||
pj_ki (pj, "inputs", inputs);
|
||||
pj_ki (pj, "outputs", outputs);
|
||||
pj_ki (pj, "ninstr", b->ninstr);
|
||||
pj_ks (pj, "traced", r_str_bool (b->traced));
|
||||
pj_end (pj);
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_kn (pj, "addr", b->addr);
|
||||
pj_ki (pj, "size", b->size);
|
||||
pj_ki (pj, "inputs", inputs);
|
||||
pj_ki (pj, "outputs", outputs);
|
||||
pj_ki (pj, "ninstr", b->ninstr);
|
||||
pj_ks (pj, "traced", r_str_bool (b->traced));
|
||||
pj_end (pj);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
{
|
||||
RListIter *iter2;
|
||||
RAnalBlock *b2;
|
||||
int inputs = 0;
|
||||
int outputs = 0;
|
||||
r_list_foreach (fcn->bbs, iter2, b2) {
|
||||
if (b2->jump == b->addr) {
|
||||
inputs++;
|
||||
}
|
||||
if (b2->fail == b->addr) {
|
||||
inputs++;
|
||||
break;
|
||||
case 'i':
|
||||
{
|
||||
RListIter *iter2;
|
||||
RAnalBlock *b2;
|
||||
int inputs = 0;
|
||||
int outputs = 0;
|
||||
r_list_foreach (fcn->bbs, iter2, b2) {
|
||||
if (b2->jump == b->addr) {
|
||||
inputs++;
|
||||
}
|
||||
if (b2->fail == b->addr) {
|
||||
inputs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b->jump != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
if (b->switch_op) {
|
||||
RList *unique_cases = r_list_uniq (b->switch_op->cases, casecmp);
|
||||
outputs += r_list_length (unique_cases);
|
||||
r_list_free (unique_cases);
|
||||
}
|
||||
if (b->jump != UT64_MAX) {
|
||||
r_cons_printf ("jump: 0x%08"PFMT64x"\n", b->jump);
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
r_cons_printf ("fail: 0x%08"PFMT64x"\n", b->fail);
|
||||
}
|
||||
r_cons_printf ("addr: 0x%08"PFMT64x"\nsize: %d\ninputs: %d\noutputs: %d\nninstr: %d\ntraced: %s\n",
|
||||
b->addr, b->size, inputs, outputs, b->ninstr, r_str_bool (b->traced));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tp = r_debug_trace_get (core->dbg, b->addr);
|
||||
r_cons_printf ("0x%08" PFMT64x " 0x%08" PFMT64x " %02X:%04X %d",
|
||||
b->addr, b->addr + b->size,
|
||||
tp? tp->times: 0, tp? tp->count: 0,
|
||||
b->size);
|
||||
if (b->jump != UT64_MAX) {
|
||||
r_cons_printf (" j 0x%08" PFMT64x, b->jump);
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
r_cons_printf (" f 0x%08" PFMT64x, b->fail);
|
||||
}
|
||||
if (b->switch_op) {
|
||||
RAnalCaseOp *cop;
|
||||
RListIter *iter;
|
||||
RList *unique_cases = r_list_uniq (b->switch_op->cases, casecmp);
|
||||
r_list_foreach (unique_cases, iter, cop) {
|
||||
r_cons_printf (" s 0x%08" PFMT64x, cop->addr);
|
||||
if (b->jump != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
r_list_free (unique_cases);
|
||||
if (b->fail != UT64_MAX) {
|
||||
outputs ++;
|
||||
}
|
||||
if (b->switch_op) {
|
||||
RList *unique_cases = r_list_uniq (b->switch_op->cases, casecmp);
|
||||
outputs += r_list_length (unique_cases);
|
||||
r_list_free (unique_cases);
|
||||
}
|
||||
if (b->jump != UT64_MAX) {
|
||||
r_cons_printf ("jump: 0x%08"PFMT64x"\n", b->jump);
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
r_cons_printf ("fail: 0x%08"PFMT64x"\n", b->fail);
|
||||
}
|
||||
r_cons_printf ("addr: 0x%08"PFMT64x"\nsize: %d\ninputs: %d\noutputs: %d\nninstr: %d\ntraced: %s\n",
|
||||
b->addr, b->size, inputs, outputs, b->ninstr, r_str_bool (b->traced));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tp = r_debug_trace_get (core->dbg, b->addr);
|
||||
r_cons_printf ("0x%08" PFMT64x " 0x%08" PFMT64x " %02X:%04X %d",
|
||||
b->addr, b->addr + b->size,
|
||||
tp? tp->times: 0, tp? tp->count: 0,
|
||||
b->size);
|
||||
if (b->jump != UT64_MAX) {
|
||||
r_cons_printf (" j 0x%08" PFMT64x, b->jump);
|
||||
}
|
||||
if (b->fail != UT64_MAX) {
|
||||
r_cons_printf (" f 0x%08" PFMT64x, b->fail);
|
||||
}
|
||||
if (b->switch_op) {
|
||||
RAnalCaseOp *cop;
|
||||
RListIter *iter;
|
||||
RList *unique_cases = r_list_uniq (b->switch_op->cases, casecmp);
|
||||
r_list_foreach (unique_cases, iter, cop) {
|
||||
r_cons_printf (" s 0x%08" PFMT64x, cop->addr);
|
||||
}
|
||||
r_list_free (unique_cases);
|
||||
}
|
||||
r_cons_newline ();
|
||||
break;
|
||||
}
|
||||
r_cons_newline ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mode == 't') {
|
||||
|
@ -2292,14 +2294,15 @@ static bool anal_fcn_del_bb(RCore *core, const char *input) {
|
|||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, -1);
|
||||
if (fcn) {
|
||||
if (!strcmp (input, "*")) {
|
||||
r_list_free (fcn->bbs);
|
||||
fcn->bbs = NULL;
|
||||
while (!r_list_empty (fcn->bbs)) {
|
||||
r_anal_function_remove_block (fcn, r_list_first (fcn->bbs));
|
||||
}
|
||||
} else {
|
||||
RAnalBlock *b;
|
||||
RListIter *iter;
|
||||
r_list_foreach (fcn->bbs, iter, b) {
|
||||
if (b->addr == addr) {
|
||||
r_list_delete (fcn->bbs, iter);
|
||||
r_anal_function_remove_block (fcn, b);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2350,13 +2353,12 @@ static int anal_fcn_add_bb(RCore *core, const char *input) {
|
|||
case 1: // get fcnaddr
|
||||
fcnaddr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
||||
}
|
||||
fcn = r_anal_get_fcn_in (core->anal, fcnaddr, 0);
|
||||
fcn = r_anal_get_function_at (core->anal, fcnaddr);
|
||||
if (fcn) {
|
||||
if (!r_anal_fcn_add_bb (core->anal, fcn, addr, size, jump, fail, type, diff))
|
||||
//if (!r_anal_fcn_add_bb_raw (core->anal, fcn, addr, size, jump, fail, type, diff))
|
||||
{
|
||||
eprintf ("afb+: Cannot add basic block at 0x%08"PFMT64x"\n", addr);
|
||||
eprintf ("# %s\n", input);
|
||||
}
|
||||
} else {
|
||||
eprintf ("afb+ Cannot find function at 0x%" PFMT64x " from 0x%08"PFMT64x" -> 0x%08"PFMT64x"\n",
|
||||
|
@ -2531,13 +2533,13 @@ static bool __setFunctionName(RCore *core, ut64 addr, const char *_name, bool pr
|
|||
r_return_val_if_fail (core && _name, false);
|
||||
char *name = getFunctionName (core, addr, _name, prefix);
|
||||
// RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, R_ANAL_FCN_TYPE_ANY);
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, addr, R_ANAL_FCN_TYPE_ANY);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, addr);
|
||||
if (fcn) {
|
||||
free (fcn->name);
|
||||
fcn->name = name;
|
||||
r_anal_function_rename (fcn, name);
|
||||
if (core->anal->cb.on_fcn_rename) {
|
||||
core->anal->cb.on_fcn_rename (core->anal, core->anal->user, fcn, name);
|
||||
}
|
||||
free (name);
|
||||
return true;
|
||||
}
|
||||
free (name);
|
||||
|
@ -2896,7 +2898,6 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
r_anal_del_jmprefs (core->anal, f);
|
||||
}
|
||||
r_list_purge (core->anal->fcns);
|
||||
core->anal->fcn_tree = NULL;
|
||||
core->anal->fcn_addr_tree = NULL;
|
||||
} else {
|
||||
ut64 addr = input[2]
|
||||
|
@ -2970,9 +2971,6 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 'f': // "aff"
|
||||
r_anal_fcn_fit_overlaps (core->anal, NULL);
|
||||
break;
|
||||
case 'u': // "afu"
|
||||
{
|
||||
if (input[2] != ' ') {
|
||||
|
@ -3021,13 +3019,10 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
int n = r_str_word_set0 (ptr);
|
||||
const char *name = NULL;
|
||||
ut64 addr = UT64_MAX;
|
||||
ut64 size = 0LL;
|
||||
RAnalDiff *diff = NULL;
|
||||
int type = R_ANAL_FCN_TYPE_FCN;
|
||||
if (n > 1) {
|
||||
switch (n) {
|
||||
case 5:
|
||||
size = r_num_math (core->num, r_str_word_get0 (ptr, 4));
|
||||
case 4:
|
||||
ptr2 = r_str_word_get0 (ptr, 3);
|
||||
if (!(diff = r_anal_diff_new ())) {
|
||||
|
@ -3056,7 +3051,8 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
case 1:
|
||||
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
||||
}
|
||||
if (!r_anal_fcn_add (core->anal, addr, size, name, type, diff)) {
|
||||
RAnalFunction *fcn = r_anal_create_function (core->anal, name, addr, type, diff);
|
||||
if (!fcn) {
|
||||
eprintf ("Cannot add function (duplicated)\n");
|
||||
}
|
||||
}
|
||||
|
@ -3097,7 +3093,7 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
{
|
||||
ut64 addr = core->offset;
|
||||
RListIter *iter;
|
||||
RList *list = r_anal_get_fcn_in_list (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
||||
RList *list = r_anal_get_functions_in (core->anal, addr);
|
||||
RAnalFunction *fcn;
|
||||
r_list_foreach (list, iter, fcn) {
|
||||
r_cons_printf ("= 0x%08" PFMT64x "\n", fcn->addr);
|
||||
|
@ -3508,10 +3504,8 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
if (fcn) {
|
||||
int bits = atoi (input + 3);
|
||||
r_anal_hint_set_bits (core->anal, fcn->addr, bits);
|
||||
r_anal_hint_set_bits (core->anal,
|
||||
fcn->addr + r_anal_fcn_size (fcn),
|
||||
core->anal->bits);
|
||||
r_anal_hint_set_bits (core->anal, r_anal_function_min_addr (fcn), bits);
|
||||
r_anal_hint_set_bits (core->anal, r_anal_function_max_addr (fcn), core->anal->bits);
|
||||
fcn->bits = bits;
|
||||
} else {
|
||||
eprintf ("afB: Cannot find function to set bits at 0x%08"PFMT64x"\n", core->offset);
|
||||
|
@ -3814,7 +3808,7 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
r_core_anal_fcn (core, ref->addr, fcn->addr, R_ANAL_REF_TYPE_CALL, depth);
|
||||
/* use recursivity here */
|
||||
#if 1
|
||||
RAnalFunction *f = r_anal_get_fcn_at (core->anal, ref->addr, 0);
|
||||
RAnalFunction *f = r_anal_get_function_at (core->anal, ref->addr);
|
||||
if (f) {
|
||||
RListIter *iter;
|
||||
RAnalRef *ref;
|
||||
|
@ -3837,7 +3831,7 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
|||
r_anal_fcn_resize (core->anal, f, addr - fcn->addr);
|
||||
r_core_anal_fcn (core, ref->addr, fcn->addr,
|
||||
R_ANAL_REF_TYPE_CALL, depth);
|
||||
f = r_anal_get_fcn_at (core->anal, fcn->addr, 0);
|
||||
f = r_anal_get_function_at (core->anal, fcn->addr);
|
||||
}
|
||||
if (!f) {
|
||||
eprintf ("af: Cannot find function at 0x%08" PFMT64x "\n", fcn->addr);
|
||||
|
@ -5947,7 +5941,7 @@ static void cmd_anal_esil(RCore *core, const char *input) {
|
|||
} else if (input[1] == 'f') {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
||||
if (fcn) {
|
||||
cmd_aea (core, 1, fcn->addr, r_anal_fcn_size (fcn));
|
||||
cmd_aea (core, 1, r_anal_function_min_addr (fcn), r_anal_function_linear_size (fcn));
|
||||
}
|
||||
} else {
|
||||
cmd_aea (core, 1, core->offset, (int)r_num_math (core->num, input+2));
|
||||
|
@ -5981,10 +5975,10 @@ static void cmd_anal_esil(RCore *core, const char *input) {
|
|||
if (fcn) {
|
||||
switch (input[2]) {
|
||||
case 'j': // "aeafj"
|
||||
cmd_aea (core, 1<<4, fcn->addr, r_anal_fcn_size (fcn));
|
||||
cmd_aea (core, 1<<4, r_anal_function_min_addr (fcn), r_anal_function_linear_size (fcn));
|
||||
break;
|
||||
default:
|
||||
cmd_aea (core, 1, fcn->addr, r_anal_fcn_size (fcn));
|
||||
cmd_aea (core, 1, r_anal_function_min_addr (fcn), r_anal_function_linear_size (fcn));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -6804,7 +6798,7 @@ static void anal_axg (RCore *core, const char *input, int level, Sdb *db, int op
|
|||
}
|
||||
|
||||
static void cmd_anal_ucall_ref (RCore *core, ut64 addr) {
|
||||
RAnalFunction * fcn = r_anal_get_fcn_at (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
||||
RAnalFunction * fcn = r_anal_get_function_at (core->anal, addr);
|
||||
if (fcn) {
|
||||
r_cons_printf (" ; %s", fcn->name);
|
||||
} else {
|
||||
|
@ -8475,7 +8469,7 @@ static int compute_coverage(RCore *core) {
|
|||
ls_foreach (core->io->maps, iter2, map) {
|
||||
if (map->perm & R_PERM_X) {
|
||||
ut64 section_end = map->itv.addr + map->itv.size;
|
||||
ut64 s = r_anal_fcn_realsize (fcn);
|
||||
ut64 s = r_anal_function_realsize (fcn);
|
||||
if (fcn->addr >= map->itv.addr && (fcn->addr + s) < section_end) {
|
||||
cov += s;
|
||||
}
|
||||
|
@ -9141,7 +9135,7 @@ static int cmd_anal_all(RCore *core, const char *input) {
|
|||
RListIter *it;
|
||||
if (off && *off) {
|
||||
ut64 addr = r_num_math (NULL, off);
|
||||
fcn = r_anal_get_fcn_at (core->anal, core->offset, 0);
|
||||
fcn = r_anal_get_function_at (core->anal, core->offset);
|
||||
if (fcn) {
|
||||
r_core_link_stroff (core, fcn);
|
||||
} else {
|
||||
|
@ -9205,7 +9199,7 @@ static int cmd_anal_all(RCore *core, const char *input) {
|
|||
|
||||
static bool anal_fcn_data (RCore *core, const char *input) {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
|
||||
ut32 fcn_size = r_anal_fcn_size (fcn);
|
||||
ut32 fcn_size = r_anal_function_size_from_entry (fcn);
|
||||
if (fcn) {
|
||||
int i;
|
||||
bool gap = false;
|
||||
|
@ -9265,7 +9259,7 @@ static bool anal_fcn_data_gaps (RCore *core, const char *input) {
|
|||
//r_cons_printf ("Cd %d @ 0x%08"PFMT64x"\n", range, end);
|
||||
}
|
||||
}
|
||||
end = fcn->addr + r_anal_fcn_size (fcn);
|
||||
end = fcn->addr + r_anal_function_size_from_entry (fcn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -9651,7 +9645,7 @@ bool go_on = true;
|
|||
const char *fcn_name = NULL;
|
||||
RAnalFunction *fcn;
|
||||
if (go_on) {
|
||||
fcn = r_anal_get_fcn_at (core->anal, pcv, 0);
|
||||
fcn = r_anal_get_function_at (core->anal, pcv);
|
||||
if (fcn) {
|
||||
fcn_name = fcn->name;
|
||||
} else {
|
||||
|
|
|
@ -974,19 +974,7 @@ static void __rebase_everything(RCore *core, RList *old_sections, ut64 old_base)
|
|||
continue;
|
||||
}
|
||||
r_anal_var_rebase (core->anal, fcn, diff);
|
||||
r_anal_fcn_tree_delete (core->anal, fcn);
|
||||
fcn->addr += diff;
|
||||
if (fcn->meta.max) {
|
||||
fcn->meta.max += diff;
|
||||
}
|
||||
if (fcn->meta.min) {
|
||||
fcn->meta.min += diff;
|
||||
}
|
||||
int j;
|
||||
for (j = 0; j < fcn->bbr.pairs * 2; j++) {
|
||||
fcn->bbr.ranges[j] += diff;
|
||||
}
|
||||
r_anal_fcn_tree_insert (core->anal, fcn);
|
||||
r_anal_function_relocate (fcn, fcn->addr + diff);
|
||||
RAnalBlock *bb;
|
||||
ut64 new_sec_addr = new_base + old_section->vaddr;
|
||||
r_list_foreach (fcn->bbs, ititit, bb) {
|
||||
|
@ -994,7 +982,7 @@ static void __rebase_everything(RCore *core, RList *old_sections, ut64 old_base)
|
|||
// Todo: Find better way to check if bb was already rebased
|
||||
continue;
|
||||
}
|
||||
bb->addr += diff;
|
||||
r_anal_block_relocate (bb, bb->addr + diff, bb->size);
|
||||
if (bb->jump != UT64_MAX) {
|
||||
bb->jump += diff;
|
||||
}
|
||||
|
|
|
@ -3920,9 +3920,7 @@ static void _pointer_table(RCore *core, ut64 origin, ut64 offset, const ut8 *buf
|
|||
|
||||
// TODO: this function is a temporary fix. All analysis should be based on realsize. However, now for same architectures realisze is not used
|
||||
static ut32 tmp_get_contsize(RAnalFunction *f) {
|
||||
int size = r_anal_fcn_contsize (f);
|
||||
size = (size > 0)? size: r_anal_fcn_size (f);
|
||||
return (size < 0)? 0: size;
|
||||
return r_anal_function_linear_size (f);
|
||||
}
|
||||
|
||||
static void __printPattern(RCore *core, const char *_input) {
|
||||
|
@ -4460,7 +4458,7 @@ static void func_walk_blocks(RCore *core, RAnalFunction *f, char input, char typ
|
|||
// XXX: hack must be reviewed/fixed in code analysis
|
||||
if (!b) {
|
||||
if (r_list_length (f->bbs) >= 1) {
|
||||
ut32 fcn_size = r_anal_fcn_realsize (f);
|
||||
ut32 fcn_size = r_anal_function_realsize (f);
|
||||
b = r_list_get_top (f->bbs);
|
||||
if (b->size > fcn_size) {
|
||||
b->size = fcn_size;
|
||||
|
@ -5007,7 +5005,7 @@ static int cmd_print(void *data, const char *input) {
|
|||
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
// R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
||||
if (f) {
|
||||
len = r_anal_fcn_size (f);
|
||||
len = r_anal_function_linear_size (f);
|
||||
if (len > core->blocksize) {
|
||||
len = core->blocksize;
|
||||
}
|
||||
|
@ -5296,7 +5294,7 @@ static int cmd_print(void *data, const char *input) {
|
|||
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
||||
if (f) {
|
||||
r_core_print_disasm_instructions (core,
|
||||
r_anal_fcn_size (f), 0);
|
||||
r_anal_function_linear_size ((RAnalFunction *) f), 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5448,8 +5446,8 @@ static int cmd_print(void *data, const char *input) {
|
|||
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
||||
if (f) {
|
||||
ut32 bsz = core->blocksize;
|
||||
// int fsz = r_anal_fcn_realsize (f);
|
||||
int fsz = r_anal_fcn_size (f); // we want max-min here
|
||||
// int fsz = r_anal_function_realsize (f);
|
||||
int fsz = r_anal_function_linear_size (f); // we want max-min here
|
||||
r_core_block_size (core, fsz);
|
||||
r_core_print_disasm_instructions (core, fsz, 0);
|
||||
r_core_block_size (core, bsz);
|
||||
|
@ -5670,8 +5668,8 @@ static int cmd_print(void *data, const char *input) {
|
|||
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset,
|
||||
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
||||
if (f) {
|
||||
ut32 rs = r_anal_fcn_realsize (f);
|
||||
ut32 fs = r_anal_fcn_size (f);
|
||||
ut32 rs = r_anal_function_realsize (f);
|
||||
ut32 fs = r_anal_function_linear_size (f);
|
||||
r_core_seek (core, oseek, SEEK_SET);
|
||||
r_core_block_size (core, R_MAX (rs, fs));
|
||||
disasm_strings (core, input, f);
|
||||
|
@ -5694,10 +5692,9 @@ static int cmd_print(void *data, const char *input) {
|
|||
if (f && input[2] == 'j') { // "pdfj"
|
||||
ut8 *loc_buf = NULL;
|
||||
RAnalBlock *b;
|
||||
ut32 fcn_size = r_anal_fcn_realsize (f);
|
||||
ut32 fcn_size = r_anal_function_realsize (f);
|
||||
const char *orig_bb_middle = r_config_get (core->config, "asm.bb.middle");
|
||||
r_config_set_i (core->config, "asm.bb.middle", false);
|
||||
cont_size = tmp_get_contsize (f);
|
||||
pj = pj_new ();
|
||||
if (!pj) {
|
||||
break;
|
||||
|
@ -5709,7 +5706,7 @@ static int cmd_print(void *data, const char *input) {
|
|||
pj_k (pj, "ops");
|
||||
pj_a (pj);
|
||||
// instructions are all outputted as a json list
|
||||
// DEAD CODE cont_size = f->_size > 0 ? f->_size : r_anal_fcn_realsize (f);
|
||||
// DEAD CODE cont_size = f->_size > 0 ? f->_size : r_anal_function_realsize (f);
|
||||
// TODO: can loc jump to another locs?
|
||||
for (; locs_it && (tmp_func = locs_it->data); locs_it = locs_it->n) {
|
||||
if (tmp_func->addr > f->addr) {
|
||||
|
@ -5721,6 +5718,7 @@ static int cmd_print(void *data, const char *input) {
|
|||
r_core_print_disasm_json (core, tmp_func->addr, loc_buf, cont_size, 0, pj);
|
||||
free (loc_buf);
|
||||
}
|
||||
r_list_sort (f->bbs, bb_cmpaddr);
|
||||
r_list_foreach (f->bbs, locs_it, b) {
|
||||
|
||||
ut8 *buf = malloc (b->size);
|
||||
|
@ -5758,20 +5756,18 @@ static int cmd_print(void *data, const char *input) {
|
|||
}
|
||||
cont_size = tmp_get_contsize (f);
|
||||
#endif
|
||||
ut32 linear = f->_size;
|
||||
ut32 bbsum = r_anal_fcn_realsize (f);
|
||||
if (bbsum + 4096 < linear) {
|
||||
ut64 linearsz = r_anal_function_linear_size (f);
|
||||
ut64 realsz = r_anal_function_realsize (f);
|
||||
if (realsz + 4096 < linearsz) {
|
||||
eprintf ("Linear size differs too much from the bbsum, please use pdr instead.\n");
|
||||
} else {
|
||||
ut64 at = f->addr;
|
||||
ut64 sz = f->_size > 0 ? f->_size : r_anal_fcn_realsize (f);
|
||||
ut32 rs = r_anal_fcn_realsize (f);
|
||||
sz = R_MAX (sz, rs);
|
||||
ut64 at = f->addr; // TODO: should be min from r_anal_fcn_get_range()?
|
||||
ut64 sz = R_MAX (linearsz, realsz);
|
||||
ut8 *buf = calloc (sz, 1);
|
||||
(void)r_io_read_at (core->io, at, buf, sz);
|
||||
core->num->value = r_core_print_disasm (core->print, core, at, buf, sz, sz, 0, 1, 0, NULL, f);
|
||||
free (buf);
|
||||
// r_core_cmdf (core, "pD %d @ 0x%08" PFMT64x, f->_size > 0 ? f->_size: r_anal_fcn_realsize (f), f->addr);
|
||||
// r_core_cmdf (core, "pD %d @ 0x%08" PFMT64x, f->_size > 0 ? f->_size: r_anal_function_realsize (f), f->addr);
|
||||
}
|
||||
#if 0
|
||||
for (; locs_it && (tmp_func = locs_it->data); locs_it = locs_it->n) {
|
||||
|
|
|
@ -837,7 +837,7 @@ R_API RList *r_core_get_boundaries_prot(RCore *core, int perm, const char *mode,
|
|||
RAnalFunction *f = r_anal_get_fcn_in (core->anal, core->offset,
|
||||
R_ANAL_FCN_TYPE_FCN | R_ANAL_FCN_TYPE_SYM);
|
||||
if (f) {
|
||||
ut64 from = f->addr, size = r_anal_fcn_size (f);
|
||||
ut64 from = f->addr, size = r_anal_function_size_from_entry (f);
|
||||
|
||||
/* Search only inside the basic block */
|
||||
if (!strcmp (mode, "anal.bb")) {
|
||||
|
@ -3724,7 +3724,7 @@ reread:
|
|||
if (input[1]) {
|
||||
addr = r_num_math (core->num, input + 2);
|
||||
} else {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, addr, 0);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, addr);
|
||||
if (fcn) {
|
||||
addr = fcn->addr;
|
||||
} else {
|
||||
|
|
|
@ -729,7 +729,7 @@ static int cmd_seek(void *data, const char *input) {
|
|||
case '\0': // "sf"
|
||||
fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
if (fcn) {
|
||||
r_core_seek (core, fcn->addr + r_anal_fcn_size (fcn), 1);
|
||||
r_core_seek (core, r_anal_function_max_addr (fcn), 1);
|
||||
}
|
||||
break;
|
||||
case ' ': // "sf "
|
||||
|
|
|
@ -1369,7 +1369,7 @@ static int cmd_type(void *data, const char *input) {
|
|||
switch (input[1]) {
|
||||
case '.': // "tx." type xrefs
|
||||
case 'f': // "txf" type xrefs
|
||||
fcn = r_anal_get_fcn_at (core->anal, core->offset, 0);
|
||||
fcn = r_anal_get_function_at (core->anal, core->offset);
|
||||
if (fcn) {
|
||||
RList *uniq = r_anal_types_from_fcn (core->anal, fcn);
|
||||
r_list_foreach (uniq , iter , type) {
|
||||
|
|
|
@ -100,7 +100,7 @@ static bool addFcnHash(RCore *core, RAnalFunction *fcn, const char *name) {
|
|||
static bool addFcnBytes(RCore *core, RAnalFunction *fcn, const char *name) {
|
||||
r_return_val_if_fail (core && fcn && name, false);
|
||||
int maxsz = r_config_get_i (core->config, "zign.maxsz");
|
||||
int fcnlen = r_anal_fcn_realsize (fcn);
|
||||
int fcnlen = r_anal_function_realsize (fcn);
|
||||
int len = R_MIN (core->io->addrbytes * fcnlen, maxsz);
|
||||
|
||||
ut8 *buf = malloc (len);
|
||||
|
@ -126,7 +126,7 @@ static bool addFcnGraph(RCore *core, RAnalFunction *fcn, const char *name) {
|
|||
};
|
||||
// XXX ebbs doesnt gets initialized if calling this from inside the struct
|
||||
graph.edges = r_anal_fcn_count_edges (fcn, &graph.ebbs);
|
||||
graph.bbsum = r_anal_fcn_size (fcn);
|
||||
graph.bbsum = r_anal_function_realsize (fcn);
|
||||
return r_sign_add_graph (core->anal, name, graph);
|
||||
}
|
||||
|
||||
|
@ -758,7 +758,7 @@ static int searchHitCB(RSignItem *it, RSearchKeyword *kw, ut64 addr, void *user)
|
|||
static int fcnMatchCB(RSignItem *it, RAnalFunction *fcn, void *user) {
|
||||
struct ctxSearchCB *ctx = (struct ctxSearchCB *) user;
|
||||
// TODO(nibble): use one counter per metric zign instead of ctx->count
|
||||
addFlag (ctx->core, it, fcn->addr, r_anal_fcn_realsize (fcn), ctx->count, ctx->prefix, ctx->rad);
|
||||
addFlag (ctx->core, it, fcn->addr, r_anal_function_realsize (fcn), ctx->count, ctx->prefix, ctx->rad);
|
||||
ctx->count++;
|
||||
return 1;
|
||||
}
|
||||
|
@ -917,7 +917,7 @@ static bool search(RCore *core, bool rad, bool only_func) {
|
|||
}
|
||||
if (useBytes && only_func) {
|
||||
eprintf ("Matching func %d / %d (hits %d)\n", count, r_list_length (core->anal->fcns), bytes_search_ctx.count);
|
||||
int fcnlen = r_anal_fcn_realsize (fcni);
|
||||
int fcnlen = r_anal_function_realsize (fcni);
|
||||
int len = R_MIN (core->io->addrbytes * fcnlen, maxsz);
|
||||
retval &= searchRange2 (core, ss, fcni->addr, fcni->addr + len, rad, &bytes_search_ctx);
|
||||
}
|
||||
|
|
|
@ -298,11 +298,11 @@ static bool __isMapped(RCore *core, ut64 addr, int perm) {
|
|||
return r_io_map_is_mapped (core->io, addr);
|
||||
}
|
||||
|
||||
static int __syncDebugMaps(RCore *core) {
|
||||
static bool __syncDebugMaps(RCore *core) {
|
||||
if (r_config_get_i (core->config, "cfg.debug")) {
|
||||
return r_debug_map_sync (core->dbg);
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
R_API int r_core_bind(RCore *core, RCoreBind *bnd) {
|
||||
|
@ -505,7 +505,7 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
|
|||
if (!off) {
|
||||
off = core->offset;
|
||||
}
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, off, 0);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, off);
|
||||
if (fcn) {
|
||||
if (ok) {
|
||||
*ok = true;
|
||||
|
@ -786,8 +786,8 @@ static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
|
|||
switch (str[2]) {
|
||||
/* function bounds (uppercase) */
|
||||
case 'B': return fcn->addr; // begin
|
||||
case 'E': return fcn->addr + fcn->_size; // end
|
||||
case 'S': return (str[3]=='S')? r_anal_fcn_realsize (fcn): r_anal_fcn_size (fcn);
|
||||
case 'E': return r_anal_function_max_addr (fcn); // end
|
||||
case 'S': return (str[3]=='S') ? r_anal_function_realsize (fcn) : r_anal_function_linear_size (fcn);
|
||||
case 'I': return fcn->ninstr;
|
||||
/* basic blocks (lowercase) */
|
||||
case 'b': return bbBegin (fcn, core->offset);
|
||||
|
|
|
@ -353,7 +353,7 @@ R_API ut64 r_core_pava (RCore *core, ut64 addr) {
|
|||
}
|
||||
|
||||
static RAnalFunction *fcnIn(RDisasmState *ds, ut64 at, int type) {
|
||||
if (ds->fcn && r_tinyrange_in (&ds->fcn->bbr, at)) {
|
||||
if (ds->fcn && r_anal_function_contains (ds->fcn, at)) {
|
||||
return ds->fcn;
|
||||
}
|
||||
return r_anal_get_fcn_in (ds->core->anal, at, type);
|
||||
|
@ -1299,8 +1299,7 @@ static void ds_show_refs(RDisasmState *ds) {
|
|||
r_io_read_at (ds->core->io, ref->at, buf, sizeof (buf));
|
||||
r_anal_op (ds->core->anal, &aop, ref->at, buf, sizeof (buf), R_ANAL_OP_MASK_ALL);
|
||||
if ((aop.type & R_ANAL_OP_TYPE_MASK) == R_ANAL_OP_TYPE_UCALL) {
|
||||
RAnalFunction * fcn = r_anal_get_fcn_at (ds->core->anal,
|
||||
ref->addr, R_ANAL_FCN_TYPE_NULL);
|
||||
RAnalFunction * fcn = r_anal_get_function_at (ds->core->anal, ref->addr);
|
||||
ds_begin_comment (ds);
|
||||
if (fcn) {
|
||||
ds_comment (ds, true, "; %s", fcn->name);
|
||||
|
@ -1441,7 +1440,7 @@ static void ds_show_xrefs(RDisasmState *ds) {
|
|||
ds_comment (ds, false, "%s%s0x%"PFMT64x, it == addrs->head ? "" : ", ", plus, *addrptr);
|
||||
}
|
||||
}
|
||||
if (realname && (!fun || r_anal_get_fcn_at (core->anal, ds->at, R_ANAL_FCN_TYPE_ROOT))) {
|
||||
if (realname && (!fun || r_anal_get_function_at (core->anal, ds->at))) {
|
||||
const char *pad = ds->show_comment_right ? "" : " ";
|
||||
if (!ds->show_comment_right) {
|
||||
ds_newline (ds);
|
||||
|
@ -1662,8 +1661,8 @@ static void ds_pre_xrefs(RDisasmState *ds, bool no_fcnlines) {
|
|||
|
||||
//TODO: this function is a temporary fix. All analysis should be based on realsize. However, now for same architectures realisze is not used
|
||||
static ut32 tmp_get_realsize (RAnalFunction *f) {
|
||||
ut32 size = r_anal_fcn_realsize (f);
|
||||
return (size > 0) ? size : r_anal_fcn_size (f);
|
||||
ut32 size = r_anal_function_realsize (f);
|
||||
return (size > 0) ? size : r_anal_function_linear_size (f);
|
||||
}
|
||||
|
||||
static void ds_show_functions_argvar(RDisasmState *ds, RAnalVar *var, const char *base, bool is_var, char sign) {
|
||||
|
@ -1803,8 +1802,8 @@ static void ds_show_functions(RDisasmState *ds) {
|
|||
bool showSig = ds->show_fcnsig && ds->show_calls;
|
||||
bool call = r_config_get_i (core->config, "asm.calls");
|
||||
const char *lang = demangle ? r_config_get (core->config, "bin.lang") : NULL;
|
||||
f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
|
||||
if (!f || (f->addr != ds->at)) {
|
||||
f = r_anal_get_function_at (core->anal, ds->at);
|
||||
if (!f) {
|
||||
return;
|
||||
}
|
||||
if (demangle) {
|
||||
|
@ -1824,8 +1823,8 @@ static void ds_show_functions(RDisasmState *ds) {
|
|||
r_cons_printf ("%s%s ", COLOR (ds, color_fline),
|
||||
core->cons->vline[LINE_CROSS]); // |-
|
||||
if (!showSig) {
|
||||
r_cons_printf ("%s%s%s %d", COLOR (ds, color_floc),
|
||||
fcn_name, COLOR_RESET (ds), r_anal_fcn_size (f));
|
||||
r_cons_printf ("%s%s%s %"PFMT64u, COLOR (ds, color_floc),
|
||||
fcn_name, COLOR_RESET (ds), r_anal_function_linear_size (f));
|
||||
ds_newline (ds);
|
||||
}
|
||||
} else {
|
||||
|
@ -1893,7 +1892,7 @@ static void ds_show_functions(RDisasmState *ds) {
|
|||
ds_print_pre (ds, true);
|
||||
r_cons_printf ("%s ", COLOR_RESET (ds));
|
||||
}
|
||||
r_cons_printf ("%d: ", r_anal_fcn_realsize (f));
|
||||
r_cons_printf ("%d: ", r_anal_function_realsize (f));
|
||||
char *sig = r_anal_fcn_format_sig (core->anal, f, fcn_name, &vars_cache, COLOR (ds, color_fname), COLOR_RESET (ds));
|
||||
if (sig) {
|
||||
r_cons_print (sig);
|
||||
|
@ -2019,14 +2018,14 @@ static void ds_setup_pre(RDisasmState *ds, bool tail, bool middle) {
|
|||
RAnalFunction *f = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
|
||||
if (f) {
|
||||
if (f->addr == ds->at) {
|
||||
if (ds->analop.size == r_anal_fcn_size (f) && !middle) {
|
||||
if (ds->analop.size == r_anal_function_linear_size (f) && !middle) {
|
||||
ds->pre = DS_PRE_FCN_TAIL;
|
||||
} else {
|
||||
ds->pre = DS_PRE_FCN_MIDDLE;
|
||||
}
|
||||
} else if (f->addr + r_anal_fcn_size (f) - ds->analop.size == ds->at) {
|
||||
} else if (r_anal_function_max_addr (f) - ds->analop.size == ds->at && f->addr == r_anal_function_min_addr (f)) {
|
||||
ds->pre = DS_PRE_FCN_TAIL;
|
||||
} else if (r_anal_fcn_is_in_offset (f, ds->at)) {
|
||||
} else if (r_anal_function_contains (f, ds->at)) {
|
||||
ds->pre = DS_PRE_FCN_MIDDLE;
|
||||
}
|
||||
if (tail) {
|
||||
|
@ -2236,7 +2235,7 @@ static void ds_show_flags(RDisasmState *ds) {
|
|||
char addr[64];
|
||||
ut64 switch_addr = UT64_MAX;
|
||||
int case_start = -1, case_prev = 0, case_current = 0;
|
||||
f = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
|
||||
f = r_anal_get_function_at (ds->core->anal, ds->at);
|
||||
const RList *flaglist = r_flag_get_list (core->flags, ds->at);
|
||||
RList *uniqlist = flaglist? r_list_uniq (flaglist, flagCmp): NULL;
|
||||
int count = 0;
|
||||
|
@ -2753,7 +2752,7 @@ static void ds_print_offset(RDisasmState *ds) {
|
|||
unsigned int seggrn = r_config_get_i (core->config, "asm.seggrn");
|
||||
|
||||
if (ds->show_reloff) {
|
||||
RAnalFunction *f = r_anal_get_fcn_at (core->anal, at, R_ANAL_FCN_TYPE_NULL);
|
||||
RAnalFunction *f = r_anal_get_function_at (core->anal, at);
|
||||
if (!f) {
|
||||
f = fcnIn (ds, at, R_ANAL_FCN_TYPE_NULL); // r_anal_get_fcn_in (core->anal, at, R_ANAL_FCN_TYPE_NULL);
|
||||
}
|
||||
|
@ -4509,7 +4508,7 @@ static void ds_print_bbline(RDisasmState *ds) {
|
|||
RAnalBlock *bb = NULL;
|
||||
RAnalFunction *f_before = NULL;
|
||||
if (ds->fcn) {
|
||||
bb = r_anal_fcn_bbget_at (ds->fcn, ds->at);
|
||||
bb = r_anal_fcn_bbget_at (ds->core->anal, ds->fcn, ds->at);
|
||||
} else {
|
||||
f_before = fcnIn (ds, ds->at - 1, R_ANAL_FCN_TYPE_NULL);
|
||||
}
|
||||
|
@ -4679,7 +4678,7 @@ static void ds_print_esil_anal(RDisasmState *ds) {
|
|||
case R_ANAL_OP_TYPE_JMP:
|
||||
{
|
||||
ut64 addr = ds->analop.jump;
|
||||
if (!r_anal_get_fcn_at (ds->core->anal, addr, R_ANAL_FCN_TYPE_NULL)
|
||||
if (!r_anal_get_function_at (ds->core->anal, addr)
|
||||
&& !r_flag_get_at (core->flags, addr, false)) {
|
||||
break;
|
||||
}
|
||||
|
@ -4706,7 +4705,7 @@ static void ds_print_esil_anal(RDisasmState *ds) {
|
|||
}
|
||||
}
|
||||
}
|
||||
fcn = r_anal_get_fcn_at (core->anal, pcv, 0);
|
||||
fcn = r_anal_get_function_at (core->anal, pcv);
|
||||
if (fcn) {
|
||||
fcn_name = fcn->name;
|
||||
} else {
|
||||
|
@ -5055,7 +5054,7 @@ static char *ds_sub_jumps(RDisasmState *ds, char *str) {
|
|||
}
|
||||
ut64 addr = ds->analop.jump;
|
||||
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (anal, addr, 0);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (anal, addr);
|
||||
if (fcn) {
|
||||
if (!set_jump_realname (ds, addr, &kw, &name)) {
|
||||
name = fcn->name;
|
||||
|
@ -5287,8 +5286,8 @@ toro:
|
|||
}
|
||||
// f = r_anal_get_fcn_in (core->anal, ds->at, R_ANAL_FCN_TYPE_NULL);
|
||||
f = ds->fcn = fcnIn (ds, ds->at, R_ANAL_FCN_TYPE_NULL);
|
||||
if (f && f->folded && r_anal_fcn_is_in_offset (f, ds->at)) {
|
||||
int delta = (ds->at <= f->addr)? (ds->at - f->addr + r_anal_fcn_size (f)): 0;
|
||||
if (f && f->folded && r_anal_function_contains (f, ds->at)) {
|
||||
int delta = (ds->at <= f->addr) ? (ds->at - r_anal_function_max_addr (f)) : 0;
|
||||
if (of != f) {
|
||||
char cmt[32];
|
||||
get_bits_comment (core, f, cmt, sizeof (cmt));
|
||||
|
@ -5304,7 +5303,7 @@ toro:
|
|||
ds_setup_print_pre (ds, true, false);
|
||||
ds_print_lines_left (ds);
|
||||
ds_print_offset (ds);
|
||||
r_cons_printf ("(%d byte folded function)\n", r_anal_fcn_size (f));
|
||||
r_cons_printf ("(%d byte folded function)\n", r_anal_function_linear_size (f));
|
||||
//r_cons_printf ("%s%s%s\n", COLOR (ds, color_fline), core->cons->vline[RDWN_CORNER], COLOR_RESET (ds));
|
||||
if (delta < 0) {
|
||||
delta = -delta;
|
||||
|
@ -5465,7 +5464,7 @@ toro:
|
|||
if (fcn) {
|
||||
RAnalBlock *bb = r_anal_fcn_bbget_in (core->anal, fcn, ds->at);
|
||||
if (!bb) {
|
||||
fcn = r_anal_get_fcn_at (core->anal, ds->at, 0);
|
||||
fcn = r_anal_get_function_at (core->anal, ds->at);
|
||||
if (fcn) {
|
||||
bb = r_anal_fcn_bbget_in (core->anal, fcn, ds->at);
|
||||
}
|
||||
|
@ -6076,7 +6075,7 @@ R_API int r_core_print_disasm_json(RCore *core, ut64 addr, ut8 *buf, int nb_byte
|
|||
pj_s (pj, R_STRBUF_SAFEGET (&ds->analop.esil));
|
||||
pj_kb (pj, "refptr", ds->analop.refptr);
|
||||
pj_kn (pj, "fcn_addr", f ? f->addr : 0);
|
||||
pj_kn (pj, "fcn_last", f ? f->addr + r_anal_fcn_size (f) - ds->oplen : 0);
|
||||
pj_kn (pj, "fcn_last", f ? r_anal_function_max_addr (f) - ds->oplen : 0);
|
||||
pj_ki (pj, "size", ds->analop.size);
|
||||
pj_ks (pj, "opcode", opstr);
|
||||
pj_ks (pj, "disasm", str);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
R_API int r_core_gdiff_fcn(RCore *c, ut64 addr, ut64 addr2) {
|
||||
RList *la, *lb;
|
||||
RAnalFunction *fa = r_anal_get_fcn_at (c->anal, addr, 0);
|
||||
RAnalFunction *fb = r_anal_get_fcn_at (c->anal, addr2, 0);
|
||||
RAnalFunction *fa = r_anal_get_function_at (c->anal, addr);
|
||||
RAnalFunction *fb = r_anal_get_function_at (c->anal, addr2);
|
||||
if (!fa || !fb) {
|
||||
return false;
|
||||
}
|
||||
|
@ -47,8 +47,7 @@ R_API int r_core_gdiff(RCore *c, RCore *c2) {
|
|||
/* remove strings */
|
||||
r_list_foreach_safe (cores[i]->anal->fcns, iter, iter2, fcn) {
|
||||
if (!strncmp (fcn->name, "str.", 4)) {
|
||||
r_anal_fcn_tree_delete (cores[i]->anal, fcn);
|
||||
r_list_delete (cores[i]->anal->fcns, iter);
|
||||
r_anal_function_delete (fcn);
|
||||
}
|
||||
}
|
||||
/* Fingerprint fcn bbs (functions basic-blocks) */
|
||||
|
@ -59,8 +58,7 @@ R_API int r_core_gdiff(RCore *c, RCore *c2) {
|
|||
}
|
||||
/* Fingerprint fcn */
|
||||
r_list_foreach (cores[i]->anal->fcns, iter, fcn) {
|
||||
int newsize = r_anal_diff_fingerprint_fcn (cores[i]->anal, fcn);
|
||||
r_anal_fcn_set_size (cores[i]->anal, fcn, newsize);
|
||||
r_anal_diff_fingerprint_fcn (cores[i]->anal, fcn);
|
||||
}
|
||||
}
|
||||
/* Diff functions */
|
||||
|
@ -98,7 +96,7 @@ R_API void r_core_diff_show(RCore *c, RCore *c2) {
|
|||
RListIter *iter;
|
||||
RAnalFunction *f;
|
||||
int maxnamelen = 0;
|
||||
int maxsize = 0;
|
||||
ut64 maxsize = 0;
|
||||
int digits = 1;
|
||||
int len;
|
||||
|
||||
|
@ -106,8 +104,8 @@ R_API void r_core_diff_show(RCore *c, RCore *c2) {
|
|||
if (f->name && (len = strlen (f->name)) > maxnamelen) {
|
||||
maxnamelen = len;
|
||||
}
|
||||
if (r_anal_fcn_size (f) > maxsize) {
|
||||
maxsize = r_anal_fcn_size (f);
|
||||
if (r_anal_function_linear_size (f) > maxsize) {
|
||||
maxsize = r_anal_function_linear_size (f);
|
||||
}
|
||||
}
|
||||
fcns = r_anal_get_fcns (c2->anal);
|
||||
|
@ -115,8 +113,8 @@ R_API void r_core_diff_show(RCore *c, RCore *c2) {
|
|||
if (f->name && (len = strlen (f->name)) > maxnamelen) {
|
||||
maxnamelen = len;
|
||||
}
|
||||
if (r_anal_fcn_size (f) > maxsize) {
|
||||
maxsize = r_anal_fcn_size (f);
|
||||
if (r_anal_function_linear_size (f) > maxsize) {
|
||||
maxsize = r_anal_function_linear_size (f);
|
||||
}
|
||||
}
|
||||
while (maxsize > 9) {
|
||||
|
@ -146,9 +144,9 @@ R_API void r_core_diff_show(RCore *c, RCore *c2) {
|
|||
match = "NEW";
|
||||
f->diff->dist = 0;
|
||||
}
|
||||
diffrow (f->addr, f->name, r_anal_fcn_size (f), maxnamelen, digits,
|
||||
f->diff->addr, f->diff->name, f->diff->size,
|
||||
match, f->diff->dist, bare);
|
||||
diffrow (f->addr, f->name, r_anal_function_linear_size (f), maxnamelen, digits,
|
||||
f->diff->addr, f->diff->name, f->diff->size,
|
||||
match, f->diff->dist, bare);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -159,9 +157,9 @@ R_API void r_core_diff_show(RCore *c, RCore *c2) {
|
|||
case R_ANAL_FCN_TYPE_FCN:
|
||||
case R_ANAL_FCN_TYPE_SYM:
|
||||
if (f->diff->type == R_ANAL_DIFF_TYPE_NULL) {
|
||||
diffrow (f->addr, f->name, r_anal_fcn_size (f), maxnamelen,
|
||||
digits, f->diff->addr, f->diff->name, f->diff->size,
|
||||
"NEW", 0, bare); //f->diff->dist, bare);
|
||||
diffrow (f->addr, f->name, r_anal_function_linear_size (f), maxnamelen,
|
||||
digits, f->diff->addr, f->diff->name, f->diff->size,
|
||||
"NEW", 0, bare); //f->diff->dist, bare);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1868,7 +1868,7 @@ static int r_cmd_java_handle_list_code_references (RCore *core, const char *inpu
|
|||
fmt = "addr:0x%"PFMT64x" method_name:\"%s\", op:\"%s\" type:\"%s\" info:\"%s\"\n";
|
||||
|
||||
r_list_foreach (anal->fcns, fcn_iter, fcn) {
|
||||
ut8 do_this_one = func_addr == -1 || r_anal_fcn_is_in_offset (fcn, func_addr);
|
||||
ut8 do_this_one = func_addr == -1 || r_anal_function_contains (fcn, func_addr);
|
||||
if (!do_this_one) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -4150,7 +4150,7 @@ R_API void r_core_visual_disasm_down(RCore *core, RAsmOp *op, int *cols) {
|
|||
f = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
op->size = 1;
|
||||
if (f && f->folded) {
|
||||
*cols = core->offset - f->addr + r_anal_fcn_size (f);
|
||||
*cols = core->offset - r_anal_function_max_addr (f);
|
||||
} else {
|
||||
r_asm_set_pc (core->assembler, core->offset);
|
||||
*cols = r_asm_disassemble (core->assembler,
|
||||
|
|
|
@ -2659,7 +2659,7 @@ static void function_rename(RCore *core, ut64 addr, const char *name) {
|
|||
r_flag_unset_name (core->flags, fcn->name);
|
||||
free (fcn->name);
|
||||
fcn->name = strdup (name);
|
||||
r_flag_set (core->flags, name, addr, r_anal_fcn_size (fcn));
|
||||
r_flag_set (core->flags, name, addr, r_anal_function_size_from_entry (fcn));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2735,13 +2735,13 @@ static ut64 var_functions_show(RCore *core, int idx, int show, int cols) {
|
|||
var_functions = r_str_newf ("%c%c %s0x%08"PFMT64x"" Color_RESET" %4d %s%s"Color_RESET"",
|
||||
(seek == fcn->addr)?'>':' ',
|
||||
(idx==i)?'*':' ',
|
||||
color_addr, fcn->addr, r_anal_fcn_realsize (fcn),
|
||||
color_addr, fcn->addr, r_anal_function_realsize (fcn),
|
||||
color_fcn, fcn->name);
|
||||
} else {
|
||||
var_functions = r_str_newf ("%c%c 0x%08"PFMT64x" %4d %s",
|
||||
(seek == fcn->addr)?'>':' ',
|
||||
(idx==i)?'*':' ',
|
||||
fcn->addr, r_anal_fcn_realsize (fcn), fcn->name);
|
||||
fcn->addr, r_anal_function_realsize (fcn), fcn->name);
|
||||
}
|
||||
if (var_functions) {
|
||||
if (!r_cons_singleton ()->show_vals) {
|
||||
|
@ -3798,7 +3798,7 @@ onemoretime:
|
|||
r_sys_sleep (1);
|
||||
}
|
||||
} else if (tgt_addr != UT64_MAX) {
|
||||
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, tgt_addr, R_ANAL_FCN_TYPE_NULL);
|
||||
RAnalFunction *fcn = r_anal_get_function_at (core->anal, tgt_addr);
|
||||
RFlagItem *f = r_flag_get_i (core->flags, tgt_addr);
|
||||
if (fcn) {
|
||||
q = r_str_newf ("?i Rename function %s to;afn `yp` 0x%"PFMT64x,
|
||||
|
@ -4005,25 +4005,13 @@ onemoretime:
|
|||
break;
|
||||
case 'f':
|
||||
{
|
||||
int funsize = 0;
|
||||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0);
|
||||
if (fcn) {
|
||||
r_anal_fcn_resize (core->anal, fcn, core->offset - fcn->addr);
|
||||
}
|
||||
//int depth = r_config_get_i (core->config, "anal.depth");
|
||||
if (core->print->cur_enabled) {
|
||||
if (core->print->ocur != -1) {
|
||||
funsize = 1 + R_ABS (core->print->cur - core->print->ocur);
|
||||
}
|
||||
//depth = 0;
|
||||
}
|
||||
r_cons_break_push (NULL, NULL);
|
||||
r_core_cmdf (core, "af @ 0x%08" PFMT64x, off); // required for thumb autodetection
|
||||
r_cons_break_pop ();
|
||||
if (funsize) {
|
||||
RAnalFunction *f = r_anal_get_fcn_in (core->anal, off, -1);
|
||||
r_anal_fcn_set_size (core->anal, f, funsize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
|
|
|
@ -180,7 +180,7 @@ static void __toggleSort (RCoreVisualViewGraph *status) {
|
|||
|
||||
static void __reset_status(RCoreVisualViewGraph *status) {
|
||||
status->addr = status->core->offset;
|
||||
status->fcn = r_anal_get_fcn_at (status->core->anal, status->addr, 0);
|
||||
status->fcn = r_anal_get_function_at (status->core->anal, status->addr);
|
||||
|
||||
status->mainCol = __fcns (status->core);
|
||||
__sort (status, status->mainCol);
|
||||
|
|
|
@ -300,7 +300,7 @@ R_API RList *r_debug_modules_list(RDebug *dbg) {
|
|||
dbg->h->modules_get (dbg): NULL;
|
||||
}
|
||||
|
||||
R_API int r_debug_map_sync(RDebug *dbg) {
|
||||
R_API bool r_debug_map_sync(RDebug *dbg) {
|
||||
bool ret = false;
|
||||
if (dbg && dbg->h && dbg->h->map_get) {
|
||||
RList *newmaps = dbg->h->map_get (dbg);
|
||||
|
@ -310,7 +310,7 @@ R_API int r_debug_map_sync(RDebug *dbg) {
|
|||
ret = true;
|
||||
}
|
||||
}
|
||||
return (int)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API RDebugMap* r_debug_map_alloc(RDebug *dbg, ut64 addr, int size, bool thp) {
|
||||
|
|
|
@ -256,8 +256,12 @@ typedef struct r_anal_fcn_store_t {
|
|||
/* Stores useful function metadata */
|
||||
/* TODO: Think about moving more stuff to this structure? */
|
||||
typedef struct r_anal_fcn_meta_t {
|
||||
ut64 min; // min address
|
||||
ut64 max; // max address
|
||||
// _min and _max are calculated lazily when queried.
|
||||
// On changes, they will either be updated (if this can be done trivially) or invalidated.
|
||||
// They are invalid iff _min == UT64_MAX.
|
||||
ut64 _min; // PRIVATE, min address, use r_anal_function_min_addr() to access
|
||||
ut64 _max; // PRIVATE, max address, use r_anal_function_max_addr() to access
|
||||
|
||||
int numrefs; // number of cross references
|
||||
int numcallrefs; // number of calls
|
||||
int sgnc; // node cardinality of the functions callgraph
|
||||
|
@ -270,7 +274,6 @@ typedef struct r_anal_fcn_meta_t {
|
|||
typedef struct r_anal_function_t {
|
||||
char* name;
|
||||
char* dsc; // For producing nice listings
|
||||
ut32 _size;
|
||||
int bits; // ((> bits 0) (set-bits bits))
|
||||
int type;
|
||||
/*item_list *rets; // Type of return value */
|
||||
|
@ -297,12 +300,11 @@ typedef struct r_anal_function_t {
|
|||
RList *locs; // list of local variables
|
||||
RList *fcn_locs; //sorted list of a function *.loc refs
|
||||
//RList *locals; // list of local labels -> moved to anal->sdb_fcns
|
||||
RList *bbs;
|
||||
RList *bbs; // TODO: should be RPVector
|
||||
RAnalFcnMeta meta;
|
||||
RRangeTiny bbr;
|
||||
RBNode rb;
|
||||
RBNode addr_rb;
|
||||
RList *imports; // maybe bound to class?
|
||||
struct r_anal_t *anal; // this function is associated with this instance
|
||||
} RAnalFunction;
|
||||
|
||||
typedef struct r_anal_func_arg_t {
|
||||
|
@ -583,7 +585,7 @@ typedef struct r_anal_switch_obj_t {
|
|||
ut64 min_val;
|
||||
ut64 def_val;
|
||||
ut64 max_val;
|
||||
RList *cases;
|
||||
RList/*<RAnalCaseOp>*/ *cases;
|
||||
} RAnalSwitchOp;
|
||||
|
||||
struct r_anal_t;
|
||||
|
@ -648,10 +650,11 @@ typedef struct r_anal_t {
|
|||
RAnalCPPABI cpp_abi;
|
||||
void *user;
|
||||
ut64 gp; // global pointer. used for mips. but can be used by other arches too in the future
|
||||
RBTree bb_tree; // all basic blocks by address. They must not overlap.
|
||||
RList *fcns;
|
||||
RBNode *fcn_tree; // keyed on meta.min
|
||||
HtUP *ht_addr_fun; // address => function
|
||||
HtPP *ht_name_fun; // name => function
|
||||
RBNode *fcn_addr_tree; // keyed on addr
|
||||
RListRange *fcnstore;
|
||||
RList *refs;
|
||||
RList *vartypes;
|
||||
RReg *reg;
|
||||
|
@ -877,6 +880,9 @@ typedef struct r_anal_cond_t {
|
|||
} RAnalCond;
|
||||
|
||||
typedef struct r_anal_bb_t {
|
||||
RBNode _rb; // private, node in the RBTree
|
||||
ut64 _max_end; // private, augmented value for RBTree
|
||||
|
||||
ut64 addr;
|
||||
ut64 size;
|
||||
ut64 jump;
|
||||
|
@ -909,6 +915,9 @@ typedef struct r_anal_bb_t {
|
|||
bool folded;
|
||||
ut64 cmpval;
|
||||
const char *cmpreg;
|
||||
RList *fcns;
|
||||
int ref;
|
||||
RAnal *anal;
|
||||
#undef RAnalBlock
|
||||
} RAnalBlock;
|
||||
|
||||
|
@ -1412,6 +1421,117 @@ R_API int r_anal_op_hint(RAnalOp *op, RAnalHint *hint);
|
|||
R_API RAnalType *r_anal_type_free(RAnalType *t);
|
||||
R_API RAnalType *r_anal_type_loadfile(RAnal *a, const char *path);
|
||||
|
||||
/* block.c */
|
||||
typedef bool (*RAnalBlockCb)(RAnalBlock *block, void *user);
|
||||
typedef bool (*RAnalAddrCb)(ut64 addr, void *user);
|
||||
|
||||
R_API void r_anal_block_check_invariants(RAnal *anal);
|
||||
R_API void r_anal_block_check_leaks(RAnal *anal);
|
||||
|
||||
// lifetime
|
||||
R_API void r_anal_block_ref(RAnalBlock *bb);
|
||||
R_API void r_anal_block_unref(RAnalBlock *bb);
|
||||
|
||||
// Create one block covering the given range.
|
||||
// This will fail if the range overlaps any existing blocks.
|
||||
R_API RAnalBlock *r_anal_create_block(RAnal *anal, ut64 addr, ut64 size);
|
||||
|
||||
static inline bool r_anal_block_contains(RAnalBlock *bb, ut64 addr) {
|
||||
return addr >= bb->addr && addr < bb->addr + bb->size;
|
||||
}
|
||||
|
||||
// Split the block at the given address into two blocks.
|
||||
// bb will stay the first block, the second block will be returned (or NULL on failure)
|
||||
// The returned block will always be refd, i.e. it is necessary to always call r_anal_block_unref() on the return value!
|
||||
R_API RAnalBlock *r_anal_block_split(RAnalBlock *bb, ut64 addr);
|
||||
|
||||
// Merge block b into a.
|
||||
// b will be FREED (not just unrefd) and is NOT VALID anymore if this function is successful!
|
||||
// This only works if b follows directly after a and their function lists are identical.
|
||||
// returns true iff the blocks could be merged
|
||||
R_API bool r_anal_block_merge(RAnalBlock *a, RAnalBlock *b);
|
||||
|
||||
// Manually delete a block and remove it from all its functions
|
||||
// If there are more references to it than from its functions only, it will not be removed immediately!
|
||||
R_API void r_anal_delete_block(RAnalBlock *bb);
|
||||
|
||||
R_API void r_anal_block_set_size(RAnalBlock *block, ut64 size);
|
||||
|
||||
// Set the address and size of the block.
|
||||
// This can fail (and return false) if there is already another block at the new address
|
||||
R_API bool r_anal_block_relocate(RAnalBlock *block, ut64 addr, ut64 size);
|
||||
|
||||
R_API RAnalBlock *r_anal_get_block_at(RAnal *anal, ut64 addr);
|
||||
R_API bool r_anal_blocks_foreach_in(RAnal *anal, ut64 addr, RAnalBlockCb cb, void *user);
|
||||
R_API RList *r_anal_get_blocks_in(RAnal *anal, ut64 addr); // values from r_anal_blocks_foreach_in as a list
|
||||
R_API void r_anal_blocks_foreach_intersect(RAnal *anal, ut64 addr, ut64 size, RAnalBlockCb cb, void *user);
|
||||
R_API RList *r_anal_get_blocks_intersect(RAnal *anal, ut64 addr, ut64 size); // values from r_anal_blocks_foreach_intersect as a list
|
||||
|
||||
// Call cb on every direct successor address of block
|
||||
// returns false iff the loop was breaked by cb
|
||||
R_API bool r_anal_block_successor_addrs_foreach(RAnalBlock *block, RAnalAddrCb cb, void *user);
|
||||
|
||||
// Call cb on block and every (recursive) successor of it
|
||||
// returns false iff the loop was breaked by cb
|
||||
R_API bool r_anal_block_recurse(RAnalBlock *block, RAnalBlockCb cb, void *user);
|
||||
|
||||
// same as r_anal_block_recurse, but returns the blocks as a list
|
||||
R_API RList *r_anal_block_recurse_list(RAnalBlock *block);
|
||||
|
||||
// ---------------------------------------
|
||||
|
||||
/* function.c */
|
||||
|
||||
R_API RAnalFunction *r_anal_function_new(RAnal *anal);
|
||||
R_API void r_anal_function_free(void *fcn);
|
||||
|
||||
// Add a function created with r_anal_function_new() to anal
|
||||
R_API bool r_anal_add_function(RAnal *anal, RAnalFunction *fcn);
|
||||
|
||||
// Create a new function and add it to anal (r_anal_function_new() + set members + r_anal_add_function())
|
||||
R_API RAnalFunction *r_anal_create_function(RAnal *anal, const char *name, ut64 addr, int type, RAnalDiff *diff);
|
||||
|
||||
// returns all functions that have a basic block containing the given address
|
||||
R_API RList *r_anal_get_functions_in(RAnal *anal, ut64 addr);
|
||||
|
||||
// returns the function that has its entrypoint at addr or NULL
|
||||
R_API RAnalFunction *r_anal_get_function_at(RAnal *anal, ut64 addr);
|
||||
|
||||
R_API bool r_anal_function_delete(RAnalFunction *fcn);
|
||||
|
||||
// rhange the entrypoint of fcn
|
||||
// This can fail (and return false) if there is already another function at the new address
|
||||
R_API bool r_anal_function_relocate(RAnalFunction *fcn, ut64 addr);
|
||||
|
||||
// rename the given function
|
||||
// This can fail (and return false) if there is another function with the name given
|
||||
R_API bool r_anal_function_rename(RAnalFunction *fcn, const char *name);
|
||||
|
||||
R_API void r_anal_function_add_block(RAnalFunction *fcn, RAnalBlock *bb);
|
||||
R_API void r_anal_function_remove_block(RAnalFunction *fcn, RAnalBlock *bb);
|
||||
|
||||
|
||||
// size of the entire range that the function spans, including holes.
|
||||
// this is exactly r_anal_function_max_addr() - r_anal_function_min_addr()
|
||||
R_API ut64 r_anal_function_linear_size(RAnalFunction *fcn);
|
||||
|
||||
// lowest address covered by the function
|
||||
R_API ut64 r_anal_function_min_addr(RAnalFunction *fcn);
|
||||
|
||||
// first address directly after the function
|
||||
R_API ut64 r_anal_function_max_addr(RAnalFunction *fcn);
|
||||
|
||||
// size from the function entrypoint (fcn->addr) to the end of the function (r_anal_function_max_addr)
|
||||
R_API ut64 r_anal_function_size_from_entry(RAnalFunction *fcn);
|
||||
|
||||
// the "real" size of the function, that is the sum of the size of the
|
||||
// basicblocks this function is composed of
|
||||
R_API ut64 r_anal_function_realsize(const RAnalFunction *fcn);
|
||||
|
||||
// returns whether the function contains a basic block that contains addr
|
||||
// This is completely independent of fcn->addr, which is only the entrypoint!
|
||||
R_API bool r_anal_function_contains(RAnalFunction *fcn, ut64 addr);
|
||||
|
||||
/* anal.c */
|
||||
R_API RAnal *r_anal_new(void);
|
||||
R_API int r_anal_purge (RAnal *anal);
|
||||
|
@ -1440,11 +1560,7 @@ R_API bool r_anal_set_fcnsign(RAnal *anal, const char *name);
|
|||
R_API const char *r_anal_get_fcnsign(RAnal *anal, const char *sym);
|
||||
|
||||
/* bb.c */
|
||||
R_API RAnalBlock *r_anal_bb_new(void);
|
||||
R_API RList *r_anal_bb_list_new(void);
|
||||
R_API void r_anal_bb_free(RAnalBlock *bb);
|
||||
R_API RAnalBlock *r_anal_bb_from_offset(RAnal *anal, ut64 off);
|
||||
R_API int r_anal_bb_is_in_offset(RAnalBlock *bb, ut64 addr);
|
||||
R_API bool r_anal_bb_set_offset(RAnalBlock *bb, int i, ut16 v);
|
||||
R_API ut16 r_anal_bb_offset_inst(RAnalBlock *bb, int i);
|
||||
R_API ut64 r_anal_bb_opaddr_i(RAnalBlock *bb, int i);
|
||||
|
@ -1521,31 +1637,20 @@ R_API void r_anal_pin_list(RAnal *a);
|
|||
|
||||
/* fcn.c */
|
||||
R_API ut32 r_anal_fcn_cost(RAnal *anal, RAnalFunction *fcn);
|
||||
R_API bool r_anal_fcn_tree_delete(RAnal *anal, RAnalFunction *data);
|
||||
R_API void r_anal_fcn_tree_insert(RAnal *anal, RAnalFunction *fcn);
|
||||
R_API int r_anal_fcn_count_edges(const RAnalFunction *fcn, int *ebbs);
|
||||
R_API RAnalFunction *r_anal_fcn_new(void);
|
||||
R_API int r_anal_fcn_is_in_offset (RAnalFunction *fcn, ut64 addr);
|
||||
R_API bool r_anal_fcn_in(RAnalFunction *fcn, ut64 addr);
|
||||
R_API RList *r_anal_get_fcn_in_list(RAnal *anal, ut64 addr, int type);
|
||||
R_API RAnalFunction *r_anal_get_fcn_at(RAnal *anal, ut64 addr, int type);
|
||||
R_API RAnalFunction *r_anal_get_fcn_in(RAnal *anal, ut64 addr, int type);
|
||||
R_DEPRECATE R_API RAnalFunction *r_anal_get_fcn_in(RAnal *anal, ut64 addr, int type); // use r_anal_get_function_at/r_anal_get_functions_in
|
||||
R_API RAnalFunction *r_anal_get_fcn_in_bounds(RAnal *anal, ut64 addr, int type);
|
||||
R_API RAnalFunction *r_anal_fcn_find_name(RAnal *anal, const char *name);
|
||||
R_API void r_anal_fcn_rename(RAnalFunction *f, const char *newName);
|
||||
R_API RList *r_anal_fcn_list_new(void);
|
||||
R_API int r_anal_fcn_insert(RAnal *anal, RAnalFunction *fcn);
|
||||
R_API void r_anal_fcn_free(void *fcn);
|
||||
R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int reftype);
|
||||
R_API int r_anal_fcn_add(RAnal *anal, ut64 addr, ut64 size,
|
||||
const char *name, int type, RAnalDiff *diff);
|
||||
R_API int r_anal_fcn_del(RAnal *anal, ut64 addr);
|
||||
R_API int r_anal_fcn_del_locs(RAnal *anal, ut64 addr);
|
||||
R_API bool r_anal_fcn_add_bb(RAnal *anal, RAnalFunction *fcn,
|
||||
ut64 addr, ut64 size,
|
||||
ut64 jump, ut64 fail, int type, RAnalDiff *diff);
|
||||
ut64 jump, ut64 fail, int type, R_BORROW RAnalDiff *diff);
|
||||
R_API bool r_anal_check_fcn(RAnal *anal, ut8 *buf, ut16 bufsz, ut64 addr, ut64 low, ut64 high);
|
||||
R_API void r_anal_fcn_update_tinyrange_bbs(RAnalFunction *fcn);
|
||||
R_API void r_anal_fcn_invalidate_read_ahead_cache(void);
|
||||
R_API void r_anal_fcn_check_bp_use(RAnal *anal, RAnalFunction *fcn);
|
||||
|
||||
|
@ -1573,15 +1678,10 @@ R_API int r_anal_var_count(RAnal *a, RAnalFunction *fcn, int kind, int type);
|
|||
|
||||
/* vars // globals. not here */
|
||||
R_API bool r_anal_var_display(RAnal *anal, int delta, char kind, const char *type);
|
||||
R_API ut32 r_anal_fcn_size(const RAnalFunction *fcn);
|
||||
R_API void r_anal_fcn_set_size(RAnal *anal, RAnalFunction *fcn, ut32 size);
|
||||
R_API ut32 r_anal_fcn_contsize(const RAnalFunction *fcn);
|
||||
R_API ut32 r_anal_fcn_realsize(const RAnalFunction *fcn);
|
||||
|
||||
R_API int r_anal_fcn_cc(RAnal *anal, RAnalFunction *fcn);
|
||||
R_API int r_anal_fcn_loops(RAnalFunction *fcn);
|
||||
R_API int r_anal_fcn_split_bb(RAnal *anal, RAnalFunction *fcn, RAnalBlock *bbi, ut64 addr);
|
||||
R_API RAnalVar *r_anal_fcn_get_var(RAnalFunction *fs, int num, int dir);
|
||||
R_API void r_anal_fcn_fit_overlaps (RAnal *anal, RAnalFunction *fcn);
|
||||
R_API void r_anal_trim_jmprefs(RAnal *anal, RAnalFunction *fcn);
|
||||
R_API void r_anal_del_jmprefs(RAnal *anal, RAnalFunction *fcn);
|
||||
R_API RAnalFunction *r_anal_fcn_next(RAnal *anal, ut64 addr);
|
||||
|
@ -1589,8 +1689,7 @@ R_API char *r_anal_fcn_to_string(RAnal *a, RAnalFunction* fs);
|
|||
R_API int r_anal_str_to_fcn(RAnal *a, RAnalFunction *f, const char *_str);
|
||||
R_API int r_anal_fcn_count (RAnal *a, ut64 from, ut64 to);
|
||||
R_API RAnalBlock *r_anal_fcn_bbget_in(const RAnal *anal, RAnalFunction *fcn, ut64 addr);
|
||||
R_API RAnalBlock *r_anal_fcn_bbget_at(RAnalFunction *fcn, ut64 addr);
|
||||
R_API bool r_anal_fcn_contains(RAnalFunction *fcn, ut64 addr);
|
||||
R_API RAnalBlock *r_anal_fcn_bbget_at(RAnal *anal, RAnalFunction *fcn, ut64 addr);
|
||||
R_API bool r_anal_fcn_bbadd(RAnalFunction *fcn, RAnalBlock *bb);
|
||||
R_API int r_anal_fcn_resize (RAnal *anal, RAnalFunction *fcn, int newsize);
|
||||
R_API bool r_anal_fcn_get_purity(RAnal *anal, RAnalFunction *fcn);
|
||||
|
|
|
@ -299,7 +299,7 @@ enum {
|
|||
|
||||
// BB and OP
|
||||
R_API ut64 r_anal_ex_map_anal_ex_to_anal_op_type(ut64 ranal2_op_type);
|
||||
R_API void r_anal_ex_op_to_bb(RAnal *anal, RAnalState *state, RAnalBlock *bb, RAnalOp *op);
|
||||
R_API RAnalBlock *r_anal_ex_op_to_bb(RAnal *anal, RAnalState *state, RAnalOp *op);
|
||||
R_API int r_anal_ex_is_op_type_eop(ut64 x);
|
||||
|
||||
R_API ut64 r_anal_ex_map_anal_ex_to_anal_bb_type (ut64 ranal2_op_type);
|
||||
|
|
|
@ -15,7 +15,7 @@ typedef char* (*RCoreCmdStrF)(void *core, const char *cmd, ...);
|
|||
typedef void (*RCorePuts)(const char *cmd);
|
||||
typedef void (*RCoreSetArchBits)(void *core, const char *arch, int bits);
|
||||
typedef bool (*RCoreIsMapped)(void *core, ut64 addr, int perm);
|
||||
typedef int (*RCoreDebugMapsSync)(void *core);
|
||||
typedef bool (*RCoreDebugMapsSync)(void *core);
|
||||
typedef const char *(*RCoreGetName)(void *core, ut64 off);
|
||||
typedef char *(*RCoreGetNameDelta)(void *core, ut64 off);
|
||||
typedef void (*RCoreSeekArchBits)(void *core, ut64 addr);
|
||||
|
|
|
@ -603,7 +603,7 @@ R_API void r_core_anal_autoname_all_fcns(RCore *core);
|
|||
R_API void r_core_anal_autoname_all_golang_fcns(RCore *core);
|
||||
R_API int r_core_anal_fcn_list(RCore *core, const char *input, const char *rad);
|
||||
R_API char *r_core_anal_fcn_name(RCore *core, RAnalFunction *fcn);
|
||||
R_API int r_core_anal_fcn_list_size(RCore *core);
|
||||
R_API ut64 r_core_anal_fcn_list_size(RCore *core);
|
||||
R_API void r_core_anal_fcn_labels(RCore *core, RAnalFunction *fcn, int rad);
|
||||
R_API int r_core_anal_fcn_clean(RCore *core, ut64 addr);
|
||||
R_API int r_core_print_bb_custom(RCore *core, RAnalFunction *fcn);
|
||||
|
|
|
@ -522,7 +522,7 @@ R_API ut64 r_debug_reg_get(RDebug *dbg, const char *name);
|
|||
R_API ut64 r_debug_reg_get_err(RDebug *dbg, const char *name, int *err, utX *value);
|
||||
|
||||
R_API ut64 r_debug_execute(RDebug *dbg, const ut8 *buf, int len, int restore);
|
||||
R_API int r_debug_map_sync(RDebug *dbg);
|
||||
R_API bool r_debug_map_sync(RDebug *dbg);
|
||||
|
||||
R_API int r_debug_stop(RDebug *dbg);
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ R_API void *r_list_get_bottom(const RList *list);
|
|||
R_API void *r_list_pop(RList *list);
|
||||
R_API void *r_list_pop_head(RList *list);
|
||||
R_API void r_list_reverse(RList *list);
|
||||
R_API RList *r_list_clone(RList *list);
|
||||
R_API RList *r_list_clone(const RList *list);
|
||||
R_API char *r_list_to_str(RList *list, char ch);
|
||||
|
||||
/* hashlike api */
|
||||
|
|
|
@ -357,9 +357,9 @@ dotherax:
|
|||
} else if (flags & (1 << 11)) { // -t
|
||||
RList *split = r_str_split_list (str, "GMT", 0);
|
||||
char *ts = r_list_head (split)->data;
|
||||
char *gmt = NULL;
|
||||
const char *gmt = NULL;
|
||||
if (r_list_length (split) >= 2 && strlen (r_list_head (split)->n->data) > 2) {
|
||||
gmt = (char *) r_list_head (split)->n->data + 2;
|
||||
gmt = (const char*) r_list_head (split)->n->data + 2;
|
||||
}
|
||||
ut32 n = r_num_math (num, ts);
|
||||
RPrint *p = r_print_new ();
|
||||
|
|
|
@ -362,7 +362,7 @@ R_API void r_list_reverse(RList *list) {
|
|||
list->tail = tmp;
|
||||
}
|
||||
|
||||
R_API RList *r_list_clone(RList *list) {
|
||||
R_API RList *r_list_clone(const RList *list) {
|
||||
RList *l = NULL;
|
||||
RListIter *iter;
|
||||
void *data;
|
||||
|
|
|
@ -2,37 +2,37 @@ NAME=aav find xrefs
|
|||
FILE=../bins/mach0/macho-bash
|
||||
EXPECT=<<EOF
|
||||
| 0x00008058 .dword 0x0000e403
|
||||
; DATA XREF from sym._parse_comsub @ 0x7d30
|
||||
; DATA XREF from sub.free_7418 @ 0x7d30
|
||||
0x0000805c .dword 0x000693da
|
||||
; DATA XREF from sym._parse_comsub @ 0x7d3e
|
||||
; DATA XREF from sub.free_7418 @ 0x7d3e
|
||||
0x00008060 .dword 0x0006c1f4 ; aav.0x0006c1f4
|
||||
; DATA XREF from sym._parse_comsub @ 0x7d48
|
||||
; DATA XREF from sub.free_7418 @ 0x7d48
|
||||
0x00008064 .dword 0x0006c1a6
|
||||
; DATA XREF from sym._parse_comsub @ 0x7e30
|
||||
; DATA XREF from sub.free_7418 @ 0x7e30
|
||||
0x00008068 .dword 0x0006c102
|
||||
; DATA XREF from sym._parse_comsub @ 0x7e3a
|
||||
; DATA XREF from sub.free_7418 @ 0x7e3a
|
||||
0x0000806c .dword 0x0006c0b4 ; aav.0x0006c0b4
|
||||
; DATA XREF from sym._parse_comsub @ 0x7e58
|
||||
; DATA XREF from sub.free_7418 @ 0x7e58
|
||||
0x00008070 .dword 0x0006c0da
|
||||
; DATA XREF from sym._parse_comsub @ 0x7e62
|
||||
; DATA XREF from sub.free_7418 @ 0x7e62
|
||||
0x00008074 .dword 0x0006c08c ; aav.0x0006c08c
|
||||
; DATA XREF from sym._parse_comsub @ 0x7e80
|
||||
; DATA XREF from sub.free_7418 @ 0x7e80
|
||||
0x00008078 .dword 0x0006c0b2
|
||||
; DATA XREF from sym._parse_comsub @ 0x7e8a
|
||||
; DATA XREF from sub.free_7418 @ 0x7e8a
|
||||
0x0000807c .dword 0x0006c064 ; aav.0x0006c064
|
||||
; DATA XREF from sym._parse_comsub @ 0x7ed8
|
||||
; DATA XREF from sub.free_7418 @ 0x7ed8
|
||||
0x00008080 .dword 0x00069232
|
||||
; DATA XREF from sym._parse_comsub @ 0x7ee8
|
||||
; DATA XREF from sub.free_7418 @ 0x7ee8
|
||||
0x00008084 .dword 0x0006c04a
|
||||
; DATA XREF from sym._parse_comsub @ 0x7ef2
|
||||
; DATA XREF from sub.free_7418 @ 0x7ef2
|
||||
0x00008088 .dword 0x0006bffc ; aav.0x0006bffc
|
||||
; DATA XREF from sym._parse_comsub @ 0x7f64
|
||||
; DATA XREF from sub.free_7418 @ 0x7f64
|
||||
0x0000808c .dword 0x0006bfce
|
||||
; DATA XREF from sym._parse_comsub @ 0x7f72
|
||||
; DATA XREF from sub.free_7418 @ 0x7f72
|
||||
0x00008090 .dword 0x0006bf7c ; aav.0x0006bf7c
|
||||
; DATA XREF from sym._parse_comsub @ 0x7fcc
|
||||
; DATA XREF from sub.free_7418 @ 0x7fcc
|
||||
0x00008094 .dword 0x0006bf66
|
||||
; DATA XREF from sym._parse_comsub @ 0x7fd6
|
||||
; DATA XREF from sub.free_7418 @ 0x7fd6
|
||||
0x00008098 .dword 0x0006bf18 ; aav.0x0006bf18
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
|
|
|
@ -5,7 +5,7 @@ aa
|
|||
e asm.var=false
|
||||
pdb
|
||||
EXPECT=<<EOF
|
||||
/ 2628: entry0 (int32_t arg_24h, int32_t arg_40h, int32_t arg_44h);
|
||||
/ 337: entry0 (int32_t arg_24h, int32_t arg_40h, int32_t arg_44h);
|
||||
| 0x006453a1 e8d8170000 call fcn.00646b7e
|
||||
| 0x006453a6 8d642444 lea esp, [arg_44h]
|
||||
| ,=< 0x006453aa 0f85a6300000 jne 0x648456
|
||||
|
|
|
@ -10,8 +10,8 @@ s main+98
|
|||
pd 3
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x000048f4 0x00004901 01:2E2F 13 j 0x000045b1 f 0x00004901
|
||||
0x00004901 0x0000491a 01:2E30 25 j 0x000045ba f 0x0000491a
|
||||
0x000048f4 0x00004901 01:2A37 13 j 0x000045b1 f 0x00004901
|
||||
0x00004901 0x0000491a 01:2A38 25 j 0x000045ba f 0x0000491a
|
||||
|
||||
| 0x000039c2 mov dword [0x0021f558], 2 ; [0x21f558:4]=1
|
||||
| 0x000039cc call fcn.00015960
|
||||
|
@ -558,7 +558,7 @@ RUN
|
|||
NAME=aac on mips be
|
||||
FILE=../bins/elf/analysis/mipsbe-busybox
|
||||
EXPECT=<<EOF
|
||||
1268
|
||||
1279
|
||||
EOF
|
||||
CMDS=<<EOF
|
||||
aac
|
||||
|
@ -2553,62 +2553,60 @@ diff: type: new
|
|||
| ; CODE XREF from fcn.00000000 @ 0x5
|
||||
| 0x00000004 c1ebfd shr ebx, 0xfd
|
||||
| 0x00000007 bb2c000000 mov ebx, 0x2c ; ','
|
||||
0x0000000c ebf7 jmp 5 ; fcn.00000000+0x5
|
||||
\ 0x0000000c ebf7 jmp 5
|
||||
| ----------- true: 0x00000005
|
||||
| ; CODE XREF from fcn.00000000 @ +0xc
|
||||
| ; CODE XREF from fcn.00000000 @ 0xc
|
||||
| 0x00000005 ebfd jmp 4
|
||||
| ----------- true: 0x00000004
|
||||
|
||||
[0x00000000]> # fcn.00000000 ();
|
||||
.------------------------.
|
||||
| 0x0 |
|
||||
| 17: fcn.00000000 (); |
|
||||
| ; '!' |
|
||||
| mov eax, 0xc1000021 |
|
||||
`------------------------'
|
||||
v
|
||||
|
|
||||
.----'
|
||||
.------------------------.
|
||||
| 0x0 |
|
||||
| 17: fcn.00000000 (); |
|
||||
| ; '!' |
|
||||
| mov eax, 0xc1000021 |
|
||||
`------------------------'
|
||||
v
|
||||
|
|
||||
.---'
|
||||
.--------.
|
||||
| | |
|
||||
|.--------------------------------------.
|
||||
|| 0x5 |
|
||||
|| ; CODE XREF from fcn.00000000 @ +0xc |
|
||||
|| jmp 4 |
|
||||
|`--------------------------------------'
|
||||
|.-------------------------------------.
|
||||
|| 0x5 |
|
||||
|| ; CODE XREF from fcn.00000000 @ 0xc |
|
||||
|| jmp 4 |
|
||||
|`-------------------------------------'
|
||||
| v
|
||||
| |
|
||||
| '.
|
||||
| |
|
||||
| .-------------------------------------.
|
||||
| | 0x4 |
|
||||
| | ; CODE XREF from fcn.00000000 @ 0x5 |
|
||||
| | shr ebx, 0xfd |
|
||||
| | ; ',' |
|
||||
| | mov ebx, 0x2c |
|
||||
| | ; fcn.00000000+0x5 |
|
||||
| | jmp 5 |
|
||||
| `-------------------------------------'
|
||||
| v
|
||||
| |
|
||||
`-----'
|
||||
| |
|
||||
|.-------------------------------------.
|
||||
|| 0x4 |
|
||||
|| ; CODE XREF from fcn.00000000 @ 0x5 |
|
||||
|| shr ebx, 0xfd |
|
||||
|| ; ',' |
|
||||
|| mov ebx, 0x2c |
|
||||
|| jmp 5 |
|
||||
|`-------------------------------------'
|
||||
| v
|
||||
| |
|
||||
`----'
|
||||
|
||||
/ 17: fcn.00000000 ();
|
||||
| 0x00000000 ~ b8210000c1 mov eax, 0xc1000021 ; '!'
|
||||
| ; CODE XREF from fcn.00000000 @ 0x5
|
||||
| .-> 0x00000004 ~ c1ebfd shr ebx, 0xfd
|
||||
| | ; CODE XREF from fcn.00000000 @ +0xc
|
||||
| | ; CODE XREF from fcn.00000000 @ 0xc
|
||||
| .`=< 0x00000005 ebfd jmp 4
|
||||
| : 0x00000007 bb2c000000 mov ebx, 0x2c ; ','
|
||||
`==< 0x0000000c ebf7 jmp 5 ; fcn.00000000+0x5
|
||||
\ `==< 0x0000000c ebf7 jmp 5
|
||||
..
|
||||
|
||||
/ 17: fcn.00000000 ();
|
||||
| 0x00000000 b8210000c1 mov eax, 0xc1000021 ; '!'
|
||||
| | ; CODE XREF from fcn.00000000 @ +0xc
|
||||
| | ; CODE XREF from fcn.00000000 @ 0xc
|
||||
| .`=< 0x00000005 ebfd jmp 4
|
||||
| : 0x00000007 bb2c000000 mov ebx, 0x2c ; ','
|
||||
`==< 0x0000000c ebf7 jmp 5 ; fcn.00000000+0x5
|
||||
\ `==< 0x0000000c ebf7 jmp 5
|
||||
..
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
NAME=af localflag
|
||||
FILE=../bins/mach0/mac-ls2
|
||||
CMDS=<<EOF
|
||||
aaa
|
||||
afi~?
|
||||
afi.
|
||||
afb.
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
32
|
||||
main
|
||||
0x1000011e8 0x100001211 01:08A6 41 j 0x100001216 f 0x100001211
|
||||
EOF
|
||||
RUN
|
|
@ -205,7 +205,7 @@ pd 2
|
|||
EOF
|
||||
EXPECT=<<EOF
|
||||
/ 0: test ();
|
||||
| 0x00000000 0000 add byte [rax], al
|
||||
0x00000000 0000 add byte [rax], al
|
||||
0x00000002 0000 add byte [rax], al
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
@ -0,0 +1,652 @@
|
|||
#include <r_anal.h>
|
||||
#include "minunit.h"
|
||||
|
||||
static bool check_invariants(RAnal *anal) {
|
||||
RBIter iter;
|
||||
RAnalBlock *block;
|
||||
ut64 last_start = UT64_MAX;
|
||||
r_rbtree_foreach (anal->bb_tree, iter, block, RAnalBlock, _rb) {
|
||||
if (last_start != UT64_MAX) {
|
||||
mu_assert ("corrupted binary tree", block->addr >= last_start);
|
||||
mu_assert_neq (block->addr, last_start, "double blocks");
|
||||
}
|
||||
last_start = block->addr;
|
||||
|
||||
mu_assert ("block->ref < 1, but it is still in the tree", block->ref >= 1);
|
||||
mu_assert ("block->ref < r_list_length (block->fcns)", block->ref >= r_list_length (block->fcns));
|
||||
|
||||
RListIter *fcniter;
|
||||
RAnalFunction *fcn;
|
||||
r_list_foreach (block->fcns, fcniter, fcn) {
|
||||
RListIter *fcniter2;
|
||||
RAnalFunction *fcn2;
|
||||
for (fcniter2 = fcniter->n; fcniter2 && (fcn2 = fcniter2->data, 1); fcniter2 = fcniter2->n) {
|
||||
mu_assert_ptrneq (fcn, fcn2, "duplicate function in basic block");
|
||||
}
|
||||
mu_assert ("block references function, but function does not reference block", r_list_contains (fcn->bbs, block));
|
||||
}
|
||||
}
|
||||
|
||||
RListIter *fcniter;
|
||||
RAnalFunction *fcn;
|
||||
r_list_foreach (anal->fcns, fcniter, fcn) {
|
||||
RListIter *blockiter;
|
||||
ut64 min = UT64_MAX;
|
||||
ut64 max = UT64_MIN;
|
||||
ut64 realsz = 0;
|
||||
r_list_foreach (fcn->bbs, blockiter, block) {
|
||||
RListIter *blockiter2;
|
||||
RAnalBlock *block2;
|
||||
if (block->addr < min) {
|
||||
min = block->addr;
|
||||
}
|
||||
if (block->addr + block->size > max) {
|
||||
max = block->addr + block->size;
|
||||
}
|
||||
realsz += block->size;
|
||||
for (blockiter2 = blockiter->n; blockiter2 && (block2 = blockiter2->data, 1); blockiter2 = blockiter2->n) {
|
||||
mu_assert_ptrneq (block, block2, "duplicate basic block in function");
|
||||
}
|
||||
mu_assert ("function references block, but block does not reference function", r_list_contains (block->fcns, fcn));
|
||||
}
|
||||
|
||||
if (fcn->meta._min != UT64_MAX) {
|
||||
mu_assert_eq (fcn->meta._min, min, "function min wrong");
|
||||
mu_assert_eq (fcn->meta._max, max, "function max wrong");
|
||||
}
|
||||
|
||||
mu_assert_eq (r_anal_function_realsize (fcn), realsz, "realsize wrong");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_leaks(RAnal *anal) {
|
||||
RBIter iter;
|
||||
RAnalBlock *block;
|
||||
r_rbtree_foreach (anal->bb_tree, iter, block, RAnalBlock, _rb) {
|
||||
if (block->ref != r_list_length (block->fcns)) {
|
||||
mu_assert ("leaked basic block", false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t blocks_count(RAnal *anal) {
|
||||
size_t count = 0;
|
||||
RBIter iter;
|
||||
RAnalBlock *block;
|
||||
r_rbtree_foreach(anal->bb_tree, iter, block, RAnalBlock, _rb) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
#define assert_invariants(anal) do { if (!check_invariants (anal)) { return false; } } while (0)
|
||||
#define assert_leaks(anal) do { if (!check_leaks (anal)) { return false; } } while (0)
|
||||
|
||||
bool test_r_anal_block_create() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
mu_assert_eq (blocks_count (anal), 0, "initial count");
|
||||
|
||||
RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
|
||||
assert_invariants (anal);
|
||||
mu_assert ("created block", block);
|
||||
mu_assert_eq (block->addr, 0x1337, "created addr");
|
||||
mu_assert_eq (block->size, 42, "created size");
|
||||
mu_assert_eq (block->ref, 1, "created initial ref");
|
||||
mu_assert_eq (blocks_count (anal), 1, "count after create");
|
||||
|
||||
RAnalBlock *block2 = r_anal_create_block (anal, 0x133f, 100);
|
||||
assert_invariants (anal);
|
||||
mu_assert ("created block (overlap)", block2);
|
||||
mu_assert_eq (block2->addr, 0x133f, "created addr");
|
||||
mu_assert_eq (block2->size, 100, "created size");
|
||||
mu_assert_eq (block2->ref, 1, "created initial ref");
|
||||
mu_assert_eq (blocks_count (anal), 2, "count after create");
|
||||
|
||||
RAnalBlock *block3 = r_anal_create_block (anal, 0x1337, 5);
|
||||
assert_invariants (anal);
|
||||
mu_assert ("no double create on same start", !block3);
|
||||
mu_assert_eq (blocks_count (anal), 2, "count after failed create");
|
||||
|
||||
r_anal_block_unref (block);
|
||||
r_anal_block_unref (block2);
|
||||
|
||||
assert_leaks (anal);
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_contains() {
|
||||
RAnalBlock dummy = { 0 };
|
||||
dummy.addr = 0x1337;
|
||||
dummy.size = 42;
|
||||
mu_assert ("contains before", !r_anal_block_contains (&dummy, 100));
|
||||
mu_assert ("contains start", r_anal_block_contains (&dummy, 0x1337));
|
||||
mu_assert ("contains inside", r_anal_block_contains (&dummy, 0x1339));
|
||||
mu_assert ("contains last", r_anal_block_contains (&dummy, 0x1337 + 42 - 1));
|
||||
mu_assert ("contains after", !r_anal_block_contains (&dummy, 0x1337 + 42));
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_split() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (blocks_count (anal), 1, "count after create");
|
||||
block->jump = 0xdeadbeef;
|
||||
block->fail = 0xc0ffee;
|
||||
block->ninstr = 5;
|
||||
r_anal_bb_set_offset (block, 0, 0);
|
||||
r_anal_bb_set_offset (block, 1, 1);
|
||||
r_anal_bb_set_offset (block, 2, 2);
|
||||
r_anal_bb_set_offset (block, 3, 4);
|
||||
r_anal_bb_set_offset (block, 4, 30);
|
||||
|
||||
RAnalBlock *second = r_anal_block_split (block, 0x1337);
|
||||
assert_invariants (anal);
|
||||
mu_assert_ptreq (second, block, "nop split on first addr");
|
||||
mu_assert_eq (blocks_count (anal), 1, "count after nop split");
|
||||
mu_assert_eq (block->ref, 2, "ref after nop split");
|
||||
r_anal_block_unref (block);
|
||||
|
||||
second = r_anal_block_split (block, 0x1339);
|
||||
assert_invariants (anal);
|
||||
mu_assert_ptrneq (second, block, "non-nop split");
|
||||
mu_assert_eq (blocks_count (anal), 2, "count after non-nop split");
|
||||
|
||||
mu_assert_eq (block->addr, 0x1337, "first addr after split");
|
||||
mu_assert_eq (block->size, 2, "first size after split");
|
||||
mu_assert_eq (second->addr, 0x1339, "first addr after split");
|
||||
mu_assert_eq (second->size, 40, "first size after split");
|
||||
|
||||
mu_assert_eq (block->jump, second->addr, "first jump");
|
||||
mu_assert_eq (block->fail, UT64_MAX, "first fail");
|
||||
mu_assert_eq (second->jump, 0xdeadbeef, "second jump");
|
||||
mu_assert_eq (second->fail, 0xc0ffee, "second fail");
|
||||
|
||||
mu_assert_eq (block->ninstr, 2, "first ninstr after split");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (block, 0), 0, "first op_pos[0]");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (block, 1), 1, "first op_pos[1]");
|
||||
|
||||
mu_assert_eq (second->ninstr, 3, "second ninstr after split");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (second, 0), 0, "second op_pos[0]");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (second, 1), 2, "second op_pos[1]");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (second, 2), 28, "second op_pos[2]");
|
||||
|
||||
r_anal_block_unref (block);
|
||||
r_anal_block_unref (second);
|
||||
|
||||
assert_leaks (anal);
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_split_in_function() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (blocks_count (anal), 1, "count after create");
|
||||
r_anal_function_add_block (fcn, block);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->ref, 2, "block refs after adding to function");
|
||||
|
||||
RAnalBlock *second = r_anal_block_split (block, 0x1339);
|
||||
assert_invariants (anal);
|
||||
mu_assert_ptrneq (second, block, "non-nop split");
|
||||
mu_assert_eq (blocks_count (anal), 2, "count after non-nop split");
|
||||
mu_assert_eq (block->ref, 2, "first block refs after adding to function");
|
||||
mu_assert_eq (second->ref, 2, "second block refs after adding to function");
|
||||
|
||||
mu_assert ("function has first block after split", r_list_contains (fcn->bbs, block));
|
||||
mu_assert ("function has second block after split", r_list_contains (fcn->bbs, second));
|
||||
mu_assert ("second block is in function after split", r_list_contains (block->fcns, fcn));
|
||||
mu_assert ("second block is in function after split", r_list_contains (second->fcns, fcn));
|
||||
|
||||
r_anal_block_unref (block);
|
||||
r_anal_block_unref (second);
|
||||
|
||||
assert_leaks (anal);
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_merge() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalBlock *first = r_anal_create_block (anal, 0x1337, 42);
|
||||
RAnalBlock *second = r_anal_create_block (anal, 0x1337 + 42, 624);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (blocks_count (anal), 2, "count after create");
|
||||
second->jump = 0xdeadbeef;
|
||||
second->fail = 0xc0ffee;
|
||||
|
||||
first->ninstr = 3;
|
||||
r_anal_bb_set_offset (first, 0, 0);
|
||||
r_anal_bb_set_offset (first, 1, 13);
|
||||
r_anal_bb_set_offset (first, 2, 16);
|
||||
|
||||
second->ninstr = 4;
|
||||
r_anal_bb_set_offset (second, 0, 0);
|
||||
r_anal_bb_set_offset (second, 1, 4);
|
||||
r_anal_bb_set_offset (second, 2, 9);
|
||||
r_anal_bb_set_offset (second, 3, 30);
|
||||
|
||||
bool success = r_anal_block_merge (first, second);
|
||||
assert_invariants (anal);
|
||||
mu_assert ("merge success", success);
|
||||
mu_assert_eq (blocks_count (anal), 1, "count after merge");
|
||||
mu_assert_eq (first->addr, 0x1337, "addr after merge");
|
||||
mu_assert_eq (first->size, 666, "size after merge");
|
||||
mu_assert_eq (first->jump, 0xdeadbeef, "jump after merge");
|
||||
mu_assert_eq (first->fail, 0xc0ffee, "fail after merge");
|
||||
|
||||
mu_assert_eq (first->ninstr, 3+4, "ninstr after merge");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (first, 0), 0, "offset 0 after merge");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (first, 1), 13, "offset 1 after merge");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (first, 2), 16, "offset 2 after merge");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (first, 3), 42+0, "offset 3 after merge");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (first, 4), 42+4, "offset 4 after merge");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (first, 5), 42+9, "offset 5 after merge");
|
||||
mu_assert_eq (r_anal_bb_offset_inst (first, 6), 42+30, "offset 6 after merge");
|
||||
|
||||
r_anal_block_unref (first);
|
||||
// second must be already freed by the merge!
|
||||
|
||||
assert_invariants (anal);
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_merge_in_function() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
|
||||
|
||||
RAnalBlock *first = r_anal_create_block (anal, 0x1337, 42);
|
||||
RAnalBlock *second = r_anal_create_block (anal, 0x1337 + 42, 624);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (blocks_count (anal), 2, "count after create");
|
||||
|
||||
r_anal_function_add_block (fcn, first);
|
||||
assert_invariants (anal);
|
||||
r_anal_function_add_block (fcn, second);
|
||||
assert_invariants (anal);
|
||||
|
||||
bool success = r_anal_block_merge (first, second);
|
||||
assert_invariants (anal);
|
||||
mu_assert ("merge success", success);
|
||||
mu_assert_eq (blocks_count (anal), 1, "count after merge");
|
||||
mu_assert_eq (r_list_length (fcn->bbs), 1, "fcn bbs after merge");
|
||||
mu_assert_eq (r_list_length (first->fcns), 1, "bb functions after merge");
|
||||
mu_assert ("function has merged block", r_list_contains (fcn->bbs, first));
|
||||
mu_assert ("merged block is in function", r_list_contains (first->fcns, fcn));
|
||||
|
||||
r_anal_block_unref (first);
|
||||
// second must be already freed by the merge!
|
||||
|
||||
assert_invariants (anal);
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_delete() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
|
||||
|
||||
RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (blocks_count (anal), 1, "count after create");
|
||||
|
||||
r_anal_function_add_block (fcn, block);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->ref, 2, "refs after adding");
|
||||
mu_assert_eq (r_list_length (fcn->bbs), 1, "fcn bbs after add");
|
||||
mu_assert_eq (r_list_length (block->fcns), 1, "bb fcns after add");
|
||||
|
||||
r_anal_delete_block (block);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->ref, 1, "refs after delete");
|
||||
mu_assert_eq (r_list_length (fcn->bbs), 0, "fcn bbs after delete");
|
||||
mu_assert_eq (r_list_length (block->fcns), 0, "bb fcns after delete");
|
||||
|
||||
r_anal_block_unref (block);
|
||||
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_set_size() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
|
||||
|
||||
RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
|
||||
assert_invariants (anal);
|
||||
|
||||
r_anal_function_add_block (fcn, block);
|
||||
assert_invariants (anal);
|
||||
|
||||
r_anal_block_set_size (block, 300);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->size, 300, "size after set_size");
|
||||
|
||||
RAnalBlock *second = r_anal_create_block (anal, 0x1337+300, 100);
|
||||
assert_invariants (anal);
|
||||
r_anal_function_add_block (fcn, block);
|
||||
assert_invariants (anal);
|
||||
r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
|
||||
assert_invariants (anal);
|
||||
|
||||
r_anal_block_set_size (second, 500);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (second->size, 500, "size after set_size");
|
||||
|
||||
r_anal_block_set_size (block, 80);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->size, 80, "size after set_size");
|
||||
|
||||
r_anal_block_unref (block);
|
||||
r_anal_block_unref (second);
|
||||
assert_invariants (anal);
|
||||
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_relocate() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalFunction *fcn = r_anal_create_function (anal, "bbowner", 0x1337, 0, NULL);
|
||||
|
||||
RAnalBlock *block = r_anal_create_block (anal, 0x1337, 42);
|
||||
assert_invariants (anal);
|
||||
|
||||
r_anal_function_add_block (fcn, block);
|
||||
assert_invariants (anal);
|
||||
r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
|
||||
assert_invariants (anal);
|
||||
|
||||
bool success = r_anal_block_relocate (block, 0x200, 0x100);
|
||||
mu_assert ("relocate success", success);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->addr, 0x200, "addr after relocate");
|
||||
mu_assert_eq (block->size, 0x100, "size after relocate");
|
||||
|
||||
RAnalBlock *second = r_anal_create_block (anal, 0x1337+300, 100);
|
||||
assert_invariants (anal);
|
||||
r_anal_function_add_block (fcn, second);
|
||||
assert_invariants (anal);
|
||||
|
||||
success = r_anal_block_relocate (second, 0x400, 0x123);
|
||||
mu_assert ("relocate success", success);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (second->addr, 0x400, "addr after relocate");
|
||||
mu_assert_eq (second->size, 0x123, "size after relocate");
|
||||
r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
|
||||
assert_invariants (anal);
|
||||
|
||||
success = r_anal_block_relocate (block, 0x400, 0x333);
|
||||
mu_assert ("relocate fail on same addr", !success);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->addr, 0x200, "addr after failed relocate");
|
||||
mu_assert_eq (block->size, 0x100, "size after failed relocate");
|
||||
r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
|
||||
assert_invariants (anal);
|
||||
|
||||
// jump after the other block
|
||||
success = r_anal_block_relocate (block, 0x500, 0x333);
|
||||
mu_assert ("relocate success", success);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->addr, 0x500, "addr after failed relocate");
|
||||
mu_assert_eq (block->size, 0x333, "size after failed relocate");
|
||||
r_anal_function_linear_size (fcn); // trigger lazy calculation of min/max cache
|
||||
assert_invariants (anal);
|
||||
|
||||
// jump before the other block
|
||||
success = r_anal_block_relocate (block, 0x10, 0x333);
|
||||
mu_assert ("relocate success", success);
|
||||
assert_invariants (anal);
|
||||
mu_assert_eq (block->addr, 0x10, "addr after failed relocate");
|
||||
mu_assert_eq (block->size, 0x333, "size after failed relocate");
|
||||
|
||||
r_anal_block_unref (block);
|
||||
r_anal_block_unref (second);
|
||||
assert_invariants (anal);
|
||||
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_query() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
#define N 200
|
||||
#define MAXSIZE 0x300
|
||||
#define SPACE 0x10000
|
||||
#define SAMPLES 300
|
||||
|
||||
RAnalBlock *blocks[N];
|
||||
size_t i;
|
||||
for (i = 0; i < N; i++) {
|
||||
blocks[i] = r_anal_create_block (anal, rand () % SPACE, rand () % MAXSIZE); // may return null on duplicates
|
||||
assert_invariants (anal);
|
||||
}
|
||||
|
||||
// --
|
||||
// test r_anal_get_block_at()
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
if (!blocks[i]) {
|
||||
continue;
|
||||
}
|
||||
mu_assert_ptreq (r_anal_get_block_at (anal, blocks[i]->addr), blocks[i], "r_anal_get_block_at");
|
||||
}
|
||||
|
||||
for (i = 0; i < SAMPLES; i++) {
|
||||
ut64 addr = rand () % SPACE;
|
||||
size_t j;
|
||||
|
||||
// goal is to check cases where r_anal_get_block_at() returns null,
|
||||
// but since the addr is random, there may be a block sometimes too.
|
||||
RAnalBlock *block = NULL;
|
||||
for (j = 0; j < N; j++) {
|
||||
if (!blocks[j]) {
|
||||
continue;
|
||||
}
|
||||
if (blocks[j]->addr == addr) {
|
||||
block = blocks[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mu_assert_ptreq (r_anal_get_block_at (anal, addr), block, "r_anal_get_block_at");
|
||||
}
|
||||
|
||||
// --
|
||||
// test r_anal_get_blocks_in()
|
||||
|
||||
for (i = 0; i < SAMPLES; i++) {
|
||||
ut64 addr = rand () % SPACE;
|
||||
RList *in = r_anal_get_blocks_in (anal, addr);
|
||||
|
||||
RAnalBlock *block;
|
||||
RListIter *it;
|
||||
r_list_foreach (in, it, block) {
|
||||
mu_assert_eq (block->ref, 2, "block refd in returned list");
|
||||
}
|
||||
|
||||
size_t linear_found = 0;
|
||||
size_t j;
|
||||
for (j = 0; j < N; j++) {
|
||||
if (!blocks[j]) {
|
||||
continue;
|
||||
}
|
||||
if (r_anal_block_contains (blocks[j], addr)) {
|
||||
linear_found++;
|
||||
mu_assert ("intersect linear found in list", r_list_contains (in, blocks[j]));
|
||||
}
|
||||
}
|
||||
mu_assert_eq ((size_t)r_list_length (in), linear_found, "r_anal_get_blocks_in count");
|
||||
r_list_free (in);
|
||||
}
|
||||
|
||||
// --
|
||||
// test r_anal_get_blocks_intersect()
|
||||
|
||||
for (i = 0; i < SAMPLES; i++) {
|
||||
ut64 addr = rand () % SPACE;
|
||||
ut64 size = rand() % MAXSIZE;
|
||||
RList *in = r_anal_get_blocks_intersect (anal, addr, size);
|
||||
|
||||
RAnalBlock *block;
|
||||
RListIter *it;
|
||||
r_list_foreach (in, it, block) {
|
||||
mu_assert_eq (block->ref, 2, "block refd in returned list");
|
||||
}
|
||||
|
||||
size_t linear_found = 0;
|
||||
size_t j;
|
||||
for (j = 0; j < N; j++) {
|
||||
RAnalBlock *block = blocks[j];
|
||||
if (!block || addr + size <= block->addr || addr >= block->addr + block->size) {
|
||||
continue;
|
||||
}
|
||||
linear_found++;
|
||||
mu_assert ("in linear found in list", r_list_contains (in, blocks[j]));
|
||||
}
|
||||
mu_assert_eq ((size_t)r_list_length (in), linear_found, "r_anal_get_blocks_intersect count");
|
||||
r_list_free (in);
|
||||
}
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
r_anal_block_unref (blocks[i]);
|
||||
}
|
||||
|
||||
assert_leaks (anal);
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool addr_list_cb(ut64 addr, void *user) {
|
||||
RList *list = user;
|
||||
r_list_push (list, (void *)addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_r_anal_block_successors() {
|
||||
RAnal *anal = r_anal_new ();
|
||||
assert_invariants (anal);
|
||||
|
||||
RAnalBlock *blocks[10];
|
||||
blocks[0] = r_anal_create_block (anal, 0x10, 0x10);
|
||||
blocks[1] = r_anal_create_block (anal, 0x30, 0x10);
|
||||
blocks[2] = r_anal_create_block (anal, 0x50, 0x10);
|
||||
blocks[3] = r_anal_create_block (anal, 0x100, 0x10);
|
||||
blocks[4] = r_anal_create_block (anal, 0x110, 0x10);
|
||||
blocks[5] = r_anal_create_block (anal, 0x120, 0x10);
|
||||
blocks[6] = r_anal_create_block (anal, 0x130, 0x10);
|
||||
blocks[7] = r_anal_create_block (anal, 0x140, 0x10);
|
||||
blocks[8] = r_anal_create_block (anal, 0xa0, 0x10);
|
||||
blocks[9] = r_anal_create_block (anal, 0xc0, 0x10);
|
||||
assert_invariants (anal);
|
||||
|
||||
blocks[0]->jump = 0x30;
|
||||
blocks[0]->fail = 0x50;
|
||||
blocks[1]->jump = 0x10;
|
||||
blocks[1]->fail = 0x50;
|
||||
blocks[2]->jump = 0x10;
|
||||
|
||||
RAnalSwitchOp *sop = r_anal_switch_op_new (0x55, 0, 10);
|
||||
r_anal_switch_op_add_case (sop, 0x55, 1, 0x100);
|
||||
r_anal_switch_op_add_case (sop, 0x55, 2, 0x110);
|
||||
r_anal_switch_op_add_case (sop, 0x55, 3, 0x120);
|
||||
r_anal_switch_op_add_case (sop, 0x55, 4, 0x130);
|
||||
r_anal_switch_op_add_case (sop, 0x55, 5, 0x140);
|
||||
blocks[2]->switch_op = sop;
|
||||
|
||||
RList *result = r_list_new ();
|
||||
r_anal_block_successor_addrs_foreach (blocks[0], addr_list_cb, result);
|
||||
mu_assert_eq (r_list_length (result), 2, "jump/fail successors count");
|
||||
mu_assert ("jmp successor", r_list_contains (result, (void *)0x30));
|
||||
mu_assert ("fail successor", r_list_contains (result, (void *)0x50));
|
||||
r_list_purge (result);
|
||||
|
||||
r_anal_block_successor_addrs_foreach (blocks[2], addr_list_cb, result);
|
||||
mu_assert_eq (r_list_length (result), 6, "switch successors count");
|
||||
mu_assert ("jmp successor", r_list_contains (result, (void *)0x10));
|
||||
mu_assert ("case successor", r_list_contains (result, (void *)0x100));
|
||||
mu_assert ("case successor", r_list_contains (result, (void *)0x110));
|
||||
mu_assert ("case successor", r_list_contains (result, (void *)0x120));
|
||||
mu_assert ("case successor", r_list_contains (result, (void *)0x130));
|
||||
mu_assert ("case successor", r_list_contains (result, (void *)0x140));
|
||||
r_list_free (result);
|
||||
|
||||
result = r_anal_block_recurse_list (blocks[0]);
|
||||
RAnalBlock *block;
|
||||
RListIter *it;
|
||||
r_list_foreach (result, it, block) {
|
||||
mu_assert_eq (block->ref, 2, "block refd in returned list");
|
||||
}
|
||||
|
||||
mu_assert_eq (r_list_length (result), 8, "recursive successors count");
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[0]));
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[1]));
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[2]));
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[3]));
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[4]));
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[5]));
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[6]));
|
||||
mu_assert ("recursive successor", r_list_contains (result, blocks[7]));
|
||||
|
||||
r_list_free (result);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof (blocks) / sizeof (RAnalBlock *); i++) {
|
||||
r_anal_block_unref (blocks[i]);
|
||||
}
|
||||
|
||||
assert_leaks (anal);
|
||||
r_anal_free (anal);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
int all_tests() {
|
||||
mu_run_test (test_r_anal_block_create);
|
||||
mu_run_test (test_r_anal_block_contains);
|
||||
mu_run_test (test_r_anal_block_split);
|
||||
mu_run_test (test_r_anal_block_split_in_function);
|
||||
mu_run_test (test_r_anal_block_merge);
|
||||
mu_run_test (test_r_anal_block_merge_in_function);
|
||||
mu_run_test (test_r_anal_block_delete);
|
||||
mu_run_test (test_r_anal_block_set_size);
|
||||
mu_run_test (test_r_anal_block_relocate);
|
||||
mu_run_test (test_r_anal_block_query);
|
||||
mu_run_test (test_r_anal_block_successors);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, NULL);
|
||||
unsigned int seed = argc > 1 ? strtoul (argv[1], NULL, 0) : tv.tv_sec + tv.tv_usec;
|
||||
printf("seed for test_anal_block: %u\n", seed);
|
||||
return all_tests();
|
||||
}
|
Loading…
Reference in New Issue