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:
Florian Märkl 2020-01-15 10:58:30 +01:00 committed by radare
parent 5bb7e28ad4
commit 14215350af
51 changed files with 2297 additions and 1383 deletions

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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;

462
libr/anal/block.c Normal file
View File

@ -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;
}

View File

@ -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) {

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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");

334
libr/anal/function.c Normal file
View File

@ -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);
}

View File

@ -2,6 +2,8 @@ r_anal_sources = [
'anal.c',
'anal_ex.c',
'bb.c',
'block.c',
'function.c',
'jmptbl.c',
'cc.c',
'class.c',

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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) {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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 "

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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':

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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 ();

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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
..
#

14
test/new/db/cmd/cmd_afb Normal file
View File

@ -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

View File

@ -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

652
test/unit/test_anal_block.c Normal file
View File

@ -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();
}