10 #define unwrap(rbnode) ((rbnode) ? container_of(rbnode, RzAnalysisBlock, _rb) : NULL)
16 for (
i = 0;
i < 2;
i++) {
27 ut64 incoming_addr = *(
ut64 *)incoming;
29 if (incoming_addr < in_tree_block->
addr) {
32 if (incoming_addr > in_tree_block->
addr) {
38 #define D if (analysis && analysis->verbose)
97 while (node && addr < node->
addr) {
107 if (addr < node->
addr + node->
size) {
108 if (!
cb(node, user)) {
143 while (node && end <= node->
addr) {
153 if (addr < node->
addr + node->
size) {
188 while (!rz_list_empty(bb->
fcns)) {
202 rz_list_foreach (block->
fcns,
iter, fcn) {
227 rz_list_foreach (block->
fcns,
iter, fcn) {
291 rz_list_foreach (bbi->
fcns,
iter, fcn) {
301 int new_bbi_instr =
i;
304 while (i < bbi->ninstr) {
306 if (off_op >= bbi->
size + bb->
size) {
314 bbi->
ninstr = new_bbi_instr;
319 if (!rz_analysis_block_is_contiguous(
a,
b)) {
329 rz_list_foreach (
a->fcns,
iter, fcn) {
337 while (!rz_list_empty(
b->fcns)) {
343 for (
i = 0;
i <
b->ninstr;
i++) {
355 a->switch_op =
b->switch_op;
363 rz_list_foreach (
a->fcns,
iter, fcn) {
385 #define CB_ADDR(addr) \
387 if (addr == UT64_MAX) { \
390 if (!cb(addr, user)) { \
435 ctx.visited = ht_up_new0();
453 ht_up_free(
ctx.visited);
463 ctx.visited = ht_up_new0();
473 bool b = !
cb(cur, user);
482 ht_up_free(
ctx.visited);
495 HtUP *visited = ht_up_new0();
505 ht_up_insert(visited, cur_bb->
addr,
NULL);
512 cur_bb = cur_ctx->
bb;
525 while (ht_up_find_kv(visited, cop->
jump,
NULL)) {
541 ht_up_insert(visited, cur_bb->
addr,
NULL);
583 if (!rz_analysis_block_contains(bb,
addr)) {
593 if (
off == inst_off) {
614 ht_up_insert(
ctx->visited,
addr,
ctx->cur_parent);
633 ctx.next_visit = &visit_a;
636 ctx.visited = ht_up_new0();
649 ctx.cur_parent = cur;
653 cur_visit =
ctx.next_visit;
662 if (
found && dst_block) {
674 ht_up_free(
ctx.visited);
695 return block->
bbhash != cur_hash;
735 ht_up_insert(succs, block->
addr, succ);
768 if (!rz_analysis_block_contains(block,
addr) ||
addr == block->
addr) {
794 rz_list_foreach (fcns_cpy, it, fcn) {
822 for (it = merge_blocks.
head; it && (block = it->
data, 1); it = it->
n) {
823 if (block->
addr == block_addr) {
845 ctx->cur_succ_count++;
851 ctx->cur_succ_count++;
862 ht_up_update(
ctx->predecessors, (
ut64)(
size_t)block,
NULL);
866 ht_up_insert(
ctx->predecessors, (
ut64)(
size_t)block,
ctx->cur_pred);
876 rz_list_foreach (fcn->
bbs, it, block) {
877 bool already_visited;
878 ht_up_find(
ctx->visited_blocks, (
ut64)(
size_t)block, &already_visited);
879 if (already_visited) {
882 ctx->cur_pred = block;
883 ctx->cur_succ_count = 0;
885 ht_up_insert(
ctx->visited_blocks, (
ut64)(
size_t)block, (
void *)
ctx->cur_succ_count);
895 .predecessors = ht_up_new0(),
896 .visited_blocks = ht_up_new0(),
897 .blocks = ht_up_new0()
900 HtUP *relevant_fcns = ht_up_new0();
902 if (!
ctx.predecessors || !
ctx.visited_blocks || !
ctx.blocks || !relevant_fcns || !fixup_candidates) {
909 rz_list_foreach (
blocks, it, block) {
912 rz_list_foreach (block->
fcns, fit, fcn) {
913 ht_up_insert(relevant_fcns, (
ut64)(
size_t)fcn,
NULL);
915 ht_up_insert(
ctx.blocks, block->
addr, block);
923 rz_list_foreach_safe (
blocks, it,
tmp, block) {
929 if (pred_succs_count != 1) {
941 if (fixup_pred == block) {
949 ctx.cur_succ_count = 0;
951 ht_up_update(
ctx.visited_blocks, (
ut64)(
size_t)predecessor, (
void *)(
size_t)
ctx.cur_succ_count);
952 rz_list_foreach (fixup_candidates,
bit, clock) {
954 ht_up_update(
ctx.predecessors, (
ut64)(
size_t)clock, predecessor);
965 ht_up_free(
ctx.predecessors);
966 ht_up_free(
ctx.visited_blocks);
967 ht_up_free(
ctx.blocks);
968 ht_up_free(relevant_fcns);
985 if (!
ctx->ret ||
ctx->ret->addr < block->
addr) {
1029 if (
i > 0 &&
v > 0) {
1031 size_t new_pos_size =
i * 2;
1037 block->
op_pos = tmp_op_pos;
1052 if (!rz_analysis_block_contains(bb,
off)) {
1059 if (
delta > delta_off) {
1060 return bb->
addr + last_delta;
1064 return bb->
addr + last_delta;
1076 return idx_next !=
UT16_MAX ? idx_next - idx_cur : bb->
size - idx_cur;
1087 if (!
a->iob.read_at) {
1097 if (!
a->iob.read_at(
a->iob.io, block->
addr,
buf, block->
size)) {
1103 while (addr < block->
addr + block->
size) {
RZ_API void rz_analysis_diff_free(RzAnalysisDiff *diff)
RZ_API void rz_analysis_function_add_block(RzAnalysisFunction *fcn, RzAnalysisBlock *bb)
RZ_API void rz_analysis_function_remove_block(RzAnalysisFunction *fcn, RzAnalysisBlock *bb)
RZ_API void rz_analysis_block_set_size(RzAnalysisBlock *block, ut64 size)
static bool automerge_get_predecessors_cb(void *user, const ut64 k, const void *v)
RZ_API bool rz_analysis_block_was_modified(RzAnalysisBlock *block)
static bool recurse_list_cb(RzAnalysisBlock *block, void *user)
static RzAnalysisBlock * block_new(RzAnalysis *a, ut64 addr, ut64 size)
static bool block_list_cb(RzAnalysisBlock *block, void *user)
RZ_API void rz_analysis_blocks_foreach_intersect(RzAnalysis *analysis, ut64 addr, ut64 size, RzAnalysisBlockCb cb, void *user)
static bool count_successors_cb(ut64 addr, void *user)
RZ_API void rz_analysis_delete_block(RzAnalysisBlock *bb)
RZ_API RzAnalysisBlock * rz_analysis_block_chop_noreturn(RzAnalysisBlock *block, ut64 addr)
RZ_API RzList * rz_analysis_block_recurse_list(RzAnalysisBlock *block)
static bool block_recurse_successor_cb(ut64 addr, void *user)
RZ_API bool rz_analysis_block_relocate(RzAnalysisBlock *block, ut64 addr, ut64 size)
static bool block_from_offset_cb(RzAnalysisBlock *block, void *user)
RZ_API bool rz_analysis_block_set_op_offset(RzAnalysisBlock *block, size_t i, ut16 v)
RZ_API void rz_analysis_block_ref(RzAnalysisBlock *bb)
RZ_API void rz_analysis_block_update_hash(RzAnalysisBlock *block)
static bool all_in(RzAnalysisBlock *node, ut64 addr, RzAnalysisBlockCb cb, void *user)
RZ_API bool rz_analysis_block_recurse_depth_first(RzAnalysisBlock *block, RzAnalysisBlockCb cb, RZ_NULLABLE RzAnalysisBlockCb on_exit, void *user)
RZ_API bool rz_analysis_blocks_foreach_in(RzAnalysis *analysis, ut64 addr, RzAnalysisBlockCb cb, void *user)
static bool automerge_predecessor_successor_cb(ut64 addr, void *user)
static void block_free(RzAnalysisBlock *block)
RZ_API RzAnalysisBlock * rz_analysis_get_block_at(RzAnalysis *analysis, ut64 addr)
RZ_API bool rz_analysis_block_recurse_followthrough(RzAnalysisBlock *block, RzAnalysisBlockCb cb, void *user)
RZ_API ut64 rz_analysis_block_get_op_size(RzAnalysisBlock *bb, size_t i)
RZ_API ut64 rz_analysis_block_get_op_addr(RzAnalysisBlock *block, size_t i)
RZ_API void rz_analysis_block_unref(RzAnalysisBlock *bb)
RZ_API void rz_analysis_block_add_switch_case(RzAnalysisBlock *block, ut64 switch_addr, ut64 case_value, ut64 case_addr)
RZ_API RzList * rz_analysis_get_blocks_in(RzAnalysis *analysis, ut64 addr)
RZ_API RzAnalysisBlock * rz_analysis_create_block(RzAnalysis *analysis, ut64 addr, ut64 size)
RZ_API ut64 rz_analysis_block_get_op_addr_in(RzAnalysisBlock *bb, ut64 off)
static void noreturn_successor_free(HtUPKv *kv)
RZ_API RzList * rz_analysis_get_blocks_intersect(RzAnalysis *analysis, ut64 addr, ut64 size)
static void __max_end(RBNode *node)
static bool noreturn_get_blocks_cb(void *user, const ut64 k, const void *v)
RZ_API bool rz_analysis_block_merge(RzAnalysisBlock *a, RzAnalysisBlock *b)
struct rz_analysis_block_recurse_context_t RzAnalysisBlockRecurseContext
RZ_API RzAnalysisBlock * rz_analysis_block_split(RzAnalysisBlock *bbi, ut64 addr)
RZ_API RzAnalysisBlock * rz_analysis_find_most_relevant_block_in(RzAnalysis *analysis, ut64 off)
RZ_API bool rz_analysis_block_recurse(RzAnalysisBlock *block, RzAnalysisBlockCb cb, void *user)
RZ_API bool rz_analysis_block_successor_addrs_foreach(RzAnalysisBlock *block, RzAnalysisAddrCb cb, void *user)
RZ_API RZ_NULLABLE RzList * rz_analysis_block_shortest_path(RzAnalysisBlock *block, ut64 dst)
RZ_API ut16 rz_analysis_block_get_op_offset(RzAnalysisBlock *block, size_t i)
static void all_intersect(RzAnalysisBlock *node, ut64 addr, ut64 size, RzAnalysisBlockCb cb, void *user)
RZ_API void rz_analysis_block_analyze_ops(RzAnalysisBlock *block)
void __block_free_rb(RBNode *node, void *user)
RZ_API bool rz_analysis_block_op_starts_at(RzAnalysisBlock *bb, ut64 addr)
static bool noreturn_successors_cb(RzAnalysisBlock *block, void *user)
RZ_API void rz_analysis_block_automerge(RzList *blocks)
static bool shortest_path_successor_cb(ut64 addr, void *user)
static bool noreturn_remove_unreachable_cb(void *user, const ut64 k, const void *v)
static bool noreturn_successors_reachable_cb(RzAnalysisBlock *block, void *user)
static int __bb_addr_cmp(const void *incoming, const RBNode *in_tree, void *user)
RZ_API void rz_analysis_cond_free(RzAnalysisCond *c)
static static fork const void static count static fd const char const char static newpath const char static path const char path
RZ_API ut32 rz_hash_xxhash(RZ_NONNULL RzHash *rh, RZ_NONNULL const ut8 *input, size_t size)
RZ_API void Ht_() free(HtName_(Ht) *ht)
RZ_API const KEY_TYPE bool * found
static void list(RzEgg *egg)
RZ_API RZ_BORROW RzListIter * rz_list_iter_get_next(RzListIter *list)
returns the next RzList iterator in the list
RZ_API RZ_BORROW RzListIter * rz_list_contains(RZ_NONNULL const RzList *list, RZ_NONNULL const void *ptr)
Returns the RzListIter of the given pointer, if found.
RZ_API RZ_BORROW RzListIter * rz_list_prepend(RZ_NONNULL RzList *list, void *data)
Appends at the beginning of the list a new element.
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
RZ_API RZ_OWN RzList * rz_list_clone(RZ_NONNULL const RzList *list)
Shallow copies of the list (but doesn't free its elements)
RZ_API void * rz_list_iter_get_data(RzListIter *list)
returns the value stored in the list element
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
RZ_API void rz_list_split_iter(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
RZ_API void rz_list_init(RZ_NONNULL RzList *list)
Initializes the RzList pointer.
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
void * realloc(void *ptr, size_t size)
void * malloc(size_t size)
assert(limit<=UINT32_MAX/2)
RZ_API bool rz_analysis_op_fini(RzAnalysisOp *op)
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
#define rz_return_if_fail(expr)
#define rz_return_val_if_fail(expr, val)
void(* RzListFree)(void *ptr)
#define RZ_LOG_DEBUG(fmtstr,...)
RZ_API RBNode * rz_rbtree_find(RBNode *root, void *data, RBComparator cmp, void *user)
RZ_API bool rz_rbtree_aug_update_sum(RBNode *root, void *data, RBNode *node, RBComparator cmp, void *cmp_user, RBNodeSum sum)
Returns true if the sum has been updated, false if node has not been found.
RZ_API bool rz_rbtree_aug_delete(RBNode **root, void *data, RBComparator cmp, void *cmp_user, RBNodeFree freefn, void *free_user, RBNodeSum sum)
Returns true if a node with an equal key is deleted.
RZ_API bool rz_rbtree_aug_insert(RBNode **root, void *data, RBNode *node, RBComparator cmp, void *cmp_user, RBNodeSum sum)
Returns true if the node was inserted successfully.
#define container_of(ptr, type, member)
RZ_API void rz_vector_pop(RzVector *vec, void *into)
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
RZ_API void * rz_pvector_pop(RzPVector *vec)
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
RZ_API void * rz_vector_push(RzVector *vec, void *x)
static bool rz_pvector_empty(RzPVector *vec)
static void ** rz_pvector_push(RzPVector *vec, void *x)
RZ_API void rz_vector_clear(RzVector *vec)
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
static bool rz_vector_empty(const RzVector *vec)
RZ_API void rz_pvector_clear(RzPVector *vec)
#define rz_pvector_foreach(vec, it)
RzAnalysisBlock * cur_pred
RzAnalysisBlock * cur_parent
RzAnalysisSwitchOp * switch_op
struct rz_list_iter_t * n
struct rz_rb_node_t * child[2]
void on_exit(uv_process_t *req, int64_t exit_status, int term_signal)
RZ_API void rz_analysis_switch_op_free(RzAnalysisSwitchOp *swop)
RZ_API RzAnalysisSwitchOp * rz_analysis_switch_op_new(ut64 addr, ut64 min_val, ut64 max_val, ut64 def_val)
RZ_API RzAnalysisCaseOp * rz_analysis_switch_op_add_case(RzAnalysisSwitchOp *swop, ut64 addr, ut64 value, ut64 jump)
ut64(WINAPI *w32_GetEnabledXStateFeatures)()