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

Go to the source code of this file.

Macros

#define ACCESS_CMP(x, y)   ((st64)((ut64)(x) - (ut64)((RzAnalysisVarAccess *)y)->offset))
 
#define STR_EQUAL(s1, s2)   (s1 && s2 && !strcmp(s1, s2))
 

Functions

static const char * __int_type_from_size (int size)
 
static RZ_OWN RzTypevar_type_clone_or_default_type (RzAnalysis *analysis, RZ_BORROW RZ_NULLABLE const RzType *type, int size)
 
RZ_API bool rz_analysis_function_rebase_vars (RzAnalysis *a, RzAnalysisFunction *fcn)
 
static bool var_same_kind (RzAnalysisVar *a, RzAnalysisVar *b)
 
static bool var_overlap (RzAnalysisVar *a, RzAnalysisVar *b, ut64 a_size)
 
RZ_API void rz_analysis_var_resolve_overlaps (RzAnalysisVar *var)
 
RZ_API RZ_BORROW RzAnalysisVarrz_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)
 
RZ_API void rz_analysis_var_set_type (RzAnalysisVar *var, RZ_OWN RzType *type, bool resolve_overlaps)
 
static void var_free (RzAnalysisVar *var)
 
RZ_API void rz_analysis_var_delete (RzAnalysisVar *var)
 
RZ_API void rz_analysis_function_delete_vars_by_kind (RzAnalysisFunction *fcn, RzAnalysisVarKind kind)
 
RZ_API void rz_analysis_function_delete_all_vars (RzAnalysisFunction *fcn)
 
RZ_API void rz_analysis_function_delete_unused_vars (RzAnalysisFunction *fcn)
 
RZ_API void rz_analysis_function_delete_var (RzAnalysisFunction *fcn, RzAnalysisVar *var)
 
RZ_API RZ_BORROW RzAnalysisVarrz_analysis_function_get_var_byname (RzAnalysisFunction *fcn, const char *name)
 
RZ_API RZ_BORROW RzAnalysisVarrz_analysis_function_get_var (RzAnalysisFunction *fcn, char kind, int delta)
 
RZ_API ut64 rz_analysis_var_addr (RzAnalysisVar *var)
 
RZ_API st64 rz_analysis_function_get_var_stackptr_at (RzAnalysisFunction *fcn, st64 delta, ut64 addr)
 
RZ_API const char * rz_analysis_function_get_var_reg_at (RzAnalysisFunction *fcn, st64 delta, ut64 addr)
 
RZ_API bool rz_analysis_var_check_name (const char *name)
 
RZ_API bool rz_analysis_var_rename (RzAnalysisVar *var, const char *new_name, bool verbose)
 
RZ_API int rz_analysis_var_get_argnum (RzAnalysisVar *var)
 
RZ_API RZ_BORROW RzPVectorrz_analysis_function_get_vars_used_at (RzAnalysisFunction *fcn, ut64 op_addr)
 
RZ_DEPRECATE RZ_API RzAnalysisVarrz_analysis_get_used_function_var (RzAnalysis *analysis, ut64 addr)
 
RZ_API RzAnalysisVarrz_analysis_var_get_dst_var (RzAnalysisVar *var)
 
RZ_API void rz_analysis_var_set_access (RzAnalysisVar *var, const char *reg, ut64 access_addr, int access_type, st64 stackptr)
 
RZ_API void rz_analysis_var_remove_access_at (RzAnalysisVar *var, ut64 address)
 
RZ_API void rz_analysis_var_clear_accesses (RzAnalysisVar *var)
 
RZ_API RzAnalysisVarAccessrz_analysis_var_get_access_at (RzAnalysisVar *var, ut64 addr)
 
RZ_API void rz_analysis_var_add_constraint (RzAnalysisVar *var, RZ_BORROW RzTypeConstraint *constraint)
 
RZ_API char * rz_analysis_var_get_constraints_readable (RzAnalysisVar *var)
 
RZ_API int rz_analysis_var_count (RzAnalysis *a, RzAnalysisFunction *fcn, int kind, int type)
 
static bool var_add_structure_fields_to_list (RzAnalysis *a, RzAnalysisVar *av, RzList *list)
 
static const char * get_regname (RzAnalysis *analysis, RzAnalysisValue *value)
 
RZ_API RZ_OWN char * rz_analysis_function_autoname_var (RzAnalysisFunction *fcn, char kind, const char *pfx, int ptr)
 
static RzAnalysisVarget_stack_var (RzAnalysisFunction *fcn, int delta)
 
static void extract_arg (RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op, const char *reg, const char *sign, char type)
 
static bool is_reg_in_src (const char *regname, RzAnalysis *analysis, RzAnalysisOp *op)
 
static bool op_affect_dst (RzAnalysisOp *op)
 
static bool arch_destroys_dst (const char *arch)
 
static bool is_used_like_arg (const char *regname, const char *opsreg, const char *opdreg, RzAnalysisOp *op, RzAnalysis *analysis)
 
RZ_API void rz_analysis_extract_rarg (RzAnalysis *analysis, RzAnalysisOp *op, RzAnalysisFunction *fcn, int *reg_set, int *count)
 
RZ_API void rz_analysis_extract_vars (RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op)
 
static RzListvar_generate_list (RzAnalysis *a, RzAnalysisFunction *fcn, int kind)
 
RZ_DEPRECATE RZ_API RzListrz_analysis_var_all_list (RzAnalysis *analysis, RzAnalysisFunction *fcn)
 
RZ_API RzListrz_analysis_var_list (RzAnalysis *a, RzAnalysisFunction *fcn, int kind)
 
static void var_field_free (RzAnalysisVarField *field)
 
RZ_DEPRECATE RZ_API RzListrz_analysis_function_get_var_fields (RzAnalysisFunction *fcn, int kind)
 
static int var_comparator (const RzAnalysisVar *a, const RzAnalysisVar *b)
 
static int regvar_comparator (const RzAnalysisVar *a, const RzAnalysisVar *b)
 
RZ_API void rz_analysis_fcn_vars_cache_init (RzAnalysis *analysis, RzAnalysisFcnVarsCache *cache, RzAnalysisFunction *fcn)
 
RZ_API void rz_analysis_fcn_vars_cache_fini (RzAnalysisFcnVarsCache *cache)
 
RZ_API char * rz_analysis_fcn_format_sig (RZ_NONNULL RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn, RZ_NULLABLE char *fcn_name, RZ_NULLABLE RzAnalysisFcnVarsCache *reuse_cache, RZ_NULLABLE const char *fcn_name_pre, RZ_NULLABLE const char *fcn_name_post)
 
RZ_API void rz_analysis_fcn_vars_add_types (RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn)
 Updates the types database for function arguments. More...
 

Macro Definition Documentation

◆ ACCESS_CMP

#define ACCESS_CMP (   x,
 
)    ((st64)((ut64)(x) - (ut64)((RzAnalysisVarAccess *)y)->offset))

Definition at line 11 of file var.c.

◆ STR_EQUAL

#define STR_EQUAL (   s1,
  s2 
)    (s1 && s2 && !strcmp(s1, s2))

Definition at line 855 of file var.c.

Function Documentation

◆ __int_type_from_size()

static const char* __int_type_from_size ( int  size)
static

Definition at line 13 of file var.c.

13  {
14  switch (size) {
15  case 1: return "int8_t";
16  case 2: return "int16_t";
17  case 4: return "int32_t";
18  case 8: return "int64_t";
19  default: return NULL;
20  }
21 }
#define NULL
Definition: cris-opc.c:27
voidpf void uLong size
Definition: ioapi.h:138

References NULL.

Referenced by var_type_clone_or_default_type().

◆ arch_destroys_dst()

static bool arch_destroys_dst ( const char *  arch)
inlinestatic

Definition at line 857 of file var.c.

857  {
858  return (STR_EQUAL(arch, "arm") || STR_EQUAL(arch, "riscv") || STR_EQUAL(arch, "ppc"));
859 }
cs_arch arch
Definition: cstool.c:13
#define STR_EQUAL(s1, s2)
Definition: var.c:855

References arch, and STR_EQUAL.

Referenced by is_used_like_arg(), and run_basic_block_analysis().

◆ extract_arg()

static void extract_arg ( RzAnalysis analysis,
RzAnalysisFunction fcn,
RzAnalysisOp op,
const char *  reg,
const char *  sign,
char  type 
)
static

Definition at line 669 of file var.c.

669  {
670  st64 ptr = 0;
671  char *addr, *esil_buf = NULL;
672 
673  rz_return_if_fail(analysis && fcn && op && reg);
674 
675  size_t i;
676  for (i = 0; i < RZ_ARRAY_SIZE(op->src); i++) {
677  if (op->src[i] && op->src[i]->reg && op->src[i]->reg->name) {
678  if (!strcmp(reg, op->src[i]->reg->name)) {
679  st64 delta = op->src[i]->delta;
680  if ((delta > 0 && *sign == '+') || (delta < 0 && *sign == '-')) {
681  ptr = RZ_ABS(op->src[i]->delta);
682  break;
683  }
684  }
685  }
686  }
687 
688  if (!ptr) {
689  const char *op_esil = rz_strbuf_get(&op->esil);
690  if (!op_esil) {
691  return;
692  }
693  esil_buf = strdup(op_esil);
694  if (!esil_buf) {
695  return;
696  }
697  char *ptr_end = strstr(esil_buf, sdb_fmt(",%s,%s,", reg, sign));
698  if (!ptr_end) {
699  free(esil_buf);
700  return;
701  }
702  *ptr_end = 0;
703  addr = ptr_end;
704  while ((addr[0] != '0' || addr[1] != 'x') && addr >= esil_buf + 1 && *addr != ',') {
705  addr--;
706  }
707  if (strncmp(addr, "0x", 2)) {
708  // XXX: This is a workaround for inconsistent esil
709  if (!op->stackop && op->dst) {
710  const char *sp = rz_reg_get_name(analysis->reg, RZ_REG_NAME_SP);
711  const char *bp = rz_reg_get_name(analysis->reg, RZ_REG_NAME_BP);
712  const char *rn = op->dst->reg ? op->dst->reg->name : NULL;
713  if (rn && ((bp && !strcmp(bp, rn)) || (sp && !strcmp(sp, rn)))) {
714  RZ_LOG_DEBUG("Analysis didn't fill op->stackop for instruction that alters stack at 0x%" PFMT64x ".\n", op->addr);
715  goto beach;
716  }
717  }
718  if (*addr == ',') {
719  addr++;
720  }
721  if (!op->stackop && op->type != RZ_ANALYSIS_OP_TYPE_PUSH && op->type != RZ_ANALYSIS_OP_TYPE_POP && op->type != RZ_ANALYSIS_OP_TYPE_RET && rz_str_isnumber(addr)) {
722  ptr = (st64)rz_num_get(NULL, addr);
723  if (ptr && op->src[0] && ptr == op->src[0]->imm) {
724  goto beach;
725  }
726  } else if ((op->stackop == RZ_ANALYSIS_STACK_SET) || (op->stackop == RZ_ANALYSIS_STACK_GET)) {
727  if (op->ptr % 4) {
728  goto beach;
729  }
730  ptr = RZ_ABS(op->ptr);
731  } else {
732  goto beach;
733  }
734  } else {
735  ptr = (st64)rz_num_get(NULL, addr);
736  }
737  }
738 
739  if (!op->src[0] || !op->dst) {
740  RZ_LOG_DEBUG("Analysis didn't fill op->src/dst at 0x%" PFMT64x ".\n", op->addr);
741  }
742 
744  if (*sign == '+') {
745  const bool isarg = type == RZ_ANALYSIS_VAR_KIND_SPV ? ptr >= fcn->stack : ptr >= fcn->bp_off;
746  const char *pfx = isarg ? ARGPREFIX : VARPREFIX;
747  st64 frame_off;
749  frame_off = ptr - fcn->stack;
750  } else {
751  frame_off = ptr - fcn->bp_off;
752  }
753  RzAnalysisVar *var = get_stack_var(fcn, frame_off);
754  if (var) {
755  rz_analysis_var_set_access(var, reg, op->addr, rw, ptr);
756  goto beach;
757  }
758  char *varname = NULL;
759  RzType *vartype = NULL;
760  if (isarg) {
761  const char *place = fcn->cc ? rz_analysis_cc_arg(analysis, fcn->cc, ST32_MAX) : NULL;
762  bool stack_rev = place ? !strcmp(place, "stack_rev") : false;
763  char *fname = rz_analysis_function_name_guess(analysis->typedb, fcn->name);
764  if (fname) {
765  ut64 sum_sz = 0;
766  size_t from, to, i;
767  if (stack_rev) {
768  const size_t cnt = rz_type_func_args_count(analysis->typedb, fname);
769  from = cnt ? cnt - 1 : cnt;
770  to = fcn->cc ? rz_analysis_cc_max_arg(analysis, fcn->cc) : 0;
771  } else {
772  from = fcn->cc ? rz_analysis_cc_max_arg(analysis, fcn->cc) : 0;
773  to = rz_type_func_args_count(analysis->typedb, fname);
774  }
775  const int bytes = (fcn->bits ? fcn->bits : analysis->bits) / 8;
776  for (i = from; stack_rev ? i >= to : i < to; stack_rev ? i-- : i++) {
777  RzType *tp = rz_type_func_args_type(analysis->typedb, fname, i);
778  if (!tp) {
779  break;
780  }
781  if (sum_sz == frame_off) {
782  vartype = tp;
783  varname = strdup(rz_type_func_args_name(analysis->typedb, fname, i));
784  break;
785  }
786  ut64 bit_sz = rz_type_db_get_bitsize(analysis->typedb, tp);
787  sum_sz += bit_sz ? bit_sz / 8 : bytes;
788  sum_sz = RZ_ROUND(sum_sz, bytes);
789  }
790  free(fname);
791  }
792  }
793  if (!varname) {
794  if (analysis->opt.varname_stack) {
795  varname = rz_str_newf("%s_%" PFMT64x "h", pfx, RZ_ABS(frame_off));
796  } else {
797  varname = rz_analysis_function_autoname_var(fcn, type, pfx, ptr);
798  }
799  }
800  if (varname) {
801  RzAnalysisVar *var = rz_analysis_function_set_var(fcn, frame_off, type, vartype, analysis->bits / 8, isarg, varname);
802  if (var) {
803  rz_analysis_var_set_access(var, reg, op->addr, rw, ptr);
804  }
805  free(varname);
806  }
807  } else {
808  st64 frame_off = -(ptr + fcn->bp_off);
809  RzAnalysisVar *var = get_stack_var(fcn, frame_off);
810  if (var) {
811  rz_analysis_var_set_access(var, reg, op->addr, rw, -ptr);
812  goto beach;
813  }
814  char *varname = analysis->opt.varname_stack
815  ? rz_str_newf("%s_%" PFMT64x "h", VARPREFIX, RZ_ABS(frame_off))
817  if (varname) {
818  RzAnalysisVar *var = rz_analysis_function_set_var(fcn, frame_off, type, NULL, analysis->bits / 8, false, varname);
819  if (var) {
820  rz_analysis_var_set_access(var, reg, op->addr, rw, -ptr);
821  }
822  free(varname);
823  }
824  }
825 beach:
826  free(esil_buf);
827 }
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
lzma_index ** i
Definition: index.h:629
static ut8 bytes[32]
Definition: asm_arc.c:23
RZ_API const char * rz_analysis_cc_arg(RzAnalysis *analysis, const char *convention, int n)
Definition: cc.c:122
RZ_API int rz_analysis_cc_max_arg(RzAnalysis *analysis, const char *cc)
Definition: cc.c:171
#define false
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
#define reg(n)
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
int type
Definition: mipsasm.c:17
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
#define VARPREFIX
Definition: rz_analysis.h:708
#define ARGPREFIX
Definition: rz_analysis.h:709
@ RZ_ANALYSIS_STACK_SET
Definition: rz_analysis.h:459
@ RZ_ANALYSIS_STACK_GET
Definition: rz_analysis.h:458
@ RZ_ANALYSIS_OP_DIR_WRITE
Definition: rz_analysis.h:791
@ RZ_ANALYSIS_VAR_ACCESS_TYPE_READ
Definition: rz_analysis.h:713
@ RZ_ANALYSIS_VAR_ACCESS_TYPE_WRITE
Definition: rz_analysis.h:714
@ RZ_ANALYSIS_VAR_KIND_SPV
Definition: rz_analysis.h:705
@ RZ_ANALYSIS_OP_TYPE_PUSH
Definition: rz_analysis.h:397
@ RZ_ANALYSIS_OP_TYPE_POP
Definition: rz_analysis.h:398
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
@ RZ_REG_NAME_SP
Definition: rz_reg.h:44
@ RZ_REG_NAME_BP
Definition: rz_reg.h:46
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API bool rz_str_isnumber(const char *str)
Definition: str.c:3550
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define PFMT64x
Definition: rz_types.h:393
#define RZ_ROUND(x, y)
#define st64
Definition: rz_types_base.h:10
#define ST32_MAX
Definition: rz_types_base.h:97
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
RzAnalysisOptions opt
Definition: rz_analysis.h:608
RzTypeDB * typedb
Definition: rz_analysis.h:602
RZ_API int rz_type_func_args_count(RzTypeDB *typedb, RZ_NONNULL const char *name)
Searches for the RzCallable type in types database and returns arguments' count.
Definition: function.c:262
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_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 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
Definition: dis.c:32
RZ_API RZ_OWN char * rz_analysis_function_autoname_var(RzAnalysisFunction *fcn, char kind, const char *pfx, int ptr)
Definition: var.c:633
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
static RzAnalysisVar * get_stack_var(RzAnalysisFunction *fcn, int delta)
Definition: var.c:657
static st64 delta
Definition: vmenus.c:2425
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int sp
Definition: z80asm.c:91
static int addr
Definition: z80asm.c:58

References addr, ARGPREFIX, rz_analysis_function_t::bits, rz_analysis_t::bits, rz_analysis_function_t::bp_off, bytes, rz_analysis_function_t::cc, delta, create_tags_rz::fname, free(), from, get_stack_var(), i, rz_analysis_function_t::name, NULL, rz_analysis_t::opt, PFMT64x, reg, rz_analysis_t::reg, RZ_ABS, rz_analysis_cc_arg(), rz_analysis_cc_max_arg(), rz_analysis_function_autoname_var(), rz_analysis_function_name_guess(), rz_analysis_function_set_var(), RZ_ANALYSIS_OP_DIR_WRITE, RZ_ANALYSIS_OP_TYPE_POP, RZ_ANALYSIS_OP_TYPE_PUSH, RZ_ANALYSIS_OP_TYPE_RET, RZ_ANALYSIS_STACK_GET, RZ_ANALYSIS_STACK_SET, RZ_ANALYSIS_VAR_ACCESS_TYPE_READ, RZ_ANALYSIS_VAR_ACCESS_TYPE_WRITE, RZ_ANALYSIS_VAR_KIND_SPV, rz_analysis_var_set_access(), RZ_ARRAY_SIZE, RZ_LOG_DEBUG, rz_num_get(), rz_reg_get_name(), RZ_REG_NAME_BP, RZ_REG_NAME_SP, rz_return_if_fail, RZ_ROUND, rz_str_isnumber(), rz_str_newf(), rz_strbuf_get(), rz_type_db_get_bitsize(), rz_type_func_args_count(), rz_type_func_args_name(), rz_type_func_args_type(), sdb_fmt(), sp, ST32_MAX, st64, rz_analysis_function_t::stack, strdup(), to, type, rz_analysis_t::typedb, ut64(), rz_analysis_options_t::varname_stack, and VARPREFIX.

Referenced by rz_analysis_extract_vars().

◆ get_regname()

static const char* get_regname ( RzAnalysis analysis,
RzAnalysisValue value 
)
static

Definition at line 621 of file var.c.

621  {
622  const char *name = NULL;
623  if (value && value->reg && value->reg->name) {
624  name = value->reg->name;
625  RzRegItem *ri = rz_reg_get(analysis->reg, value->reg->name, -1);
626  if (ri && (ri->size == 32) && (analysis->bits == 64)) {
627  name = rz_reg_32_to_64(analysis->reg, value->reg->name);
628  }
629  }
630  return name;
631 }
static int value
Definition: cmd_api.c:93
const char * name
Definition: op.c:541
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API const char * rz_reg_32_to_64(RzReg *reg, const char *rreg32)
Definition: reg.c:17
Definition: z80asm.h:102
int size
in bits> 8,16,32,64 ... 128/256
Definition: rz_reg.h:120

References rz_analysis_t::bits, name, NULL, rz_analysis_t::reg, rz_reg_32_to_64(), rz_reg_get(), rz_reg_item_t::size, and value.

Referenced by is_reg_in_src(), and rz_analysis_extract_rarg().

◆ get_stack_var()

static RzAnalysisVar* get_stack_var ( RzAnalysisFunction fcn,
int  delta 
)
static

Definition at line 657 of file var.c.

657  {
658  void **it;
659  rz_pvector_foreach (&fcn->vars, it) {
660  RzAnalysisVar *var = *it;
661  bool is_stack = var->kind == RZ_ANALYSIS_VAR_KIND_SPV || var->kind == RZ_ANALYSIS_VAR_KIND_BPV;
662  if (is_stack && var->delta == delta) {
663  return var;
664  }
665  }
666  return NULL;
667 }
@ RZ_ANALYSIS_VAR_KIND_BPV
Definition: rz_analysis.h:704
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
RzAnalysisVarKind kind
Definition: rz_analysis.h:728

References delta, rz_analysis_var_t::delta, rz_analysis_var_t::kind, NULL, RZ_ANALYSIS_VAR_KIND_BPV, RZ_ANALYSIS_VAR_KIND_SPV, rz_pvector_foreach, and rz_analysis_function_t::vars.

Referenced by extract_arg().

◆ is_reg_in_src()

static bool is_reg_in_src ( const char *  regname,
RzAnalysis analysis,
RzAnalysisOp op 
)
static

Definition at line 902 of file var.c.

902  {
903  const char *opsreg0 = op->src[0] ? get_regname(analysis, op->src[0]) : NULL;
904  const char *opsreg1 = op->src[1] ? get_regname(analysis, op->src[1]) : NULL;
905  const char *opsreg2 = op->src[2] ? get_regname(analysis, op->src[2]) : NULL;
906  return (STR_EQUAL(regname, opsreg0)) || (STR_EQUAL(regname, opsreg1)) || (STR_EQUAL(regname, opsreg2));
907 }
static const char * get_regname(RzAnalysis *analysis, RzAnalysisValue *value)
Definition: var.c:621
static char * regname(int reg)
Definition: dis.c:71

References get_regname(), NULL, regname(), and STR_EQUAL.

Referenced by is_used_like_arg(), and rz_analysis_extract_rarg().

◆ is_used_like_arg()

static bool is_used_like_arg ( const char *  regname,
const char *  opsreg,
const char *  opdreg,
RzAnalysisOp op,
RzAnalysis analysis 
)
static

Definition at line 861 of file var.c.

861  {
862  RzAnalysisValue *dst = op->dst;
863  RzAnalysisValue *src = op->src[0];
864  switch (op->type) {
866  return false;
868  return (is_reg_in_src(regname, analysis, op)) || (STR_EQUAL(opdreg, regname) && dst->memref);
870  if (STR_EQUAL(opdreg, regname)) {
871  return false;
872  }
873  if (is_reg_in_src(regname, analysis, op)) {
874  return true;
875  }
876  return false;
879  if (is_reg_in_src(regname, analysis, op)) {
880  return true;
881  }
882  if (STR_EQUAL(opdreg, regname)) {
883  return false;
884  }
885  return false;
887  if (STR_EQUAL(opsreg, opdreg) && !src->memref && !dst->memref) {
888  return false;
889  }
890  // fallthrough
891  default:
892  if (op_affect_dst(op) && arch_destroys_dst(analysis->cur->arch)) {
893  if (is_reg_in_src(regname, analysis, op)) {
894  return true;
895  }
896  return false;
897  }
898  return ((STR_EQUAL(opdreg, regname)) || (is_reg_in_src(regname, analysis, op)));
899  }
900 }
lzma_index * src
Definition: index.h:567
char * dst
Definition: lz4.h:724
@ RZ_ANALYSIS_OP_TYPE_LOAD
Definition: rz_analysis.h:416
@ RZ_ANALYSIS_OP_TYPE_CMOV
Definition: rz_analysis.h:391
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_LEA
Definition: rz_analysis.h:417
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
struct rz_analysis_plugin_t * cur
Definition: rz_analysis.h:586
static bool arch_destroys_dst(const char *arch)
Definition: var.c:857
static bool is_reg_in_src(const char *regname, RzAnalysis *analysis, RzAnalysisOp *op)
Definition: var.c:902
static bool op_affect_dst(RzAnalysisOp *op)
Definition: var.c:831

References rz_analysis_plugin_t::arch, arch_destroys_dst(), rz_analysis_t::cur, dst, is_reg_in_src(), op_affect_dst(), regname(), RZ_ANALYSIS_OP_TYPE_CMOV, RZ_ANALYSIS_OP_TYPE_LEA, RZ_ANALYSIS_OP_TYPE_LOAD, RZ_ANALYSIS_OP_TYPE_MOV, RZ_ANALYSIS_OP_TYPE_POP, RZ_ANALYSIS_OP_TYPE_XOR, src, and STR_EQUAL.

Referenced by rz_analysis_extract_rarg().

◆ op_affect_dst()

static bool op_affect_dst ( RzAnalysisOp op)
inlinestatic

Definition at line 831 of file var.c.

831  {
832  switch (op->type) {
849  return true;
850  default:
851  return false;
852  }
853 }
@ RZ_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_MUL
Definition: rz_analysis.h:404
@ 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_NOR
Definition: rz_analysis.h:413
@ RZ_ANALYSIS_OP_TYPE_ROR
Definition: rz_analysis.h:419
@ RZ_ANALYSIS_OP_TYPE_SAR
Definition: rz_analysis.h:409
@ 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_DIV
Definition: rz_analysis.h:405
@ RZ_ANALYSIS_OP_TYPE_CAST
Definition: rz_analysis.h:426
@ RZ_ANALYSIS_OP_TYPE_SHL
Definition: rz_analysis.h:407
@ RZ_ANALYSIS_OP_TYPE_NOT
Definition: rz_analysis.h:414

References RZ_ANALYSIS_OP_TYPE_ADD, RZ_ANALYSIS_OP_TYPE_AND, RZ_ANALYSIS_OP_TYPE_CAST, RZ_ANALYSIS_OP_TYPE_DIV, RZ_ANALYSIS_OP_TYPE_MUL, RZ_ANALYSIS_OP_TYPE_NOR, RZ_ANALYSIS_OP_TYPE_NOT, RZ_ANALYSIS_OP_TYPE_OR, 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, and RZ_ANALYSIS_OP_TYPE_XOR.

Referenced by is_used_like_arg().

◆ regvar_comparator()

static int regvar_comparator ( const RzAnalysisVar a,
const RzAnalysisVar b 
)
static

Definition at line 1204 of file var.c.

1204  {
1205  // avoid NULL dereference
1206  return (a && b) ? (a->argnum > b->argnum) - (a->argnum < b->argnum) : 0;
1207 }
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41

References a, and b.

Referenced by rz_analysis_fcn_vars_cache_init().

◆ rz_analysis_extract_rarg()

RZ_API void rz_analysis_extract_rarg ( RzAnalysis analysis,
RzAnalysisOp op,
RzAnalysisFunction fcn,
int reg_set,
int count 
)

Definition at line 909 of file var.c.

909  {
910  int i, argc = 0;
911  rz_return_if_fail(analysis && op && fcn);
912  const char *opsreg = op->src[0] ? get_regname(analysis, op->src[0]) : NULL;
913  const char *opdreg = op->dst ? get_regname(analysis, op->dst) : NULL;
914  const int size = (fcn->bits ? fcn->bits : analysis->bits) / 8;
915  if (!fcn->cc) {
916  RZ_LOG_DEBUG("No calling convention for function '%s' to extract register arguments\n", fcn->name);
917  return;
918  }
919  char *fname = rz_analysis_function_name_guess(analysis->typedb, fcn->name);
920  int max_count = rz_analysis_cc_max_arg(analysis, fcn->cc);
921  if (!max_count || (*count >= max_count)) {
922  free(fname);
923  return;
924  }
925  if (fname) {
926  argc = rz_type_func_args_count(analysis->typedb, fname);
927  }
928 
929  bool is_call = (op->type & 0xf) == RZ_ANALYSIS_OP_TYPE_CALL || (op->type & 0xf) == RZ_ANALYSIS_OP_TYPE_UCALL;
930  if (is_call && *count < max_count) {
931  RzList *callee_rargs_l = NULL;
932  int callee_rargs = 0;
933  char *callee = NULL;
934  ut64 offset = op->jump == UT64_MAX ? op->ptr : op->jump;
936  if (!f) {
937  RzCore *core = (RzCore *)analysis->coreb.core;
939  if (flag) {
940  callee = rz_analysis_function_name_guess(analysis->typedb, flag->name);
941  if (callee) {
942  const char *cc = rz_analysis_cc_func(analysis, callee);
943  if (cc && !strcmp(fcn->cc, cc)) {
944  callee_rargs = RZ_MIN(max_count, rz_type_func_args_count(analysis->typedb, callee));
945  }
946  }
947  }
948  } else if (!f->is_variadic && !strcmp(fcn->cc, f->cc)) {
949  callee = rz_analysis_function_name_guess(analysis->typedb, f->name);
950  if (callee) {
951  callee_rargs = RZ_MIN(max_count, rz_type_func_args_count(analysis->typedb, callee));
952  }
953  callee_rargs = callee_rargs
954  ? callee_rargs
956  callee_rargs_l = rz_analysis_var_list(analysis, f, RZ_ANALYSIS_VAR_KIND_REG);
957  }
958  size_t i;
959  for (i = 0; i < callee_rargs; i++) {
960  if (reg_set[i]) {
961  continue;
962  }
963  const char *vname = NULL;
964  RzType *type = NULL;
965  char *name = NULL;
966  int delta = 0;
967  const char *regname = rz_analysis_cc_arg(analysis, fcn->cc, i);
968  RzRegItem *ri = rz_reg_get(analysis->reg, regname, -1);
969  if (ri) {
970  delta = ri->index;
971  }
972  if (fname) {
973  type = rz_type_func_args_type(analysis->typedb, fname, i);
974  vname = rz_type_func_args_name(analysis->typedb, fname, i);
975  }
976  if (!vname && callee) {
977  type = rz_type_func_args_type(analysis->typedb, callee, i);
978  vname = rz_type_func_args_name(analysis->typedb, callee, i);
979  }
980  if (vname) {
981  reg_set[i] = 1;
982  } else {
983  RzListIter *it;
984  RzAnalysisVar *arg, *found_arg = NULL;
985  rz_list_foreach (callee_rargs_l, it, arg) {
986  if (rz_analysis_var_get_argnum(arg) == i) {
987  found_arg = arg;
988  break;
989  }
990  }
991  if (found_arg) {
992  type = found_arg->type;
993  vname = name = strdup(found_arg->name);
994  }
995  }
996  if (!vname) {
997  name = rz_str_newf("arg%zu", i + 1);
998  vname = name;
999  }
1001  (*count)++;
1002  free(name);
1003  }
1004  free(callee);
1005  rz_list_free(callee_rargs_l);
1006  free(fname);
1007  return;
1008  }
1009 
1010  for (i = 0; i < max_count; i++) {
1011  const char *regname = rz_analysis_cc_arg(analysis, fcn->cc, i);
1012  if (regname) {
1013  int delta = 0;
1014  RzRegItem *ri = NULL;
1015  RzAnalysisVar *var = NULL;
1016  bool is_used_like_an_arg = is_used_like_arg(regname, opsreg, opdreg, op, analysis);
1017  if (reg_set[i] != 2 && is_used_like_an_arg) {
1018  ri = rz_reg_get(analysis->reg, regname, -1);
1019  if (ri) {
1020  delta = ri->index;
1021  }
1022  }
1023  if (reg_set[i] == 1 && is_used_like_an_arg) {
1025  } else if (reg_set[i] != 2 && is_used_like_an_arg) {
1026  const char *vname = NULL;
1027  RzType *type = NULL;
1028  char *name = NULL;
1029  if ((i < argc) && fname) {
1030  type = rz_type_func_args_type(analysis->typedb, fname, i);
1031  vname = rz_type_func_args_name(analysis->typedb, fname, i);
1032  }
1033  if (!vname) {
1034  name = rz_str_newf("arg%d", i + 1);
1035  vname = name;
1036  }
1038  free(name);
1039  (*count)++;
1040  } else {
1041  if (is_reg_in_src(regname, analysis, op) || STR_EQUAL(opdreg, regname)) {
1042  reg_set[i] = 2;
1043  }
1044  continue;
1045  }
1046  if (is_reg_in_src(regname, analysis, op) || STR_EQUAL(regname, opdreg)) {
1047  reg_set[i] = 1;
1048  }
1049  if (var) {
1051  rz_meta_set_string(analysis, RZ_META_TYPE_VARTYPE, op->addr, var->name);
1052  }
1053  }
1054  }
1055 
1056  const char *selfreg = rz_analysis_cc_self(analysis, fcn->cc);
1057  if (selfreg) {
1058  bool is_used_like_an_arg = is_used_like_arg(selfreg, opsreg, opdreg, op, analysis);
1059  if (reg_set[i] != 2 && is_used_like_an_arg) {
1060  int delta = 0;
1061  char *vname = strdup("self");
1062  RzRegItem *ri = rz_reg_get(analysis->reg, selfreg, -1);
1063  if (ri) {
1064  delta = ri->index;
1065  }
1067  if (newvar) {
1069  }
1070  rz_meta_set_string(analysis, RZ_META_TYPE_VARTYPE, op->addr, vname);
1071  free(vname);
1072  (*count)++;
1073  } else {
1074  if (is_reg_in_src(selfreg, analysis, op) || STR_EQUAL(opdreg, selfreg)) {
1075  reg_set[i] = 2;
1076  }
1077  }
1078  i++;
1079  }
1080 
1081  const char *errorreg = rz_analysis_cc_error(analysis, fcn->cc);
1082  if (errorreg) {
1083  if (reg_set[i] == 0 && STR_EQUAL(opdreg, errorreg)) {
1084  int delta = 0;
1085  char *vname = strdup("error");
1086  RzRegItem *ri = rz_reg_get(analysis->reg, errorreg, -1);
1087  if (ri) {
1088  delta = ri->index;
1089  }
1091  if (newvar) {
1093  }
1094  rz_meta_set_string(analysis, RZ_META_TYPE_VARTYPE, op->addr, vname);
1095  free(vname);
1096  (*count)++;
1097  reg_set[i] = 2;
1098  }
1099  }
1100  free(fname);
1101 }
RZ_API RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
RZ_API const char * rz_analysis_cc_func(RzAnalysis *analysis, const char *func_name)
Definition: cc.c:220
RZ_API const char * rz_analysis_cc_self(RzAnalysis *analysis, const char *convention)
Definition: cc.c:138
RZ_API const char * rz_analysis_cc_error(RzAnalysis *analysis, const char *convention)
Definition: cc.c:155
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
RZ_API RzFlagItem * rz_flag_get_by_spaces(RzFlag *f, ut64 off,...)
Definition: flag.c:326
voidpf uLong offset
Definition: ioapi.h:144
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static size_t max_count
Definition: malloc.c:67
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
@ RZ_META_TYPE_VARTYPE
Definition: rz_analysis.h:297
@ RZ_ANALYSIS_VAR_KIND_REG
Definition: rz_analysis.h:703
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
#define RZ_FLAGS_FS_IMPORTS
Definition: rz_core.h:59
#define RZ_MIN(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
#define f(i)
Definition: sha256.c:46
RzCoreBind coreb
Definition: rz_analysis.h:580
void * core
Definition: rz_bind.h:31
RzFlag * flags
Definition: rz_core.h:330
int index
Index in register profile.
Definition: rz_reg.h:126
RZ_API RZ_BORROW RzAnalysisVar * rz_analysis_function_get_var(RzAnalysisFunction *fcn, char kind, int delta)
Definition: var.c:259
RZ_API int rz_analysis_var_count(RzAnalysis *a, RzAnalysisFunction *fcn, int kind, int type)
Definition: var.c:574
RZ_API RzList * rz_analysis_var_list(RzAnalysis *a, RzAnalysisFunction *fcn, int kind)
Definition: var.c:1154
static bool is_used_like_arg(const char *regname, const char *opsreg, const char *opdreg, RzAnalysisOp *op, RzAnalysis *analysis)
Definition: var.c:861
RZ_API int rz_analysis_var_get_argnum(RzAnalysisVar *var)
Definition: var.c:369

References arg(), rz_analysis_function_t::bits, rz_analysis_t::bits, rz_analysis_function_t::cc, rz_core_bind_t::core, rz_analysis_t::coreb, count, delta, f, rz_core_t::flags, create_tags_rz::fname, free(), get_regname(), i, rz_reg_item_t::index, is_reg_in_src(), is_used_like_arg(), max_count, name, rz_analysis_function_t::name, rz_analysis_var_t::name, NULL, rz_analysis_t::reg, regname(), rz_analysis_var_t::regname, rz_analysis_cc_arg(), rz_analysis_cc_error(), rz_analysis_cc_func(), rz_analysis_cc_max_arg(), rz_analysis_cc_self(), rz_analysis_function_get_var(), rz_analysis_function_name_guess(), rz_analysis_function_set_var(), rz_analysis_get_function_at(), RZ_ANALYSIS_OP_TYPE_CALL, RZ_ANALYSIS_OP_TYPE_UCALL, RZ_ANALYSIS_VAR_ACCESS_TYPE_READ, rz_analysis_var_count(), rz_analysis_var_get_argnum(), RZ_ANALYSIS_VAR_KIND_REG, rz_analysis_var_list(), rz_analysis_var_set_access(), rz_flag_get_by_spaces(), RZ_FLAGS_FS_IMPORTS, rz_list_free(), RZ_LOG_DEBUG, rz_meta_set_string(), RZ_META_TYPE_VARTYPE, RZ_MIN, rz_reg_get(), rz_return_if_fail, rz_str_newf(), rz_type_func_args_count(), rz_type_func_args_name(), rz_type_func_args_type(), STR_EQUAL, strdup(), type, rz_analysis_var_t::type, rz_analysis_t::typedb, ut64(), and UT64_MAX.

Referenced by analysis_block_cb().

◆ rz_analysis_extract_vars()

RZ_API void rz_analysis_extract_vars ( RzAnalysis analysis,
RzAnalysisFunction fcn,
RzAnalysisOp op 
)

Definition at line 1103 of file var.c.

1103  {
1104  rz_return_if_fail(analysis && fcn && op);
1105 
1106  const char *BP = rz_reg_get_name(analysis->reg, RZ_REG_NAME_BP);
1107  const char *SP = rz_reg_get_name(analysis->reg, RZ_REG_NAME_SP);
1108  if (BP) {
1109  extract_arg(analysis, fcn, op, BP, "+", RZ_ANALYSIS_VAR_KIND_BPV);
1110  extract_arg(analysis, fcn, op, BP, "-", RZ_ANALYSIS_VAR_KIND_BPV);
1111  }
1112  if (SP) {
1113  extract_arg(analysis, fcn, op, SP, "+", RZ_ANALYSIS_VAR_KIND_SPV);
1114  }
1115 }
#define SP(t, s, c)
Definition: engine.c:123
static void extract_arg(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op, const char *reg, const char *sign, char type)
Definition: var.c:669

References extract_arg(), rz_analysis_t::reg, RZ_ANALYSIS_VAR_KIND_BPV, RZ_ANALYSIS_VAR_KIND_SPV, rz_reg_get_name(), RZ_REG_NAME_BP, RZ_REG_NAME_SP, rz_return_if_fail, and SP.

Referenced by analysis_block_cb(), run_basic_block_analysis(), and update_varz_analysisysis().

◆ rz_analysis_fcn_format_sig()

RZ_API char* rz_analysis_fcn_format_sig ( RZ_NONNULL RzAnalysis analysis,
RZ_NONNULL RzAnalysisFunction fcn,
RZ_NULLABLE char *  fcn_name,
RZ_NULLABLE RzAnalysisFcnVarsCache *  reuse_cache,
RZ_NULLABLE const char *  fcn_name_pre,
RZ_NULLABLE const char *  fcn_name_post 
)

Definition at line 1232 of file var.c.

1233  {
1234  RzAnalysisFcnVarsCache *cache = NULL;
1235 
1236  if (!fcn_name) {
1237  fcn_name = fcn->name;
1238  if (!fcn_name) {
1239  return NULL;
1240  }
1241  }
1242 
1244  if (!buf) {
1245  return NULL;
1246  }
1247 
1248  char *type_fcn_name = rz_analysis_function_name_guess(analysis->typedb, fcn_name);
1249  if (type_fcn_name && rz_type_func_exist(analysis->typedb, type_fcn_name)) {
1250  RzType *fcn_type = rz_type_func_ret(analysis->typedb, type_fcn_name);
1251  if (fcn_type) {
1252  char *fcn_type_str = rz_type_as_string(analysis->typedb, fcn_type);
1253  if (fcn_type_str) {
1254  const char *sp = fcn_type->kind == RZ_TYPE_KIND_POINTER ? "" : " ";
1255  rz_strbuf_appendf(buf, "%s%s", fcn_type_str, sp);
1256  free(fcn_type_str);
1257  }
1258  }
1259  }
1260 
1261  if (fcn_name_pre) {
1262  rz_strbuf_append(buf, fcn_name_pre);
1263  }
1264  rz_strbuf_append(buf, fcn_name);
1265  if (fcn_name_post) {
1266  rz_strbuf_append(buf, fcn_name_post);
1267  }
1268  rz_strbuf_append(buf, " (");
1269 
1270  if (type_fcn_name && rz_type_func_exist(analysis->typedb, type_fcn_name)) {
1271  int i, argc = rz_type_func_args_count(analysis->typedb, type_fcn_name);
1272  bool comma = true;
1273  // This avoids false positives present in argument recovery
1274  // and straight away print arguments fetched from types db
1275  for (i = 0; i < argc; i++) {
1276  RzType *type = rz_type_func_args_type(analysis->typedb, type_fcn_name, i);
1277  const char *name = rz_type_func_args_name(analysis->typedb, type_fcn_name, i);
1278  if (!type || !name) {
1279  RZ_LOG_ERROR("Missing type for %s\n", type_fcn_name);
1280  goto beach;
1281  }
1282  char *type_str = rz_type_as_string(analysis->typedb, type);
1283  if (i == argc - 1) {
1284  comma = false;
1285  }
1286  const char *sp = type->kind == RZ_TYPE_KIND_POINTER ? "" : " ";
1287  rz_strbuf_appendf(buf, "%s%s%s%s", type_str, sp, name, comma ? ", " : "");
1288  free(type_str);
1289  }
1290  goto beach;
1291  }
1292  RZ_FREE(type_fcn_name);
1293 
1294  cache = reuse_cache;
1295  if (!cache) {
1296  cache = RZ_NEW0(RzAnalysisFcnVarsCache);
1297  if (!cache) {
1298  type_fcn_name = NULL;
1299  goto beach;
1300  }
1301  rz_analysis_fcn_vars_cache_init(analysis, cache, fcn);
1302  }
1303 
1304  bool comma = true;
1305  bool arg_bp = false;
1306  size_t tmp_len;
1307  RzAnalysisVar *var;
1308  RzListIter *iter;
1309 
1310  rz_list_foreach (cache->rvars, iter, var) {
1311  // assume self, error are always the last
1312  if (!strcmp(var->name, "self") || !strcmp(var->name, "error")) {
1314  break;
1315  }
1316  char *vartype = rz_type_as_string(analysis->typedb, var->type);
1317  tmp_len = strlen(vartype);
1318  rz_strbuf_appendf(buf, "%s%s%s%s", vartype,
1319  tmp_len && vartype[tmp_len - 1] == '*' ? "" : " ",
1320  var->name, iter->n ? ", " : "");
1321  free(vartype);
1322  }
1323 
1324  rz_list_foreach (cache->bvars, iter, var) {
1325  if (var->isarg) {
1326  if (!rz_list_empty(cache->rvars) && comma) {
1327  rz_strbuf_append(buf, ", ");
1328  comma = false;
1329  }
1330  arg_bp = true;
1331  char *vartype = rz_type_as_string(analysis->typedb, var->type);
1332  tmp_len = strlen(vartype);
1333  rz_strbuf_appendf(buf, "%s%s%s%s", vartype,
1334  tmp_len && vartype[tmp_len - 1] == '*' ? "" : " ",
1335  var->name, iter->n ? ", " : "");
1336  free(vartype);
1337  }
1338  }
1339 
1340  comma = true;
1341  const char *maybe_comma = ", ";
1342  rz_list_foreach (cache->svars, iter, var) {
1343  if (var->isarg) {
1344  if (!*maybe_comma || ((arg_bp || !rz_list_empty(cache->rvars)) && comma)) {
1345  comma = false;
1346  rz_strbuf_append(buf, ", ");
1347  }
1348  char *vartype = rz_type_as_string(analysis->typedb, var->type);
1349  tmp_len = strlen(vartype);
1350  if (iter->n && ((RzAnalysisVar *)iter->n->data)->isarg) {
1351  maybe_comma = ", ";
1352  } else {
1353  maybe_comma = "";
1354  }
1355  rz_strbuf_appendf(buf, "%s%s%s%s", vartype,
1356  tmp_len && vartype[tmp_len - 1] == '*' ? "" : " ",
1357  var->name, maybe_comma);
1358  free(vartype);
1359  }
1360  }
1361 
1362 beach:
1363  rz_strbuf_append(buf, ");");
1364  RZ_FREE(type_fcn_name);
1365  if (!reuse_cache) {
1366  // !reuse_cache => we created our own cache
1368  free(cache);
1369  }
1370  return rz_strbuf_drain(buf);
1371 }
voidpf void * buf
Definition: ioapi.h:138
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API bool rz_strbuf_slice(RZ_NONNULL RzStrBuf *sb, size_t from, size_t len)
Cuts the current string into a substring.
Definition: strbuf.c:122
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
@ RZ_TYPE_KIND_POINTER
Definition: rz_type.h:129
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
RzTypeKind kind
Definition: rz_type.h:155
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 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 RZ_OWN char * rz_type_as_string(const RzTypeDB *typedb, RZ_NONNULL const RzType *type)
Returns the type C representation.
Definition: type.c:817
RZ_API void rz_analysis_fcn_vars_cache_fini(RzAnalysisFcnVarsCache *cache)
Definition: var.c:1223
RZ_API void rz_analysis_fcn_vars_cache_init(RzAnalysis *analysis, RzAnalysisFcnVarsCache *cache, RzAnalysisFunction *fcn)
Definition: var.c:1209
static int comma
Definition: z80asm.c:76

References comma, free(), i, rz_analysis_var_t::isarg, rz_type_t::kind, rz_analysis_var_t::name, NULL, rz_analysis_fcn_vars_cache_fini(), rz_analysis_fcn_vars_cache_init(), rz_analysis_function_name_guess(), RZ_FREE, RZ_LOG_ERROR, RZ_NEW0, rz_strbuf_append(), rz_strbuf_appendf(), rz_strbuf_drain(), rz_strbuf_length(), rz_strbuf_new(), rz_strbuf_slice(), rz_type_as_string(), rz_type_func_args_count(), rz_type_func_args_name(), rz_type_func_args_type(), rz_type_func_exist(), rz_type_func_ret(), RZ_TYPE_KIND_POINTER, sp, type, and rz_analysis_var_t::type.

Referenced by ds_show_functions(), and rz_core_analysis_function_signature().

◆ rz_analysis_fcn_vars_add_types()

RZ_API void rz_analysis_fcn_vars_add_types ( RzAnalysis analysis,
RZ_NONNULL RzAnalysisFunction fcn 
)

Updates the types database for function arguments.

Searches if the types database has the function with the same name. if there is a match - updates the RzCallable type of the function by adding the new function arguments' types.

Parameters
analysisRzAnalysis instance
fcnFunction which arguments we should save into the types database

Definition at line 1383 of file var.c.

1383  {
1384  rz_return_if_fail(analysis && fcn && fcn->name);
1385 
1386  // Do not syncronize types if the function already exist in the types database
1387  if (rz_type_func_exist(analysis->typedb, fcn->name)) {
1388  return;
1389  }
1390 
1391  // Avoid saving the autonamed functions into the types database
1392  if (rz_analysis_function_is_autonamed(fcn->name)) {
1393  return;
1394  }
1395 
1396  RzAnalysisFcnVarsCache cache;
1397  rz_analysis_fcn_vars_cache_init(analysis, &cache, fcn);
1398  RzListIter *iter;
1399  RzAnalysisVar *var;
1400 
1401  RzList *all_vars = cache.rvars;
1402  rz_list_join(all_vars, cache.bvars);
1403  rz_list_join(all_vars, cache.svars);
1404 
1405  // TODO: Save also the return type
1406  RzCallable *callable = rz_type_func_new(analysis->typedb, fcn->name, NULL);
1407 
1408  rz_list_foreach (all_vars, iter, var) {
1409  if (var->isarg) {
1410  // Since we create a new argument type we should clone it here
1411  RzType *cloned = rz_type_clone(var->type);
1412  RzCallableArg *arg = rz_type_callable_arg_new(analysis->typedb, var->name, cloned);
1413  if (arg) {
1414  rz_type_callable_arg_add(callable, arg);
1415  } else {
1416  rz_type_free(cloned);
1417  }
1418  }
1419  }
1420  rz_type_func_save(analysis->typedb, callable);
1422 }
RZ_API bool rz_analysis_function_is_autonamed(RZ_NONNULL char *name)
Checks if the function name was generated by Rizin automatically.
Definition: function.c:443
RZ_API bool rz_list_join(RZ_NONNULL RzList *list1, RZ_NONNULL RzList *list2)
Joins 2 list into one (list2 pointer needs to be freed by the user)
Definition: list.c:209
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 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
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 bool rz_type_func_save(RzTypeDB *typedb, RZ_NONNULL RzCallable *callable)
Stores RzCallable type in the types database.
Definition: function.c:147
RZ_API void rz_type_free(RZ_NULLABLE RzType *type)
Frees the RzType.
Definition: type.c:1273
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 rz_analysis_var_t::isarg, rz_analysis_var_t::name, NULL, rz_analysis_fcn_vars_cache_fini(), rz_analysis_fcn_vars_cache_init(), rz_analysis_function_is_autonamed(), rz_list_join(), rz_return_if_fail, rz_type_callable_arg_add(), rz_type_callable_arg_new(), rz_type_clone(), rz_type_free(), rz_type_func_exist(), rz_type_func_new(), rz_type_func_save(), rz_analysis_var_t::type, and rz_analysis_t::typedb.

Referenced by rz_core_analysis_function_add(), and rz_core_analysis_types_propagation().

◆ rz_analysis_fcn_vars_cache_fini()

RZ_API void rz_analysis_fcn_vars_cache_fini ( RzAnalysisFcnVarsCache *  cache)

Definition at line 1223 of file var.c.

1223  {
1224  if (!cache) {
1225  return;
1226  }
1227  rz_list_free(cache->bvars);
1228  rz_list_free(cache->rvars);
1229  rz_list_free(cache->svars);
1230 }

References rz_list_free().

Referenced by ds_show_functions(), rz_analysis_fcn_format_sig(), rz_analysis_fcn_vars_add_types(), and rz_core_analysis_function_signature().

◆ rz_analysis_fcn_vars_cache_init()

RZ_API void rz_analysis_fcn_vars_cache_init ( RzAnalysis analysis,
RzAnalysisFcnVarsCache *  cache,
RzAnalysisFunction fcn 
)

Definition at line 1209 of file var.c.

1209  {
1210  cache->bvars = rz_analysis_var_list(analysis, fcn, RZ_ANALYSIS_VAR_KIND_BPV);
1211  cache->rvars = rz_analysis_var_list(analysis, fcn, RZ_ANALYSIS_VAR_KIND_REG);
1212  cache->svars = rz_analysis_var_list(analysis, fcn, RZ_ANALYSIS_VAR_KIND_SPV);
1214  RzListIter *it;
1215  RzAnalysisVar *var;
1216  rz_list_foreach (cache->rvars, it, var) {
1217  var->argnum = rz_analysis_var_get_argnum(var);
1218  }
1221 }
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
static int var_comparator(const RzAnalysisVar *a, const RzAnalysisVar *b)
Definition: var.c:1199
static int regvar_comparator(const RzAnalysisVar *a, const RzAnalysisVar *b)
Definition: var.c:1204

References rz_analysis_var_t::argnum, regvar_comparator(), rz_analysis_var_get_argnum(), RZ_ANALYSIS_VAR_KIND_BPV, RZ_ANALYSIS_VAR_KIND_REG, RZ_ANALYSIS_VAR_KIND_SPV, rz_analysis_var_list(), rz_list_sort(), and var_comparator().

Referenced by ds_show_functions(), rz_analysis_fcn_format_sig(), rz_analysis_fcn_vars_add_types(), and rz_core_analysis_function_signature().

◆ rz_analysis_function_autoname_var()

RZ_API RZ_OWN char* rz_analysis_function_autoname_var ( RzAnalysisFunction fcn,
char  kind,
const char *  pfx,
int  ptr 
)

Definition at line 633 of file var.c.

633  {
634  void **it;
635  const ut32 uptr = RZ_ABS(ptr);
636  char *varname = rz_str_newf("%s_%xh", pfx, uptr);
637  rz_pvector_foreach (&fcn->vars, it) {
638  RzAnalysisVar *var = *it;
639  if (!strcmp(varname, var->name)) {
640  if (var->kind != kind) {
641  const char *k = kind == RZ_ANALYSIS_VAR_KIND_SPV ? "sp" : "bp";
642  free(varname);
643  varname = rz_str_newf("%s_%s_%xh", pfx, k, uptr);
644  return varname;
645  }
646  int i = 2;
647  do {
648  free(varname);
649  varname = rz_str_newf("%s_%xh_%u", pfx, uptr, i++);
650  } while (rz_analysis_function_get_var_byname(fcn, varname));
651  return varname;
652  }
653  }
654  return varname;
655 }
uint32_t ut32
const char * k
Definition: dsignal.c:11
RZ_API RZ_BORROW RzAnalysisVar * rz_analysis_function_get_var_byname(RzAnalysisFunction *fcn, const char *name)
Definition: var.c:247

References free(), i, k, rz_analysis_var_t::kind, rz_analysis_var_t::name, RZ_ABS, rz_analysis_function_get_var_byname(), RZ_ANALYSIS_VAR_KIND_SPV, rz_pvector_foreach, rz_str_newf(), and rz_analysis_function_t::vars.

Referenced by extract_arg(), and handle_var_stack_access().

◆ rz_analysis_function_delete_all_vars()

RZ_API void rz_analysis_function_delete_all_vars ( RzAnalysisFunction fcn)

Definition at line 220 of file var.c.

220  {
221  void **it;
222  rz_pvector_foreach (&fcn->vars, it) {
223  var_free(*it);
224  }
225  rz_pvector_clear(&fcn->vars);
226  fcn->argnum = 0;
227 }
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
static void var_free(RzAnalysisVar *var)
Definition: var.c:179

References rz_analysis_function_t::argnum, rz_pvector_clear(), rz_pvector_foreach, var_free(), and rz_analysis_function_t::vars.

Referenced by rz_analysis_function_free(), rz_analysis_function_set_type(), and rz_analysis_function_vars_detect_handler().

◆ rz_analysis_function_delete_unused_vars()

RZ_API void rz_analysis_function_delete_unused_vars ( RzAnalysisFunction fcn)

Definition at line 229 of file var.c.

229  {
230  void **v;
231  RzPVector *vars_clone = (RzPVector *)rz_vector_clone((RzVector *)&fcn->vars);
232  rz_pvector_foreach (vars_clone, v) {
233  RzAnalysisVar *var = *v;
234  if (rz_vector_empty(&var->accesses)) {
236  }
237  }
238  rz_pvector_free(vars_clone);
239 }
const char * v
Definition: dsignal.c:12
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RZ_API RzVector * rz_vector_clone(RzVector *vec)
Definition: vector.c:101
static bool rz_vector_empty(const RzVector *vec)
Definition: rz_vector.h:74
RZ_API void rz_analysis_function_delete_var(RzAnalysisFunction *fcn, RzAnalysisVar *var)
Definition: var.c:241

References rz_analysis_var_t::accesses, rz_analysis_function_delete_var(), rz_pvector_foreach, rz_pvector_free(), rz_vector_clone(), rz_vector_empty(), v, and rz_analysis_function_t::vars.

Referenced by rz_analysis_update_analysis_range(), and update_analysis().

◆ rz_analysis_function_delete_var()

RZ_API void rz_analysis_function_delete_var ( RzAnalysisFunction fcn,
RzAnalysisVar var 
)

Definition at line 241 of file var.c.

241  {
242  rz_return_if_fail(fcn && var);
243  rz_pvector_remove_data(&fcn->vars, var);
244  var_free(var);
245 }
RZ_API void rz_pvector_remove_data(RzPVector *vec, void *x)
Definition: vector.c:362

References rz_pvector_remove_data(), rz_return_if_fail, var_free(), and rz_analysis_function_t::vars.

Referenced by fcn_takeover_block_recursive_followthrough_cb(), rz_analysis_function_delete_unused_vars(), and rz_analysis_function_set_type().

◆ rz_analysis_function_delete_vars_by_kind()

RZ_API void rz_analysis_function_delete_vars_by_kind ( RzAnalysisFunction fcn,
RzAnalysisVarKind  kind 
)

Definition at line 206 of file var.c.

206  {
207  rz_return_if_fail(fcn);
208  size_t i;
209  for (i = 0; i < rz_pvector_len(&fcn->vars);) {
210  RzAnalysisVar *var = rz_pvector_at(&fcn->vars, i);
211  if (var->kind == kind) {
212  rz_pvector_remove_at(&fcn->vars, i);
213  var_free(var);
214  continue;
215  }
216  i++;
217  }
218 }
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API void * rz_pvector_remove_at(RzPVector *vec, size_t index)
Definition: vector.c:355
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236

References i, rz_analysis_var_t::kind, rz_pvector_at(), rz_pvector_len(), rz_pvector_remove_at(), rz_return_if_fail, var_free(), and rz_analysis_function_t::vars.

Referenced by __core_analysis_fcn(), and analysis_function_vars_del_all().

◆ rz_analysis_function_get_var()

RZ_API RZ_BORROW RzAnalysisVar* rz_analysis_function_get_var ( RzAnalysisFunction fcn,
char  kind,
int  delta 
)

◆ rz_analysis_function_get_var_byname()

◆ rz_analysis_function_get_var_fields()

RZ_DEPRECATE RZ_API RzList* rz_analysis_function_get_var_fields ( RzAnalysisFunction fcn,
int  kind 
)

Definition at line 1166 of file var.c.

1166  {
1167  if (!fcn) {
1168  return NULL;
1169  }
1171  if (kind < 1) {
1172  kind = RZ_ANALYSIS_VAR_KIND_BPV; // by default show vars
1173  }
1174  void **it;
1175  rz_pvector_foreach (&fcn->vars, it) {
1176  RzAnalysisVar *var = *it;
1177  if (var->kind != kind) {
1178  continue;
1179  }
1181  // this var is a struct and var_add_structure_fields_to_list added all the fields
1182  continue;
1183  }
1185  if (!field) {
1186  break;
1187  }
1188  field->name = strdup(var->name);
1189  if (!field->name) {
1190  var_field_free(field);
1191  break;
1192  }
1193  field->delta = var->delta;
1194  rz_list_push(list, field);
1195  }
1196  return list;
1197 }
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
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_DEPRECATE struct rz_analysis_var_field_t RzAnalysisVarField
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
struct rz_analysis_t * analysis
Definition: rz_analysis.h:267
static void var_field_free(RzAnalysisVarField *field)
Definition: var.c:1158
static bool var_add_structure_fields_to_list(RzAnalysis *a, RzAnalysisVar *av, RzList *list)
Definition: var.c:593

References rz_analysis_function_t::analysis, rz_analysis_var_t::delta, rz_analysis_var_t::kind, list(), rz_analysis_var_t::name, NULL, RZ_ANALYSIS_VAR_KIND_BPV, rz_list_newf(), rz_list_push(), RZ_NEW0, rz_pvector_foreach, strdup(), var_add_structure_fields_to_list(), var_field_free(), and rz_analysis_function_t::vars.

Referenced by rz_core_init().

◆ rz_analysis_function_get_var_reg_at()

RZ_API const char* rz_analysis_function_get_var_reg_at ( RzAnalysisFunction fcn,
st64  delta,
ut64  addr 
)

Definition at line 314 of file var.c.

314  {
315  st64 offset = (st64)addr - (st64)fcn->addr;
316  RzPVector *inst_accesses = ht_up_find(fcn->inst_vars, offset, NULL);
317  if (!inst_accesses) {
318  return NULL;
319  }
320  RzAnalysisVar *var = NULL;
321  void **it;
322  rz_pvector_foreach (inst_accesses, it) {
323  RzAnalysisVar *v = *it;
324  if (v->delta == delta) {
325  var = v;
326  break;
327  }
328  }
329  if (!var) {
330  return NULL;
331  }
332  size_t index;
334  RzAnalysisVarAccess *acc = NULL;
335  if (index < var->accesses.len) {
336  acc = rz_vector_index_ptr(&var->accesses, index);
337  }
338  if (!acc || acc->offset != offset) {
339  return NULL;
340  }
341  return acc->reg;
342 }
#define rz_vector_lower_bound(vec, x, i, cmp)
Definition: rz_vector.h:190
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
Definition: rz_vector.h:88
#define ACCESS_CMP(x, y)
Definition: var.c:11

References ACCESS_CMP, rz_analysis_var_t::accesses, addr, rz_analysis_function_t::addr, delta, rz_analysis_function_t::inst_vars, NULL, rz_analysis_var_access_t::offset, rz_analysis_var_access_t::reg, rz_pvector_foreach, rz_vector_index_ptr(), rz_vector_lower_bound, st64, and v.

Referenced by get_reg_at(), rz_core_analysis_bytes(), and rz_core_disasm_instruction().

◆ rz_analysis_function_get_var_stackptr_at()

RZ_API st64 rz_analysis_function_get_var_stackptr_at ( RzAnalysisFunction fcn,
st64  delta,
ut64  addr 
)

Definition at line 284 of file var.c.

284  {
285  st64 offset = (st64)addr - (st64)fcn->addr;
286  RzPVector *inst_accesses = ht_up_find(fcn->inst_vars, offset, NULL);
287  if (!inst_accesses) {
288  return ST64_MAX;
289  }
290  RzAnalysisVar *var = NULL;
291  void **it;
292  rz_pvector_foreach (inst_accesses, it) {
293  RzAnalysisVar *v = *it;
294  if (v->delta == delta) {
295  var = v;
296  break;
297  }
298  }
299  if (!var) {
300  return ST64_MAX;
301  }
302  size_t index;
304  RzAnalysisVarAccess *acc = NULL;
305  if (index < var->accesses.len) {
306  acc = rz_vector_index_ptr(&var->accesses, index);
307  }
308  if (!acc || acc->offset != offset) {
309  return ST64_MAX;
310  }
311  return acc->stackptr;
312 }
#define ST64_MAX
Definition: rz_types_base.h:84

References ACCESS_CMP, rz_analysis_var_t::accesses, addr, rz_analysis_function_t::addr, delta, rz_analysis_function_t::inst_vars, NULL, rz_analysis_var_access_t::offset, rz_pvector_foreach, rz_vector_index_ptr(), rz_vector_lower_bound, st64, ST64_MAX, rz_analysis_var_access_t::stackptr, and v.

Referenced by get_ptr_at(), rz_core_analysis_bytes(), and rz_core_disasm_instruction().

◆ rz_analysis_function_get_vars_used_at()

◆ rz_analysis_function_rebase_vars()

RZ_API bool rz_analysis_function_rebase_vars ( RzAnalysis a,
RzAnalysisFunction fcn 
)

Definition at line 44 of file var.c.

44  {
45  rz_return_val_if_fail(a && fcn, false);
46  RzListIter *it;
47  RzAnalysisVar *var;
48  RzList *var_list = rz_analysis_var_all_list(a, fcn);
49  rz_return_val_if_fail(var_list, false);
50 
51  rz_list_foreach (var_list, it, var) {
52  // Resync delta in case the registers list changed
53  if (var->isarg && var->kind == 'r') {
54  RzRegItem *reg = rz_reg_get(a->reg, var->regname, -1);
55  if (reg) {
56  if (var->delta != reg->index) {
57  var->delta = reg->index;
58  }
59  }
60  }
61  }
62 
63  rz_list_free(var_list);
64  return true;
65 }
RZ_DEPRECATE RZ_API RzList * rz_analysis_var_all_list(RzAnalysis *analysis, RzAnalysisFunction *fcn)
Definition: var.c:1135

References a, rz_analysis_var_t::delta, rz_analysis_var_t::isarg, rz_analysis_var_t::kind, reg, rz_analysis_var_t::regname, rz_analysis_var_all_list(), rz_list_free(), rz_reg_get(), and rz_return_val_if_fail.

Referenced by __rebase_everything().

◆ rz_analysis_function_set_var()

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 at line 111 of file var.c.

111  {
114  if (existing && (existing->kind != kind || existing->delta != delta)) {
115  // var name already exists at a different kind+delta
116  return NULL;
117  }
118  RzRegItem *reg = NULL;
119  if (!kind) {
121  }
122  switch (kind) {
123  case RZ_ANALYSIS_VAR_KIND_BPV: // base pointer var/args
124  case RZ_ANALYSIS_VAR_KIND_SPV: // stack pointer var/args
125  case RZ_ANALYSIS_VAR_KIND_REG: // registers args
126  break;
127  default:
128  RZ_LOG_ERROR("Invalid var kind '%c'\n", kind);
129  return NULL;
130  }
131  if (kind == RZ_ANALYSIS_VAR_KIND_REG) {
133  if (!reg) {
134  RZ_LOG_ERROR("Register wasn't found at the given delta\n");
135  return NULL;
136  }
137  }
139  if (!var) {
140  var = RZ_NEW0(RzAnalysisVar);
141  if (!var) {
142  return NULL;
143  }
144  rz_pvector_push(&fcn->vars, var);
145  var->fcn = fcn;
148  } else {
149  free(var->name);
150  free(var->regname);
151  if (var->type != type) {
152  // only free if not assigning the own type to itself
153  rz_type_free(var->type);
154  var->type = NULL;
155  }
156  }
157  var->name = strdup(name);
158  var->regname = reg ? strdup(reg->name) : NULL; // TODO: no strdup here? pool? or not keep regname at all?
159  if (!var->type || var->type != type) {
160  // only clone if we don't already own this type (and didn't free it above)
162  }
163  var->kind = kind;
164  var->isarg = isarg;
165  var->delta = delta;
167  return var;
168 }
RZ_API RzRegItem * rz_reg_index_get(RzReg *reg, int idx)
Definition: reg.c:262
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
RzAnalysisFunction * fcn
Definition: rz_analysis.h:726
RzVector constraints
Definition: rz_analysis.h:734
type constrained by the type conditions
Definition: rz_type.h:209
RZ_API void rz_analysis_var_resolve_overlaps(RzAnalysisVar *var)
Definition: var.c:77
static RZ_OWN RzType * var_type_clone_or_default_type(RzAnalysis *analysis, RZ_BORROW RZ_NULLABLE const RzType *type, int size)
Definition: var.c:23

References rz_analysis_var_t::accesses, rz_analysis_function_t::analysis, rz_analysis_var_t::constraints, delta, rz_analysis_var_t::delta, rz_analysis_var_t::fcn, free(), rz_analysis_var_t::isarg, rz_analysis_var_t::kind, rz_analysis_var_t::name, NULL, reg, rz_analysis_t::reg, rz_analysis_var_t::regname, RZ_ABS, rz_analysis_function_get_var(), rz_analysis_function_get_var_byname(), RZ_ANALYSIS_VAR_KIND_BPV, RZ_ANALYSIS_VAR_KIND_REG, RZ_ANALYSIS_VAR_KIND_SPV, rz_analysis_var_resolve_overlaps(), RZ_LOG_ERROR, RZ_NEW0, rz_pvector_push(), rz_reg_index_get(), rz_return_val_if_fail, rz_type_free(), rz_vector_init(), strdup(), type, rz_analysis_var_t::type, var_type_clone_or_default_type(), and rz_analysis_function_t::vars.

Referenced by extract_arg(), fcn_takeover_block_recursive_followthrough_cb(), handle_var_stack_access(), rz_analysis_dwarf_integrate_functions(), rz_analysis_extract_rarg(), rz_analysis_function_set_type(), rz_analysis_function_vars_bp_handler(), rz_analysis_function_vars_regs_handler(), and rz_analysis_function_vars_sp_handler().

◆ rz_analysis_get_used_function_var()

RZ_DEPRECATE RZ_API RzAnalysisVar* rz_analysis_get_used_function_var ( RzAnalysis analysis,
ut64  addr 
)

Definition at line 398 of file var.c.

398  {
399  RzList *fcns = rz_analysis_get_functions_in(analysis, addr);
400  if (!fcns) {
401  return NULL;
402  }
403  RzAnalysisVar *var = NULL;
404  RzListIter *it;
405  RzAnalysisFunction *fcn;
406  rz_list_foreach (fcns, it, fcn) {
408  if (used_vars && !rz_pvector_empty(used_vars)) {
409  var = rz_pvector_at(used_vars, 0);
410  break;
411  }
412  }
413  rz_list_free(fcns);
414  return var;
415 }
RZ_API RzList * rz_analysis_get_functions_in(RzAnalysis *analysis, ut64 addr)
Definition: function.c:20
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
RZ_API RZ_BORROW RzPVector * rz_analysis_function_get_vars_used_at(RzAnalysisFunction *fcn, ut64 op_addr)
Definition: var.c:393

References addr, NULL, rz_analysis_function_get_vars_used_at(), rz_analysis_get_functions_in(), rz_list_free(), rz_pvector_at(), and rz_pvector_empty().

Referenced by handle_stack_canary(), rz_core_analysis_name(), rz_core_analysis_rename(), rz_core_analysis_var_rename(), rz_core_link_stroff(), rz_core_visual_define(), and type_match().

◆ rz_analysis_var_add_constraint()

RZ_API void rz_analysis_var_add_constraint ( RzAnalysisVar var,
RZ_BORROW RzTypeConstraint constraint 
)

Definition at line 524 of file var.c.

524  {
525  rz_vector_push(&var->constraints, constraint);
526 }
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197

References rz_analysis_var_t::constraints, and rz_vector_push().

Referenced by propagate_types_among_used_variables().

◆ rz_analysis_var_addr()

RZ_API ut64 rz_analysis_var_addr ( RzAnalysisVar var)

Definition at line 270 of file var.c.

270  {
272  RzAnalysis *analysis = var->fcn->analysis;
273  const char *regname = NULL;
274  if (var->kind == RZ_ANALYSIS_VAR_KIND_BPV) {
276  return rz_reg_getv(analysis->reg, regname) + var->delta + var->fcn->bp_off;
277  } else if (var->kind == RZ_ANALYSIS_VAR_KIND_SPV) {
279  return rz_reg_getv(analysis->reg, regname) + var->delta;
280  }
281  return 0;
282 }
RZ_API ut64 rz_reg_getv(RzReg *reg, const char *name)
Definition: reg.c:332

References rz_analysis_function_t::analysis, rz_analysis_function_t::bp_off, rz_analysis_var_t::delta, rz_analysis_var_t::fcn, rz_analysis_var_t::kind, NULL, rz_analysis_t::reg, regname(), RZ_ANALYSIS_VAR_KIND_BPV, RZ_ANALYSIS_VAR_KIND_SPV, rz_reg_get_name(), rz_reg_getv(), RZ_REG_NAME_BP, RZ_REG_NAME_SP, rz_return_val_if_fail, and UT64_MAX.

Referenced by type_format_print_variable().

◆ rz_analysis_var_all_list()

RZ_DEPRECATE RZ_API RzList* rz_analysis_var_all_list ( RzAnalysis analysis,
RzAnalysisFunction fcn 
)

Definition at line 1135 of file var.c.

1135  {
1136  // rz_analysis_var_list if there are not vars with that kind returns a list with
1137  // zero element.. which is an unnecessary loss of cpu time
1138  RzList *list = rz_list_new();
1139  if (!list) {
1140  return NULL;
1141  }
1142  RzList *reg_vars = rz_analysis_var_list(analysis, fcn, RZ_ANALYSIS_VAR_KIND_REG);
1143  RzList *bpv_vars = rz_analysis_var_list(analysis, fcn, RZ_ANALYSIS_VAR_KIND_BPV);
1144  RzList *spv_vars = rz_analysis_var_list(analysis, fcn, RZ_ANALYSIS_VAR_KIND_SPV);
1145  rz_list_join(list, reg_vars);
1146  rz_list_join(list, bpv_vars);
1147  rz_list_join(list, spv_vars);
1148  rz_list_free(reg_vars);
1149  rz_list_free(bpv_vars);
1150  rz_list_free(spv_vars);
1151  return list;
1152 }
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 list(), NULL, RZ_ANALYSIS_VAR_KIND_BPV, RZ_ANALYSIS_VAR_KIND_REG, RZ_ANALYSIS_VAR_KIND_SPV, rz_analysis_var_list(), rz_list_free(), rz_list_join(), and rz_list_new().

Referenced by analysis_function_vars_accesses(), autocmplt_cmd_arg_fcn_var(), list_vars(), run_basic_block_analysis(), rz_analysis_function_rebase_vars(), rz_analysis_function_vars_dis_refs_handler(), rz_analysis_function_vars_handler(), rz_analysis_function_vars_stackframe_handler(), rz_analysis_types_from_fcn(), rz_core_analysis_all_vars_display(), var_variables_show(), variable_rename(), and variable_set_type().

◆ rz_analysis_var_check_name()

RZ_API bool rz_analysis_var_check_name ( const char *  name)

Definition at line 344 of file var.c.

344  {
345  return !isdigit(*name) && strcspn(name, "., =/");
346 }
#define isdigit(c)
Definition: safe-ctype.h:131

References isdigit.

Referenced by rz_analysis_var_rename().

◆ rz_analysis_var_clear_accesses()

RZ_API void rz_analysis_var_clear_accesses ( RzAnalysisVar var)

Definition at line 492 of file var.c.

492  {
493  rz_return_if_fail(var);
494  RzAnalysisFunction *fcn = var->fcn;
495  if (fcn->inst_vars) {
496  // remove all inverse references to the var's accesses
497  RzAnalysisVarAccess *acc;
498  rz_vector_foreach(&var->accesses, acc) {
499  RzPVector *inst_accesses = ht_up_find(fcn->inst_vars, (ut64)acc->offset, NULL);
500  if (!inst_accesses) {
501  continue;
502  }
503  rz_pvector_remove_data(inst_accesses, var);
504  }
505  }
506  rz_vector_clear(&var->accesses);
507 }
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
RZ_API void rz_vector_clear(RzVector *vec)
Definition: vector.c:68

References rz_analysis_var_t::accesses, rz_analysis_var_t::fcn, rz_analysis_function_t::inst_vars, NULL, rz_analysis_var_access_t::offset, rz_pvector_remove_data(), rz_return_if_fail, rz_vector_clear(), rz_vector_foreach, and ut64().

Referenced by var_free().

◆ rz_analysis_var_count()

RZ_API int rz_analysis_var_count ( RzAnalysis a,
RzAnalysisFunction fcn,
int  kind,
int  type 
)

Definition at line 574 of file var.c.

574  {
575  // type { local: 0, arg: 1 };
576  RzList *list = rz_analysis_var_list(a, fcn, kind);
577  RzAnalysisVar *var;
578  RzListIter *iter;
579  int count[2] = {
580  0
581  };
582  rz_list_foreach (list, iter, var) {
583  if (kind == RZ_ANALYSIS_VAR_KIND_REG) {
584  count[1]++;
585  continue;
586  }
587  count[var->isarg]++;
588  }
590  return count[type];
591 }

References a, count, rz_analysis_var_t::isarg, list(), RZ_ANALYSIS_VAR_KIND_REG, rz_analysis_var_list(), rz_list_free(), and type.

Referenced by core_analysis_graph_nodes(), draw_graph_nodes(), ds_print_esil_analysis(), fcn_print_info(), function_list_print_to_table(), function_print_to_json(), and rz_analysis_extract_rarg().

◆ rz_analysis_var_delete()

RZ_API void rz_analysis_var_delete ( RzAnalysisVar var)

Definition at line 192 of file var.c.

192  {
193  rz_return_if_fail(var);
194  RzAnalysisFunction *fcn = var->fcn;
195  size_t i;
196  for (i = 0; i < rz_pvector_len(&fcn->vars); i++) {
197  RzAnalysisVar *v = rz_pvector_at(&fcn->vars, i);
198  if (v == var) {
199  rz_pvector_remove_at(&fcn->vars, i);
200  var_free(v);
201  return;
202  }
203  }
204 }

References rz_analysis_var_t::fcn, i, rz_pvector_at(), rz_pvector_len(), rz_pvector_remove_at(), rz_return_if_fail, v, var_free(), and rz_analysis_function_t::vars.

Referenced by rz_analysis_var_resolve_overlaps(), and rz_core_analysis_function_delete_var().

◆ rz_analysis_var_get_access_at()

RZ_API RzAnalysisVarAccess* rz_analysis_var_get_access_at ( RzAnalysisVar var,
ut64  addr 
)

Definition at line 509 of file var.c.

509  {
511  st64 offset = (st64)addr - (st64)var->fcn->addr;
512  size_t index;
514  if (index >= var->accesses.len) {
515  return NULL;
516  }
517  RzAnalysisVarAccess *acc = rz_vector_index_ptr(&var->accesses, index);
518  if (acc->offset == offset) {
519  return acc;
520  }
521  return NULL;
522 }
size_t len
Definition: rz_vector.h:47

References ACCESS_CMP, rz_analysis_var_t::accesses, addr, rz_analysis_function_t::addr, rz_analysis_var_t::fcn, rz_vector_t::len, NULL, rz_analysis_var_access_t::offset, rz_return_val_if_fail, rz_vector_index_ptr(), rz_vector_lower_bound, and st64.

Referenced by fcn_takeover_block_recursive_followthrough_cb(), and rz_analysis_var_get_dst_var().

◆ rz_analysis_var_get_argnum()

RZ_API int rz_analysis_var_get_argnum ( RzAnalysisVar var)

Definition at line 369 of file var.c.

369  {
370  rz_return_val_if_fail(var, -1);
371  RzAnalysis *analysis = var->fcn->analysis;
372  if (!var->isarg || var->kind != RZ_ANALYSIS_VAR_KIND_REG) { // TODO: support bp and sp too
373  return -1;
374  }
375  if (!var->regname) {
376  return -1;
377  }
378  RzRegItem *reg = rz_reg_get(analysis->reg, var->regname, -1);
379  if (!reg) {
380  return -1;
381  }
382  int i;
383  int arg_max = var->fcn->cc ? rz_analysis_cc_max_arg(analysis, var->fcn->cc) : 0;
384  for (i = 0; i < arg_max; i++) {
385  const char *reg_arg = rz_analysis_cc_arg(analysis, var->fcn->cc, i);
386  if (reg_arg && !strcmp(reg->name, reg_arg)) {
387  return i;
388  }
389  }
390  return -1;
391 }

References rz_analysis_function_t::analysis, rz_analysis_function_t::cc, rz_analysis_var_t::fcn, i, rz_analysis_var_t::isarg, rz_analysis_var_t::kind, reg, rz_analysis_t::reg, rz_analysis_var_t::regname, rz_analysis_cc_arg(), rz_analysis_cc_max_arg(), RZ_ANALYSIS_VAR_KIND_REG, rz_reg_get(), and rz_return_val_if_fail.

Referenced by rz_analysis_extract_rarg(), rz_analysis_fcn_vars_cache_init(), and rz_analysis_function_args().

◆ rz_analysis_var_get_constraints_readable()

RZ_API char* rz_analysis_var_get_constraints_readable ( RzAnalysisVar var)

Definition at line 528 of file var.c.

528  {
529  size_t n = var->constraints.len;
530  if (!n) {
531  return NULL;
532  }
533  bool low = false, high = false;
534  RzStrBuf sb;
535  rz_strbuf_init(&sb);
536  size_t i;
537  for (i = 0; i < n; i += 1) {
539  switch (constr->cond) {
540  case RZ_TYPE_COND_LE:
541  if (high) {
542  rz_strbuf_append(&sb, " && ");
543  }
544  rz_strbuf_appendf(&sb, "<= 0x%" PFMT64x "", constr->val);
545  low = true;
546  break;
547  case RZ_TYPE_COND_LT:
548  if (high) {
549  rz_strbuf_append(&sb, " && ");
550  }
551  rz_strbuf_appendf(&sb, "< 0x%" PFMT64x "", constr->val);
552  low = true;
553  break;
554  case RZ_TYPE_COND_GE:
555  rz_strbuf_appendf(&sb, ">= 0x%" PFMT64x "", constr->val);
556  high = true;
557  break;
558  case RZ_TYPE_COND_GT:
559  rz_strbuf_appendf(&sb, "> 0x%" PFMT64x "", constr->val);
560  high = true;
561  break;
562  default:
563  break;
564  }
565  if (low && high && i != n - 1) {
566  rz_strbuf_append(&sb, " || ");
567  low = false;
568  high = false;
569  }
570  }
571  return rz_strbuf_drain_nofree(&sb);
572 }
static SblHeader sb
Definition: bin_mbn.c:26
int n
Definition: mipsasm.c:19
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
Definition: strbuf.c:349
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
@ RZ_TYPE_COND_LE
Less or equal.
Definition: rz_type.h:188
@ RZ_TYPE_COND_GE
Greater or equal.
Definition: rz_type.h:186
@ RZ_TYPE_COND_GT
Greater than.
Definition: rz_type.h:187
@ RZ_TYPE_COND_LT
Less than.
Definition: rz_type.h:189
RzTypeCond cond
Definition: rz_type.h:210

References rz_type_constraint_t::cond, rz_analysis_var_t::constraints, i, rz_vector_t::len, n, NULL, PFMT64x, rz_strbuf_append(), rz_strbuf_appendf(), rz_strbuf_drain_nofree(), rz_strbuf_init(), RZ_TYPE_COND_GE, RZ_TYPE_COND_GT, RZ_TYPE_COND_LE, RZ_TYPE_COND_LT, rz_vector_index_ptr(), sb, and rz_type_constraint_t::val.

Referenced by ds_show_functions_argvar().

◆ rz_analysis_var_get_dst_var()

RZ_API RzAnalysisVar* rz_analysis_var_get_dst_var ( RzAnalysisVar var)

Definition at line 417 of file var.c.

417  {
419  RzAnalysisVarAccess *acc;
420  rz_vector_foreach(&var->accesses, acc) {
421  if (!(acc->type & RZ_ANALYSIS_VAR_ACCESS_TYPE_READ)) {
422  continue;
423  }
424  ut64 addr = var->fcn->addr + acc->offset;
426  void **it;
427  rz_pvector_foreach (used_vars, it) {
428  RzAnalysisVar *used_var = *it;
429  if (used_var == var) {
430  continue;
431  }
433  if (other_acc && other_acc->type & RZ_ANALYSIS_VAR_ACCESS_TYPE_WRITE) {
434  return used_var;
435  }
436  }
437  }
438  return NULL;
439 }
RZ_API RzAnalysisVarAccess * rz_analysis_var_get_access_at(RzAnalysisVar *var, ut64 addr)
Definition: var.c:509

References rz_analysis_var_t::accesses, addr, rz_analysis_function_t::addr, rz_analysis_var_t::fcn, NULL, rz_analysis_var_access_t::offset, rz_analysis_function_get_vars_used_at(), RZ_ANALYSIS_VAR_ACCESS_TYPE_READ, RZ_ANALYSIS_VAR_ACCESS_TYPE_WRITE, rz_analysis_var_get_access_at(), rz_pvector_foreach, rz_return_val_if_fail, rz_vector_foreach, rz_analysis_var_access_t::type, and ut64().

Referenced by retype_callee_arg(), and rz_core_analysis_type_match().

◆ rz_analysis_var_list()

RZ_API RzList* rz_analysis_var_list ( RzAnalysis a,
RzAnalysisFunction fcn,
int  kind 
)

Definition at line 1154 of file var.c.

1154  {
1155  return var_generate_list(a, fcn, kind);
1156 }
static RzList * var_generate_list(RzAnalysis *a, RzAnalysisFunction *fcn, int kind)
Definition: var.c:1117

References a, and var_generate_list().

Referenced by core_analysis_var_list_show(), rz_analysis_extract_rarg(), rz_analysis_fcn_vars_cache_init(), rz_analysis_var_all_list(), rz_analysis_var_count(), rz_core_analysis_everything(), and rz_core_autocomplete().

◆ rz_analysis_var_remove_access_at()

RZ_API void rz_analysis_var_remove_access_at ( RzAnalysisVar var,
ut64  address 
)

Definition at line 476 of file var.c.

476  {
477  rz_return_if_fail(var);
478  st64 offset = (st64)address - (st64)var->fcn->addr;
479  size_t index;
481  if (index >= var->accesses.len) {
482  return;
483  }
484  RzAnalysisVarAccess *acc = rz_vector_index_ptr(&var->accesses, index);
485  if (acc->offset == offset) {
486  rz_vector_remove_at(&var->accesses, index, NULL);
487  RzPVector *inst_accesses = ht_up_find(var->fcn->inst_vars, (ut64)offset, NULL);
488  rz_pvector_remove_data(inst_accesses, var);
489  }
490 }
RZ_API void rz_vector_remove_at(RzVector *vec, size_t index, void *into)
Definition: vector.c:127

References ACCESS_CMP, rz_analysis_var_t::accesses, rz_analysis_function_t::addr, rz_analysis_var_t::fcn, rz_analysis_function_t::inst_vars, rz_vector_t::len, NULL, rz_analysis_var_access_t::offset, rz_pvector_remove_data(), rz_return_if_fail, rz_vector_index_ptr(), rz_vector_lower_bound, rz_vector_remove_at(), st64, and ut64().

Referenced by clear_bb_vars(), and fcn_takeover_block_recursive_followthrough_cb().

◆ rz_analysis_var_rename()

RZ_API bool rz_analysis_var_rename ( RzAnalysisVar var,
const char *  new_name,
bool  verbose 
)

Definition at line 348 of file var.c.

348  {
349  rz_return_val_if_fail(var, false);
350  if (!rz_analysis_var_check_name(new_name)) {
351  return false;
352  }
354  if (v1) {
355  if (verbose) {
356  RZ_LOG_WARN("variable or arg with name `%s` already exist\n", new_name);
357  }
358  return false;
359  }
360  char *nn = strdup(new_name);
361  if (!nn) {
362  return false;
363  }
364  free(var->name);
365  var->name = nn;
366  return true;
367 }
@ v1
Definition: lanai.h:85
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
RZ_API bool rz_analysis_var_check_name(const char *name)
Definition: var.c:344
static int verbose
Definition: z80asm.c:73

References rz_analysis_var_t::fcn, free(), rz_analysis_var_t::name, rz_analysis_function_get_var_byname(), rz_analysis_var_check_name(), RZ_LOG_WARN, rz_return_val_if_fail, strdup(), v1, and verbose.

Referenced by resolve_type_links(), rz_core_analysis_rename(), rz_core_analysis_var_rename(), rz_core_visual_define(), and var_rename().

◆ rz_analysis_var_resolve_overlaps()

RZ_API void rz_analysis_var_resolve_overlaps ( RzAnalysisVar var)

Definition at line 77 of file var.c.

77  {
78  // We do not touch variables stored in registers
79  // or arguments
80  if (!var->type || var->isarg || var->kind == RZ_ANALYSIS_VAR_KIND_REG) {
81  return;
82  }
83  // We ignore overlaps between atomic types because current
84  // detection of the variable default type is suboptimal.
85  // The default type is `intXX_t` where XX is the bitness of the platform
86  // But some binaries can use variables of the smaller size by default
87  // and Rizin doesn't detect bitwidth perfectly. Thus, we skip ATOMIC
88  // types in the overlap detection.
90  return;
91  }
92  ut64 varsize = rz_type_db_get_bitsize(var->fcn->analysis->typedb, var->type) / 8;
93  if (!varsize) {
94  return;
95  }
96  // delete variables which are overlaid by the variable type
97  RzPVector *cloned_vars = (RzPVector *)rz_vector_clone((RzVector *)&var->fcn->vars);
98  void **it;
99  rz_pvector_foreach (cloned_vars, it) {
100  RzAnalysisVar *other = *it;
101  if (!other) {
102  continue;
103  }
104  if (strcmp(var->name, other->name) && var_overlap(var, other, varsize)) {
105  rz_analysis_var_delete(other);
106  }
107  }
108  rz_pvector_free(cloned_vars);
109 }
RZ_API bool rz_type_is_strictly_atomic(const RzTypeDB *typedb, RZ_NONNULL const RzType *type)
Checks if the RzType is strictly atomic.
Definition: helpers.c:349
RZ_API void rz_analysis_var_delete(RzAnalysisVar *var)
Definition: var.c:192
static bool var_overlap(RzAnalysisVar *a, RzAnalysisVar *b, ut64 a_size)
Definition: var.c:71

References rz_analysis_function_t::analysis, rz_analysis_var_t::fcn, rz_analysis_var_t::isarg, rz_analysis_var_t::kind, rz_analysis_var_t::name, rz_analysis_var_delete(), RZ_ANALYSIS_VAR_KIND_REG, rz_pvector_foreach, rz_pvector_free(), rz_type_db_get_bitsize(), rz_type_is_strictly_atomic(), rz_vector_clone(), rz_analysis_var_t::type, rz_analysis_t::typedb, ut64(), var_overlap(), and rz_analysis_function_t::vars.

Referenced by rz_analysis_function_set_var(), rz_analysis_var_set_type(), and vars_resolve_overlaps().

◆ rz_analysis_var_set_access()

RZ_API void rz_analysis_var_set_access ( RzAnalysisVar var,
const char *  reg,
ut64  access_addr,
int  access_type,
st64  stackptr 
)

Definition at line 441 of file var.c.

441  {
442  rz_return_if_fail(var);
443  st64 offset = (st64)access_addr - (st64)var->fcn->addr;
444 
445  // accesses are stored ordered by offset, use binary search to get the matching existing or the index to insert a new one
446  size_t index;
448  RzAnalysisVarAccess *acc = NULL;
449  if (index < var->accesses.len) {
450  acc = rz_vector_index_ptr(&var->accesses, index);
451  }
452  if (!acc || acc->offset != offset) {
453  acc = rz_vector_insert(&var->accesses, index, NULL);
454  acc->offset = offset;
455  acc->type = 0;
456  }
457 
458  acc->type |= (ut8)access_type;
459  acc->stackptr = stackptr;
461 
462  // add the inverse reference from the instruction to the var
463  RzPVector *inst_accesses = ht_up_find(var->fcn->inst_vars, (ut64)offset, NULL);
464  if (!inst_accesses) {
465  inst_accesses = rz_pvector_new(NULL);
466  if (!inst_accesses) {
467  return;
468  }
469  ht_up_insert(var->fcn->inst_vars, (ut64)offset, inst_accesses);
470  }
471  if (!rz_pvector_contains(inst_accesses, var)) {
472  rz_pvector_push(inst_accesses, var);
473  }
474 }
#define ut8
Definition: dcpu16.h:8
RZ_API const char * rz_str_constpool_get(RzStrConstPool *pool, const char *str)
Definition: str_constpool.c:19
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
RZ_API void ** rz_pvector_contains(RzPVector *vec, void *x)
Definition: vector.c:344
RZ_API void * rz_vector_insert(RzVector *vec, size_t index, void *x)
Definition: vector.c:151
RzStrConstPool constpool
Definition: rz_analysis.h:620

References ACCESS_CMP, rz_analysis_var_t::accesses, rz_analysis_function_t::addr, rz_analysis_function_t::analysis, rz_analysis_t::constpool, rz_analysis_var_t::fcn, rz_analysis_function_t::inst_vars, NULL, rz_analysis_var_access_t::offset, reg, rz_analysis_var_access_t::reg, rz_pvector_contains(), rz_pvector_new(), rz_pvector_push(), rz_return_if_fail, rz_str_constpool_get(), rz_vector_index_ptr(), rz_vector_insert(), rz_vector_lower_bound, st64, rz_analysis_var_access_t::stackptr, rz_analysis_var_access_t::type, ut64(), and ut8.

Referenced by analysis_function_vars_getsetref(), extract_arg(), fcn_takeover_block_recursive_followthrough_cb(), handle_var_stack_access(), and rz_analysis_extract_rarg().

◆ rz_analysis_var_set_type()

RZ_API void rz_analysis_var_set_type ( RzAnalysisVar var,
RZ_OWN RzType type,
bool  resolve_overlaps 
)

Definition at line 170 of file var.c.

170  {
171  // We do not free the old type here because the new type can contain
172  // the old one, for example it can wrap the old type as a pointer or an array
173  var->type = type;
174  if (resolve_overlaps) {
176  }
177 }

References rz_analysis_var_resolve_overlaps(), type, and rz_analysis_var_t::type.

Referenced by resolve_type_links(), rz_analysis_function_vars_type_handler(), var_type_set(), and variable_set_type().

◆ var_add_structure_fields_to_list()

static bool var_add_structure_fields_to_list ( RzAnalysis a,
RzAnalysisVar av,
RzList list 
)
static

Definition at line 593 of file var.c.

593  {
594  if (av->type->kind != RZ_TYPE_KIND_IDENTIFIER) {
595  return false;
596  }
597  if (!av->type->identifier.name) {
598  return false;
599  }
600  RzBaseType *btype = rz_type_db_get_base_type(a->typedb, av->type->identifier.name);
601  if (!btype || btype->kind != RZ_BASE_TYPE_KIND_STRUCT) {
602  return false;
603  }
604  if (rz_vector_empty(&btype->struct_data.members)) {
605  return false;
606  }
607  RzTypeStructMember *member;
608  ut64 member_offset = 0;
609  rz_vector_foreach(&btype->struct_data.members, member) {
610  char *new_name = rz_str_newf("%s.%s", av->name, member->name);
612  field->name = new_name;
613  field->delta = av->delta + member_offset;
614  field->field = true;
615  rz_list_append(list, field);
616  member_offset += rz_type_db_get_bitsize(a->typedb, member->type) / 8;
617  }
618  return false;
619 }
RZ_API RZ_BORROW RzBaseType * rz_type_db_get_base_type(const RzTypeDB *typedb, RZ_NONNULL const char *name)
Searches for the RzBaseType in the types database given the name.
Definition: base.c:57
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
@ RZ_BASE_TYPE_KIND_STRUCT
Definition: rz_type.h:73
@ RZ_TYPE_KIND_IDENTIFIER
Definition: rz_type.h:128
RzBaseTypeStruct struct_data
Definition: rz_type.h:118
RzBaseTypeKind kind
Definition: rz_type.h:115
struct rz_type_t::@292::@294 identifier

References a, rz_analysis_var_t::delta, rz_type_t::identifier, rz_base_type_t::kind, rz_type_t::kind, list(), rz_base_type_struct_t::members, rz_analysis_var_t::name, rz_type_struct_member_t::name, RZ_BASE_TYPE_KIND_STRUCT, rz_list_append(), RZ_NEW0, rz_str_newf(), rz_type_db_get_base_type(), rz_type_db_get_bitsize(), RZ_TYPE_KIND_IDENTIFIER, rz_vector_empty(), rz_vector_foreach, rz_base_type_t::struct_data, rz_analysis_var_t::type, rz_type_struct_member_t::type, and ut64().

Referenced by rz_analysis_function_get_var_fields().

◆ var_comparator()

static int var_comparator ( const RzAnalysisVar a,
const RzAnalysisVar b 
)
static

Definition at line 1199 of file var.c.

1199  {
1200  // avoid NULL dereference
1201  return (a && b) ? (a->delta > b->delta) - (a->delta < b->delta) : 0;
1202 }

References a, and b.

Referenced by rz_analysis_fcn_vars_cache_init().

◆ var_field_free()

static void var_field_free ( RzAnalysisVarField field)
static

Definition at line 1158 of file var.c.

1158  {
1159  if (!field) {
1160  return;
1161  }
1162  free(field->name);
1163  free(field);
1164 }

References free().

Referenced by rz_analysis_function_get_var_fields().

◆ var_free()

static void var_free ( RzAnalysisVar var)
static

Definition at line 179 of file var.c.

179  {
180  if (!var) {
181  return;
182  }
183  rz_type_free(var->type);
186  free(var->name);
187  free(var->regname);
188  free(var->comment);
189  free(var);
190 }
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API void rz_analysis_var_clear_accesses(RzAnalysisVar *var)
Definition: var.c:492

References rz_analysis_var_t::comment, rz_analysis_var_t::constraints, free(), rz_analysis_var_t::name, rz_analysis_var_t::regname, rz_analysis_var_clear_accesses(), rz_type_free(), rz_vector_fini(), and rz_analysis_var_t::type.

Referenced by rz_analysis_function_delete_all_vars(), rz_analysis_function_delete_var(), rz_analysis_function_delete_vars_by_kind(), and rz_analysis_var_delete().

◆ var_generate_list()

static RzList* var_generate_list ( RzAnalysis a,
RzAnalysisFunction fcn,
int  kind 
)
static

Definition at line 1117 of file var.c.

1117  {
1118  if (!a || !fcn) {
1119  return NULL;
1120  }
1121  RzList *list = rz_list_new();
1122  if (kind < 1) {
1123  kind = RZ_ANALYSIS_VAR_KIND_BPV; // by default show vars
1124  }
1125  void **it;
1126  rz_pvector_foreach (&fcn->vars, it) {
1127  RzAnalysisVar *var = *it;
1128  if (var->kind == kind) {
1129  rz_list_push(list, var);
1130  }
1131  }
1132  return list;
1133 }

References a, rz_analysis_var_t::kind, list(), NULL, RZ_ANALYSIS_VAR_KIND_BPV, rz_list_new(), rz_list_push(), rz_pvector_foreach, and rz_analysis_function_t::vars.

Referenced by rz_analysis_var_list().

◆ var_overlap()

static bool var_overlap ( RzAnalysisVar a,
RzAnalysisVar b,
ut64  a_size 
)
inlinestatic

Definition at line 71 of file var.c.

71  {
72  return var_same_kind(a, b) && b->delta > a->delta && b->delta < a->delta + a_size;
73 }
static bool var_same_kind(RzAnalysisVar *a, RzAnalysisVar *b)
Definition: var.c:67

References a, b, and var_same_kind().

Referenced by rz_analysis_var_resolve_overlaps().

◆ var_same_kind()

static bool var_same_kind ( RzAnalysisVar a,
RzAnalysisVar b 
)
inlinestatic

Definition at line 67 of file var.c.

67  {
68  return a->kind == b->kind && a->isarg == b->isarg;
69 }

References a, and b.

Referenced by var_overlap().

◆ var_type_clone_or_default_type()

static RZ_OWN RzType* var_type_clone_or_default_type ( RzAnalysis analysis,
RZ_BORROW RZ_NULLABLE const RzType type,
int  size 
)
static

Definition at line 23 of file var.c.

23  {
24  if (type) {
25  return rz_type_clone(type);
26  }
27  const char *typestr = __int_type_from_size(size);
28  if (!typestr) {
29  typestr = __int_type_from_size(analysis->bits);
30  }
31  if (!typestr) {
32  typestr = "int32_t";
33  }
34  char *error_msg = NULL;
35  RzType *result = rz_type_parse_string_single(analysis->typedb->parser, typestr, &error_msg);
36  if (!result || error_msg) {
37  RZ_LOG_ERROR("Invalid var type: %s\n%s", typestr, error_msg);
38  free(error_msg);
39  return NULL;
40  }
41  return result;
42 }
RZ_API RZ_OWN RzType * rz_type_parse_string_single(RzTypeParser *parser, const char *code, char **error_msg)
Parses the single C type definition.
Definition: c_cpp_parser.c:309
RzTypeParser * parser
Definition: rz_type.h:37
static const char * __int_type_from_size(int size)
Definition: var.c:13

References __int_type_from_size(), rz_analysis_t::bits, free(), NULL, rz_type_db_t::parser, RZ_LOG_ERROR, rz_type_clone(), rz_type_parse_string_single(), type, and rz_analysis_t::typedb.

Referenced by rz_analysis_function_set_var().