Rizin
unix-like reverse engineering framework and cli tools
fcn.c File Reference
#include <rz_analysis.h>
#include <rz_parse.h>
#include <rz_util.h>
#include <rz_list.h>

Go to the source code of this file.

Classes

struct  fcn_tree_iter_t
 
struct  leaddr_pair
 
struct  BlockTakeoverCtx
 
struct  BlockRecurseCtx
 

Macros

#define READ_AHEAD   1
 
#define SDB_KEY_BB   "bb.0x%" PFMT64x ".0x%" PFMT64x
 
#define JMPTBL_LEA_SEARCH_SZ   64
 
#define BB_ALIGN   0x10
 
#define MAX_SCAN_SIZE   0x7ffffff
 
#define MAX_FLG_NAME_SIZE   64
 
#define MAX_FCN_SIZE   (1024 * 256)
 
#define DB   a->sdb_fcns
 
#define EXISTS(x, ...)   snprintf(key, sizeof(key) - 1, x, ##__VA_ARGS__), sdb_exists(DB, key)
 
#define SETKEY(x, ...)   snprintf(key, sizeof(key) - 1, x, ##__VA_ARGS__);
 
#define gotoBeach(x)
 

Typedefs

typedef struct fcn_tree_iter_t FcnTreeIter
 

Functions

RZ_API const char * rz_analysis_fcntype_tostring (int type)
 
static int read_ahead (RzAnalysis *analysis, ut64 addr, ut8 *buf, int len)
 
RZ_API void rz_analysis_fcn_invalidate_read_ahead_cache (void)
 
RZ_API int rz_analysis_function_resize (RzAnalysisFunction *fcn, int newsize)
 
static RzAnalysisBlockfcn_append_basic_block (RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr)
 
static bool isInvalidMemory (RzAnalysis *analysis, const ut8 *buf, int len)
 
static bool isSymbolNextInstruction (RzAnalysis *analysis, RzAnalysisOp *op)
 
static bool is_delta_pointer_table (RzAnalysis *analysis, ut64 addr, ut64 lea_ptr, ut64 *jmptbl_addr, ut64 *casetbl_addr, RzAnalysisOp *jmp_aop)
 
static ut64 try_get_cmpval_from_parents (RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *my_bb, const char *cmp_reg)
 
static bool regs_exist (RzAnalysisValue *src, RzAnalysisValue *dst)
 
static int skip_hp (RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op, RzAnalysisBlock *bb, ut64 addr, char *tmp_buf, int oplen, int un_idx, int *idx)
 
static bool purity_checked (HtUP *ht, RzAnalysisFunction *fcn)
 
static void check_purity (HtUP *ht, RzAnalysisFunction *fcn)
 
static void free_leaddr_pair (void *pair)
 
static RzAnalysisBlockbbget (RzAnalysis *analysis, ut64 addr, bool jumpmid)
 
static bool fcn_takeover_block_recursive_followthrough_cb (RzAnalysisBlock *block, void *user)
 
static void fcn_takeover_block_recursive (RzAnalysisFunction *fcn, RzAnalysisBlock *start_block)
 
static const char * retpoline_reg (RzAnalysis *analysis, ut64 addr)
 
static void analyze_retpoline (RzAnalysis *analysis, RzAnalysisOp *op)
 
static bool op_is_set_bp (RzAnalysisOp *op, const char *bp_reg, const char *sp_reg)
 
static bool does_arch_destroys_dst (const char *arch)
 
static int analyze_function_locally (RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 address)
 
static void set_bb_branches (RZ_OUT RzAnalysisBlock *bb, const ut64 jump, const ut64 fail)
 
static RzAnalysisBBEndCause run_basic_block_analysis (RzAnalysisTaskItem *item, RzVector *tasks)
 Analyses the given task item item for branches. More...
 
RZ_API bool rz_analysis_task_item_new (RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzVector *tasks, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NULLABLE RzAnalysisBlock *block, ut64 address)
 Adds a new task item to the tasks parameter. More...
 
RZ_API int rz_analysis_run_tasks (RZ_NONNULL RzVector *tasks)
 Runs analysis on the task items. More...
 
RZ_API bool rz_analysis_check_fcn (RzAnalysis *analysis, ut8 *buf, ut16 bufsz, ut64 addr, ut64 low, ut64 high)
 
RZ_API void rz_analysis_trim_jmprefs (RzAnalysis *analysis, RzAnalysisFunction *fcn)
 
RZ_API void rz_analysis_del_jmprefs (RzAnalysis *analysis, RzAnalysisFunction *fcn)
 
RZ_API int rz_analysis_fcn (RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr, ut64 len, int reftype)
 
RZ_API int rz_analysis_fcn_del_locs (RzAnalysis *analysis, ut64 addr)
 
RZ_API int rz_analysis_fcn_del (RzAnalysis *a, ut64 addr)
 
RZ_DEPRECATE RZ_API RzAnalysisFunctionrz_analysis_get_fcn_in (RzAnalysis *analysis, ut64 addr, int type)
 
RZ_DEPRECATE RZ_API RzAnalysisFunctionrz_analysis_get_fcn_in_bounds (RzAnalysis *analysis, ut64 addr, int type)
 
RZ_API RzAnalysisFunctionrz_analysis_get_function_byname (RzAnalysis *a, const char *name)
 
RZ_API bool rz_analysis_fcn_add_bb (RzAnalysis *a, RzAnalysisFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, RZ_BORROW RzAnalysisDiff *diff)
 
RZ_API int rz_analysis_function_loops (RzAnalysisFunction *fcn)
 
RZ_API int rz_analysis_function_complexity (RzAnalysisFunction *fcn)
 
RZ_API int rz_analysis_function_get_arg_count (RzAnalysis *analysis, RzAnalysisFunction *f)
 Gets the RzCallable's arg count for the given function. More...
 
RZ_API char * rz_analysis_function_get_json (RzAnalysisFunction *function)
 
RZ_API RZ_OWN char * rz_analysis_function_get_signature (RZ_NONNULL RzAnalysisFunction *function)
 
RZ_API bool rz_analysis_function_set_type (RzAnalysis *a, RZ_NONNULL RzAnalysisFunction *f, RZ_NONNULL RzCallable *callable)
 Sets the RzCallable type for the given function. More...
 
RZ_API bool rz_analysis_function_set_type_str (RzAnalysis *a, RZ_NONNULL RzAnalysisFunction *f, RZ_NONNULL const char *sig)
 Parses the function type and sets it for the given function. More...
 
RZ_API RzAnalysisFunctionrz_analysis_fcn_next (RzAnalysis *analysis, ut64 addr)
 
RZ_API int rz_analysis_fcn_count (RzAnalysis *analysis, ut64 from, ut64 to)
 
RZ_API RzAnalysisBlockrz_analysis_fcn_bbget_in (const RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr)
 
RZ_API RzAnalysisBlockrz_analysis_fcn_bbget_at (RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr)
 
RZ_API ut32 rz_analysis_function_cost (RzAnalysisFunction *fcn)
 
RZ_API int rz_analysis_function_count_edges (const RzAnalysisFunction *fcn, RZ_NULLABLE int *ebbs)
 
RZ_API bool rz_analysis_function_purity (RzAnalysisFunction *fcn)
 
static bool can_affect_bp (RzAnalysis *analysis, RzAnalysisOp *op)
 
static void __analysis_fcn_check_bp_use (RzAnalysis *analysis, RzAnalysisFunction *fcn)
 
RZ_API void rz_analysis_function_check_bp_use (RzAnalysisFunction *fcn)
 
static bool mark_as_visited (RzAnalysisBlock *bb, void *user)
 
static bool analize_addr_cb (ut64 addr, void *user)
 
static bool analize_descendents (RzAnalysisBlock *bb, void *user)
 
static void free_ht_up (HtUPKv *kv)
 
static void update_varz_analysisysis (RzAnalysisFunction *fcn, int align, ut64 from, ut64 to)
 
static void clear_bb_vars (RzAnalysisFunction *fcn, RzAnalysisBlock *bb, ut64 from, ut64 to)
 
static void update_analysis (RzAnalysis *analysis, RzList *fcns, HtUP *reachable)
 
static void calc_reachable_and_remove_block (RzList *fcns, RzAnalysisFunction *fcn, RzAnalysisBlock *bb, HtUP *reachable)
 
RZ_API void rz_analysis_update_analysis_range (RzAnalysis *analysis, ut64 addr, int size)
 
RZ_API void rz_analysis_function_update_analysis (RzAnalysisFunction *fcn)
 
RZ_API size_t rz_analysis_function_arg_count (RzAnalysis *a, RzAnalysisFunction *fcn)
 Returns the argument count of a function. More...
 
RZ_API RZ_OWN RzPVectorrz_analysis_function_args (RzAnalysis *a, RzAnalysisFunction *fcn)
 Returns vector of all function arguments. More...
 
static int typecmp (const void *a, const void *b)
 
RZ_API RZ_OWN RzListrz_analysis_types_from_fcn (RzAnalysis *analysis, RzAnalysisFunction *fcn)
 
RZ_API RZ_OWN RzCallablerz_analysis_function_clone_type (RzAnalysis *analysis, const RzAnalysisFunction *f)
 Clones the RzCallable type for the given function. More...
 
RZ_API RZ_OWN RzCallablerz_analysis_function_create_type (RzAnalysis *analysis, RzAnalysisFunction *f)
 Creates the RzCallable type for the given function. More...
 
RZ_API void rz_analysis_function_derive_return_type (RzAnalysisFunction *f, RzCallable **callable)
 Sets the RzCallable return type for the given function. More...
 
RZ_API bool rz_analysis_function_derive_args (RzAnalysis *analysis, RzAnalysisFunction *f, RzCallable **callable)
 Sets the RzCallable args for the given function. More...
 
RZ_API RZ_OWN RzCallablerz_analysis_function_derive_type (RzAnalysis *analysis, RzAnalysisFunction *f)
 Derives the RzCallable type for the given function. More...
 

Variables

static ut64 cache_addr = UT64_MAX
 

Macro Definition Documentation

◆ BB_ALIGN

#define BB_ALIGN   0x10

Definition at line 15 of file fcn.c.

◆ DB

#define DB   a->sdb_fcns

Definition at line 25 of file fcn.c.

◆ EXISTS

#define EXISTS (   x,
  ... 
)    snprintf(key, sizeof(key) - 1, x, ##__VA_ARGS__), sdb_exists(DB, key)

Definition at line 26 of file fcn.c.

◆ gotoBeach

#define gotoBeach (   x)
Value:
ret = x; \
goto beach;
int x
Definition: mipsasm.c:20

Definition at line 139 of file fcn.c.

◆ JMPTBL_LEA_SEARCH_SZ

#define JMPTBL_LEA_SEARCH_SZ   64

Definition at line 14 of file fcn.c.

◆ MAX_FCN_SIZE

#define MAX_FCN_SIZE   (1024 * 256)

Definition at line 23 of file fcn.c.

◆ MAX_FLG_NAME_SIZE

#define MAX_FLG_NAME_SIZE   64

Definition at line 19 of file fcn.c.

◆ MAX_SCAN_SIZE

#define MAX_SCAN_SIZE   0x7ffffff

Definition at line 16 of file fcn.c.

◆ READ_AHEAD

#define READ_AHEAD   1

Definition at line 11 of file fcn.c.

◆ SDB_KEY_BB

#define SDB_KEY_BB   "bb.0x%" PFMT64x ".0x%" PFMT64x

Definition at line 12 of file fcn.c.

◆ SETKEY

#define SETKEY (   x,
  ... 
)    snprintf(key, sizeof(key) - 1, x, ##__VA_ARGS__);

Definition at line 27 of file fcn.c.

Typedef Documentation

◆ FcnTreeIter

typedef struct fcn_tree_iter_t FcnTreeIter

Function Documentation

◆ __analysis_fcn_check_bp_use()

static void __analysis_fcn_check_bp_use ( RzAnalysis analysis,
RzAnalysisFunction fcn 
)
static

Definition at line 2165 of file fcn.c.

2165  {
2166  RzListIter *iter;
2167  RzAnalysisBlock *bb;
2168  char str_to_find[40] = "\"type\":\"reg\",\"value\":\"";
2169  char *pos;
2170  strncat(str_to_find, analysis->reg->name[RZ_REG_NAME_BP], 39);
2171  if (!fcn) {
2172  return;
2173  }
2174  rz_list_foreach (fcn->bbs, iter, bb) {
2175  RzAnalysisOp op;
2176  ut64 at, end = bb->addr + bb->size;
2177  ut8 *buf = malloc(bb->size);
2178  if (!buf) {
2179  continue;
2180  }
2181  (void)analysis->iob.read_at(analysis->iob.io, bb->addr, (ut8 *)buf, bb->size);
2182  int idx = 0;
2183  for (at = bb->addr; at < end;) {
2185  if (op.size < 1) {
2186  op.size = 1;
2187  }
2188  switch (op.type) {
2191  if (can_affect_bp(analysis, &op) && op.src[0] && op.src[0]->reg && op.src[0]->reg->name && strcmp(op.src[0]->reg->name, analysis->reg->name[RZ_REG_NAME_SP])) {
2192  fcn->bp_frame = false;
2194  free(buf);
2195  return;
2196  }
2197  break;
2211  // op.dst is not filled for these operations, so for now, check for bp as dst looks like this; in the future it may be just replaced with call to can_affect_bp
2212  pos = op.opex.ptr ? strstr(op.opex.ptr, str_to_find) : NULL;
2213  if (pos && pos - op.opex.ptr < 60) {
2214  fcn->bp_frame = false;
2216  free(buf);
2217  return;
2218  }
2219  break;
2221  if (op.opex.ptr && strstr(op.opex.ptr, str_to_find)) {
2222  fcn->bp_frame = false;
2224  free(buf);
2225  return;
2226  }
2227  break;
2229  break;
2230  default:
2231  break;
2232  }
2233  idx += op.size;
2234  at += op.size;
2236  }
2237  free(buf);
2238  }
2239 }
ut8 op
Definition: 6502dis.c:13
#define NULL
Definition: cris-opc.c:27
static bool can_affect_bp(RzAnalysis *analysis, RzAnalysisOp *op)
Definition: fcn.c:2147
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
int idx
Definition: setup.py:197
RZ_API bool rz_analysis_op_fini(RzAnalysisOp *op)
Definition: op.c:37
RZ_API int rz_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: op.c:96
@ RZ_ANALYSIS_OP_MASK_VAL
Definition: rz_analysis.h:442
@ RZ_ANALYSIS_OP_MASK_OPEX
Definition: rz_analysis.h:444
@ RZ_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_ROL
Definition: rz_analysis.h:420
@ RZ_ANALYSIS_OP_TYPE_AND
Definition: rz_analysis.h:411
@ RZ_ANALYSIS_OP_TYPE_SAL
Definition: rz_analysis.h:408
@ RZ_ANALYSIS_OP_TYPE_ROR
Definition: rz_analysis.h:419
@ RZ_ANALYSIS_OP_TYPE_SAR
Definition: rz_analysis.h:409
@ RZ_ANALYSIS_OP_TYPE_CMOV
Definition: rz_analysis.h:391
@ RZ_ANALYSIS_OP_TYPE_XCHG
Definition: rz_analysis.h:421
@ RZ_ANALYSIS_OP_TYPE_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_OR
Definition: rz_analysis.h:410
@ RZ_ANALYSIS_OP_TYPE_SHR
Definition: rz_analysis.h:406
@ RZ_ANALYSIS_OP_TYPE_POP
Definition: rz_analysis.h:398
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_SHL
Definition: rz_analysis.h:407
@ RZ_ANALYSIS_OP_TYPE_NOT
Definition: rz_analysis.h:414
@ RZ_ANALYSIS_OP_TYPE_LEA
Definition: rz_analysis.h:417
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
@ RZ_REG_NAME_SP
Definition: rz_reg.h:44
@ RZ_REG_NAME_BP
Definition: rz_reg.h:46
RzIOBind iob
Definition: rz_analysis.h:574
RzIOReadAt read_at
Definition: rz_io.h:240
RzIO * io
Definition: rz_io.h:232
char * name[RZ_REG_NAME_LAST]
Definition: rz_reg.h:149
int pos
Definition: main.c:11
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References rz_analysis_bb_t::addr, rz_analysis_function_t::bbs, rz_analysis_function_t::bp_frame, can_affect_bp(), test_evm::end, free(), setup::idx, rz_io_bind_t::io, rz_analysis_t::iob, malloc(), rz_reg_t::name, NULL, op, pos, rz_io_bind_t::read_at, rz_analysis_t::reg, rz_analysis_op(), rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_OPEX, RZ_ANALYSIS_OP_MASK_VAL, RZ_ANALYSIS_OP_TYPE_ADD, RZ_ANALYSIS_OP_TYPE_AND, RZ_ANALYSIS_OP_TYPE_CMOV, RZ_ANALYSIS_OP_TYPE_LEA, RZ_ANALYSIS_OP_TYPE_MOV, RZ_ANALYSIS_OP_TYPE_NOT, RZ_ANALYSIS_OP_TYPE_OR, RZ_ANALYSIS_OP_TYPE_POP, RZ_ANALYSIS_OP_TYPE_ROL, RZ_ANALYSIS_OP_TYPE_ROR, RZ_ANALYSIS_OP_TYPE_SAL, RZ_ANALYSIS_OP_TYPE_SAR, RZ_ANALYSIS_OP_TYPE_SHL, RZ_ANALYSIS_OP_TYPE_SHR, RZ_ANALYSIS_OP_TYPE_SUB, RZ_ANALYSIS_OP_TYPE_XCHG, RZ_ANALYSIS_OP_TYPE_XOR, RZ_REG_NAME_BP, RZ_REG_NAME_SP, rz_analysis_bb_t::size, and ut64().

Referenced by rz_analysis_function_check_bp_use().

◆ analize_addr_cb()

static bool analize_addr_cb ( ut64  addr,
void *  user 
)
static

Definition at line 2257 of file fcn.c.

2257  {
2258  BlockRecurseCtx *ctx = user;
2259  RzAnalysis *analysis = ctx->fcn->analysis;
2260  RzAnalysisBlock *existing_bb = rz_analysis_get_block_at(analysis, addr);
2261  if (!existing_bb || !rz_list_contains(ctx->fcn->bbs, existing_bb)) {
2262  int old_len = rz_list_length(ctx->fcn->bbs);
2263  analyze_function_locally(ctx->fcn->analysis, ctx->fcn, addr);
2264  if (old_len != rz_list_length(ctx->fcn->bbs)) {
2266  }
2267  }
2268  ht_up_insert(ctx->visited, addr, NULL);
2269  return true;
2270 }
RZ_API RzAnalysisBlock * rz_analysis_get_block_at(RzAnalysis *analysis, ut64 addr)
Definition: block.c:90
RZ_API bool rz_analysis_block_recurse(RzAnalysisBlock *block, RzAnalysisBlockCb cb, void *user)
Definition: block.c:430
static int analyze_function_locally(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 address)
Definition: fcn.c:529
static bool mark_as_visited(RzAnalysisBlock *bb, void *user)
Definition: fcn.c:2251
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.
Definition: list.c:592
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
static int addr
Definition: z80asm.c:58

References addr, analyze_function_locally(), mark_as_visited(), NULL, rz_analysis_block_recurse(), rz_analysis_get_block_at(), rz_list_contains(), and rz_list_length().

Referenced by analize_descendents().

◆ analize_descendents()

static bool analize_descendents ( RzAnalysisBlock bb,
void *  user 
)
static

Definition at line 2272 of file fcn.c.

2272  {
2274 }
RZ_API bool rz_analysis_block_successor_addrs_foreach(RzAnalysisBlock *block, RzAnalysisAddrCb cb, void *user)
Definition: block.c:384
static bool analize_addr_cb(ut64 addr, void *user)
Definition: fcn.c:2257

References analize_addr_cb(), and rz_analysis_block_successor_addrs_foreach().

Referenced by update_analysis().

◆ analyze_function_locally()

static int analyze_function_locally ( RzAnalysis analysis,
RzAnalysisFunction fcn,
ut64  address 
)
static

Definition at line 529 of file fcn.c.

529  {
531  RzVector tasks;
532  rz_vector_init(&tasks, sizeof(RzAnalysisTaskItem), NULL, NULL);
533  RzAnalysisTaskItem item = { fcn, NULL, fcn->stack, address };
534  rz_vector_push(&tasks, &item);
535  int saved_stack = fcn->stack; // TODO: DO NOT use fcn->stack to keep track of stack during analysis
536  int ret = rz_analysis_run_tasks(&tasks);
537  rz_vector_fini(&tasks);
538  fcn->stack = saved_stack;
539  return ret;
540 }
RZ_API int rz_analysis_run_tasks(RZ_NONNULL RzVector *tasks)
Runs analysis on the task items.
Definition: fcn.c:1509
@ RZ_ANALYSIS_RET_ERROR
Definition: rz_analysis.h:474
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33

References NULL, RZ_ANALYSIS_RET_ERROR, rz_analysis_run_tasks(), rz_return_val_if_fail, rz_vector_fini(), rz_vector_init(), rz_vector_push(), and rz_analysis_function_t::stack.

Referenced by analize_addr_cb(), run_basic_block_analysis(), and update_analysis().

◆ analyze_retpoline()

static void analyze_retpoline ( RzAnalysis analysis,
RzAnalysisOp op 
)
static

Definition at line 506 of file fcn.c.

506  {
507  if (analysis->opt.retpoline) {
508  const char *rr = retpoline_reg(analysis, op->jump);
509  if (rr) {
511  op->reg = rr;
512  }
513  }
514 }
static const char * retpoline_reg(RzAnalysis *analysis, ut64 addr)
Definition: fcn.c:479
@ RZ_ANALYSIS_OP_TYPE_RJMP
Definition: rz_analysis.h:370
RzAnalysisOptions opt
Definition: rz_analysis.h:608

References rz_analysis_t::opt, rz_analysis_options_t::retpoline, retpoline_reg(), and RZ_ANALYSIS_OP_TYPE_RJMP.

Referenced by run_basic_block_analysis().

◆ bbget()

static RzAnalysisBlock* bbget ( RzAnalysis analysis,
ut64  addr,
bool  jumpmid 
)
static

Definition at line 359 of file fcn.c.

359  {
360  RzList *intersecting = rz_analysis_get_blocks_in(analysis, addr);
361  RzListIter *iter;
362  RzAnalysisBlock *bb;
363 
364  RzAnalysisBlock *ret = NULL;
365  rz_list_foreach (intersecting, iter, bb) {
366  ut64 eaddr = bb->addr + bb->size;
367  if (((bb->addr >= eaddr && addr == bb->addr) ||
368  rz_analysis_block_contains(bb, addr)) &&
369  (!jumpmid || rz_analysis_block_op_starts_at(bb, addr))) {
370  if (analysis->opt.delay) {
371  ut8 *buf = malloc(bb->size);
372  if (analysis->iob.read_at(analysis->iob.io, bb->addr, buf, bb->size)) {
373  const int last_instr_idx = bb->ninstr - 1;
374  bool in_delay_slot = false;
375  for (int i = last_instr_idx; i >= 0; i--) {
377  const ut64 at = bb->addr + off;
378  if (addr <= at || off >= bb->size) {
379  continue;
380  }
382  int size = rz_analysis_op(analysis, &op, at, buf + off, bb->size - off, RZ_ANALYSIS_OP_MASK_BASIC);
383  if (size > 0 && op.delay) {
384  if (op.delay >= last_instr_idx - i) {
385  in_delay_slot = true;
386  }
388  break;
389  }
391  }
392  if (in_delay_slot) {
393  free(buf);
394  continue;
395  }
396  }
397  free(buf);
398  }
399  ret = bb;
400  break;
401  }
402  }
403  rz_list_free(intersecting);
404  return ret;
405 }
lzma_index ** i
Definition: index.h:629
RZ_API RzList * rz_analysis_get_blocks_in(RzAnalysis *analysis, ut64 addr)
Definition: block.c:133
RZ_API ut16 rz_analysis_block_get_op_offset(RzAnalysisBlock *block, size_t i)
Definition: block.c:1006
RZ_API bool rz_analysis_block_op_starts_at(RzAnalysisBlock *bb, ut64 addr)
Definition: block.c:582
voidpf void uLong size
Definition: ioapi.h:138
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
int off
Definition: pal.c:13
@ RZ_ANALYSIS_OP_MASK_BASIC
Definition: rz_analysis.h:440

References addr, rz_analysis_bb_t::addr, rz_analysis_options_t::delay, free(), i, rz_io_bind_t::io, rz_analysis_t::iob, malloc(), rz_analysis_bb_t::ninstr, NULL, off, op, rz_analysis_t::opt, rz_io_bind_t::read_at, rz_analysis_block_get_op_offset(), rz_analysis_block_op_starts_at(), rz_analysis_get_blocks_in(), rz_analysis_op(), rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_BASIC, rz_list_free(), rz_analysis_bb_t::size, and ut64().

Referenced by run_basic_block_analysis().

◆ calc_reachable_and_remove_block()

static void calc_reachable_and_remove_block ( RzList fcns,
RzAnalysisFunction fcn,
RzAnalysisBlock bb,
HtUP *  reachable 
)
static

Definition at line 2381 of file fcn.c.

2381  {
2382  clear_bb_vars(fcn, bb, bb->addr, bb->addr + bb->size);
2383  if (!rz_list_contains(fcns, fcn)) {
2384  rz_list_append(fcns, fcn);
2385 
2386  // Calculate reachable blocks from the start of function
2387  HtUP *ht = ht_up_new0();
2388  BlockRecurseCtx ctx = { fcn, ht };
2390  ht_up_insert(reachable, fcn->addr, ht);
2391  }
2392  fcn->ninstr -= bb->ninstr;
2394 }
RZ_API void rz_analysis_function_remove_block(RzAnalysisFunction *fcn, RzAnalysisBlock *bb)
Definition: function.c:286
static void clear_bb_vars(RzAnalysisFunction *fcn, RzAnalysisBlock *bb, ut64 from, ut64 to)
Definition: fcn.c:2312
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
struct rz_analysis_t * analysis
Definition: rz_analysis.h:267

References rz_analysis_function_t::addr, rz_analysis_bb_t::addr, rz_analysis_function_t::analysis, clear_bb_vars(), mark_as_visited(), rz_analysis_function_t::ninstr, rz_analysis_bb_t::ninstr, rz_analysis_block_recurse(), rz_analysis_function_remove_block(), rz_analysis_get_block_at(), rz_list_append(), rz_list_contains(), and rz_analysis_bb_t::size.

Referenced by rz_analysis_function_update_analysis(), and rz_analysis_update_analysis_range().

◆ can_affect_bp()

static bool can_affect_bp ( RzAnalysis analysis,
RzAnalysisOp op 
)
static

Definition at line 2147 of file fcn.c.

2147  {
2148  RzAnalysisValue *dst = op->dst;
2149  RzAnalysisValue *src = op->src[0];
2150  const char *opdreg = (dst && dst->reg) ? dst->reg->name : NULL;
2151  const char *opsreg = (src && src->reg) ? src->reg->name : NULL;
2152  const char *bp_name = analysis->reg->name[RZ_REG_NAME_BP];
2153  bool is_bp_dst = opdreg && !dst->memref && !strcmp(opdreg, bp_name);
2154  bool is_bp_src = opsreg && !src->memref && !strcmp(opsreg, bp_name);
2155  if (op->type == RZ_ANALYSIS_OP_TYPE_XCHG) {
2156  return is_bp_src || is_bp_dst;
2157  }
2158  return is_bp_dst;
2159 }
lzma_index * src
Definition: index.h:567
char * dst
Definition: lz4.h:724

References dst, rz_reg_t::name, NULL, rz_analysis_t::reg, RZ_ANALYSIS_OP_TYPE_XCHG, RZ_REG_NAME_BP, and src.

Referenced by __analysis_fcn_check_bp_use().

◆ check_purity()

static void check_purity ( HtUP *  ht,
RzAnalysisFunction fcn 
)
static

Definition at line 319 of file fcn.c.

319  {
320  RzListIter *iter;
322  RzAnalysisXRef *xref;
323  ht_up_insert(ht, fcn->addr, NULL);
324  fcn->is_pure = true;
325  rz_list_foreach (xrefs, iter, xref) {
327  RzAnalysisFunction *called_fcn = rz_analysis_get_fcn_in(fcn->analysis, xref->to, 0);
328  if (!called_fcn) {
329  continue;
330  }
331  if (!purity_checked(ht, called_fcn)) {
332  check_purity(ht, called_fcn);
333  }
334  if (!called_fcn->is_pure) {
335  fcn->is_pure = false;
336  break;
337  }
338  }
339  if (xref->type == RZ_ANALYSIS_XREF_TYPE_DATA) {
340  fcn->is_pure = false;
341  break;
342  }
343  }
344  rz_list_free(xrefs);
345 }
static void check_purity(HtUP *ht, RzAnalysisFunction *fcn)
Definition: fcn.c:319
static bool purity_checked(HtUP *ht, RzAnalysisFunction *fcn)
Definition: fcn.c:306
RZ_DEPRECATE RZ_API RzAnalysisFunction * rz_analysis_get_fcn_in(RzAnalysis *analysis, ut64 addr, int type)
Definition: fcn.c:1687
@ RZ_ANALYSIS_XREF_TYPE_CODE
Definition: rz_analysis.h:900
@ RZ_ANALYSIS_XREF_TYPE_CALL
Definition: rz_analysis.h:901
@ RZ_ANALYSIS_XREF_TYPE_DATA
Definition: rz_analysis.h:902
RzAnalysisXRefType type
Definition: rz_analysis.h:909
RZ_API RzList * rz_analysis_function_get_xrefs_from(RzAnalysisFunction *fcn)
Definition: xrefs.c:297

References rz_analysis_function_t::addr, rz_analysis_function_t::analysis, rz_analysis_function_t::is_pure, NULL, purity_checked(), rz_analysis_function_get_xrefs_from(), rz_analysis_get_fcn_in(), RZ_ANALYSIS_XREF_TYPE_CALL, RZ_ANALYSIS_XREF_TYPE_CODE, RZ_ANALYSIS_XREF_TYPE_DATA, rz_list_free(), rz_analysis_ref_t::to, and rz_analysis_ref_t::type.

Referenced by rz_analysis_function_purity().

◆ clear_bb_vars()

static void clear_bb_vars ( RzAnalysisFunction fcn,
RzAnalysisBlock bb,
ut64  from,
ut64  to 
)
static

Definition at line 2312 of file fcn.c.

2312  {
2313  int i;
2314  if (rz_pvector_empty(&fcn->vars)) {
2315  return;
2316  }
2317  for (i = 0; i < bb->ninstr; i++) {
2319  if (addr < from) {
2320  continue;
2321  }
2322  if (addr >= to || addr == UT64_MAX) {
2323  break;
2324  }
2326  if (vars) {
2327  RzPVector *vars_clone = (RzPVector *)rz_vector_clone((RzVector *)vars);
2328  void **v;
2329  rz_pvector_foreach (vars_clone, v) {
2331  }
2332  rz_pvector_clear(vars_clone);
2333  }
2334  }
2335 }
RZ_API ut64 rz_analysis_block_get_op_addr(RzAnalysisBlock *block, size_t i)
Definition: block.c:1016
const char * v
Definition: dsignal.c:12
#define UT64_MAX
Definition: rz_types_base.h:86
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
RZ_API RzVector * rz_vector_clone(RzVector *vec)
Definition: vector.c:101
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
RZ_API void rz_analysis_var_remove_access_at(RzAnalysisVar *var, ut64 address)
Definition: var.c:476
RZ_API RZ_BORROW RzPVector * rz_analysis_function_get_vars_used_at(RzAnalysisFunction *fcn, ut64 op_addr)
Definition: var.c:393

References addr, from, i, rz_analysis_bb_t::ninstr, rz_analysis_block_get_op_addr(), rz_analysis_function_get_vars_used_at(), rz_analysis_var_remove_access_at(), rz_pvector_clear(), rz_pvector_empty(), rz_pvector_foreach, rz_vector_clone(), to, ut64(), UT64_MAX, v, and rz_analysis_function_t::vars.

Referenced by calc_reachable_and_remove_block(), and rz_analysis_update_analysis_range().

◆ does_arch_destroys_dst()

static bool does_arch_destroys_dst ( const char *  arch)
inlinestatic

Definition at line 525 of file fcn.c.

525  {
526  return arch && (!strncmp(arch, "arm", 3) || !strcmp(arch, "riscv") || !strcmp(arch, "ppc"));
527 }
cs_arch arch
Definition: cstool.c:13

References arch.

Referenced by run_basic_block_analysis().

◆ fcn_append_basic_block()

static RzAnalysisBlock* fcn_append_basic_block ( RzAnalysis analysis,
RzAnalysisFunction fcn,
ut64  addr 
)
static

Definition at line 128 of file fcn.c.

128  {
129  RzAnalysisBlock *bb = rz_analysis_create_block(analysis, addr, 0);
130  if (!bb) {
131  return NULL;
132  }
134  bb->stackptr = fcn->stack;
135  bb->parent_stackptr = fcn->stack;
136  return bb;
137 }
RZ_API void rz_analysis_function_add_block(RzAnalysisFunction *fcn, RzAnalysisBlock *bb)
Definition: function.c:264
RZ_API RzAnalysisBlock * rz_analysis_create_block(RzAnalysis *analysis, ut64 addr, ut64 size)
Definition: block.c:174

References addr, NULL, rz_analysis_bb_t::parent_stackptr, rz_analysis_create_block(), rz_analysis_function_add_block(), rz_analysis_function_t::stack, and rz_analysis_bb_t::stackptr.

Referenced by run_basic_block_analysis().

◆ fcn_takeover_block_recursive()

static void fcn_takeover_block_recursive ( RzAnalysisFunction fcn,
RzAnalysisBlock start_block 
)
static

Definition at line 474 of file fcn.c.

474  {
475  BlockTakeoverCtx ctx = { fcn, start_block->parent_stackptr - fcn->stack };
477 }
RZ_API bool rz_analysis_block_recurse_followthrough(RzAnalysisBlock *block, RzAnalysisBlockCb cb, void *user)
Definition: block.c:458
static bool fcn_takeover_block_recursive_followthrough_cb(RzAnalysisBlock *block, void *user)
Definition: fcn.c:412

References fcn_takeover_block_recursive_followthrough_cb(), rz_analysis_bb_t::parent_stackptr, rz_analysis_block_recurse_followthrough(), and rz_analysis_function_t::stack.

Referenced by run_basic_block_analysis().

◆ fcn_takeover_block_recursive_followthrough_cb()

static bool fcn_takeover_block_recursive_followthrough_cb ( RzAnalysisBlock block,
void *  user 
)
static

Definition at line 412 of file fcn.c.

412  {
413  BlockTakeoverCtx *ctx = user;
414  RzAnalysisFunction *our_fcn = ctx->fcn;
415  rz_analysis_block_ref(block);
416  while (!rz_list_empty(block->fcns)) {
417  RzAnalysisFunction *other_fcn = rz_list_first(block->fcns);
418  if (other_fcn->addr == block->addr) {
419  return false;
420  }
421  // Steal vars from this block
422  size_t i;
423  for (i = 0; i < block->ninstr; i++) {
424  const ut64 addr = rz_analysis_block_get_op_addr(block, i);
425  RzPVector *vars_used = rz_analysis_function_get_vars_used_at(other_fcn, addr);
426  if (!vars_used) {
427  continue;
428  }
429  // vars_used will get modified if rz_analysis_var_remove_access_at gets called
430  RzPVector *cloned_vars_used = (RzPVector *)rz_vector_clone((RzVector *)vars_used);
431  void **it;
432  rz_pvector_foreach (cloned_vars_used, it) {
433  RzAnalysisVar *other_var = *it;
434  int actual_delta = 0;
435  switch (other_var->kind) {
437  actual_delta = other_var->delta + ctx->stack_diff;
438  break;
440  actual_delta = other_var->delta + (other_fcn->bp_off - our_fcn->bp_off);
441  break;
443  actual_delta = other_var->delta;
444  break;
445  }
446  RzAnalysisVar *our_var = rz_analysis_function_get_var(our_fcn, other_var->kind, actual_delta);
447  if (!our_var) {
448  our_var = rz_analysis_function_set_var(our_fcn, actual_delta, other_var->kind, other_var->type, 0, other_var->isarg, other_var->name);
449  }
450  if (our_var) {
452  rz_analysis_var_set_access(our_var, acc->reg, addr, acc->type, acc->stackptr);
453  }
455  if (rz_vector_empty(&other_var->accesses)) {
456  rz_analysis_function_delete_var(other_fcn, other_var);
457  }
458  }
459  rz_pvector_free(cloned_vars_used);
460  }
461 
462  // TODO: remove block->ninstr from other_fcn considering delay slots
463  rz_analysis_function_remove_block(other_fcn, block);
464  }
465  block->stackptr -= ctx->stack_diff;
466  block->parent_stackptr -= ctx->stack_diff;
467  rz_analysis_function_add_block(our_fcn, block);
468  // TODO: add block->ninstr from our_fcn considering delay slots
470  return true;
471 }
RZ_API void rz_analysis_block_ref(RzAnalysisBlock *bb)
Definition: block.c:40
RZ_API void rz_analysis_block_unref(RzAnalysisBlock *bb)
Definition: block.c:370
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:77
@ RZ_ANALYSIS_VAR_KIND_REG
Definition: rz_analysis.h:703
@ RZ_ANALYSIS_VAR_KIND_SPV
Definition: rz_analysis.h:705
@ RZ_ANALYSIS_VAR_KIND_BPV
Definition: rz_analysis.h:704
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
static bool rz_vector_empty(const RzVector *vec)
Definition: rz_vector.h:74
RzAnalysisVarKind kind
Definition: rz_analysis.h:728
RZ_API RZ_BORROW RzAnalysisVar * rz_analysis_function_get_var(RzAnalysisFunction *fcn, char kind, int delta)
Definition: var.c:259
RZ_API void rz_analysis_var_set_access(RzAnalysisVar *var, const char *reg, ut64 access_addr, int access_type, st64 stackptr)
Definition: var.c:441
RZ_API RZ_BORROW RzAnalysisVar * rz_analysis_function_set_var(RzAnalysisFunction *fcn, int delta, char kind, RZ_BORROW RZ_NULLABLE const RzType *type, int size, bool isarg, RZ_NONNULL const char *name)
Definition: var.c:111
RZ_API RzAnalysisVarAccess * rz_analysis_var_get_access_at(RzAnalysisVar *var, ut64 addr)
Definition: var.c:509
RZ_API void rz_analysis_function_delete_var(RzAnalysisFunction *fcn, RzAnalysisVar *var)
Definition: var.c:241

References rz_analysis_var_t::accesses, addr, rz_analysis_function_t::addr, rz_analysis_bb_t::addr, rz_analysis_function_t::bp_off, rz_analysis_var_t::delta, rz_analysis_bb_t::fcns, i, rz_analysis_var_t::isarg, rz_analysis_var_t::kind, rz_analysis_var_t::name, rz_analysis_bb_t::ninstr, rz_analysis_bb_t::parent_stackptr, rz_analysis_var_access_t::reg, rz_analysis_block_get_op_addr(), rz_analysis_block_ref(), rz_analysis_block_unref(), rz_analysis_function_add_block(), rz_analysis_function_delete_var(), rz_analysis_function_get_var(), rz_analysis_function_get_vars_used_at(), rz_analysis_function_remove_block(), rz_analysis_function_set_var(), rz_analysis_var_get_access_at(), RZ_ANALYSIS_VAR_KIND_BPV, RZ_ANALYSIS_VAR_KIND_REG, RZ_ANALYSIS_VAR_KIND_SPV, rz_analysis_var_remove_access_at(), rz_analysis_var_set_access(), rz_list_first(), rz_pvector_foreach, rz_pvector_free(), rz_vector_clone(), rz_vector_empty(), rz_analysis_var_access_t::stackptr, rz_analysis_bb_t::stackptr, rz_analysis_var_access_t::type, rz_analysis_var_t::type, and ut64().

Referenced by fcn_takeover_block_recursive().

◆ free_ht_up()

static void free_ht_up ( HtUPKv *  kv)
static

Definition at line 2276 of file fcn.c.

2276  {
2277  ht_up_free((HtUP *)kv->value);
2278 }

Referenced by rz_analysis_function_update_analysis(), and rz_analysis_update_analysis_range().

◆ free_leaddr_pair()

static void free_leaddr_pair ( void *  pair)
static

Definition at line 353 of file fcn.c.

353  {
354  leaddr_pair *_pair = pair;
355  free(_pair->reg);
356  free(_pair);
357 }
char * reg
Definition: fcn.c:350

References free(), and leaddr_pair::reg.

Referenced by run_basic_block_analysis().

◆ is_delta_pointer_table()

static bool is_delta_pointer_table ( RzAnalysis analysis,
ut64  addr,
ut64  lea_ptr,
ut64 jmptbl_addr,
ut64 casetbl_addr,
RzAnalysisOp jmp_aop 
)
static

Definition at line 166 of file fcn.c.

166  {
167  int i;
168  ut64 dst;
169  st32 jmptbl[64] = { 0 };
170  /* check if current instruction is followed by an ujmp */
172  RzAnalysisOp *aop = jmp_aop;
173  RzAnalysisOp omov_aop = { 0 };
174  RzAnalysisOp mov_aop = { 0 };
175  RzAnalysisOp add_aop = { 0 };
176  RzRegItem *reg_src = NULL, *o_reg_dst = NULL;
177  RzAnalysisValue cur_scr, cur_dst = { 0 };
178  read_ahead(analysis, addr, (ut8 *)buf, sizeof(buf));
179  bool isValid = false;
180  for (i = 0; i + 8 < JMPTBL_LEA_SEARCH_SZ; i++) {
181  ut64 at = addr + i;
182  int left = JMPTBL_LEA_SEARCH_SZ - i;
184  if (len < 1) {
185  len = 1;
186  }
188  isValid = true;
189  break;
190  } else if (aop->type == RZ_ANALYSIS_OP_TYPE_JMP || aop->type == RZ_ANALYSIS_OP_TYPE_CJMP) {
191  break;
192  }
193  if (aop->type == RZ_ANALYSIS_OP_TYPE_MOV) {
194  omov_aop = mov_aop;
195  mov_aop = *aop;
196  o_reg_dst = cur_dst.reg;
197  if (mov_aop.dst) {
198  cur_dst = *mov_aop.dst;
199  }
200  if (mov_aop.src[0]) {
201  cur_scr = *mov_aop.src[0];
202  reg_src = cur_scr.regdelta;
203  }
204  }
205  if (aop->type == RZ_ANALYSIS_OP_TYPE_ADD) {
206  add_aop = *aop;
207  }
208  rz_analysis_op_fini(aop);
209  i += len - 1;
210  }
211  if (!isValid) {
212  return false;
213  }
214 
215  // check if we have a msvc 19xx style jump table using rva table entries
216  // lea reg1, [base_addr]
217  // mov reg2, dword [reg1 + tbl_off*4 + tbl_loc_off]
218  // add reg2, reg1
219  // jmp reg2
220  if (mov_aop.type && add_aop.type && mov_aop.addr < add_aop.addr && add_aop.addr < jmp_aop->addr && mov_aop.disp && mov_aop.disp != UT64_MAX) {
221  // disp in this case should be tbl_loc_off
222  *jmptbl_addr += mov_aop.disp;
223  if (o_reg_dst && reg_src && o_reg_dst->offset == reg_src->offset && omov_aop.disp != UT64_MAX) {
224  // Special case for indirection
225  // lea reg1, [base_addr]
226  // movzx reg2, byte [reg1 + tbl_off + casetbl_loc_off]
227  // mov reg3, dword [reg1 + reg2*4 + tbl_loc_off]
228  // add reg3, reg1
229  // jmp reg3
230  *casetbl_addr += omov_aop.disp;
231  }
232  }
233 #if 0
234  // required for the last jmptbl.. but seems to work without it and breaks other tests
235  if (mov_aop.type && mov_aop.ptr) {
236  *jmptbl_addr += mov_aop.ptr;
237  // absjmptbl
238  lea_ptr = mov_aop.ptr;
239  }
240 #endif
241  /* check if jump table contains valid deltas */
242  read_ahead(analysis, *jmptbl_addr, (ut8 *)&jmptbl, 64);
243  for (i = 0; i < 3; i++) {
244  dst = lea_ptr + (st32)rz_read_le32(jmptbl);
245  if (!analysis->iob.is_valid_offset(analysis->iob.io, dst, 0)) {
246  RZ_LOG_VERBOSE("Jump table target is not valid: 0x%" PFMT64x "\n", dst);
247  return false;
248  }
249  if (!UT64_ADD_OVFCHK(jmp_aop->addr, analysis->opt.jmptbl_maxoffset) &&
250  dst > jmp_aop->addr + analysis->opt.jmptbl_maxoffset) {
251  RZ_LOG_VERBOSE("Jump table target is too far away: 0x%" PFMT64x "\n", dst);
252  return false;
253  }
254  if (analysis->opt.jmpabove && !UT64_SUB_OVFCHK(jmp_aop->addr, analysis->opt.jmptbl_maxoffset) &&
255  dst < jmp_aop->addr - analysis->opt.jmptbl_maxoffset) {
256  RZ_LOG_VERBOSE("Jump table target is too far away: 0x%" PFMT64x "\n", dst);
257  return false;
258  }
259  }
260  return true;
261 }
size_t len
Definition: 6502dis.c:15
static bool isValid(ut64 addr)
Definition: analysis_objc.c:51
#define JMPTBL_LEA_SEARCH_SZ
Definition: fcn.c:14
static int read_ahead(RzAnalysis *analysis, ut64 addr, ut8 *buf, int len)
Definition: fcn.c:52
@ RZ_ANALYSIS_OP_MASK_HINT
Definition: rz_analysis.h:443
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_UJMP
Definition: rz_analysis.h:369
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
#define RZ_LOG_VERBOSE(fmtstr,...)
Definition: rz_log.h:52
#define PFMT64x
Definition: rz_types.h:393
#define st32
Definition: rz_types_base.h:12
#define UT64_SUB_OVFCHK(a, b)
#define UT64_ADD_OVFCHK(x, y)
RzAnalysisValue * dst
Definition: rz_analysis.h:840
RzAnalysisValue * src[3]
Definition: rz_analysis.h:839
RzRegItem * regdelta
Definition: rz_analysis.h:785
RzIOIsValidOff is_valid_offset
Definition: rz_io.h:257
int offset
Offset into register profile in bits.
Definition: rz_reg.h:121

References addr, rz_analysis_op_t::addr, rz_analysis_op_t::disp, rz_analysis_op_t::dst, dst, i, rz_io_bind_t::io, rz_analysis_t::iob, rz_io_bind_t::is_valid_offset, isValid(), rz_analysis_options_t::jmpabove, JMPTBL_LEA_SEARCH_SZ, rz_analysis_options_t::jmptbl_maxoffset, len, NULL, rz_reg_item_t::offset, rz_analysis_t::opt, PFMT64x, rz_analysis_op_t::ptr, read_ahead(), rz_analysis_value_t::reg, rz_analysis_value_t::regdelta, rz_analysis_op(), rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_BASIC, RZ_ANALYSIS_OP_MASK_HINT, RZ_ANALYSIS_OP_MASK_VAL, RZ_ANALYSIS_OP_TYPE_ADD, RZ_ANALYSIS_OP_TYPE_CJMP, RZ_ANALYSIS_OP_TYPE_JMP, RZ_ANALYSIS_OP_TYPE_MOV, RZ_ANALYSIS_OP_TYPE_RJMP, RZ_ANALYSIS_OP_TYPE_UJMP, RZ_LOG_VERBOSE, rz_read_le32(), rz_analysis_op_t::src, st32, rz_analysis_op_t::type, ut64(), UT64_ADD_OVFCHK, UT64_MAX, and UT64_SUB_OVFCHK.

Referenced by run_basic_block_analysis().

◆ isInvalidMemory()

static bool isInvalidMemory ( RzAnalysis analysis,
const ut8 buf,
int  len 
)
static

Definition at line 143 of file fcn.c.

143  {
144  if (analysis->opt.nonull > 0) {
145  int i;
146  const int count = RZ_MIN(len, analysis->opt.nonull);
147  for (i = 0; i < count; i++) {
148  if (buf[i]) {
149  break;
150  }
151  }
152  if (i == count) {
153  return true;
154  }
155  }
156  return !memcmp(buf, "\xff\xff\xff\xff", RZ_MIN(len, 4));
157 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
#define RZ_MIN(x, y)

References count, i, len, rz_analysis_options_t::nonull, rz_analysis_t::opt, and RZ_MIN.

Referenced by run_basic_block_analysis().

◆ isSymbolNextInstruction()

static bool isSymbolNextInstruction ( RzAnalysis analysis,
RzAnalysisOp op 
)
static

Definition at line 159 of file fcn.c.

159  {
160  rz_return_val_if_fail(analysis && op && analysis->flb.get_at, false);
161 
162  RzFlagItem *fi = analysis->flb.get_at(analysis->flb.f, op->addr + op->size, false);
163  return (fi && fi->name && (strstr(fi->name, "imp.") || strstr(fi->name, "sym.") || strstr(fi->name, "entry") || strstr(fi->name, "main")));
164 }
RzFlagBind flb
Definition: rz_analysis.h:575
RzFlagGetAt get_at
Definition: rz_flag.h:81
RzFlag * f
Definition: rz_flag.h:78
char * name
Definition: rz_flag.h:35

References rz_flag_bind_t::f, rz_analysis_t::flb, rz_flag_bind_t::get_at, rz_flag_item_t::name, and rz_return_val_if_fail.

Referenced by run_basic_block_analysis().

◆ mark_as_visited()

static bool mark_as_visited ( RzAnalysisBlock bb,
void *  user 
)
static

Definition at line 2251 of file fcn.c.

2251  {
2252  BlockRecurseCtx *ctx = user;
2253  ht_up_insert(ctx->visited, bb->addr, NULL);
2254  return true;
2255 }

References rz_analysis_bb_t::addr, and NULL.

Referenced by analize_addr_cb(), and calc_reachable_and_remove_block().

◆ op_is_set_bp()

static bool op_is_set_bp ( RzAnalysisOp op,
const char *  bp_reg,
const char *  sp_reg 
)
inlinestatic

Definition at line 516 of file fcn.c.

516  {
517  bool has_dst_reg = op->dst && op->dst->reg && op->dst->reg->name;
518  bool has_src_reg = op->src[0] && op->src[0]->reg && op->src[0]->reg->name;
519  if (has_dst_reg && has_src_reg) {
520  return !strcmp(bp_reg, op->dst->reg->name) && !strcmp(sp_reg, op->src[0]->reg->name);
521  }
522  return false;
523 }

Referenced by run_basic_block_analysis().

◆ purity_checked()

static bool purity_checked ( HtUP *  ht,
RzAnalysisFunction fcn 
)
static

Definition at line 306 of file fcn.c.

306  {
307  bool checked;
308  ht_up_find(ht, fcn->addr, &checked);
309  return checked;
310 }

References rz_analysis_function_t::addr.

Referenced by check_purity().

◆ read_ahead()

static int read_ahead ( RzAnalysis analysis,
ut64  addr,
ut8 buf,
int  len 
)
static

Definition at line 52 of file fcn.c.

52  {
53  static ut8 cache[1024];
54  const int cache_len = sizeof(cache);
55 
56  if (len < 1) {
57  return 0;
58  }
59  if (len > cache_len) {
60  int a = analysis->iob.read_at(analysis->iob.io, addr, buf, len); // double read
61  memcpy(cache, buf, cache_len);
62  cache_addr = addr;
63  return a;
64  }
65 
66  ut64 addr_end = UT64_ADD_OVFCHK(addr, len) ? UT64_MAX : addr + len;
67  ut64 cache_addr_end = UT64_ADD_OVFCHK(cache_addr, cache_len) ? UT64_MAX : cache_addr + cache_len;
68  bool isCached = ((addr != UT64_MAX) && (addr >= cache_addr) && (addr_end < cache_addr_end));
69  if (isCached) {
70  memcpy(buf, cache + (addr - cache_addr), len);
71  } else {
72  analysis->iob.read_at(analysis->iob.io, addr, cache, sizeof(cache));
73  memcpy(buf, cache, len);
74  cache_addr = addr;
75  }
76  return len;
77 }
static ut64 cache_addr
Definition: fcn.c:49
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define a(i)
Definition: sha256.c:41

References a, addr, cache_addr, rz_io_bind_t::io, rz_analysis_t::iob, len, memcpy(), rz_io_bind_t::read_at, ut64(), UT64_ADD_OVFCHK, and UT64_MAX.

Referenced by is_delta_pointer_table(), and run_basic_block_analysis().

◆ regs_exist()

static bool regs_exist ( RzAnalysisValue src,
RzAnalysisValue dst 
)
static

Definition at line 282 of file fcn.c.

282  {
283  rz_return_val_if_fail(src && dst, false);
284  return src->reg && dst->reg && src->reg->name && dst->reg->name;
285 }

References dst, rz_return_val_if_fail, and src.

Referenced by run_basic_block_analysis().

◆ retpoline_reg()

static const char* retpoline_reg ( RzAnalysis analysis,
ut64  addr 
)
static

Definition at line 479 of file fcn.c.

479  {
480  RzFlagItem *flag = analysis->flag_get(analysis->flb.f, addr);
481  if (flag) {
482  const char *token = "x86_indirect_thunk_";
483  const char *thunk = strstr(flag->name, token);
484  if (thunk) {
485  return thunk + strlen(token);
486  }
487  }
488 #if 0
489 // TODO: implement following code analysis check for stripped binaries:
490 // 1) op(addr).type == CALL
491 // 2) call_dest = op(addr).addr
492 // 3) op(call_dest).type == STORE
493 // 4) op(call_dest + op(call_dest).size).type == RET
494 [0x00000a65]> pid 6
495 0x00000a65 sym.__x86_indirect_thunk_rax:
496 0x00000a65 .------- e807000000 call 0xa71
497 0x00000a6a | f390 pause
498 0x00000a6c | 0faee8 lfence
499 0x00000a6f | ebf9 jmp 0xa6a
500 0x00000a71 `----> 48890424 mov qword [rsp], rax
501 0x00000a75 c3 ret
502 #endif
503  return NULL;
504 }
#define jmp
static RzILOpEffect * mov(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:351
lsl lsr asr ror lsl lsr asr ror lsl lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror lsl lsr asr ror c3
int call(int a, int b)
Definition: bcj_test.c:25
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
RzFlagGetAtAddr flag_get
Definition: rz_analysis.h:616

References addr, c3, call(), rz_flag_bind_t::f, rz_analysis_t::flag_get, rz_analysis_t::flb, jmp, mov(), rz_flag_item_t::name, NULL, pid, and rax.

Referenced by analyze_retpoline().

◆ run_basic_block_analysis()

static RzAnalysisBBEndCause run_basic_block_analysis ( RzAnalysisTaskItem item,
RzVector tasks 
)
static

Analyses the given task item item for branches.

Analysis starts for all instructions from item->start_address. If a branch is encountered a new task item is added to the list tasks. If an end of a basic function block is encountered (e.g. an invalid instruction), the cause for it is returned.

Parameters
itemThe task item with the parent function and start address to start analysing from.
tasksThe task list to append the new task items to.
Returns
RzAnalysisBBEndCause Cause a basic block ended.

Definition at line 559 of file fcn.c.

559  {
561  RzAnalysis *analysis = item->fcn->analysis;
562  RzAnalysisFunction *fcn = item->fcn;
563  fcn->stack = item->stack;
564  ut64 addr = item->start_address;
565  ut64 len = analysis->opt.bb_max_size;
566  const int continue_after_jump = analysis->opt.afterjmp;
567  const int addrbytes = analysis->iob.io ? analysis->iob.io->addrbytes : 1;
568  char *last_reg_mov_lea_name = NULL;
569  char *movbasereg = NULL;
570  RzAnalysisBlock *bb = item->block;
571  RzAnalysisBlock *bbg = NULL;
572  RzAnalysisBBEndCause ret = RZ_ANALYSIS_RET_END, skip_ret = 0;
573  bool overlapped = false;
574  RzAnalysisOp op = { 0 };
575  int oplen, idx = 0;
576  int lea_cnt = 0;
577  static ut64 cmpval = UT64_MAX; // inherited across functions, otherwise it breaks :?
578  bool varset = false;
579  struct {
580  int cnt;
581  int idx;
582  int after;
583  int pending;
584  int adjust;
585  int un_idx; // delay.un_idx
586  } delay = {
587  0
588  };
589  char tmp_buf[MAX_FLG_NAME_SIZE + 5] = "skip";
591  bool is_arm = false, is_x86 = false, is_amd64 = false, is_dalvik = false, is_hexagon = false;
592  if (analysis->cur->arch) {
593  is_arm = !strncmp(analysis->cur->arch, "arm", 3);
594  is_x86 = !strncmp(analysis->cur->arch, "x86", 3);
595  is_dalvik = !strncmp(analysis->cur->arch, "dalvik", 6);
596  is_hexagon = !strncmp(analysis->cur->arch, "hexagon", 7);
597  }
598  is_amd64 = is_x86 ? fcn->cc && !strcmp(fcn->cc, "amd64") : false;
599  bool can_jmpmid = analysis->opt.jmpmid && (is_dalvik || is_x86);
600 
601  RzRegItem *variadic_reg = NULL;
602  if (is_amd64) {
603  variadic_reg = rz_reg_get(analysis->reg, "rax", RZ_REG_TYPE_GPR);
604  }
605  bool has_variadic_reg = !!variadic_reg;
606 
607  if (rz_cons_is_breaked()) {
608  rz_analysis_task_item_new(analysis, tasks, fcn, bb, addr);
609  return RZ_ANALYSIS_RET_END;
610  }
611  if (analysis->sleep) {
612  rz_sys_usleep(analysis->sleep);
613  }
614 
615  // check if address is readable
616  if (!analysis->iob.is_valid_offset(analysis->iob.io, addr, 0)) {
617  if (addr != UT64_MAX && !analysis->iob.io->va) {
618  RZ_LOG_DEBUG("Invalid address 0x%" PFMT64x ". Try with io.va=true\n", addr);
619  }
620  return RZ_ANALYSIS_RET_ERROR; // MUST BE TOO DEEP
621  }
622 
623  RzAnalysisFunction *fcn_at_addr = rz_analysis_get_function_at(analysis, addr);
624  if (fcn_at_addr && fcn_at_addr != fcn) {
625  return RZ_ANALYSIS_RET_ERROR; // MUST BE NOT FOUND
626  }
627 
628  if (!bb) {
629  RzAnalysisBlock *existing_bb = bbget(analysis, addr, can_jmpmid);
630  if (existing_bb) {
631  bool existing_in_fcn = rz_list_contains(existing_bb->fcns, fcn);
632  existing_bb = rz_analysis_block_split(existing_bb, addr);
633  if (!existing_in_fcn && existing_bb) {
634  if (existing_bb->addr == fcn->addr) {
635  // our function starts directly there, so we steal what is ours!
636  fcn_takeover_block_recursive(fcn, existing_bb);
637  }
638  }
639  if (existing_bb) {
640  rz_analysis_block_unref(existing_bb);
641  }
642  if (analysis->opt.recont) {
643  return RZ_ANALYSIS_RET_END;
644  }
645  RZ_LOG_DEBUG("%s fails at 0x%" PFMT64x ".\n", __FUNCTION__, addr);
646  return RZ_ANALYSIS_RET_ERROR; // MUST BE NOT DUP
647  }
648 
649  item->block = bb = fcn_append_basic_block(analysis, fcn, addr);
650  // we checked before whether there is a bb at addr, so the create should have succeeded
652  }
653 
654  if (!analysis->leaddrs) {
656  if (!analysis->leaddrs) {
657  RZ_LOG_ERROR("Cannot allocate list of pairs<reg, addr> values.\n");
659  }
660  }
661  static ut64 lea_jmptbl_ip = UT64_MAX;
662  ut64 last_reg_mov_lea_val = UT64_MAX;
663  bool last_is_reg_mov_lea = false;
664  bool last_is_push = false;
665  bool last_is_mov_lr_pc = false;
666  ut64 last_push_addr = UT64_MAX;
667  if (analysis->limit && addr + idx < analysis->limit->from) {
669  }
670  RzAnalysisFunction *tmp_fcn = rz_analysis_get_fcn_in(analysis, addr, 0);
671  if (tmp_fcn) {
672  // Checks if var is already analyzed at given addr
673  RzList *list = rz_analysis_var_all_list(analysis, tmp_fcn);
674  if (!rz_list_empty(list)) {
675  varset = true;
676  }
678  }
679  ut64 movdisp = UT64_MAX; // used by jmptbl when coded as "mov reg, [reg * scale + disp]"
680  ut64 movscale = 0;
681  ut8 buf[32]; // 32 bytes is enough to hold any instruction.
682  int maxlen = len * addrbytes;
683  if (is_dalvik) {
684  bool skipAnalysis = false;
685  if (!strncmp(fcn->name, "sym.", 4)) {
686  if (!strncmp(fcn->name + 4, "imp.", 4)) {
687  skipAnalysis = true;
688  } else if (strstr(fcn->name, "field")) {
689  skipAnalysis = true;
690  }
691  }
692  if (skipAnalysis) {
694  }
695  }
696  if ((maxlen - (addrbytes * idx)) > MAX_SCAN_SIZE) {
697  RZ_LOG_DEBUG("Skipping large memory region during basic block analysis.\n");
698  maxlen = 0;
699  }
700 
701  while (addrbytes * idx < maxlen) {
702  ut32 at_delta;
703  ut64 at;
704  if (!last_is_reg_mov_lea) {
705  free(last_reg_mov_lea_name);
706  last_reg_mov_lea_name = NULL;
707  }
708  if (analysis->limit && analysis->limit->to <= addr + idx) {
709  break;
710  }
711  repeat:
712  at_delta = addrbytes * idx;
713  at = addr + at_delta;
714  if (rz_cons_is_breaked()) {
715  rz_analysis_task_item_new(analysis, tasks, fcn, bb, at);
716  break;
717  }
718  ut64 bytes_read = RZ_MIN(len - at_delta, sizeof(buf));
719  ret = read_ahead(analysis, at, buf, bytes_read);
720 
721  if (ret < 0) {
722  RZ_LOG_ERROR("Failed to read ahead\n");
723  break;
724  }
725  if (isInvalidMemory(analysis, buf, bytes_read)) {
726  RZ_LOG_DEBUG("FFFF opcode at 0x%08" PFMT64x "\n", at);
728  }
730  if ((oplen = rz_analysis_op(analysis, &op, at, buf, bytes_read, RZ_ANALYSIS_OP_MASK_ESIL | RZ_ANALYSIS_OP_MASK_VAL | RZ_ANALYSIS_OP_MASK_HINT)) < 1) {
731  RZ_LOG_DEBUG("Invalid instruction at 0x%" PFMT64x " with %d bits\n", at, analysis->bits);
732  // gotoBeach (RZ_ANALYSIS_RET_ERROR);
733  // RET_END causes infinite loops somehow
735  }
736 
737  const char *bp_reg = analysis->reg->name[RZ_REG_NAME_BP];
738  const char *sp_reg = analysis->reg->name[RZ_REG_NAME_SP];
739  bool has_stack_regs = bp_reg && sp_reg;
740 
741  if (analysis->opt.nopskip && fcn->addr == at) {
742  RzFlagItem *fi = analysis->flb.get_at(analysis->flb.f, addr, false);
743  if (!fi || strncmp(fi->name, "sym.", 4)) {
744  if ((addr + delay.un_idx - oplen) == fcn->addr) {
745  if (rz_analysis_block_relocate(bb, bb->addr + oplen, bb->size - oplen)) {
746  fcn->addr += oplen;
747  idx = delay.un_idx;
748  goto repeat;
749  }
750  }
751  }
752  switch (op.type & RZ_ANALYSIS_OP_TYPE_MASK) {
756  if (rz_analysis_block_relocate(bb, at + op.size, bb->size)) {
757  addr = at + op.size;
758  fcn->addr = addr;
759  goto repeat;
760  }
761  }
762  }
763 
764  if (op.hint.new_bits) {
765  rz_analysis_hint_set_bits(analysis, op.jump, op.hint.new_bits);
766  }
767  if (idx > 0 && !overlapped) {
768  bbg = bbget(analysis, at, can_jmpmid);
769  if (bbg && bbg != bb) {
770  bb->jump = at;
771  if (can_jmpmid) {
772  // This happens when we purposefully walked over another block and overlapped it
773  // and now we hit an offset where the instructions match again.
774  // So we need to split the overwalked block.
775  RzAnalysisBlock *split = rz_analysis_block_split(bbg, at);
777  }
778  overlapped = true;
779  RZ_LOG_DEBUG("Overlapped at 0x%08" PFMT64x "\n", at);
780  }
781  }
782  if (!overlapped) {
783  ut64 newbbsize = bb->size + oplen;
784  if (newbbsize > MAX_FCN_SIZE) {
786  }
787  rz_analysis_block_set_op_offset(bb, bb->ninstr++, at - bb->addr);
788  rz_analysis_block_set_size(bb, newbbsize);
789  fcn->ninstr++;
790  }
791  if (analysis->opt.trycatch) {
792  const char *name = analysis->coreb.getName(analysis->coreb.core, at);
793  if (name) {
794  if (rz_str_startswith(name, "try.") && rz_str_endswith(name, ".from")) {
795  char *handle = strdup(name);
796  // handle = rz_str_replace (handle, ".from", ".to", 0);
797  ut64 from_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
798  handle = rz_str_replace(handle, ".from", ".catch", 0);
799  ut64 handle_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
800  handle = rz_str_replace(handle, ".catch", ".filter", 0);
801  ut64 filter_addr = analysis->coreb.numGet(analysis->coreb.core, handle);
802  if (filter_addr) {
803  rz_analysis_xrefs_set(analysis, op.addr, filter_addr, RZ_ANALYSIS_XREF_TYPE_CALL);
804  }
805  bb->jump = at + oplen;
806  if (from_addr != bb->addr) {
807  bb->fail = handle_addr;
808  ret = analyze_function_locally(analysis, fcn, handle_addr);
809  if (bb->size == 0) {
811  }
814  bb = fcn_append_basic_block(analysis, fcn, bb->jump);
815  if (!bb) {
817  }
818  }
819  }
820  }
821  }
822  idx += oplen;
823  delay.un_idx = idx;
824  if (analysis->opt.delay && op.delay > 0 && !delay.pending) {
825  // Handle first pass through a branch delay jump:
826  // Come back and handle the current instruction later.
827  // Save the location of it in `delay.idx`
828  // note, we have still increased size of basic block
829  // (and function)
830  RZ_LOG_DEBUG("Enter branch delay at 0x%08" PFMT64x ". bb->sz=%" PFMT64u "\n", at - oplen, bb->size);
831  delay.idx = idx - oplen;
832  delay.cnt = op.delay;
833  delay.pending = 1; // we need this in case the actual idx is zero...
834  delay.adjust = !overlapped; // adjustment is required later to avoid double count
835  continue;
836  }
837 
838  if (delay.cnt > 0) {
839  // if we had passed a branch delay instruction, keep
840  // track of how many still to process.
841  delay.cnt--;
842  if (!delay.cnt) {
843  RZ_LOG_DEBUG("Last branch delayed opcode at 0x%08" PFMT64x ". bb->sz=%" PFMT64u "\n", addr + idx - oplen, bb->size);
844  delay.after = idx;
845  idx = delay.idx;
846  // At this point, we are still looking at the
847  // last instruction in the branch delay group.
848  // Next time, we will again be looking
849  // at the original instruction that entered
850  // the branch delay.
851  }
852  } else if (op.delay > 0 && delay.pending) {
853  RZ_LOG_DEBUG("Revisit branch delay jump at 0x%08" PFMT64x ". bb->sz=%" PFMT64u "\n", addr + idx - oplen, bb->size);
854  // This is the second pass of the branch delaying opcode
855  // But we also already counted this instruction in the
856  // size of the current basic block, so we need to fix that
857  if (delay.adjust) {
858  rz_analysis_block_set_size(bb, (ut64)addrbytes * (ut64)delay.after);
859  fcn->ninstr--;
860  RZ_LOG_DEBUG("Correct for branch delay @ 0x%08" PFMT64x " bb.addr=0x%08" PFMT64x " corrected.bb=%" PFMT64u " f.uncorr=%" PFMT64u "\n",
861  addr + idx - oplen, bb->addr, bb->size, rz_analysis_function_linear_size(fcn));
862  }
863  // Next time, we go to the opcode after the delay count
864  // Take care not to use this below, use delay.un_idx instead ...
865  idx = delay.after;
866  delay.pending = delay.after = delay.idx = delay.adjust = 0;
867  }
868  // Note: if we got two branch delay instructions in a row due to an
869  // compiler bug or junk or something it wont get treated as a delay
870  if (analysis->opt.vars && !varset) {
871  rz_analysis_extract_vars(analysis, fcn, &op);
872  }
873  if (has_stack_regs && arch_destroys_dst) {
874  if (op_is_set_bp(&op, bp_reg, sp_reg) && op.src[1]) {
875  switch (op.type & RZ_ANALYSIS_OP_TYPE_MASK) {
877  fcn->bp_off = fcn->stack - op.src[1]->imm;
878  break;
880  fcn->bp_off = fcn->stack + op.src[1]->imm;
881  break;
882  }
883  }
884  }
885  switch (op.stackop) {
887  if (RZ_ABS(op.stackptr) < 8096) {
888  fcn->stack += op.stackptr;
889  if (fcn->stack > fcn->maxstack) {
890  fcn->maxstack = fcn->stack;
891  }
892  }
893  bb->stackptr += op.stackptr;
894  break;
896  bb->stackptr = 0;
897  break;
898  default:
899  break;
900  }
901  if (op.ptr && op.ptr != UT64_MAX && op.ptr != UT32_MAX) {
902  // swapped parameters
904  }
905  analyze_retpoline(analysis, &op);
906 
907  switch (op.type & RZ_ANALYSIS_OP_TYPE_MASK) {
910  last_is_reg_mov_lea = false;
911  if (is_arm) { // mov lr, pc
912  const char *esil = rz_strbuf_get(&op.esil);
913  if (!rz_str_cmp(esil, "pc,lr,=", -1)) {
914  last_is_mov_lr_pc = true;
915  }
916  }
917  if (has_stack_regs && op_is_set_bp(&op, bp_reg, sp_reg)) {
918  fcn->bp_off = fcn->stack;
919  }
920  // Is this a mov of immediate value into a register?
921  if (op.dst && op.dst->reg && op.dst->reg->name && op.val > 0 && op.val != UT64_MAX) {
922  free(last_reg_mov_lea_name);
923  if ((last_reg_mov_lea_name = strdup(op.dst->reg->name))) {
924  last_reg_mov_lea_val = op.val;
925  last_is_reg_mov_lea = true;
926  }
927  }
928  // skip mov reg, reg
929  if (analysis->opt.jmptbl && op.scale && op.ireg) {
930  movdisp = op.disp;
931  movscale = op.scale;
932  if (op.src[0] && op.src[0]->reg) {
933  free(movbasereg);
934  movbasereg = strdup(op.src[0]->reg->name);
935  } else {
936  RZ_FREE(movbasereg);
937  }
938  }
939  if (analysis->opt.hpskip && regs_exist(op.src[0], op.dst) && !strcmp(op.src[0]->reg->name, op.dst->reg->name)) {
940  skip_ret = skip_hp(analysis, fcn, &op, bb, addr, tmp_buf, oplen, delay.un_idx, &idx);
941  if (skip_ret == 1) {
942  goto repeat;
943  }
944  if (skip_ret == 2) {
946  }
947  }
948  break;
950  last_is_reg_mov_lea = false;
951  // if first byte in op.ptr is 0xff, then set leaddr assuming its a jumptable
952  if (op.ptr != UT64_MAX) {
953  leaddr_pair *pair = RZ_NEW(leaddr_pair);
954  if (!pair) {
955  RZ_LOG_ERROR("Cannot allocate pair<reg, addr> structure\n");
957  }
958  pair->op_addr = op.addr;
959  pair->leaddr = op.ptr; // XXX movdisp is dupped but seems to be trashed sometimes(?), better track leaddr separately
960  pair->reg = op.reg
961  ? strdup(op.reg)
962  : op.dst && op.dst->reg
963  ? strdup(op.dst->reg->name)
964  : NULL;
965  lea_cnt++;
966  rz_list_append(analysis->leaddrs, pair);
967  }
968  if (has_stack_regs && op_is_set_bp(&op, bp_reg, sp_reg)) {
969  fcn->bp_off = fcn->stack - op.src[0]->delta;
970  }
971  if (op.dst && op.dst->reg && op.dst->reg->name && op.ptr > 0 && op.ptr != UT64_MAX) {
972  free(last_reg_mov_lea_name);
973  if ((last_reg_mov_lea_name = strdup(op.dst->reg->name))) {
974  last_reg_mov_lea_val = op.ptr;
975  last_is_reg_mov_lea = true;
976  }
977  }
978  // skip lea reg,[reg]
979  if (analysis->opt.hpskip && regs_exist(op.src[0], op.dst) && !strcmp(op.src[0]->reg->name, op.dst->reg->name)) {
980  skip_ret = skip_hp(analysis, fcn, &op, bb, at, tmp_buf, oplen, delay.un_idx, &idx);
981  if (skip_ret == 1) {
982  goto repeat;
983  }
984  if (skip_ret == 2) {
986  }
987  }
988  if (analysis->opt.jmptbl) {
989  RzAnalysisOp jmp_aop = { 0 };
990  ut64 jmptbl_addr = op.ptr;
991  ut64 casetbl_addr = op.ptr;
992  if (is_delta_pointer_table(analysis, op.addr, op.ptr, &jmptbl_addr, &casetbl_addr, &jmp_aop)) {
993  // we require both checks here since rz_analysis_get_jmptbl_info uses
994  // BB info of the final jmptbl jump, which is no present with
995  // is_delta_pointer_table just scanning ahead
996  // rz_analysis_get_delta_jmptbl_info doesn't work at times where the
997  // lea comes after the cmp/default case cjmp, which can be
998  // handled with rz_analysis_get_jmptbl_info
999  RzAnalysisJmpTableParams params = {
1000  .jmp_address = jmp_aop.addr,
1001  .jmptbl_loc = jmptbl_addr,
1002  .casetbl_loc = casetbl_addr,
1003  .entry_size = 4,
1004  .jmptbl_off = op.ptr,
1005  .tasks = tasks
1006  };
1007  if (rz_analysis_get_jmptbl_info(analysis, fcn, bb, jmp_aop.addr, &params) || rz_analysis_get_delta_jmptbl_info(analysis, fcn, jmp_aop.addr, op.addr, &params)) {
1008  ret = casetbl_addr == op.ptr
1009  ? rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, &params)
1010  : rz_analysis_walkthrough_casetbl(analysis, fcn, bb, &params);
1011  if (ret) {
1012  lea_jmptbl_ip = jmp_aop.addr;
1013  }
1014  }
1015  }
1016  rz_analysis_op_fini(&jmp_aop);
1017  }
1018  break;
1020  if (analysis->opt.loads) {
1021  if (analysis->iob.is_valid_offset(analysis->iob.io, op.ptr, 0)) {
1022  rz_meta_set(analysis, RZ_META_TYPE_DATA, op.ptr, 4, "");
1023  }
1024  }
1025  break;
1026  // Case of valid but unused "add [rax], al"
1028  if (analysis->opt.ijmp) {
1029  if ((op.size + 4 <= bytes_read) && !memcmp(buf + op.size, "\x00\x00\x00\x00", 4)) {
1030  rz_analysis_block_set_size(bb, bb->size - oplen);
1031  op.type = RZ_ANALYSIS_OP_TYPE_RET;
1033  }
1034  }
1035  break;
1039  if (analysis->opt.aftertrap) {
1040  continue;
1041  }
1044  // do nothing, because the nopskip goes before this switch
1045  break;
1047  if (op.jump == UT64_MAX) {
1049  }
1050  {
1051  RzFlagItem *fi = analysis->flb.get_at(analysis->flb.f, op.jump, false);
1052  if (fi && strstr(fi->name, "imp.")) {
1054  }
1055  }
1056  if (rz_cons_is_breaked()) {
1058  }
1059  if (analysis->opt.jmpref) {
1060  (void)rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_XREF_TYPE_CODE);
1061  }
1062  if (!analysis->opt.jmpabove && (op.jump < fcn->addr)) {
1064  }
1065  if (rz_analysis_noreturn_at(analysis, op.jump)) {
1066  if (continue_after_jump && is_hexagon) {
1067  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1068  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.addr + op.size);
1069  if (!overlapped) {
1070  set_bb_branches(bb, op.jump, op.addr + op.size);
1071  }
1073  }
1075  }
1076  {
1077  bool must_eob = true;
1078  RzIOMap *map = analysis->iob.map_get(analysis->iob.io, addr);
1079  if (map) {
1080  must_eob = (op.jump < map->itv.addr || op.jump >= map->itv.addr + map->itv.size);
1081  }
1082  if (must_eob) {
1083  if (continue_after_jump && is_hexagon) {
1084  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1085  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.addr + op.size);
1086  if (!overlapped) {
1087  set_bb_branches(bb, op.jump, op.addr + op.size);
1088  }
1090  }
1091  op.jump = UT64_MAX;
1093  }
1094  }
1095  if (!overlapped) {
1096  set_bb_branches(bb, op.jump, UT64_MAX);
1097  }
1098  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1099  if (continue_after_jump && (is_hexagon || (is_dalvik && op.cond == RZ_TYPE_COND_EXCEPTION))) {
1100  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.addr + op.size);
1102  }
1103  int tc = analysis->opt.tailcall;
1104  if (tc) {
1105  int diff = op.jump - op.addr;
1106  if (tc < 0) {
1107  ut8 buf[32];
1108  (void)analysis->iob.read_at(analysis->iob.io, op.jump, (ut8 *)buf, sizeof(buf));
1109  if (rz_analysis_is_prelude(analysis, buf, sizeof(buf))) {
1110  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1111  }
1112  } else if (RZ_ABS(diff) > tc) {
1113  (void)rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_XREF_TYPE_CALL);
1114  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1116  }
1117  }
1118  goto beach;
1119  break;
1121  if (op.val != UT64_MAX && op.val > 0 && op.val < analysis->opt.jmptbl_maxcount) {
1122  // if register is not stack
1123  cmpval = op.val;
1124  }
1125  break;
1126  case RZ_ANALYSIS_OP_TYPE_CMP: {
1127  ut64 val = is_x86 ? op.val : op.ptr;
1128  if (val) {
1129  if (val < analysis->opt.jmptbl_maxcount) {
1130  cmpval = val;
1131  }
1132  bb->cmpval = val;
1133  bb->cmpreg = op.reg;
1136  }
1137  } break;
1142  if (op.prefix & RZ_ANALYSIS_OP_PREFIX_HWLOOP_END) {
1143  if (op.jump != 0) {
1144  rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_XREF_TYPE_CODE);
1145  }
1146  if (op.fail != 0) {
1147  rz_analysis_xrefs_set(analysis, op.addr, op.fail, RZ_ANALYSIS_XREF_TYPE_CODE);
1148  }
1149  if (continue_after_jump) {
1150  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.addr + op.size);
1151  }
1152  if (!overlapped) {
1153  // If it is an endloop01 instruction the jump to the inner loop is not added yet.
1154  set_bb_branches(bb, op.jump, op.addr + op.size);
1155  }
1157  }
1158  if (analysis->opt.cjmpref) {
1159  rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_XREF_TYPE_CODE);
1160  if (is_hexagon) {
1161  rz_analysis_xrefs_set(analysis, op.addr, op.fail, RZ_ANALYSIS_XREF_TYPE_CODE);
1162  }
1163  }
1164  if (!overlapped) {
1165  set_bb_branches(bb, op.jump, op.fail);
1166  }
1167  if (bb->cond) {
1168  bb->cond->type = op.cond;
1169  }
1170  if (analysis->opt.jmptbl) {
1171  if (op.ptr != UT64_MAX) {
1172  if (cmpval != UT64_MAX && op.fail != UT64_MAX && (op.reg || op.ireg)) {
1173  RzAnalysisJmpTableParams params = {
1174  .jmp_address = op.addr,
1175  .case_shift = 0,
1176  .jmptbl_loc = op.ptr,
1177  .casetbl_loc = UT64_MAX,
1178  .entry_size = analysis->bits >> 3,
1179  .table_count = cmpval + 1,
1180  .jmptbl_off = op.ptr,
1181  .default_case = op.fail,
1182  .tasks = tasks
1183  };
1184  if (op.ireg) {
1185  rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, &params);
1186  } else { // op.reg
1187  rz_analysis_walkthrough_arm_jmptbl_style(analysis, fcn, bb, &params);
1188  }
1189  // check if op.jump and op.fail contain jump table location
1190  // clear jump address, because it's jump table location
1191  if (op.jump == op.ptr) {
1192  op.jump = UT64_MAX;
1193  } else if (op.fail == op.ptr) {
1194  op.fail = UT64_MAX;
1195  }
1196  cmpval = UT64_MAX;
1197  }
1198  }
1199  }
1200  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.fail);
1201  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1202  if (continue_after_jump && is_hexagon) {
1203  if (op.type == RZ_ANALYSIS_OP_TYPE_RCJMP) {
1204  break;
1205  }
1206  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.addr + op.size);
1208  }
1209  if (!continue_after_jump) {
1210  if (op.jump < fcn->addr) {
1211  if (!overlapped) {
1212  bb->jump = op.jump;
1213  bb->fail = UT64_MAX;
1214  }
1216  }
1217  }
1218 
1219  // XXX breaks mips analysis too !op.delay
1220  // this will be all x86, arm (at least)
1221  // without which the analysis is really slow,
1222  // presumably because each opcode would get revisited
1223  // (and already covered by a bb) many times
1224  if (!is_dalvik) {
1225  goto beach;
1226  }
1227  // For some reason, branch delayed code (MIPS) needs to continue
1228  break;
1233  /* call [dst] */
1234  // XXX: this is TYPE_MCALL or indirect-call
1235  (void)rz_analysis_xrefs_set(analysis, op.addr, op.ptr, RZ_ANALYSIS_XREF_TYPE_CALL);
1236 
1237  if (rz_analysis_noreturn_at(analysis, op.ptr)) {
1239  if (f) {
1240  f->is_noreturn = true;
1241  }
1243  }
1244  break;
1247  /* call dst */
1248  (void)rz_analysis_xrefs_set(analysis, op.addr, op.jump, RZ_ANALYSIS_XREF_TYPE_CALL);
1249 
1250  if (rz_analysis_noreturn_at(analysis, op.jump)) {
1252  if (f) {
1253  f->is_noreturn = true;
1254  }
1256  }
1257  break;
1260  if (is_hexagon) {
1261  if (op.analysis_vals[0].plugin_specific == 31) {
1262  // jumpr Rs instruction which uses R31.
1263  // This is a return, but not typed as such.
1265  } else {
1266  // Ignore
1267  break;
1268  }
1269  }
1270  if (is_arm && last_is_mov_lr_pc) {
1271  break;
1272  }
1273  /* fall through */
1277  // if the next instruction is a symbol
1278  if (analysis->opt.ijmp && isSymbolNextInstruction(analysis, &op)) {
1280  }
1281  // switch statement
1282  if (analysis->opt.jmptbl && lea_jmptbl_ip != op.addr) {
1283  RzAnalysisJmpTableParams params = {
1284  .jmp_address = op.addr,
1285  .entry_size = analysis->bits >> 3,
1286  .jmptbl_loc = op.ptr,
1287  .jmptbl_off = op.ptr,
1288  .tasks = tasks
1289  };
1290  // op.ireg since rip relative addressing produces way too many false positives otherwise
1291  // op.ireg is 0 for rip relative, "rax", etc otherwise
1292  if (op.ptr != UT64_MAX && op.ireg) { // direct jump
1293  if (rz_analysis_get_jmptbl_info(analysis, fcn, bb, op.addr, &params)) {
1294  bool case_table = false;
1295  RzAnalysisOp prev_op;
1296  analysis->iob.read_at(analysis->iob.io, op.addr - op.size, buf, sizeof(buf));
1297  if (rz_analysis_op(analysis, &prev_op, op.addr - op.size, buf, sizeof(buf), RZ_ANALYSIS_OP_MASK_VAL) > 0) {
1298  bool prev_op_has_dst_name = prev_op.dst && prev_op.dst->reg && prev_op.dst->reg->name;
1299  bool op_has_src_name = op.src[0] && op.src[0]->reg && op.src[0]->reg->name;
1300  bool same_reg = (op.ireg && prev_op_has_dst_name && !strcmp(op.ireg, prev_op.dst->reg->name)) || (op_has_src_name && prev_op_has_dst_name && !strcmp(op.src[0]->reg->name, prev_op.dst->reg->name));
1301  if (prev_op.type == RZ_ANALYSIS_OP_TYPE_MOV && prev_op.disp && prev_op.disp != UT64_MAX && same_reg) {
1302  // movzx reg, byte [reg + case_table]
1303  // jmp dword [reg*4 + jump_table]
1304  params.casetbl_loc = prev_op.disp;
1305  if (rz_analysis_walkthrough_casetbl(analysis, fcn, bb, &params)) {
1306  ret = case_table = true;
1307  }
1308  }
1309  }
1310  rz_analysis_op_fini(&prev_op);
1311  if (!case_table) {
1312  ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, &params);
1313  }
1314  }
1315  } else if (op.ptr != UT64_MAX && op.reg) { // direct jump
1316  if (rz_analysis_get_jmptbl_info(analysis, fcn, bb, op.addr, &params)) {
1317  ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, &params);
1318  }
1319  } else if (movdisp != UT64_MAX) {
1320  ut64 lea_op_off = UT64_MAX;
1321  RzListIter *iter;
1322  leaddr_pair *pair;
1323  params.jmptbl_off = 0;
1324  if (movbasereg) {
1325  // find nearest candidate leaddr before op.addr
1326  rz_list_foreach_prev(analysis->leaddrs, iter, pair) {
1327  if (pair->op_addr >= op.addr) {
1328  continue;
1329  }
1330  if ((lea_op_off == UT64_MAX || lea_op_off > op.addr - pair->op_addr) && pair->reg && !strcmp(movbasereg, pair->reg)) {
1331  lea_op_off = op.addr - pair->op_addr;
1332  params.jmptbl_off = pair->leaddr;
1333  }
1334  }
1335  }
1336  if (!rz_analysis_get_jmptbl_info(analysis, fcn, bb, op.addr, &params)) {
1337  params.table_count = cmpval + 1;
1338  params.default_case = -1;
1339  }
1340  params.jmptbl_loc = params.jmptbl_off + movdisp;
1341  params.entry_size = movscale;
1342  ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, &params);
1343  cmpval = UT64_MAX;
1344  } else if (is_arm) {
1345  params.jmptbl_loc = op.addr + op.size;
1346  params.jmptbl_off = op.addr + 4;
1347  params.default_case = UT64_MAX;
1348  if (op.ptrsize == 1) { // TBB
1349  ut64 pred_cmpval = try_get_cmpval_from_parents(analysis, fcn, bb, op.ireg);
1350  params.table_count = 0;
1351  if (pred_cmpval != UT64_MAX) {
1352  params.table_count += pred_cmpval;
1353  } else {
1354  params.table_count += cmpval;
1355  }
1356  params.entry_size = 1;
1357  ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, &params);
1358  // skip inlined jumptable
1359  idx += params.table_count;
1360  } else if (op.ptrsize == 2) { // LDRH on thumb/arm
1361  ut64 pred_cmpval = try_get_cmpval_from_parents(analysis, fcn, bb, op.ireg);
1362  params.table_count = 1;
1363  if (pred_cmpval != UT64_MAX) {
1364  params.table_count += pred_cmpval;
1365  } else {
1366  params.table_count += cmpval;
1367  }
1368  params.entry_size = 2;
1369  ret = rz_analysis_walkthrough_jmptbl(analysis, fcn, bb, &params);
1370  // skip inlined jumptable
1371  idx += (params.table_count * 2);
1372  }
1373  }
1374  }
1375  if (lea_jmptbl_ip == op.addr) {
1376  lea_jmptbl_ip = UT64_MAX;
1377  }
1378  if (analysis->opt.ijmp) {
1379  if (continue_after_jump) {
1380  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.fail);
1381  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1382  if (overlapped) {
1383  goto analopfinish;
1384  }
1385  }
1386  if (rz_analysis_noreturn_at(analysis, op.jump) || op.eob) {
1387  goto analopfinish;
1388  }
1389  } else {
1390  analopfinish:
1391  if (op.type == RZ_ANALYSIS_OP_TYPE_RJMP) {
1393  } else {
1395  }
1396  }
1397  break;
1399  last_is_push = true;
1400  last_push_addr = op.val;
1401  if (analysis->iob.is_valid_offset(analysis->iob.io, last_push_addr, 1)) {
1402  (void)rz_analysis_xrefs_set(analysis, op.addr, last_push_addr, RZ_ANALYSIS_XREF_TYPE_DATA);
1403  }
1404  break;
1406  if ((op.type & RZ_ANALYSIS_OP_TYPE_REG) && last_is_reg_mov_lea && op.src[0] && op.src[0]->reg && op.src[0]->reg->name && !strcmp(op.src[0]->reg->name, last_reg_mov_lea_name)) {
1407  last_is_push = true;
1408  last_push_addr = last_reg_mov_lea_val;
1409  if (analysis->iob.is_valid_offset(analysis->iob.io, last_push_addr, 1)) {
1410  (void)rz_analysis_xrefs_set(analysis, op.addr, last_push_addr, RZ_ANALYSIS_XREF_TYPE_DATA);
1411  }
1412  }
1413  break;
1415  if (op.family == RZ_ANALYSIS_OP_FAMILY_PRIV) {
1417  }
1418  if (last_is_push && analysis->opt.pushret) {
1419  op.type = RZ_ANALYSIS_OP_TYPE_JMP;
1420  op.jump = last_push_addr;
1421  bb->jump = op.jump;
1422  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.jump);
1423  goto beach;
1424  }
1425  if (!op.cond) {
1426  RZ_LOG_DEBUG("RET 0x%08" PFMT64x ". overlap=%s %" PFMT64u " %" PFMT64u "\n",
1427  addr + delay.un_idx - oplen, rz_str_bool(overlapped),
1430  }
1431  break;
1433  if (continue_after_jump && is_hexagon) {
1434  rz_analysis_task_item_new(analysis, tasks, fcn, NULL, op.addr + op.size);
1435  set_bb_branches(bb, op.addr + op.size, UT64_MAX);
1437  }
1438  }
1440  last_is_reg_mov_lea = false;
1441  }
1442  if (op.type != RZ_ANALYSIS_OP_TYPE_PUSH && op.type != RZ_ANALYSIS_OP_TYPE_RPUSH) {
1443  last_is_push = false;
1444  }
1445  if (is_arm && op.type != RZ_ANALYSIS_OP_TYPE_MOV) {
1446  last_is_mov_lr_pc = false;
1447  }
1448  if (has_variadic_reg && !fcn->is_variadic) {
1449  variadic_reg = rz_reg_get(analysis->reg, "rax", RZ_REG_TYPE_GPR);
1450  bool dst_is_variadic = op.dst && op.dst->reg && variadic_reg && op.dst->reg->offset == variadic_reg->offset;
1451  bool op_is_cmp = (op.type == RZ_ANALYSIS_OP_TYPE_CMP) || op.type == RZ_ANALYSIS_OP_TYPE_ACMP;
1452  if (dst_is_variadic && !op_is_cmp) {
1453  has_variadic_reg = false;
1454  } else if (op_is_cmp) {
1455  if (op.src[0] && op.src[0]->reg && (op.dst->reg == op.src[0]->reg) && dst_is_variadic) {
1456  fcn->is_variadic = true;
1457  }
1458  }
1459  }
1460  }
1461 beach:
1463  RZ_FREE(last_reg_mov_lea_name);
1464  if (bb) {
1465  if (bb->size) {
1467  } else {
1469  }
1471  }
1472  free(movbasereg);
1473  return ret;
1474 }
RZ_API RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
RZ_API ut64 rz_analysis_function_linear_size(RzAnalysisFunction *fcn)
Definition: function.c:318
RZ_API bool rz_analysis_is_prelude(RzAnalysis *analysis, const ut8 *data, int len)
Definition: analysis.c:676
RZ_API bool rz_analysis_noreturn_at(RzAnalysis *analysis, ut64 addr)
Definition: analysis.c:597
ut16 val
Definition: armass64_const.h:6
static mcore_handle handle
Definition: asm_mcore.c:8
RZ_API void rz_analysis_block_set_size(RzAnalysisBlock *block, ut64 size)
Definition: block.c:194
RZ_API bool rz_analysis_block_relocate(RzAnalysisBlock *block, ut64 addr, ut64 size)
Definition: block.c:213
RZ_API bool rz_analysis_block_set_op_offset(RzAnalysisBlock *block, size_t i, ut16 v)
Definition: block.c:1027
RZ_API void rz_analysis_block_update_hash(RzAnalysisBlock *block)
Definition: block.c:698
RZ_API RzAnalysisBlock * rz_analysis_block_split(RzAnalysisBlock *bbi, ut64 addr)
Definition: block.c:255
RZ_API RzAnalysisCond * rz_analysis_cond_new_from_op(RzAnalysisOp *op)
Definition: cond.c:92
RZ_API void rz_analysis_cond_free(RzAnalysisCond *c)
Definition: cond.c:19
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
#define false
uint32_t ut32
size_t map(int syms, int left, int len)
Definition: enough.c:237
#define MAX_FLG_NAME_SIZE
Definition: fcn.c:19
static void free_leaddr_pair(void *pair)
Definition: fcn.c:353
static ut64 try_get_cmpval_from_parents(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisBlock *my_bb, const char *cmp_reg)
Definition: fcn.c:263
static RzAnalysisBlock * fcn_append_basic_block(RzAnalysis *analysis, RzAnalysisFunction *fcn, ut64 addr)
Definition: fcn.c:128
static void fcn_takeover_block_recursive(RzAnalysisFunction *fcn, RzAnalysisBlock *start_block)
Definition: fcn.c:474
static void set_bb_branches(RZ_OUT RzAnalysisBlock *bb, const ut64 jump, const ut64 fail)
Definition: fcn.c:542
#define MAX_FCN_SIZE
Definition: fcn.c:23
#define MAX_SCAN_SIZE
Definition: fcn.c:16
static bool isInvalidMemory(RzAnalysis *analysis, const ut8 *buf, int len)
Definition: fcn.c:143
static bool op_is_set_bp(RzAnalysisOp *op, const char *bp_reg, const char *sp_reg)
Definition: fcn.c:516
static bool is_delta_pointer_table(RzAnalysis *analysis, ut64 addr, ut64 lea_ptr, ut64 *jmptbl_addr, ut64 *casetbl_addr, RzAnalysisOp *jmp_aop)
Definition: fcn.c:166
RZ_API bool rz_analysis_task_item_new(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzVector *tasks, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NULLABLE RzAnalysisBlock *block, ut64 address)
Adds a new task item to the tasks parameter.
Definition: fcn.c:1488
static bool isSymbolNextInstruction(RzAnalysis *analysis, RzAnalysisOp *op)
Definition: fcn.c:159
static RzAnalysisBlock * bbget(RzAnalysis *analysis, ut64 addr, bool jumpmid)
Definition: fcn.c:359
static void analyze_retpoline(RzAnalysis *analysis, RzAnalysisOp *op)
Definition: fcn.c:506
#define gotoBeach(x)
Definition: fcn.c:139
static int skip_hp(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op, RzAnalysisBlock *bb, ut64 addr, char *tmp_buf, int oplen, int un_idx, int *idx)
Definition: fcn.c:288
static bool does_arch_destroys_dst(const char *arch)
Definition: fcn.c:525
static bool regs_exist(RzAnalysisValue *src, RzAnalysisValue *dst)
Definition: fcn.c:282
RZ_API void rz_analysis_hint_set_bits(RzAnalysis *a, ut64 addr, int bits)
Definition: hint.c:288
RZ_API bool rz_analysis_walkthrough_arm_jmptbl_style(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params)
Marks for analysis ARM specific jump table cases.
Definition: jmptbl.c:391
RZ_API bool rz_analysis_get_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, ut64 jmp_address, RZ_NONNULL RzAnalysisJmpTableParams *params)
Gets some necessary information about a jump table to perform analysis on.
Definition: jmptbl.c:443
RZ_API bool rz_analysis_walkthrough_jmptbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params)
Marks the jump table cases for analysis.
Definition: jmptbl.c:176
RZ_API bool rz_analysis_get_delta_jmptbl_info(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, ut64 jmp_address, ut64 lea_address, RZ_NONNULL RzAnalysisJmpTableParams *params)
Gets some necessary information about a jump table to perform analysis on.
Definition: jmptbl.c:288
RZ_API bool rz_analysis_walkthrough_casetbl(RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzAnalysisBlock *block, RZ_NONNULL RzAnalysisJmpTableParams *params)
Marks for analysis jump table cases with a space optimization for multiple cases corresponding to the...
Definition: jmptbl.c:76
#define reg(n)
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
@ RZ_ABS
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
RZ_API bool rz_meta_set(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, ut64 size, const char *str)
Definition: meta.c:191
static int is_arm(RzBinPEObj *bin)
Definition: pe_info.c:12
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
static void repeat(struct parse *, sopno, int, int)
Definition: regcomp.c:1155
RzAnalysisBBEndCause
Definition: rz_analysis.h:472
@ RZ_ANALYSIS_RET_BRANCH
Definition: rz_analysis.h:476
@ RZ_ANALYSIS_RET_COND
Definition: rz_analysis.h:477
@ RZ_ANALYSIS_RET_NOP
Definition: rz_analysis.h:473
@ RZ_ANALYSIS_RET_END
Definition: rz_analysis.h:475
@ RZ_ANALYSIS_FCN_TYPE_INT
Definition: rz_analysis.h:197
@ RZ_ANALYSIS_STACK_RESET
Definition: rz_analysis.h:460
@ RZ_ANALYSIS_STACK_INC
Definition: rz_analysis.h:457
@ RZ_ANALYSIS_OP_FAMILY_PRIV
Definition: rz_analysis.h:316
@ RZ_META_TYPE_DATA
Definition: rz_analysis.h:289
@ RZ_ANALYSIS_OP_PREFIX_HWLOOP_END
Definition: rz_analysis.h:353
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
#define RZ_ANALYSIS_OP_TYPE_MASK
Definition: rz_analysis.h:358
@ RZ_ANALYSIS_OP_TYPE_CMP
Definition: rz_analysis.h:399
@ RZ_ANALYSIS_OP_TYPE_ICALL
Definition: rz_analysis.h:381
@ RZ_ANALYSIS_OP_TYPE_LOAD
Definition: rz_analysis.h:416
@ RZ_ANALYSIS_OP_TYPE_UPUSH
Definition: rz_analysis.h:395
@ RZ_ANALYSIS_OP_TYPE_RPUSH
Definition: rz_analysis.h:396
@ RZ_ANALYSIS_OP_TYPE_IJMP
Definition: rz_analysis.h:371
@ RZ_ANALYSIS_OP_TYPE_MJMP
Definition: rz_analysis.h:375
@ RZ_ANALYSIS_OP_TYPE_TRAP
Definition: rz_analysis.h:392
@ RZ_ANALYSIS_OP_TYPE_CCALL
Definition: rz_analysis.h:383
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_REG
Definition: rz_analysis.h:365
@ RZ_ANALYSIS_OP_TYPE_RCJMP
Definition: rz_analysis.h:374
@ RZ_ANALYSIS_OP_TYPE_CRET
Definition: rz_analysis.h:386
@ RZ_ANALYSIS_OP_TYPE_PUSH
Definition: rz_analysis.h:397
@ RZ_ANALYSIS_OP_TYPE_IRJMP
Definition: rz_analysis.h:372
@ RZ_ANALYSIS_OP_TYPE_UCJMP
Definition: rz_analysis.h:377
@ RZ_ANALYSIS_OP_TYPE_ILL
Definition: rz_analysis.h:387
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_NOP
Definition: rz_analysis.h:389
@ RZ_ANALYSIS_OP_TYPE_ACMP
Definition: rz_analysis.h:400
@ RZ_ANALYSIS_OP_TYPE_RCALL
Definition: rz_analysis.h:380
@ RZ_ANALYSIS_OP_TYPE_MCJMP
Definition: rz_analysis.h:376
@ RZ_ANALYSIS_OP_TYPE_IRCALL
Definition: rz_analysis.h:382
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
RZ_API const char * rz_str_bool(int b)
Definition: str.c:3896
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API int rz_str_cmp(const char *dst, const char *orig, int len)
Definition: str.c:974
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API int rz_sys_usleep(int usecs)
Sleep for usecs microseconds.
Definition: sys.c:317
@ RZ_TYPE_COND_EXCEPTION
Definition: rz_type.h:203
#define RZ_NEW(x)
Definition: rz_types.h:285
#define PFMT64u
Definition: rz_types.h:395
#define RZ_FREE(x)
Definition: rz_types.h:369
#define UT32_MAX
Definition: rz_types_base.h:99
#define f(i)
Definition: sha256.c:46
ut64 leaddr
Definition: fcn.c:349
ut64 op_addr
Definition: fcn.c:348
Definition: z80asm.h:102
RzAnalysisCond * cond
Definition: rz_analysis.h:873
const char * cmpreg
Definition: rz_analysis.h:883
RzAnalysisRange * limit
Definition: rz_analysis.h:587
RzList * leaddrs
Definition: rz_analysis.h:621
struct rz_analysis_plugin_t * cur
Definition: rz_analysis.h:586
RzCoreBind coreb
Definition: rz_analysis.h:580
RzAnalysisBlock * block
Definition: rz_analysis.h:893
RzAnalysisFunction * fcn
Definition: rz_analysis.h:892
RzCoreNumGet numGet
Definition: rz_bind.h:47
void * core
Definition: rz_bind.h:31
RzCoreGetName getName
Definition: rz_bind.h:40
RzIOMapGet map_get
Definition: rz_io.h:259
size_t addrbytes
Definition: rz_io.h:66
int va
Definition: rz_io.h:63
char * name
Definition: rz_reg.h:118
void after(uv_work_t *req, int status)
Definition: main.c:26
ut64 maxlen
Definition: core.c:76
static bool arch_destroys_dst(const char *arch)
Definition: var.c:857
RZ_API void rz_analysis_extract_vars(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op)
Definition: var.c:1103
RZ_DEPRECATE RZ_API RzList * rz_analysis_var_all_list(RzAnalysis *analysis, RzAnalysisFunction *fcn)
Definition: var.c:1135
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
RZ_API bool rz_analysis_xrefs_set(RzAnalysis *analysis, ut64 from, ut64 to, RzAnalysisXRefType type)
Definition: xrefs.c:117

References addr, rz_analysis_function_t::addr, rz_analysis_op_t::addr, rz_analysis_bb_t::addr, rz_io_t::addrbytes, after(), rz_analysis_options_t::afterjmp, rz_analysis_options_t::aftertrap, rz_analysis_function_t::analysis, analyze_function_locally(), analyze_retpoline(), rz_analysis_plugin_t::arch, arch_destroys_dst(), rz_analysis_options_t::bb_max_size, bbget(), rz_analysis_t::bits, rz_analysis_task_item::block, rz_analysis_function_t::bp_off, rz_analysis_function_t::cc, rz_analysis_options_t::cjmpref, rz_analysis_bb_t::cmpreg, rz_analysis_bb_t::cmpval, rz_analysis_bb_t::cond, rz_core_bind_t::core, rz_analysis_t::coreb, rz_analysis_t::cur, rz_analysis_options_t::delay, rz_analysis_op_t::disp, does_arch_destroys_dst(), rz_analysis_op_t::dst, rz_flag_bind_t::f, f, rz_analysis_bb_t::fail, rz_analysis_task_item::fcn, fcn_append_basic_block(), fcn_takeover_block_recursive(), rz_analysis_bb_t::fcns, rz_analysis_t::flb, free(), free_leaddr_pair(), rz_flag_bind_t::get_at, rz_core_bind_t::getName, gotoBeach, handle, rz_analysis_options_t::hpskip, setup::idx, if(), rz_analysis_options_t::ijmp, rz_io_bind_t::io, rz_analysis_t::iob, is_arm(), is_delta_pointer_table(), rz_io_bind_t::is_valid_offset, rz_analysis_function_t::is_variadic, isInvalidMemory(), isSymbolNextInstruction(), rz_analysis_options_t::jmpabove, rz_analysis_options_t::jmpmid, rz_analysis_options_t::jmpref, rz_analysis_options_t::jmptbl, rz_analysis_options_t::jmptbl_maxcount, rz_analysis_bb_t::jump, leaddr_pair::leaddr, rz_analysis_t::leaddrs, len, rz_analysis_t::limit, limit, list(), rz_analysis_options_t::loads, map(), rz_io_bind_t::map_get, MAX_FCN_SIZE, MAX_FLG_NAME_SIZE, MAX_SCAN_SIZE, maxlen, rz_analysis_function_t::maxstack, rz_analysis_function_t::name, rz_flag_item_t::name, rz_reg_item_t::name, rz_reg_t::name, rz_analysis_function_t::ninstr, rz_analysis_bb_t::ninstr, rz_analysis_options_t::nopskip, NULL, rz_core_bind_t::numGet, rz_reg_item_t::offset, leaddr_pair::op_addr, op_is_set_bp(), rz_analysis_t::opt, PFMT64u, PFMT64x, rz_analysis_options_t::pushret, read_ahead(), rz_io_bind_t::read_at, rz_analysis_options_t::recont, leaddr_pair::reg, rz_analysis_t::reg, rz_analysis_value_t::reg, regs_exist(), repeat(), RZ_ABS, rz_analysis_block_relocate(), rz_analysis_block_set_op_offset(), rz_analysis_block_set_size(), rz_analysis_block_split(), rz_analysis_block_unref(), rz_analysis_block_update_hash(), rz_analysis_cond_free(), rz_analysis_cond_new_from_op(), rz_analysis_extract_vars(), RZ_ANALYSIS_FCN_TYPE_INT, rz_analysis_function_linear_size(), rz_analysis_function_remove_block(), rz_analysis_get_delta_jmptbl_info(), rz_analysis_get_fcn_in(), rz_analysis_get_function_at(), rz_analysis_get_jmptbl_info(), rz_analysis_hint_set_bits(), rz_analysis_is_prelude(), rz_analysis_noreturn_at(), rz_analysis_op(), RZ_ANALYSIS_OP_FAMILY_PRIV, rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_ESIL, RZ_ANALYSIS_OP_MASK_HINT, RZ_ANALYSIS_OP_MASK_VAL, RZ_ANALYSIS_OP_PREFIX_HWLOOP_END, RZ_ANALYSIS_OP_TYPE_ACMP, RZ_ANALYSIS_OP_TYPE_ADD, RZ_ANALYSIS_OP_TYPE_CALL, RZ_ANALYSIS_OP_TYPE_CCALL, RZ_ANALYSIS_OP_TYPE_CJMP, RZ_ANALYSIS_OP_TYPE_CMOV, RZ_ANALYSIS_OP_TYPE_CMP, RZ_ANALYSIS_OP_TYPE_CRET, RZ_ANALYSIS_OP_TYPE_ICALL, RZ_ANALYSIS_OP_TYPE_IJMP, RZ_ANALYSIS_OP_TYPE_ILL, RZ_ANALYSIS_OP_TYPE_IRCALL, RZ_ANALYSIS_OP_TYPE_IRJMP, RZ_ANALYSIS_OP_TYPE_JMP, RZ_ANALYSIS_OP_TYPE_LEA, RZ_ANALYSIS_OP_TYPE_LOAD, RZ_ANALYSIS_OP_TYPE_MASK, RZ_ANALYSIS_OP_TYPE_MCJMP, RZ_ANALYSIS_OP_TYPE_MJMP, RZ_ANALYSIS_OP_TYPE_MOV, RZ_ANALYSIS_OP_TYPE_NOP, RZ_ANALYSIS_OP_TYPE_PUSH, RZ_ANALYSIS_OP_TYPE_RCALL, RZ_ANALYSIS_OP_TYPE_RCJMP, RZ_ANALYSIS_OP_TYPE_REG, RZ_ANALYSIS_OP_TYPE_RET, RZ_ANALYSIS_OP_TYPE_RJMP, RZ_ANALYSIS_OP_TYPE_RPUSH, RZ_ANALYSIS_OP_TYPE_SUB, RZ_ANALYSIS_OP_TYPE_TRAP, RZ_ANALYSIS_OP_TYPE_UCALL, RZ_ANALYSIS_OP_TYPE_UCJMP, RZ_ANALYSIS_OP_TYPE_UJMP, RZ_ANALYSIS_OP_TYPE_UPUSH, RZ_ANALYSIS_RET_BRANCH, RZ_ANALYSIS_RET_COND, RZ_ANALYSIS_RET_END, RZ_ANALYSIS_RET_ERROR, RZ_ANALYSIS_RET_NOP, RZ_ANALYSIS_STACK_INC, RZ_ANALYSIS_STACK_RESET, rz_analysis_task_item_new(), rz_analysis_var_all_list(), rz_analysis_walkthrough_arm_jmptbl_style(), rz_analysis_walkthrough_casetbl(), rz_analysis_walkthrough_jmptbl(), RZ_ANALYSIS_XREF_TYPE_CALL, RZ_ANALYSIS_XREF_TYPE_CODE, RZ_ANALYSIS_XREF_TYPE_DATA, rz_analysis_xrefs_set(), rz_cons_is_breaked(), RZ_FREE, rz_list_append(), rz_list_contains(), rz_list_free(), rz_list_newf(), RZ_LOG_DEBUG, RZ_LOG_ERROR, rz_meta_set(), RZ_META_TYPE_DATA, RZ_MIN, RZ_NEW, rz_reg_get(), RZ_REG_NAME_BP, RZ_REG_NAME_SP, RZ_REG_TYPE_GPR, rz_return_val_if_fail, rz_str_bool(), rz_str_cmp(), rz_str_endswith(), rz_str_replace(), rz_str_startswith(), rz_strbuf_get(), rz_sys_usleep(), RZ_TYPE_COND_EXCEPTION, set_bb_branches(), rz_analysis_bb_t::size, skip_hp(), rz_analysis_t::sleep, rz_analysis_function_t::stack, rz_analysis_task_item::stack, rz_analysis_bb_t::stackptr, rz_analysis_task_item::start_address, strdup(), rz_analysis_options_t::tailcall, rz_analysis_range_t::to, try_get_cmpval_from_parents(), rz_analysis_options_t::trycatch, rz_analysis_function_t::type, rz_analysis_op_t::type, rz_analysis_cond_t::type, UT32_MAX, ut64(), UT64_MAX, rz_io_t::va, val, and rz_analysis_options_t::vars.

Referenced by rz_analysis_run_tasks().

◆ rz_analysis_check_fcn()

RZ_API bool rz_analysis_check_fcn ( RzAnalysis analysis,
ut8 buf,
ut16  bufsz,
ut64  addr,
ut64  low,
ut64  high 
)

Definition at line 1538 of file fcn.c.

1538  {
1539  RzAnalysisOp op = {
1540  0
1541  };
1542  int i, oplen, opcnt = 0, pushcnt = 0, movcnt = 0, brcnt = 0;
1543  if (rz_analysis_is_prelude(analysis, buf, bufsz)) {
1544  return true;
1545  }
1546  for (i = 0; i < bufsz && opcnt < 10; i += oplen, opcnt++) {
1548  if ((oplen = rz_analysis_op(analysis, &op, addr + i, buf + i, bufsz - i, RZ_ANALYSIS_OP_MASK_BASIC | RZ_ANALYSIS_OP_MASK_HINT)) < 1) {
1549  return false;
1550  }
1551  switch (op.type) {
1555  pushcnt++;
1556  break;
1559  movcnt++;
1560  break;
1564  if (op.jump < low || op.jump >= high) {
1565  return false;
1566  }
1567  brcnt++;
1568  break;
1570  return false;
1571  default:
1572  break;
1573  }
1574  }
1575  return (pushcnt + movcnt + brcnt > 5);
1576 }
@ RZ_ANALYSIS_OP_TYPE_UNK
Definition: rz_analysis.h:388

References addr, i, rz_analysis_is_prelude(), rz_analysis_op(), rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_BASIC, RZ_ANALYSIS_OP_MASK_HINT, RZ_ANALYSIS_OP_TYPE_CALL, RZ_ANALYSIS_OP_TYPE_CJMP, RZ_ANALYSIS_OP_TYPE_CMOV, RZ_ANALYSIS_OP_TYPE_JMP, RZ_ANALYSIS_OP_TYPE_MOV, RZ_ANALYSIS_OP_TYPE_PUSH, RZ_ANALYSIS_OP_TYPE_RPUSH, RZ_ANALYSIS_OP_TYPE_UNK, and RZ_ANALYSIS_OP_TYPE_UPUSH.

Referenced by rz_analysis_try_get_fcn().

◆ rz_analysis_del_jmprefs()

RZ_API void rz_analysis_del_jmprefs ( RzAnalysis analysis,
RzAnalysisFunction fcn 
)

Definition at line 1592 of file fcn.c.

1592  {
1593  RzAnalysisXRef *xref;
1595  RzListIter *iter;
1596 
1597  rz_list_foreach (xrefs, iter, xref) {
1598  if (xref->type == RZ_ANALYSIS_XREF_TYPE_CODE) {
1599  rz_analysis_xrefs_deln(analysis, xref->from, xref->to, xref->type);
1600  }
1601  }
1602  rz_list_free(xrefs);
1603 }
RZ_API bool rz_analysis_xrefs_deln(RzAnalysis *analysis, ut64 from, ut64 to, RzAnalysisXRefType type)
Definition: xrefs.c:148

References rz_analysis_ref_t::from, rz_analysis_function_get_xrefs_from(), RZ_ANALYSIS_XREF_TYPE_CODE, rz_analysis_xrefs_deln(), rz_list_free(), rz_analysis_ref_t::to, and rz_analysis_ref_t::type.

Referenced by rz_analysis_function_del_all_handler().

◆ rz_analysis_fcn()

RZ_API int rz_analysis_fcn ( RzAnalysis analysis,
RzAnalysisFunction fcn,
ut64  addr,
ut64  len,
int  reftype 
)

Definition at line 1606 of file fcn.c.

1606  {
1608  void **it;
1609  rz_pvector_foreach (metas, it) {
1610  RzAnalysisMetaItem *meta = ((RzIntervalNode *)*it)->data;
1611  switch (meta->type) {
1612  case RZ_META_TYPE_DATA:
1613  case RZ_META_TYPE_STRING:
1614  case RZ_META_TYPE_FORMAT:
1616  return 0;
1617  default:
1618  break;
1619  }
1620  }
1622  if (analysis->opt.norevisit) {
1623  if (!analysis->visited) {
1624  analysis->visited = set_u_new();
1625  }
1626  if (set_u_contains(analysis->visited, addr)) {
1627  RZ_LOG_DEBUG("rz_analysis_fcn: analysis.norevisit at 0x%08" PFMT64x " %c\n", addr, reftype);
1628  return RZ_ANALYSIS_RET_END;
1629  }
1630  set_u_add(analysis->visited, addr);
1631  } else {
1632  if (analysis->visited) {
1633  set_u_free(analysis->visited);
1634  analysis->visited = NULL;
1635  }
1636  }
1637  /* defines fcn. or loc. prefix */
1639  if (fcn->addr == UT64_MAX) {
1640  fcn->addr = addr;
1641  }
1642  fcn->maxstack = 0;
1643  if (fcn->cc && !strcmp(fcn->cc, "ms")) {
1644  // Probably should put this on the cc sdb
1645  const int shadow_store = 0x28; // First 4 args + retaddr
1646  fcn->stack = fcn->maxstack = fcn->reg_save_area = shadow_store;
1647  }
1648  RzVector tasks;
1649  rz_vector_init(&tasks, sizeof(RzAnalysisTaskItem), NULL, NULL);
1650  rz_analysis_task_item_new(analysis, &tasks, fcn, NULL, addr);
1651  int ret = rz_analysis_run_tasks(&tasks);
1652  rz_vector_fini(&tasks);
1653  return ret;
1654 }
RZ_API RzPVector * rz_meta_get_all_in(RzAnalysis *a, ut64 at, RzAnalysisMetaType type)
Definition: meta.c:223
@ RZ_ANALYSIS_FCN_TYPE_LOC
Definition: rz_analysis.h:194
@ RZ_ANALYSIS_FCN_TYPE_FCN
Definition: rz_analysis.h:193
@ RZ_META_TYPE_ANY
Definition: rz_analysis.h:288
@ RZ_META_TYPE_STRING
Definition: rz_analysis.h:291
@ RZ_META_TYPE_FORMAT
Definition: rz_analysis.h:292
RZ_API SetU * set_u_new(void)
Definition: set.c:30
RZ_API void set_u_free(SetU *s)
Definition: set.c:46
RZ_API void set_u_add(SetU *s, ut64 u)
Definition: set.c:34
RZ_API bool set_u_contains(SetU *s, ut64 u)
Definition: set.c:38
RzAnalysisMetaType type
Definition: rz_analysis.h:302
SetU * visited
Definition: rz_analysis.h:619
static struct Type metas[]
Definition: swift.c:39
reftype
Definition: z80asm.h:66

References addr, rz_analysis_function_t::addr, rz_analysis_function_t::cc, rz_analysis_function_t::maxstack, metas, rz_analysis_options_t::norevisit, NULL, rz_analysis_t::opt, PFMT64x, rz_analysis_function_t::reg_save_area, RZ_ANALYSIS_FCN_TYPE_FCN, RZ_ANALYSIS_FCN_TYPE_LOC, RZ_ANALYSIS_RET_END, rz_analysis_run_tasks(), rz_analysis_task_item_new(), RZ_ANALYSIS_XREF_TYPE_CODE, RZ_LOG_DEBUG, rz_meta_get_all_in(), RZ_META_TYPE_ANY, RZ_META_TYPE_DATA, RZ_META_TYPE_FORMAT, RZ_META_TYPE_STRING, rz_pvector_foreach, rz_pvector_free(), rz_vector_fini(), rz_vector_init(), set_u_add(), set_u_contains(), set_u_free(), set_u_new(), rz_analysis_function_t::stack, rz_analysis_function_t::type, rz_analysis_meta_item_t::type, UT64_MAX, and rz_analysis_t::visited.

Referenced by __core_analysis_fcn().

◆ rz_analysis_fcn_add_bb()

RZ_API bool rz_analysis_fcn_add_bb ( RzAnalysis a,
RzAnalysisFunction fcn,
ut64  addr,
ut64  size,
ut64  jump,
ut64  fail,
RZ_BORROW RzAnalysisDiff diff 
)

Definition at line 1739 of file fcn.c.

1739  {
1740  if (size == 0) {
1741  RZ_LOG_ERROR("Empty basic block at 0x%08" PFMT64x " (not allowed).\n", addr);
1743  return false;
1744  }
1745  if (size > a->opt.bb_max_size) {
1746  RZ_LOG_ERROR("Cannot allocate such big bb of %" PFMT64d " bytes at 0x%08" PFMT64x "\n", (st64)size, addr);
1748  return false;
1749  }
1750 
1752  if (block) {
1753  rz_analysis_delete_block(block);
1754  block = NULL;
1755  }
1756 
1757  block = rz_analysis_create_block(a, addr, size);
1758  if (!block) {
1759  return false;
1760  }
1761 
1763  rz_analysis_function_add_block(fcn, block);
1764 
1765  block->jump = jump;
1766  block->fail = fail;
1767  if (diff) {
1768  if (!block->diff) {
1769  block->diff = rz_analysis_diff_new();
1770  }
1771  if (block->diff) {
1772  block->diff->type = diff->type;
1773  block->diff->addr = diff->addr;
1774  if (diff->name) {
1775  RZ_FREE(block->diff->name);
1776  block->diff->name = strdup(diff->name);
1777  }
1778  }
1779  }
1780  rz_analysis_block_unref(block);
1781  return true;
1782 }
RZ_API RZ_OWN RzAnalysisDiff * rz_analysis_diff_new(void)
Definition: diff.c:9
int jump(int a, int b)
Definition: bcj_test.c:35
RZ_API void rz_analysis_delete_block(RzAnalysisBlock *bb)
Definition: block.c:186
RZ_API void rz_analysis_block_analyze_ops(RzAnalysisBlock *block)
Definition: block.c:1084
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define PFMT64d
Definition: rz_types.h:394
#define st64
Definition: rz_types_base.h:10
RzAnalysisDiff * diff
Definition: rz_analysis.h:872
#define fail(test)
Definition: tests.h:29

References a, addr, rz_analysis_diff_t::addr, rz_analysis_bb_t::diff, rz_analysis_bb_t::fail, fail, rz_analysis_bb_t::jump, jump(), rz_analysis_diff_t::name, NULL, PFMT64d, PFMT64x, rz_analysis_block_analyze_ops(), rz_analysis_block_unref(), rz_analysis_create_block(), rz_analysis_delete_block(), rz_analysis_diff_new(), rz_analysis_function_add_block(), rz_analysis_get_block_at(), RZ_FREE, RZ_LOG_ERROR, rz_warn_if_reached, st64, strdup(), and rz_analysis_diff_t::type.

Referenced by rz_analysis_function_blocks_add_handler().

◆ rz_analysis_fcn_bbget_at()

RZ_API RzAnalysisBlock* rz_analysis_fcn_bbget_at ( RzAnalysis analysis,
RzAnalysisFunction fcn,
ut64  addr 
)

Definition at line 2063 of file fcn.c.

2063  {
2066  if (b) {
2067  return b;
2068  }
2069  RzListIter *iter;
2070  RzAnalysisBlock *bb;
2071  rz_list_foreach (fcn->bbs, iter, bb) {
2072  if (addr == bb->addr) {
2073  return bb;
2074  }
2075  }
2076  return NULL;
2077 }
#define b(i)
Definition: sha256.c:42

References addr, rz_analysis_bb_t::addr, b, rz_analysis_function_t::bbs, NULL, rz_analysis_get_block_at(), rz_return_val_if_fail, and UT64_MAX.

Referenced by ds_print_bbline().

◆ rz_analysis_fcn_bbget_in()

RZ_API RzAnalysisBlock* rz_analysis_fcn_bbget_in ( const RzAnalysis analysis,
RzAnalysisFunction fcn,
ut64  addr 
)

Definition at line 2042 of file fcn.c.

2042  {
2043  rz_return_val_if_fail(analysis && fcn, NULL);
2044  if (addr == UT64_MAX) {
2045  return NULL;
2046  }
2047  bool can_jmpmid = false;
2048  if (analysis->cur->arch) {
2049  bool is_x86 = !strncmp(analysis->cur->arch, "x86", 3);
2050  bool is_dalvik = !strncmp(analysis->cur->arch, "dalvik", 6);
2051  can_jmpmid = analysis->opt.jmpmid && (is_dalvik || is_x86);
2052  }
2053  RzListIter *iter;
2054  RzAnalysisBlock *bb;
2055  rz_list_foreach (fcn->bbs, iter, bb) {
2056  if (addr >= bb->addr && addr < (bb->addr + bb->size) && (!can_jmpmid || rz_analysis_block_op_starts_at(bb, addr))) {
2057  return bb;
2058  }
2059  }
2060  return NULL;
2061 }

References addr, rz_analysis_bb_t::addr, rz_analysis_plugin_t::arch, rz_analysis_function_t::bbs, rz_analysis_t::cur, rz_analysis_options_t::jmpmid, NULL, rz_analysis_t::opt, rz_analysis_block_op_starts_at(), rz_return_val_if_fail, rz_analysis_bb_t::size, and UT64_MAX.

Referenced by handleMidBB(), propagate_types_among_used_variables(), and rz_core_print_disasm().

◆ rz_analysis_fcn_count()

RZ_API int rz_analysis_fcn_count ( RzAnalysis analysis,
ut64  from,
ut64  to 
)

Definition at line 2028 of file fcn.c.

2028  {
2029  int n = 0;
2030  RzAnalysisFunction *fcni;
2031  RzListIter *iter;
2032  rz_list_foreach (analysis->fcns, iter, fcni) {
2033  if (fcni->addr >= from && fcni->addr < to) {
2034  n++;
2035  }
2036  }
2037  return n;
2038 }
int n
Definition: mipsasm.c:19
RzList * fcns
Definition: rz_analysis.h:565

References rz_analysis_function_t::addr, rz_analysis_t::fcns, from, n, and to.

◆ rz_analysis_fcn_del()

RZ_API int rz_analysis_fcn_del ( RzAnalysis a,
ut64  addr 
)

Definition at line 1675 of file fcn.c.

1675  {
1676  RzAnalysisFunction *fcn;
1677  RzListIter *iter, *iter_tmp;
1678  rz_list_foreach_safe (a->fcns, iter, iter_tmp, fcn) {
1679  RZ_LOG_DEBUG("removing function at %" PFMT64x " %" PFMT64x "\n", fcn->addr, addr);
1680  if (fcn->addr == addr) {
1682  }
1683  }
1684  return true;
1685 }
RZ_API bool rz_analysis_function_delete(RzAnalysisFunction *fcn)
Definition: function.c:180

References a, addr, rz_analysis_function_t::addr, PFMT64x, rz_analysis_function_delete(), and RZ_LOG_DEBUG.

Referenced by rz_analysis_fcn_del_locs(), rz_analysis_function_del_handler(), rz_core_analysis_undefine(), and rz_core_visual_analysis().

◆ rz_analysis_fcn_del_locs()

RZ_API int rz_analysis_fcn_del_locs ( RzAnalysis analysis,
ut64  addr 
)

Definition at line 1657 of file fcn.c.

1657  {
1658  RzListIter *iter, *iter2;
1660  if (!f) {
1661  return false;
1662  }
1663  rz_list_foreach_safe (analysis->fcns, iter, iter2, fcn) {
1664  if (fcn->type != RZ_ANALYSIS_FCN_TYPE_LOC) {
1665  continue;
1666  }
1667  if (rz_analysis_function_contains(fcn, addr)) {
1669  }
1670  }
1671  rz_analysis_fcn_del(analysis, addr);
1672  return true;
1673 }
RZ_API bool rz_analysis_function_contains(RzAnalysisFunction *fcn, ut64 addr)
Definition: function.c:361
RZ_API int rz_analysis_fcn_del(RzAnalysis *a, ut64 addr)
Definition: fcn.c:1675
@ RZ_ANALYSIS_FCN_TYPE_ROOT
Definition: rz_analysis.h:198

References addr, f, rz_analysis_t::fcns, rz_analysis_fcn_del(), RZ_ANALYSIS_FCN_TYPE_LOC, RZ_ANALYSIS_FCN_TYPE_ROOT, rz_analysis_function_contains(), rz_analysis_function_delete(), rz_analysis_get_fcn_in(), and rz_analysis_function_t::type.

Referenced by rz_analysis_function_del_handler(), rz_core_analysis_undefine(), and rz_core_visual_analysis().

◆ rz_analysis_fcn_invalidate_read_ahead_cache()

RZ_API void rz_analysis_fcn_invalidate_read_ahead_cache ( void  )

Definition at line 84 of file fcn.c.

84  {
85 #if READ_AHEAD
87 #endif
88 }

References cache_addr, and UT64_MAX.

Referenced by __core_analysis_fcn(), and update_analysis().

◆ rz_analysis_fcn_next()

RZ_API RzAnalysisFunction* rz_analysis_fcn_next ( RzAnalysis analysis,
ut64  addr 
)

Definition at line 2015 of file fcn.c.

2015  {
2016  RzAnalysisFunction *fcni;
2017  RzListIter *iter;
2018  RzAnalysisFunction *closer = NULL;
2019  rz_list_foreach (analysis->fcns, iter, fcni) {
2020  // if (fcni->addr == addr)
2021  if (fcni->addr > addr && (!closer || fcni->addr < closer->addr)) {
2022  closer = fcni;
2023  }
2024  }
2025  return closer;
2026 }

References addr, rz_analysis_function_t::addr, rz_analysis_t::fcns, and NULL.

◆ rz_analysis_fcntype_tostring()

RZ_API const char* rz_analysis_fcntype_tostring ( int  type)

Definition at line 35 of file fcn.c.

35  {
36  switch (type) {
37  case RZ_ANALYSIS_FCN_TYPE_NULL: return "null";
38  case RZ_ANALYSIS_FCN_TYPE_FCN: return "fcn";
39  case RZ_ANALYSIS_FCN_TYPE_LOC: return "loc";
40  case RZ_ANALYSIS_FCN_TYPE_SYM: return "sym";
41  case RZ_ANALYSIS_FCN_TYPE_IMP: return "imp";
42  case RZ_ANALYSIS_FCN_TYPE_INT: return "int"; // interrupt
43  case RZ_ANALYSIS_FCN_TYPE_ROOT: return "root";
44  }
45  return "unk";
46 }
int type
Definition: mipsasm.c:17
@ RZ_ANALYSIS_FCN_TYPE_SYM
Definition: rz_analysis.h:195
@ RZ_ANALYSIS_FCN_TYPE_IMP
Definition: rz_analysis.h:196
@ RZ_ANALYSIS_FCN_TYPE_NULL
Definition: rz_analysis.h:192

References RZ_ANALYSIS_FCN_TYPE_FCN, RZ_ANALYSIS_FCN_TYPE_IMP, RZ_ANALYSIS_FCN_TYPE_INT, RZ_ANALYSIS_FCN_TYPE_LOC, RZ_ANALYSIS_FCN_TYPE_NULL, RZ_ANALYSIS_FCN_TYPE_ROOT, RZ_ANALYSIS_FCN_TYPE_SYM, and type.

Referenced by __core_analysis_fcn(), core_analysis_graph_nodes(), draw_graph_nodes(), fcn_print_info(), function_print_to_json(), and function_rename().

◆ rz_analysis_function_arg_count()

RZ_API size_t rz_analysis_function_arg_count ( RzAnalysis a,
RzAnalysisFunction fcn 
)

Returns the argument count of a function.

Parameters
aRzAnalysis instance
fFunction

Definition at line 2460 of file fcn.c.

2460  {
2461  if (!a || !fcn) {
2462  return 0;
2463  }
2464  void **it;
2465  size_t count = 0;
2466  rz_pvector_foreach (&fcn->vars, it) {
2467  RzAnalysisVar *var = *it;
2468  if (var->isarg) {
2469  count++;
2470  }
2471  }
2472  return count;
2473 }

References a, count, rz_analysis_var_t::isarg, rz_pvector_foreach, and rz_analysis_function_t::vars.

◆ rz_analysis_function_args()

RZ_API RZ_OWN RzPVector* rz_analysis_function_args ( RzAnalysis a,
RzAnalysisFunction fcn 
)

Returns vector of all function arguments.

Parameters
aRzAnalysis instance
fFunction

Definition at line 2481 of file fcn.c.

2481  {
2482  if (!a || !fcn) {
2483  return NULL;
2484  }
2486  if (!tmp) {
2487  return NULL;
2488  }
2489  RzAnalysisVar *var;
2490  void **it;
2491  int rarg_idx = 0;
2492  // Resort the pvector to order "reg_arg - stack_arg"
2493  rz_pvector_foreach (&fcn->vars, it) {
2494  var = *it;
2495  if (var->kind == RZ_ANALYSIS_VAR_KIND_REG) {
2496  rz_pvector_insert(tmp, rarg_idx++, var);
2497  } else {
2498  rz_pvector_push(tmp, var);
2499  }
2500  }
2501 
2503  if (!args) {
2505  return NULL;
2506  }
2507  rz_pvector_foreach (tmp, it) {
2508  var = *it;
2509  if (var->isarg) {
2510  int argnum;
2511  if (var->kind == RZ_ANALYSIS_VAR_KIND_REG) {
2512  argnum = rz_analysis_var_get_argnum(var);
2513  if (argnum < 0) {
2514  RZ_LOG_INFO("%s : arg \"%s\" has wrong position: %d\n", fcn->name, var->name, argnum);
2515  continue;
2516  }
2517  } else {
2518  argnum = fcn->argnum;
2519  }
2520  // pvector api is a bit ugly here, essentially we make a (possibly sparse) array
2521  // where each var is assigned at its argnum
2522  if (argnum >= rz_pvector_len(args)) {
2523  if (!rz_pvector_reserve(args, argnum + 1)) {
2524  goto cleanup;
2525  }
2526  while (argnum >= rz_pvector_len(args)) {
2528  }
2529  }
2530  rz_pvector_set(args, argnum, var);
2531  fcn->argnum++;
2532  }
2533  }
2534 cleanup:
2536  return args;
2537 }
void cleanup(void)
Definition: enough.c:244
int args
Definition: mipsasm.c:18
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
static void ** rz_pvector_reserve(RzPVector *vec, size_t capacity)
Definition: rz_vector.h:312
static void rz_pvector_set(RzPVector *vec, size_t index, void *e)
Definition: rz_vector.h:241
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
static void ** rz_pvector_insert(RzPVector *vec, size_t index, void *x)
Definition: rz_vector.h:284
RZ_API int rz_analysis_var_get_argnum(RzAnalysisVar *var)
Definition: var.c:369

References a, rz_analysis_function_t::argnum, args, cleanup(), rz_analysis_var_t::isarg, rz_analysis_var_t::kind, rz_analysis_function_t::name, rz_analysis_var_t::name, NULL, rz_analysis_var_get_argnum(), RZ_ANALYSIS_VAR_KIND_REG, RZ_LOG_INFO, rz_pvector_foreach, rz_pvector_free(), rz_pvector_insert(), rz_pvector_len(), rz_pvector_new(), rz_pvector_push(), rz_pvector_reserve(), rz_pvector_set(), autogen_x86imm::tmp, and rz_analysis_function_t::vars.

Referenced by rz_analysis_function_derive_args().

◆ rz_analysis_function_check_bp_use()

RZ_API void rz_analysis_function_check_bp_use ( RzAnalysisFunction fcn)

Definition at line 2241 of file fcn.c.

2241  {
2242  rz_return_if_fail(fcn);
2244 }
static void __analysis_fcn_check_bp_use(RzAnalysis *analysis, RzAnalysisFunction *fcn)
Definition: fcn.c:2165
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100

References __analysis_fcn_check_bp_use(), rz_analysis_function_t::analysis, and rz_return_if_fail.

Referenced by __core_analysis_fcn().

◆ rz_analysis_function_clone_type()

RZ_API RZ_OWN RzCallable* rz_analysis_function_clone_type ( RzAnalysis analysis,
const RzAnalysisFunction f 
)

Clones the RzCallable type for the given function.

Searches the types database for the given function and returns a clone of the RzCallable type.

Parameters
analysisRzAnalysis instance
fFunction to update

Definition at line 2568 of file fcn.c.

2568  {
2569  rz_return_val_if_fail(analysis && f, NULL);
2570  // Check first if there is a match with some pre-existing RzCallable type in the database
2571  char *shortname = rz_analysis_function_name_guess(analysis->typedb, f->name);
2572  if (!shortname) {
2573  shortname = strdup(f->name);
2574  }
2575  // At this point the `callable` pointer is *borrowed*
2576  RzCallable *callable = rz_type_func_get(analysis->typedb, shortname);
2577  free(shortname);
2578  if (callable) {
2579  // TODO: Decide what to do if there is a mismatch between type
2580  // stored in the RzTypeDB database and the actual type of the
2581  // RzAnalysisFunction
2582  return rz_type_callable_clone(callable);
2583  }
2584  return NULL;
2585 }
RZ_API RZ_OWN char * rz_analysis_function_name_guess(RzTypeDB *typedb, RZ_NONNULL char *name)
Checks if varions function name variations present in the database.
Definition: function.c:458
RzTypeDB * typedb
Definition: rz_analysis.h:602
RZ_API RZ_OWN RzCallable * rz_type_callable_clone(RZ_BORROW RZ_NONNULL const RzCallable *callable)
Creates an exact clone of the RzCallable type.
Definition: function.c:33
RZ_API RZ_BORROW RzCallable * rz_type_func_get(RzTypeDB *typedb, RZ_NONNULL const char *name)
Returns the RzCallable from the database by name.
Definition: function.c:162

References f, free(), NULL, rz_analysis_function_name_guess(), rz_return_val_if_fail, rz_type_callable_clone(), rz_type_func_get(), strdup(), and rz_analysis_t::typedb.

Referenced by rz_analysis_function_derive_type().

◆ rz_analysis_function_complexity()

RZ_API int rz_analysis_function_complexity ( RzAnalysisFunction fcn)

Definition at line 1799 of file fcn.c.

1799  {
1800  /*
1801  CC = E - N + 2P
1802  E = the number of edges of the graph.
1803  N = the number of nodes of the graph.
1804  P = the number of connected components (exit nodes).
1805  */
1806  RzAnalysis *analysis = fcn->analysis;
1807  int E = 0, N = 0, P = 0;
1808  RzListIter *iter;
1809  RzAnalysisBlock *bb;
1810 
1811  rz_list_foreach (fcn->bbs, iter, bb) {
1812  N++; // nodes
1813  if (!analysis && bb->jump == UT64_MAX && bb->fail != UT64_MAX) {
1814  RZ_LOG_DEBUG("invalid bb jump/fail pair at 0x%08" PFMT64x " (fcn 0x%08" PFMT64x "\n", bb->addr, fcn->addr);
1815  }
1816  if (bb->jump == UT64_MAX && bb->fail == UT64_MAX) {
1817  P++; // exit nodes
1818  } else {
1819  E++; // edges
1820  if (bb->fail != UT64_MAX) {
1821  E++;
1822  }
1823  }
1824  if (bb->switch_op && bb->switch_op->cases) {
1825  E += rz_list_length(bb->switch_op->cases);
1826  }
1827  }
1828 
1829  int result = E - N + (2 * P);
1830  if (result < 1 && !analysis) {
1831  RZ_LOG_DEBUG("CC = E(%d) - N(%d) + (2 * P(%d)) < 1 at 0x%08" PFMT64x "\n", E, N, P, fcn->addr);
1832  }
1833  return result;
1834 }
#define P
RzAnalysisSwitchOp * switch_op
Definition: rz_analysis.h:874
#define N
Definition: zip_err_str.c:8
#define E
Definition: zip_err_str.c:12

References rz_analysis_function_t::addr, rz_analysis_bb_t::addr, rz_analysis_function_t::analysis, rz_analysis_function_t::bbs, rz_analysis_switch_obj_t::cases, E, rz_analysis_bb_t::fail, rz_analysis_bb_t::jump, N, P, PFMT64x, rz_list_length(), RZ_LOG_DEBUG, rz_analysis_bb_t::switch_op, and UT64_MAX.

Referenced by fcn_print_info(), function_list_print_to_table(), and function_print_to_json().

◆ rz_analysis_function_cost()

RZ_API ut32 rz_analysis_function_cost ( RzAnalysisFunction fcn)

Definition at line 2080 of file fcn.c.

2080  {
2081  RzListIter *iter;
2082  RzAnalysisBlock *bb;
2083  ut32 totalCycles = 0;
2084  if (!fcn) {
2085  return 0;
2086  }
2087  RzAnalysis *analysis = fcn->analysis;
2088  rz_list_foreach (fcn->bbs, iter, bb) {
2089  RzAnalysisOp op;
2090  ut64 at, end = bb->addr + bb->size;
2091  ut8 *buf = malloc(bb->size);
2092  if (!buf) {
2093  continue;
2094  }
2095  (void)analysis->iob.read_at(analysis->iob.io, bb->addr, (ut8 *)buf, bb->size);
2096  int idx = 0;
2097  for (at = bb->addr; at < end;) {
2098  memset(&op, 0, sizeof(op));
2099  (void)rz_analysis_op(analysis, &op, at, buf + idx, bb->size - idx, RZ_ANALYSIS_OP_MASK_BASIC);
2100  if (op.size < 1) {
2101  op.size = 1;
2102  }
2103  idx += op.size;
2104  at += op.size;
2105  totalCycles += op.cycles;
2107  }
2108  free(buf);
2109  }
2110  return totalCycles;
2111 }
return memset(p, 0, total)

References rz_analysis_bb_t::addr, rz_analysis_function_t::analysis, rz_analysis_function_t::bbs, test_evm::end, free(), setup::idx, rz_io_bind_t::io, rz_analysis_t::iob, malloc(), memset(), op, rz_io_bind_t::read_at, rz_analysis_op(), rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_BASIC, rz_analysis_bb_t::size, and ut64().

Referenced by fcn_print_info(), function_list_print_to_table(), and function_print_to_json().

◆ rz_analysis_function_count_edges()

RZ_API int rz_analysis_function_count_edges ( const RzAnalysisFunction fcn,
RZ_NULLABLE int ebbs 
)

Definition at line 2113 of file fcn.c.

2113  {
2114  rz_return_val_if_fail(fcn, 0);
2115  RzListIter *iter;
2116  RzAnalysisBlock *bb;
2117  int edges = 0;
2118  if (ebbs) {
2119  *ebbs = 0;
2120  }
2121  rz_list_foreach (fcn->bbs, iter, bb) {
2122  if (ebbs && bb->jump == UT64_MAX && bb->fail == UT64_MAX) {
2123  *ebbs = *ebbs + 1;
2124  } else {
2125  if (bb->jump != UT64_MAX) {
2126  edges++;
2127  }
2128  if (bb->fail != UT64_MAX) {
2129  edges++;
2130  }
2131  }
2132  }
2133  return edges;
2134 }

References rz_analysis_function_t::bbs, rz_analysis_bb_t::fail, rz_analysis_bb_t::jump, rz_return_val_if_fail, and UT64_MAX.

Referenced by fcn_print_info(), function_list_print_to_table(), and function_print_to_json().

◆ rz_analysis_function_create_type()

RZ_API RZ_OWN RzCallable* rz_analysis_function_create_type ( RzAnalysis analysis,
RzAnalysisFunction f 
)

Creates the RzCallable type for the given function.

Creates the RzCallable type for the given function by searching in the types database and returning it.

Parameters
analysisRzAnalysis instance
fFunction to update

Definition at line 2596 of file fcn.c.

2596  {
2597  // TODO: Figure out if we should use shortname or a fullname here
2598  RzCallable *callable = rz_type_func_new(analysis->typedb, f->name, NULL);
2599  if (!callable) {
2600  return NULL;
2601  }
2602  return callable;
2603 }
RZ_API RZ_OWN RzCallable * rz_type_func_new(RzTypeDB *typedb, RZ_NONNULL const char *name, RZ_OWN RZ_NULLABLE RzType *type)
Creates a new RzCallable type.
Definition: function.c:131

References f, NULL, rz_type_func_new(), and rz_analysis_t::typedb.

Referenced by rz_analysis_function_derive_type().

◆ rz_analysis_function_derive_args()

RZ_API bool rz_analysis_function_derive_args ( RzAnalysis analysis,
RzAnalysisFunction f,
RzCallable **  callable 
)

Sets the RzCallable args for the given function.

Gets the given function's arguments (names and types) and if it has none it simply returns. Otherwise, it creates RzCallableArgs and adds them to RzCallable.

Parameters
analysisRzAnalysis instance
fFunction to update
callableA function type

Definition at line 2632 of file fcn.c.

2632  {
2633  RzPVector *args = rz_analysis_function_args(analysis, f);
2634  if (!args || rz_pvector_empty(args)) {
2636  return true;
2637  }
2638  void **it;
2639  rz_pvector_foreach (args, it) {
2640  RzAnalysisVar *var = *it;
2641  if (!var) {
2642  // TODO: maybe create a stub void arg here?
2643  continue;
2644  }
2645  RzType *cloned_type = rz_type_clone(var->type);
2646  if (!cloned_type) {
2648  rz_type_callable_free(*callable);
2649  RZ_LOG_ERROR("Cannot parse function's argument type\n");
2650  return false;
2651  }
2652  RzCallableArg *arg = rz_type_callable_arg_new(analysis->typedb, var->name, cloned_type);
2653  if (!arg) {
2655  rz_type_callable_free(*callable);
2656  RZ_LOG_ERROR("Cannot create callable argument\n");
2657  return false;
2658  }
2659  rz_type_callable_arg_add(*callable, arg);
2660  }
2662  return true;
2663 }
RZ_API RZ_OWN RzPVector * rz_analysis_function_args(RzAnalysis *a, RzAnalysisFunction *fcn)
Returns vector of all function arguments.
Definition: fcn.c:2481
RZ_API bool rz_type_callable_arg_add(RZ_NONNULL RzCallable *callable, RZ_OWN RZ_NONNULL RzCallableArg *arg)
Adds a new argument to the RzCallable.
Definition: function.c:116
RZ_API RZ_OWN RzCallableArg * rz_type_callable_arg_new(RzTypeDB *typedb, RZ_NONNULL const char *name, RZ_OWN RZ_NONNULL RzType *type)
Creates a new RzCallableArg given the name and type.
Definition: function.c:69
RZ_API void rz_type_callable_free(RZ_NONNULL RzCallable *callable)
Frees the RzCallable.
Definition: function.c:55
RZ_API RZ_OWN RzType * rz_type_clone(RZ_BORROW RZ_NONNULL const RzType *type)
Creates an exact clone of the RzType.
Definition: type.c:1181

References args, f, rz_analysis_var_t::name, rz_analysis_function_args(), RZ_LOG_ERROR, rz_pvector_empty(), rz_pvector_foreach, rz_pvector_free(), rz_type_callable_arg_add(), rz_type_callable_arg_new(), rz_type_callable_free(), rz_type_clone(), rz_analysis_var_t::type, and rz_analysis_t::typedb.

Referenced by rz_analysis_function_derive_type().

◆ rz_analysis_function_derive_return_type()

RZ_API void rz_analysis_function_derive_return_type ( RzAnalysisFunction f,
RzCallable **  callable 
)

Sets the RzCallable return type for the given function.

Checks if the given function's return type exists and adds it to RzCallable by cloning it.

Parameters
analysisRzAnalysis instance
fFunction to update
callableA function type

Definition at line 2615 of file fcn.c.

2615  {
2616  if (f->ret_type) {
2617  (*callable)->ret = rz_type_clone(f->ret_type);
2618  }
2619 }

References f, and rz_type_clone().

Referenced by rz_analysis_function_derive_type().

◆ rz_analysis_function_derive_type()

RZ_API RZ_OWN RzCallable* rz_analysis_function_derive_type ( RzAnalysis analysis,
RzAnalysisFunction f 
)

Derives the RzCallable type for the given function.

Checks if the type is defined already for this function, if yes - it returns pointer to the one stored in the types database. If not - it creates a new RzCallable instance based on the function name, its arguments' names and types.

Parameters
analysisRzAnalysis instance
fFunction to update

Definition at line 2676 of file fcn.c.

2676  {
2677  RzCallable *callable = rz_analysis_function_clone_type(analysis, f);
2678  if (!callable) {
2679  // If there is no match - create a new one.
2680  callable = rz_analysis_function_create_type(analysis, f);
2681  if (!callable) {
2682  return NULL;
2683  }
2684  // Derive retvar and args from that function
2686  if (!rz_analysis_function_derive_args(analysis, f, &callable)) {
2687  return NULL;
2688  }
2689  }
2690  return callable;
2691 }
RZ_API bool rz_analysis_function_derive_args(RzAnalysis *analysis, RzAnalysisFunction *f, RzCallable **callable)
Sets the RzCallable args for the given function.
Definition: fcn.c:2632
RZ_API RZ_OWN RzCallable * rz_analysis_function_clone_type(RzAnalysis *analysis, const RzAnalysisFunction *f)
Clones the RzCallable type for the given function.
Definition: fcn.c:2568
RZ_API RZ_OWN RzCallable * rz_analysis_function_create_type(RzAnalysis *analysis, RzAnalysisFunction *f)
Creates the RzCallable type for the given function.
Definition: fcn.c:2596
RZ_API void rz_analysis_function_derive_return_type(RzAnalysisFunction *f, RzCallable **callable)
Sets the RzCallable return type for the given function.
Definition: fcn.c:2615

References f, NULL, rz_analysis_function_clone_type(), rz_analysis_function_create_type(), rz_analysis_function_derive_args(), and rz_analysis_function_derive_return_type().

Referenced by function_type_derive(), rz_analysis_function_get_arg_count(), and rz_analysis_function_get_signature().

◆ rz_analysis_function_get_arg_count()

RZ_API int rz_analysis_function_get_arg_count ( RzAnalysis analysis,
RzAnalysisFunction f 
)

Gets the RzCallable's arg count for the given function.

Derives the RzCallable type for the given function, saves it if it exists, and returns its arguments count.

Parameters
analysisRzAnalysis instance
fFunction to update

Definition at line 1845 of file fcn.c.

1845  {
1846  RzCallable *callable = rz_analysis_function_derive_type(analysis, f);
1847  if (!callable) {
1848  return -1;
1849  }
1850  rz_type_func_save(analysis->typedb, callable);
1851  return rz_pvector_len(callable->args);
1852 }
RZ_API RZ_OWN RzCallable * rz_analysis_function_derive_type(RzAnalysis *analysis, RzAnalysisFunction *f)
Derives the RzCallable type for the given function.
Definition: fcn.c:2676
RzPVector * args
optional for the time being
Definition: rz_type.h:149
RZ_API bool rz_type_func_save(RzTypeDB *typedb, RZ_NONNULL RzCallable *callable)
Stores RzCallable type in the types database.
Definition: function.c:147

References rz_callable_at::args, f, rz_analysis_function_derive_type(), rz_pvector_len(), rz_type_func_save(), and rz_analysis_t::typedb.

Referenced by rz_analysis_function_get_json().

◆ rz_analysis_function_get_json()

RZ_API char* rz_analysis_function_get_json ( RzAnalysisFunction function)

Definition at line 1855 of file fcn.c.

1855  {
1856  RzAnalysis *a = function->analysis;
1857  PJ *pj = pj_new();
1858  char *ret_type_str = NULL;
1859  RzType *ret_type = rz_type_func_ret(a->typedb, function->name);
1860  if (ret_type) {
1861  ret_type_str = rz_type_as_string(a->typedb, ret_type);
1862  }
1863  int argc = rz_analysis_function_get_arg_count(a, function);
1864 
1865  pj_o(pj);
1866  pj_ks(pj, "name", function->name);
1867  const bool no_return = rz_analysis_noreturn_at_addr(a, function->addr);
1868  pj_kb(pj, "noreturn", no_return);
1869  pj_ks(pj, "ret", ret_type_str ? ret_type_str : "void");
1870  if (function->cc) {
1871  pj_ks(pj, "cc", function->cc);
1872  }
1873  pj_k(pj, "args");
1874  pj_a(pj);
1875  for (int i = 0; i < argc; i++) {
1876  pj_o(pj);
1877  const char *arg_name = rz_type_func_args_name(a->typedb, function->name, i);
1878  RzType *arg_type = rz_type_func_args_type(a->typedb, function->name, i);
1879  char *arg_type_str = rz_type_as_string(a->typedb, arg_type);
1880  pj_ks(pj, "name", arg_name);
1881  pj_ks(pj, "type", arg_type_str);
1882  const char *cc_arg = rz_reg_get_name(a->reg, rz_reg_get_name_idx(sdb_fmt("A%d", i)));
1883  if (cc_arg) {
1884  pj_ks(pj, "cc", cc_arg);
1885  }
1886  pj_end(pj);
1887  free(arg_type_str);
1888  }
1889  pj_end(pj);
1890  pj_end(pj);
1891  free(ret_type_str);
1892  return pj_drain(pj);
1893 }
RZ_API bool rz_analysis_noreturn_at_addr(RzAnalysis *analysis, ut64 addr)
Definition: analysis.c:557
RZ_API int rz_analysis_function_get_arg_count(RzAnalysis *analysis, RzAnalysisFunction *f)
Gets the RzCallable's arg count for the given function.
Definition: fcn.c:1845
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
RZ_API int rz_reg_get_name_idx(const char *type)
Definition: reg.c:102
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_kb(PJ *j, const char *k, bool v)
Definition: pj.c:177
RZ_API char * pj_drain(PJ *j)
Definition: pj.c:50
RZ_API PJ * pj_k(PJ *j, const char *k)
Definition: pj.c:104
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
Definition: rz_pj.h:12
RZ_API RZ_BORROW const char * rz_type_func_args_name(RzTypeDB *typedb, RZ_NONNULL const char *name, int i)
Searches for the RzCallable type in types database and returns argument name.
Definition: function.c:302
RZ_API RZ_BORROW RzType * rz_type_func_ret(RzTypeDB *typedb, RZ_NONNULL const char *name)
Searches for the RzCallable type in types database and returns return type.
Definition: function.c:215
RZ_API RZ_BORROW RzType * rz_type_func_args_type(RzTypeDB *typedb, RZ_NONNULL const char *name, int i)
Searches for the RzCallable type in types database and returns argument type.
Definition: function.c:278
RZ_API RZ_OWN char * rz_type_as_string(const RzTypeDB *typedb, RZ_NONNULL const RzType *type)
Returns the type C representation.
Definition: type.c:817

References a, free(), i, NULL, pj_a(), pj_drain(), pj_end(), pj_k(), pj_kb(), pj_ks(), pj_new(), pj_o(), rz_analysis_function_get_arg_count(), rz_analysis_noreturn_at_addr(), rz_reg_get_name(), rz_reg_get_name_idx(), rz_type_as_string(), rz_type_func_args_name(), rz_type_func_args_type(), rz_type_func_ret(), and sdb_fmt().

Referenced by rz_analysis_function_signature_handler().

◆ rz_analysis_function_get_signature()

RZ_API RZ_OWN char* rz_analysis_function_get_signature ( RZ_NONNULL RzAnalysisFunction function)

Definition at line 1895 of file fcn.c.

1895  {
1896  rz_return_val_if_fail(function, NULL);
1897  RzAnalysis *a = function->analysis;
1898 
1899  RzCallable *callable = rz_analysis_function_derive_type(a, function);
1900  if (!callable) {
1901  return NULL;
1902  }
1903  char *signature = rz_type_callable_as_string(a->typedb, callable);
1904  rz_type_callable_free(callable);
1905  char *result = rz_str_newf("%s;", signature);
1906  free(signature);
1907  return result;
1908 }
static char * signature(RzBinFile *bf, bool json)
Definition: bin_pe.c:117
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API RZ_OWN char * rz_type_callable_as_string(const RzTypeDB *typedb, RZ_NONNULL const RzCallable *callable)
Returns the callable C representation.
Definition: function.c:487

References a, free(), NULL, rz_analysis_function_derive_type(), rz_return_val_if_fail, rz_str_newf(), rz_type_callable_as_string(), rz_type_callable_free(), and signature().

Referenced by ds_show_functions(), rz_analysis_function_signature_handler(), and rz_core_analysis_function_signature_editor().

◆ rz_analysis_function_loops()

RZ_API int rz_analysis_function_loops ( RzAnalysisFunction fcn)

Definition at line 1784 of file fcn.c.

1784  {
1785  RzListIter *iter;
1786  RzAnalysisBlock *bb;
1787  ut32 loops = 0;
1788  rz_list_foreach (fcn->bbs, iter, bb) {
1789  if (bb->jump != UT64_MAX && bb->jump < bb->addr) {
1790  loops++;
1791  }
1792  if (bb->fail != UT64_MAX && bb->fail < bb->addr) {
1793  loops++;
1794  }
1795  }
1796  return loops;
1797 }

References rz_analysis_bb_t::addr, rz_analysis_function_t::bbs, rz_analysis_bb_t::fail, rz_analysis_bb_t::jump, and UT64_MAX.

Referenced by fcn_print_info(), function_list_print_to_table(), and function_print_to_json().

◆ rz_analysis_function_purity()

RZ_API bool rz_analysis_function_purity ( RzAnalysisFunction fcn)

Definition at line 2136 of file fcn.c.

2136  {
2137  if (fcn->has_changed) {
2138  HtUP *ht = ht_up_new(NULL, NULL, NULL);
2139  if (ht) {
2140  check_purity(ht, fcn);
2141  ht_up_free(ht);
2142  }
2143  }
2144  return fcn->is_pure;
2145 }

References check_purity(), rz_analysis_function_t::has_changed, rz_analysis_function_t::is_pure, and NULL.

Referenced by fcn_print_info(), and function_print_to_json().

◆ rz_analysis_function_resize()

RZ_API int rz_analysis_function_resize ( RzAnalysisFunction fcn,
int  newsize 
)

Definition at line 90 of file fcn.c.

90  {
91  RzAnalysis *analysis = fcn->analysis;
92  RzAnalysisBlock *bb;
93  RzListIter *iter, *iter2;
94 
95  rz_return_val_if_fail(fcn, false);
96 
97  if (newsize < 1) {
98  return false;
99  }
100 
101  // XXX this is something we should probably do for all the archs
102  bool is_arm = analysis->cur->arch && !strncmp(analysis->cur->arch, "arm", 3);
103  if (is_arm) {
104  return true;
105  }
106 
107  ut64 eof = fcn->addr + newsize;
108  rz_list_foreach_safe (fcn->bbs, iter, iter2, bb) {
109  if (bb->addr >= eof) {
111  continue;
112  }
113  if (bb->addr + bb->size >= eof) {
114  rz_analysis_block_set_size(bb, eof - bb->addr);
116  }
117  if (bb->jump != UT64_MAX && bb->jump >= eof) {
118  bb->jump = UT64_MAX;
119  }
120  if (bb->fail != UT64_MAX && bb->fail >= eof) {
121  bb->fail = UT64_MAX;
122  }
123  }
124  return true;
125 }

References rz_analysis_function_t::addr, rz_analysis_bb_t::addr, rz_analysis_function_t::analysis, rz_analysis_plugin_t::arch, rz_analysis_function_t::bbs, rz_analysis_t::cur, rz_analysis_bb_t::fail, is_arm(), rz_analysis_bb_t::jump, rz_analysis_block_set_size(), rz_analysis_block_update_hash(), rz_analysis_function_remove_block(), rz_return_val_if_fail, rz_analysis_bb_t::size, ut64(), and UT64_MAX.

Referenced by module_match_buffer(), rz_core_analysis_fcn(), rz_core_analysis_function_add(), rz_core_analysis_function_until(), and rz_core_visual_define().

◆ rz_analysis_function_set_type()

RZ_API bool rz_analysis_function_set_type ( RzAnalysis a,
RZ_NONNULL RzAnalysisFunction f,
RZ_NONNULL RzCallable callable 
)

Sets the RzCallable type for the given function.

Checks if the type is defined already for this function, if yes - it removes the existing one and sets the one defined by the RzCallable. If there is a mismatch between existing arguments - it overwrites their types and names, removes arguments if necessary.

Parameters
aRzAnalysis instance
fFunction to update
callableA function type

Definition at line 1922 of file fcn.c.

1922  {
1923  rz_return_val_if_fail(a && f && callable, false);
1924  // At first, we check if the arguments match, and rename/retype them
1925  void **it;
1926  size_t index = 0;
1927  if (rz_pvector_empty(callable->args)) {
1929  }
1930  size_t args_count = rz_pvector_len(callable->args);
1931  RzPVector *cloned_vars = (RzPVector *)rz_vector_clone((RzVector *)&f->vars);
1932  rz_pvector_foreach (cloned_vars, it) {
1933  RzAnalysisVar *var = *it;
1934  if (!var->isarg) {
1935  continue;
1936  }
1937  if (index < args_count) {
1938  RzCallableArg *arg = *rz_pvector_index_ptr(callable->args, index);
1939  if (arg) {
1940  free(var->name);
1941  if (arg->name) {
1942  var->name = strdup(arg->name);
1943  }
1944  rz_type_free(var->type);
1945  var->type = rz_type_clone(arg->type);
1946  }
1947  index++;
1948  } else {
1949  // There is no match for this argument in the RzCallable type,
1950  // thus we remove it from the function
1952  }
1953  }
1954  // For f->vars is already empty, add args into it
1955  for (; index < args_count; index++) {
1956  RzCallableArg *arg = *rz_pvector_index_ptr(callable->args, index);
1957  if (arg && arg->type) {
1958  size_t size = rz_type_db_get_bitsize(a->typedb, arg->type);
1959  // For user defined args, we set its delta and kind to its index and stack var by default
1961  }
1962  }
1963 
1964  if (callable->noret) {
1965  f->is_noreturn = true;
1966  } else {
1967  f->ret_type = callable->ret;
1968  }
1969  rz_pvector_free(cloned_vars);
1970  return true;
1971 }
static void ** rz_pvector_index_ptr(RzPVector *vec, size_t index)
Definition: rz_vector.h:251
const char * name
Definition: sparc-opc.c:1838
RZ_API ut64 rz_type_db_get_bitsize(const RzTypeDB *typedb, RZ_NONNULL RzType *type)
Returns the type size in bits (target dependent)
Definition: type.c:779
RZ_API void rz_type_free(RZ_NULLABLE RzType *type)
Frees the RzType.
Definition: type.c:1273
RZ_API void rz_analysis_function_delete_all_vars(RzAnalysisFunction *fcn)
Definition: var.c:220

References a, f, free(), rz_analysis_var_t::isarg, arg::name, rz_analysis_var_t::name, rz_analysis_function_delete_all_vars(), rz_analysis_function_delete_var(), rz_analysis_function_set_var(), RZ_ANALYSIS_VAR_KIND_BPV, rz_pvector_empty(), rz_pvector_foreach, rz_pvector_free(), rz_pvector_index_ptr(), rz_pvector_len(), rz_return_val_if_fail, rz_type_clone(), rz_type_db_get_bitsize(), rz_type_free(), rz_vector_clone(), strdup(), and rz_analysis_var_t::type.

Referenced by rz_analysis_function_set_type_str().

◆ rz_analysis_function_set_type_str()

RZ_API bool rz_analysis_function_set_type_str ( RzAnalysis a,
RZ_NONNULL RzAnalysisFunction f,
RZ_NONNULL const char *  sig 
)

Parses the function type and sets it for the given function.

Checks if the type is defined already for this function, if yes - it removes the existing one and parses the one defined in the signature. The function type should be valid C syntax supplied with name, like int *func(char arg0, const int *arg1, float foo[]);

Parameters
aRzAnalysis instance
fFunction to update
sigA function type ("signature" or "prototype")

Definition at line 1985 of file fcn.c.

1985  {
1986  rz_return_val_if_fail(a && f && sig, false);
1987  char *error_msg = NULL;
1988  // At first we should check if the type is already presented in the types database
1989  // and remove it if exists
1990  if (rz_type_func_exist(a->typedb, f->name)) {
1991  rz_type_func_delete(a->typedb, f->name);
1992  }
1993  // Then we create a new one by parsing the string
1994  RzType *result = rz_type_parse_string_declaration_single(a->typedb->parser, sig, &error_msg);
1995  if (!result) {
1996  if (error_msg) {
1997  RZ_LOG_ERROR("%s", error_msg);
1998  free(error_msg);
1999  }
2000  RZ_LOG_ERROR("Cannot parse callable type\n");
2001  return false;
2002  }
2003  // Parsed result should be RzCallable
2004  if (result->kind != RZ_TYPE_KIND_CALLABLE) {
2005  RZ_LOG_ERROR("Parsed function signature should be RzCallable\n");
2006  return false;
2007  }
2008  if (!result->callable) {
2009  RZ_LOG_ERROR("Parsed function signature should not be NULL\n");
2010  return false;
2011  }
2012  return rz_analysis_function_set_type(a, f, result->callable);
2013 }
RZ_API RZ_OWN RzType * rz_type_parse_string_declaration_single(RzTypeParser *parser, const char *code, char **error_msg)
Parses the single C type declaration.
Definition: c_cpp_parser.c:411
RZ_API bool rz_analysis_function_set_type(RzAnalysis *a, RZ_NONNULL RzAnalysisFunction *f, RZ_NONNULL RzCallable *callable)
Sets the RzCallable type for the given function.
Definition: fcn.c:1922
@ RZ_TYPE_KIND_CALLABLE
Definition: rz_type.h:131
RzTypeKind kind
Definition: rz_type.h:155
RzCallable * callable
Definition: rz_type.h:170
RZ_API bool rz_type_func_exist(RzTypeDB *typedb, RZ_NONNULL const char *name)
Checks if the RzCallable type exists in the database given the name.
Definition: function.c:203
RZ_API bool rz_type_func_delete(RzTypeDB *typedb, RZ_NONNULL const char *name)
Removes RzCallable type from the types database.
Definition: function.c:179

References a, rz_type_t::callable, f, free(), rz_type_t::kind, NULL, rz_analysis_function_set_type(), RZ_LOG_ERROR, rz_return_val_if_fail, rz_type_func_delete(), rz_type_func_exist(), RZ_TYPE_KIND_CALLABLE, and rz_type_parse_string_declaration_single().

Referenced by rz_core_analysis_function_set_signature().

◆ rz_analysis_function_update_analysis()

RZ_API void rz_analysis_function_update_analysis ( RzAnalysisFunction fcn)

Definition at line 2435 of file fcn.c.

2435  {
2436  rz_return_if_fail(fcn);
2437  RzListIter *it, *it2, *tmp, *tmp2;
2438  RzAnalysisBlock *bb;
2440  RzList *fcns = rz_list_new();
2441  HtUP *reachable = ht_up_new(NULL, free_ht_up, NULL);
2442  rz_list_foreach_safe (fcn->bbs, it, tmp, bb) {
2444  rz_list_foreach_safe (bb->fcns, it2, tmp2, f) {
2445  calc_reachable_and_remove_block(fcns, f, bb, reachable);
2446  }
2447  }
2448  }
2449  update_analysis(fcn->analysis, fcns, reachable);
2450  ht_up_free(reachable);
2451  rz_list_free(fcns);
2452 }
RZ_API bool rz_analysis_block_was_modified(RzAnalysisBlock *block)
Definition: block.c:680
static void calc_reachable_and_remove_block(RzList *fcns, RzAnalysisFunction *fcn, RzAnalysisBlock *bb, HtUP *reachable)
Definition: fcn.c:2381
static void free_ht_up(HtUPKv *kv)
Definition: fcn.c:2276
static void update_analysis(RzAnalysis *analysis, RzList *fcns, HtUP *reachable)
Definition: fcn.c:2337
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235

References rz_analysis_function_t::analysis, rz_analysis_function_t::bbs, calc_reachable_and_remove_block(), f, rz_analysis_bb_t::fcns, free_ht_up(), NULL, rz_analysis_block_was_modified(), rz_list_free(), rz_list_new(), rz_return_if_fail, autogen_x86imm::tmp, and update_analysis().

Referenced by check_function_modified().

◆ rz_analysis_get_fcn_in()

RZ_DEPRECATE RZ_API RzAnalysisFunction* rz_analysis_get_fcn_in ( RzAnalysis analysis,
ut64  addr,
int  type 
)

Definition at line 1687 of file fcn.c.

1687  {
1689  RzAnalysisFunction *ret = NULL;
1690  if (list && !rz_list_empty(list)) {
1692  RzAnalysisFunction *fcn;
1693  RzListIter *iter;
1694  rz_list_foreach (list, iter, fcn) {
1695  if (fcn->addr == addr) {
1696  ret = fcn;
1697  break;
1698  }
1699  }
1700  } else {
1701  ret = rz_list_first(list);
1702  }
1703  }
1704  rz_list_free(list);
1705  return ret;
1706 }
RZ_API RzList * rz_analysis_get_functions_in(RzAnalysis *analysis, ut64 addr)
Definition: function.c:20

References addr, rz_analysis_function_t::addr, list(), NULL, RZ_ANALYSIS_FCN_TYPE_ROOT, rz_analysis_get_functions_in(), rz_list_first(), rz_list_free(), and type.

Referenced by __analysis_esil_function(), __check_func(), __check_func_diff(), __core_analysis_fcn(), __refs(), __xrefs(), _CbInRangeAav(), agraph_refresh(), analBars(), analysis_fcn_data(), analysis_graph_to(), analysis_path_exists(), autocmplt_cmd_arg_fcn_var(), backtrace_vars(), backtrace_x86_32_analysis(), backtrace_x86_64_analysis(), check_purity(), cmd_analysis_esil(), cmd_analysis_graph(), cmd_print_bars(), DEFINE_HANDLE_TS_FCN_AND_SYMBOL(), disasm_strings(), do_ref_search(), ds_show_xrefs(), fcnIn(), get_cgnodes(), getpcfromstack(), getref(), handleMidBB(), is_skippable_addr(), meta_variable_comment_append(), meta_variable_comment_editor(), meta_variable_comment_list(), meta_variable_comment_list_all(), meta_variable_comment_remove(), num_callback(), print_meta_list(), propagate_types_among_used_variables(), run_basic_block_analysis(), rz_analysis_aefa(), rz_analysis_bind(), rz_analysis_fcn_del_locs(), rz_analysis_list_vtables(), rz_analysis_noreturn_add(), rz_analysis_noreturn_drop(), rz_analysis_op_to_string(), rz_analysis_trace_bb(), rz_analysis_xrefs_to_graph_cmd_handler(), rz_analysis_xrefs_to_list_handler(), rz_cmd_disassemble_recursively_from_current_block_handler(), rz_cmd_disassemble_recursively_handler(), rz_cmd_disassembly_function_handler(), rz_cmd_disassembly_function_summary_handler(), rz_cmd_print(), rz_comment_function_remove_handler(), rz_core_analysis_address(), rz_core_analysis_coderefs(), rz_core_analysis_datarefs(), rz_core_analysis_fcn(), rz_core_analysis_function_add(), rz_core_analysis_function_set_signature(), rz_core_analysis_function_signature(), rz_core_analysis_function_signature_editor(), rz_core_analysis_function_until(), rz_core_analysis_graph(), rz_core_analysis_hasrefs_to_depth(), rz_core_analysis_resolve_jumps(), rz_core_analysis_undefine(), rz_core_analysis_var_rename(), rz_core_autocomplete(), rz_core_cmd_foreach3(), rz_core_debug_backtraces(), rz_core_get_boundaries_prot(), rz_core_hint_begin(), rz_core_print_disasm_json(), rz_core_search_value_in_range(), rz_core_visual_cmd(), rz_core_visual_define(), rz_core_visual_graph(), rz_core_visual_title(), rz_core_visual_view_graph(), rz_core_visual_xrefs(), rz_debug_thread_list(), rz_flag_local_add_handler(), rz_flag_local_list_handler(), rz_flag_local_remove_handler(), rz_print_areas_no_functions_handler(), rz_seek_function_current_handler(), rz_seek_function_handler(), set_retval(), type_format_print_variable(), var_rename(), var_variables_show(), variable_rename(), and variable_set_type().

◆ rz_analysis_get_fcn_in_bounds()

RZ_DEPRECATE RZ_API RzAnalysisFunction* rz_analysis_get_fcn_in_bounds ( RzAnalysis analysis,
ut64  addr,
int  type 
)

Definition at line 1708 of file fcn.c.

1708  {
1709  RzAnalysisFunction *fcn, *ret = NULL;
1710  RzListIter *iter;
1712  rz_list_foreach (analysis->fcns, iter, fcn) {
1713  if (addr == fcn->addr) {
1714  return fcn;
1715  }
1716  }
1717  return NULL;
1718  }
1719  rz_list_foreach (analysis->fcns, iter, fcn) {
1720  if (!type || (fcn && fcn->type & type)) {
1721  if (rz_analysis_function_contains(fcn, addr)) {
1722  return fcn;
1723  }
1724  }
1725  }
1726  return ret;
1727 }

References addr, rz_analysis_function_t::addr, rz_analysis_t::fcns, NULL, RZ_ANALYSIS_FCN_TYPE_ROOT, rz_analysis_function_contains(), type, and rz_analysis_function_t::type.

Referenced by rz_core_search_value_in_range(), and xrefs_graph().

◆ rz_analysis_get_function_byname()

RZ_API RzAnalysisFunction* rz_analysis_get_function_byname ( RzAnalysis a,
const char *  name 
)

Definition at line 1729 of file fcn.c.

1729  {
1730  bool found = false;
1731  RzAnalysisFunction *f = ht_pp_find(a->ht_name_fun, name, &found);
1732  if (f && found) {
1733  return f;
1734  }
1735  return NULL;
1736 }
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130

References a, f, found, and NULL.

Referenced by function_type_derive(), num_callback(), retype_callee_arg(), rz_core_analysis_function_signature(), and rz_seek_function_handler().

◆ rz_analysis_run_tasks()

RZ_API int rz_analysis_run_tasks ( RZ_NONNULL RzVector tasks)

Runs analysis on the task items.

Runs control-flow and variable usage analysis on each of the task items until tasks vector becomes empty. Items are removed from the tasks vector as they are processed. Items are added to the tasks vector as new basic blocks are found to be analyzed.

Parameters
tasksPointer to RzVector of RzAnalysisTaskItem to be performed analysis on.

Definition at line 1509 of file fcn.c.

1509  {
1511  int ret = RZ_ANALYSIS_RET_ERROR;
1512  while (!rz_vector_empty(tasks)) {
1513  RzAnalysisTaskItem item;
1514  rz_vector_pop(tasks, &item);
1515  int r = run_basic_block_analysis(&item, tasks);
1516  switch (r) {
1518  case RZ_ANALYSIS_RET_COND:
1519  continue;
1520  case RZ_ANALYSIS_RET_NOP:
1521  case RZ_ANALYSIS_RET_ERROR:
1522  if (ret != RZ_ANALYSIS_RET_END) {
1523  ret = r;
1524  }
1525  break;
1526  case RZ_ANALYSIS_RET_END:
1527  default:
1528  ret = r;
1529  break;
1530  }
1531  if (rz_cons_is_breaked()) {
1532  break;
1533  }
1534  }
1535  return ret;
1536 }
#define r
Definition: crypto_rc6.c:12
static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, RzVector *tasks)
Analyses the given task item item for branches.
Definition: fcn.c:559
RZ_API void rz_vector_pop(RzVector *vec, void *into)
Definition: vector.c:184

References r, run_basic_block_analysis(), RZ_ANALYSIS_RET_BRANCH, RZ_ANALYSIS_RET_COND, RZ_ANALYSIS_RET_END, RZ_ANALYSIS_RET_ERROR, RZ_ANALYSIS_RET_NOP, rz_cons_is_breaked(), rz_return_val_if_fail, rz_vector_empty(), and rz_vector_pop().

Referenced by analyze_function_locally(), and rz_analysis_fcn().

◆ rz_analysis_task_item_new()

RZ_API bool rz_analysis_task_item_new ( RZ_NONNULL RzAnalysis analysis,
RZ_NONNULL RzVector tasks,
RZ_NONNULL RzAnalysisFunction fcn,
RZ_NULLABLE RzAnalysisBlock block,
ut64  address 
)

Adds a new task item to the tasks parameter.

Used to create a new item to the tasks parameter that can be worked on later by the rz_analysis_run_tasks function.

Parameters
analysisPointer to RzAnalysis instance.
tasksPointer to RzVector to add a new RzAnalysisTaskItem to.
fcnPointer to RzAnalysisFunction in which analysis will be performed on.
blockPointer to RzAnalysisBlock in which analysis will be performed on. If null, analysis will take care of block creation.
addressAddress where analysis will start from

Definition at line 1488 of file fcn.c.

1488  {
1489  rz_return_val_if_fail(analysis && tasks && fcn, false);
1490  RzAnalysisTaskItem item = { fcn, block, fcn->stack, address };
1491  RzAnalysisTaskItem *it;
1492  rz_vector_foreach(tasks, it) {
1493  if (item.start_address == it->start_address) {
1494  return true;
1495  }
1496  }
1497  return rz_vector_push(tasks, &item);
1498 }
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169

References rz_return_val_if_fail, rz_vector_foreach, rz_vector_push(), rz_analysis_task_item::stack, and rz_analysis_task_item::start_address.

Referenced by run_basic_block_analysis(), rz_analysis_fcn(), rz_analysis_walkthrough_arm_jmptbl_style(), rz_analysis_walkthrough_casetbl(), and rz_analysis_walkthrough_jmptbl().

◆ rz_analysis_trim_jmprefs()

RZ_API void rz_analysis_trim_jmprefs ( RzAnalysis analysis,
RzAnalysisFunction fcn 
)

Definition at line 1578 of file fcn.c.

1578  {
1579  RzAnalysisXRef *xref;
1581  RzListIter *iter;
1582  const bool is_x86 = analysis->cur->arch && !strcmp(analysis->cur->arch, "x86"); // HACK
1583 
1584  rz_list_foreach (xrefs, iter, xref) {
1585  if (xref->type == RZ_ANALYSIS_XREF_TYPE_CODE && rz_analysis_function_contains(fcn, xref->to) && (!is_x86 || !rz_analysis_function_contains(fcn, xref->from))) {
1586  rz_analysis_xrefs_deln(analysis, xref->from, xref->to, xref->type);
1587  }
1588  }
1589  rz_list_free(xrefs);
1590 }

References rz_analysis_plugin_t::arch, rz_analysis_t::cur, rz_analysis_ref_t::from, rz_analysis_function_contains(), rz_analysis_function_get_xrefs_from(), RZ_ANALYSIS_XREF_TYPE_CODE, rz_analysis_xrefs_deln(), rz_list_free(), rz_analysis_ref_t::to, and rz_analysis_ref_t::type.

Referenced by module_match_buffer().

◆ rz_analysis_types_from_fcn()

RZ_API RZ_OWN RzList* rz_analysis_types_from_fcn ( RzAnalysis analysis,
RzAnalysisFunction fcn 
)

Definition at line 2545 of file fcn.c.

2545  {
2546  RzListIter *iter;
2547  RzAnalysisVar *var;
2548  RzList *list = rz_analysis_var_all_list(analysis, fcn);
2549  RzList *type_used = rz_list_new();
2550  rz_list_foreach (list, iter, var) {
2551  rz_list_append(type_used, var->type);
2552  }
2553  RzList *uniq = rz_list_uniq(type_used, typecmp);
2554  rz_list_free(type_used);
2555  rz_list_free(list);
2556  return uniq;
2557 }
static int typecmp(const void *a, const void *b)
Definition: fcn.c:2539
RZ_API RZ_OWN RzList * rz_list_uniq(RZ_NONNULL const RzList *list, RZ_NONNULL RzListComparator cmp)
Returns a new RzList which contains only unique values.
Definition: list.c:756

References list(), rz_analysis_var_all_list(), rz_list_append(), rz_list_free(), rz_list_new(), rz_list_uniq(), rz_analysis_var_t::type, and typecmp().

Referenced by types_xrefs(), types_xrefs_all(), types_xrefs_function(), types_xrefs_graph(), and types_xrefs_summary().

◆ rz_analysis_update_analysis_range()

RZ_API void rz_analysis_update_analysis_range ( RzAnalysis analysis,
ut64  addr,
int  size 
)

Definition at line 2396 of file fcn.c.

2396  {
2397  rz_return_if_fail(analysis);
2398  RzListIter *it, *it2, *tmp;
2399  RzAnalysisBlock *bb;
2400  RzAnalysisFunction *fcn;
2402  if (rz_list_empty(blocks)) {
2404  return;
2405  }
2406  RzList *fcns = rz_list_new();
2407  HtUP *reachable = ht_up_new(NULL, free_ht_up, NULL);
2408  const int align = rz_analysis_archinfo(analysis, RZ_ANALYSIS_ARCHINFO_ALIGN);
2409  const ut64 end_write = addr + size;
2410 
2411  rz_list_foreach (blocks, it, bb) {
2412  if (!rz_analysis_block_was_modified(bb)) {
2413  continue;
2414  }
2415  rz_list_foreach_safe (bb->fcns, it2, tmp, fcn) {
2416  if (align > 1) {
2417  if ((end_write < rz_analysis_block_get_op_addr(bb, bb->ninstr - 1)) && (!bb->switch_op || end_write < bb->switch_op->addr)) {
2418  // Special case when instructions are aligned and we don't
2419  // need to worry about a write messing with the jump instructions
2420  clear_bb_vars(fcn, bb, addr > bb->addr ? addr : bb->addr, end_write);
2421  update_varz_analysisysis(fcn, align, addr > bb->addr ? addr : bb->addr, end_write);
2423  continue;
2424  }
2425  }
2426  calc_reachable_and_remove_block(fcns, fcn, bb, reachable);
2427  }
2428  }
2429  rz_list_free(blocks); // This will call rz_analysis_block_unref to actually remove blocks from RzAnalysis
2430  update_analysis(analysis, fcns, reachable);
2431  ht_up_free(reachable);
2432  rz_list_free(fcns);
2433 }
RZ_API int rz_analysis_archinfo(RzAnalysis *analysis, int query)
Definition: analysis.c:449
RZ_API RzList * rz_analysis_get_blocks_intersect(RzAnalysis *analysis, ut64 addr, ut64 size)
Definition: block.c:165
static void update_varz_analysisysis(RzAnalysisFunction *fcn, int align, ut64 from, ut64 to)
Definition: fcn.c:2280
#define RZ_ANALYSIS_ARCHINFO_ALIGN
Definition: rz_analysis.h:100
uint64_t blocks
Definition: list.c:104
RZ_API void rz_analysis_function_delete_unused_vars(RzAnalysisFunction *fcn)
Definition: var.c:229

References addr, rz_analysis_switch_obj_t::addr, rz_analysis_bb_t::addr, blocks, calc_reachable_and_remove_block(), clear_bb_vars(), rz_analysis_bb_t::fcns, free_ht_up(), rz_analysis_bb_t::ninstr, NULL, rz_analysis_archinfo(), RZ_ANALYSIS_ARCHINFO_ALIGN, rz_analysis_block_get_op_addr(), rz_analysis_block_was_modified(), rz_analysis_function_delete_unused_vars(), rz_analysis_get_blocks_intersect(), rz_list_free(), rz_list_new(), rz_return_if_fail, rz_analysis_bb_t::switch_op, autogen_x86imm::tmp, update_analysis(), update_varz_analysisysis(), and ut64().

Referenced by ev_iowrite_cb().

◆ set_bb_branches()

static void set_bb_branches ( RZ_OUT RzAnalysisBlock bb,
const ut64  jump,
const ut64  fail 
)
inlinestatic

Definition at line 542 of file fcn.c.

542  {
543  bb->jump = jump;
544  bb->fail = fail;
545 }

References fail, and jump().

Referenced by run_basic_block_analysis().

◆ skip_hp()

static int skip_hp ( RzAnalysis analysis,
RzAnalysisFunction fcn,
RzAnalysisOp op,
RzAnalysisBlock bb,
ut64  addr,
char *  tmp_buf,
int  oplen,
int  un_idx,
int idx 
)
static

Definition at line 288 of file fcn.c.

289  {
290  // this step is required in order to prevent infinite recursion in some cases
291  if ((addr + un_idx - oplen) == fcn->addr) {
292  // use addr instead of op->addr to mark repeat
293  if (!analysis->flb.exist_at(analysis->flb.f, "skip", 4, addr)) {
294  snprintf(tmp_buf + 5, MAX_FLG_NAME_SIZE - 6, "%" PFMT64u, addr);
295  analysis->flb.set(analysis->flb.f, tmp_buf, addr, oplen);
296  fcn->addr += oplen;
297  rz_analysis_block_relocate(bb, bb->addr + oplen, bb->size - oplen);
298  *idx = un_idx;
299  return 1;
300  }
301  return 2;
302  }
303  return 0;
304 }
snprintf
Definition: kernel.h:364
RzFlagExistAt exist_at
Definition: rz_flag.h:79
RzFlagSet set
Definition: rz_flag.h:84

References addr, rz_analysis_function_t::addr, rz_analysis_bb_t::addr, rz_flag_bind_t::exist_at, rz_flag_bind_t::f, rz_analysis_t::flb, setup::idx, MAX_FLG_NAME_SIZE, PFMT64u, rz_analysis_block_relocate(), rz_flag_bind_t::set, rz_analysis_bb_t::size, and snprintf.

Referenced by run_basic_block_analysis().

◆ try_get_cmpval_from_parents()

static ut64 try_get_cmpval_from_parents ( RzAnalysis analysis,
RzAnalysisFunction fcn,
RzAnalysisBlock my_bb,
const char *  cmp_reg 
)
static

Definition at line 263 of file fcn.c.

263  {
264  rz_return_val_if_fail(fcn && fcn->bbs && cmp_reg, UT64_MAX);
265  RzListIter *iter;
266  RzAnalysisBlock *tmp_bb;
267  rz_list_foreach (fcn->bbs, iter, tmp_bb) {
268  if (tmp_bb->jump == my_bb->addr || tmp_bb->fail == my_bb->addr) {
269  if (tmp_bb->cmpreg == cmp_reg) {
270  if (tmp_bb->cond) {
271  if (tmp_bb->cond->type == RZ_TYPE_COND_HI || tmp_bb->cond->type == RZ_TYPE_COND_GT) {
272  return tmp_bb->cmpval + 1;
273  }
274  }
275  return tmp_bb->cmpval;
276  }
277  }
278  }
279  return UT64_MAX;
280 }
@ RZ_TYPE_COND_HI
Unsigned higher Greater than, or unordered.
Definition: rz_type.h:197
@ RZ_TYPE_COND_GT
Greater than.
Definition: rz_type.h:187

References rz_analysis_bb_t::addr, rz_analysis_function_t::bbs, rz_analysis_bb_t::cmpreg, rz_analysis_bb_t::cmpval, rz_analysis_bb_t::cond, rz_analysis_bb_t::fail, rz_analysis_bb_t::jump, rz_return_val_if_fail, RZ_TYPE_COND_GT, RZ_TYPE_COND_HI, rz_analysis_cond_t::type, and UT64_MAX.

Referenced by run_basic_block_analysis().

◆ typecmp()

static int typecmp ( const void *  a,
const void *  b 
)
static

Definition at line 2539 of file fcn.c.

2539  {
2540  const RzType *t1 = a;
2541  const RzType *t2 = b;
2542  return !rz_types_equal(t1, t2);
2543 }
RZ_API bool rz_types_equal(RZ_NONNULL const RzType *type1, RZ_NONNULL const RzType *type2)
Checks if two types are identical.
Definition: type.c:1218

References a, b, rz_types_equal(), and benchmark::t1.

Referenced by rz_analysis_types_from_fcn().

◆ update_analysis()

static void update_analysis ( RzAnalysis analysis,
RzList fcns,
HtUP *  reachable 
)
static

Definition at line 2337 of file fcn.c.

2337  {
2338  RzListIter *it, *it2, *tmp;
2339  RzAnalysisFunction *fcn;
2340  bool old_jmpmid = analysis->opt.jmpmid;
2341  analysis->opt.jmpmid = true;
2343  rz_list_foreach (fcns, it, fcn) {
2344  // Recurse through blocks of function, mark reachable,
2345  // analyze edges that don't have a block
2346  RzAnalysisBlock *bb = rz_analysis_get_block_at(analysis, fcn->addr);
2347  if (!bb) {
2348  analyze_function_locally(analysis, fcn, fcn->addr);
2349  bb = rz_analysis_get_block_at(analysis, fcn->addr);
2350  if (!bb) {
2351  continue;
2352  }
2353  }
2354  HtUP *ht = ht_up_new0();
2355  ht_up_insert(ht, bb->addr, NULL);
2356  BlockRecurseCtx ctx = { fcn, ht };
2358 
2359  // Remove non-reachable blocks
2360  rz_list_foreach_safe (fcn->bbs, it2, tmp, bb) {
2361  if (ht_up_find_kv(ht, bb->addr, NULL)) {
2362  continue;
2363  }
2364  HtUP *o_visited = ht_up_find(reachable, fcn->addr, NULL);
2365  if (!ht_up_find_kv(o_visited, bb->addr, NULL)) {
2366  // Avoid removing blocks that were already not reachable
2367  continue;
2368  }
2369  fcn->ninstr -= bb->ninstr;
2371  }
2372 
2373  RzList *bbs = rz_list_clone(fcn->bbs);
2376  rz_list_free(bbs);
2377  }
2378  analysis->opt.jmpmid = old_jmpmid;
2379 }
RZ_API void rz_analysis_block_automerge(RzList *blocks)
Definition: block.c:892
RZ_API void rz_analysis_fcn_invalidate_read_ahead_cache(void)
Definition: fcn.c:84
static bool analize_descendents(RzAnalysisBlock *bb, void *user)
Definition: fcn.c:2272
RZ_API RZ_OWN RzList * rz_list_clone(RZ_NONNULL const RzList *list)
Shallow copies of the list (but doesn't free its elements)
Definition: list.c:496

References rz_analysis_function_t::addr, rz_analysis_bb_t::addr, analize_descendents(), analyze_function_locally(), rz_analysis_function_t::bbs, rz_analysis_options_t::jmpmid, rz_analysis_function_t::ninstr, rz_analysis_bb_t::ninstr, NULL, rz_analysis_t::opt, rz_analysis_block_automerge(), rz_analysis_block_recurse(), rz_analysis_fcn_invalidate_read_ahead_cache(), rz_analysis_function_delete_unused_vars(), rz_analysis_function_remove_block(), rz_analysis_get_block_at(), rz_list_clone(), rz_list_free(), and autogen_x86imm::tmp.

Referenced by rz_analysis_function_update_analysis(), and rz_analysis_update_analysis_range().

◆ update_varz_analysisysis()

static void update_varz_analysisysis ( RzAnalysisFunction fcn,
int  align,
ut64  from,
ut64  to 
)
static

Definition at line 2280 of file fcn.c.

2280  {
2281  RzAnalysis *analysis = fcn->analysis;
2282  ut64 cur_addr;
2283  int opsz;
2284  from = align ? from - (from % align) : from;
2285  to = align ? RZ_ROUND(to, align) : to;
2286  if (UT64_SUB_OVFCHK(to, from)) {
2287  return;
2288  }
2289  ut64 len = to - from;
2290  ut8 *buf = malloc(len);
2291  if (!buf) {
2292  return;
2293  }
2294  if (analysis->iob.read_at(analysis->iob.io, from, buf, len) < len) {
2295  return;
2296  }
2297  for (cur_addr = from; cur_addr < to; cur_addr += opsz, len -= opsz) {
2298  RzAnalysisOp op;
2299  int ret = rz_analysis_op(analysis->coreb.core, &op, cur_addr, buf, len, RZ_ANALYSIS_OP_MASK_ESIL | RZ_ANALYSIS_OP_MASK_VAL);
2300  if (ret < 1 || op.size < 1) {
2302  break;
2303  }
2304  opsz = op.size;
2305  rz_analysis_extract_vars(analysis, fcn, &op);
2307  }
2308  free(buf);
2309 }
#define RZ_ROUND(x, y)

References rz_analysis_function_t::analysis, rz_core_bind_t::core, rz_analysis_t::coreb, free(), from, rz_io_bind_t::io, rz_analysis_t::iob, len, malloc(), op, rz_io_bind_t::read_at, rz_analysis_extract_vars(), rz_analysis_op(), rz_analysis_op_fini(), RZ_ANALYSIS_OP_MASK_ESIL, RZ_ANALYSIS_OP_MASK_VAL, RZ_ROUND, to, ut64(), and UT64_SUB_OVFCHK.

Referenced by rz_analysis_update_analysis_range().

Variable Documentation

◆ cache_addr

ut64 cache_addr = UT64_MAX
static

Definition at line 49 of file fcn.c.

Referenced by read_ahead(), and rz_analysis_fcn_invalidate_read_ahead_cache().