Rizin
unix-like reverse engineering framework and cli tools
var.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2010-2020 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2010-2020 oddcoder <ahmedsoliman@oddcoder.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_analysis.h>
6 #include <rz_util.h>
7 #include <rz_cons.h>
8 #include <rz_core.h>
9 #include <rz_list.h>
10 
11 #define ACCESS_CMP(x, y) ((st64)((ut64)(x) - (ut64)((RzAnalysisVarAccess *)y)->offset))
12 
13 static const char *__int_type_from_size(int size) {
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 }
22 
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 }
43 
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 }
66 
67 static inline bool var_same_kind(RzAnalysisVar *a, RzAnalysisVar *b) {
68  return a->kind == b->kind && a->isarg == b->isarg;
69 }
70 
71 static inline bool var_overlap(RzAnalysisVar *a, RzAnalysisVar *b, ut64 a_size) {
72  return var_same_kind(a, b) && b->delta > a->delta && b->delta < a->delta + a_size;
73 }
74 
75 // Search for all variables that are located at the offset
76 // overlapped by var and remove them
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 }
110 
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 }
169 
170 RZ_API void rz_analysis_var_set_type(RzAnalysisVar *var, RZ_OWN RzType *type, bool resolve_overlaps) {
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 }
178 
179 static void var_free(RzAnalysisVar *var) {
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 }
191 
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 }
205 
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 }
219 
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 }
228 
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 }
240 
242  rz_return_if_fail(fcn && var);
243  rz_pvector_remove_data(&fcn->vars, var);
244  var_free(var);
245 }
246 
249  void **it;
250  rz_pvector_foreach (&fcn->vars, it) {
251  RzAnalysisVar *var = *it;
252  if (!strcmp(var->name, name)) {
253  return var;
254  }
255  }
256  return NULL;
257 }
258 
260  void **it;
261  rz_pvector_foreach (&fcn->vars, it) {
262  RzAnalysisVar *var = *it;
263  if (var->kind == kind && var->delta == delta) {
264  return var;
265  }
266  }
267  return NULL;
268 }
269 
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 }
283 
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 }
313 
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 }
343 
345  return !isdigit(*name) && strcspn(name, "., =/");
346 }
347 
348 RZ_API bool rz_analysis_var_rename(RzAnalysisVar *var, const char *new_name, bool verbose) {
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 }
368 
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 }
392 
395  return ht_up_find(fcn->inst_vars, (st64)op_addr - (st64)fcn->addr, NULL);
396 }
397 
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 }
416 
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 }
440 
441 RZ_API void rz_analysis_var_set_access(RzAnalysisVar *var, const char *reg, ut64 access_addr, int access_type, st64 stackptr) {
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 }
475 
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 }
491 
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 }
508 
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 }
523 
525  rz_vector_push(&var->constraints, constraint);
526 }
527 
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 }
573 
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 }
592 
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 }
620 
621 static const char *get_regname(RzAnalysis *analysis, RzAnalysisValue *value) {
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 }
632 
633 RZ_API RZ_OWN char *rz_analysis_function_autoname_var(RzAnalysisFunction *fcn, char kind, const char *pfx, int ptr) {
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 }
656 
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 }
668 
669 static void extract_arg(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op, const char *reg, const char *sign, char type) {
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 }
828 
829 static bool is_reg_in_src(const char *regname, RzAnalysis *analysis, RzAnalysisOp *op);
830 
831 static inline bool op_affect_dst(RzAnalysisOp *op) {
832  switch (op->type) {
849  return true;
850  default:
851  return false;
852  }
853 }
854 
855 #define STR_EQUAL(s1, s2) (s1 && s2 && !strcmp(s1, s2))
856 
857 static inline bool arch_destroys_dst(const char *arch) {
858  return (STR_EQUAL(arch, "arm") || STR_EQUAL(arch, "riscv") || STR_EQUAL(arch, "ppc"));
859 }
860 
861 static bool is_used_like_arg(const char *regname, const char *opsreg, const char *opdreg, RzAnalysisOp *op, RzAnalysis *analysis) {
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 }
901 
902 static bool is_reg_in_src(const char *regname, RzAnalysis *analysis, RzAnalysisOp *op) {
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 }
908 
909 RZ_API void rz_analysis_extract_rarg(RzAnalysis *analysis, RzAnalysisOp *op, RzAnalysisFunction *fcn, int *reg_set, int *count) {
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 }
1102 
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 }
1116 
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 }
1134 
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 }
1153 
1154 RZ_API RzList /*<RzAnalysisVar *>*/ *rz_analysis_var_list(RzAnalysis *a, RzAnalysisFunction *fcn, int kind) {
1155  return var_generate_list(a, fcn, kind);
1156 }
1157 
1158 static void var_field_free(RzAnalysisVarField *field) {
1159  if (!field) {
1160  return;
1161  }
1162  free(field->name);
1163  free(field);
1164 }
1165 
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 }
1198 
1199 static int var_comparator(const RzAnalysisVar *a, const RzAnalysisVar *b) {
1200  // avoid NULL dereference
1201  return (a && b) ? (a->delta > b->delta) - (a->delta < b->delta) : 0;
1202 }
1203 
1204 static int regvar_comparator(const RzAnalysisVar *a, const RzAnalysisVar *b) {
1205  // avoid NULL dereference
1206  return (a && b) ? (a->argnum > b->argnum) - (a->argnum < b->argnum) : 0;
1207 }
1208 
1209 RZ_API void rz_analysis_fcn_vars_cache_init(RzAnalysis *analysis, RzAnalysisFcnVarsCache *cache, RzAnalysisFunction *fcn) {
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 }
1222 
1223 RZ_API void rz_analysis_fcn_vars_cache_fini(RzAnalysisFcnVarsCache *cache) {
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 }
1231 
1233  RZ_NULLABLE RzAnalysisFcnVarsCache *reuse_cache, RZ_NULLABLE const char *fcn_name_pre, RZ_NULLABLE const char *fcn_name_post) {
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 }
1372 
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 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
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 RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
RZ_API RzList * rz_analysis_get_functions_in(RzAnalysis *analysis, ut64 addr)
Definition: function.c:20
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
static ut8 bytes[32]
Definition: asm_arc.c:23
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
static SblHeader sb
Definition: bin_mbn.c:26
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
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_arg(RzAnalysis *analysis, const char *convention, int n)
Definition: cc.c:122
RZ_API const char * rz_analysis_cc_self(RzAnalysis *analysis, const char *convention)
Definition: cc.c:138
RZ_API int rz_analysis_cc_max_arg(RzAnalysis *analysis, const char *cc)
Definition: cc.c:171
RZ_API const char * rz_analysis_cc_error(RzAnalysis *analysis, const char *convention)
Definition: cc.c:155
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
cs_arch arch
Definition: cstool.c:13
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 ut8
Definition: dcpu16.h:8
uint32_t ut32
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
#define SP(t, s, c)
Definition: engine.c:123
RZ_API RzFlagItem * rz_flag_get_by_spaces(RzFlag *f, ut64 off,...)
Definition: flag.c:326
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
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 Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
#define reg(n)
@ v1
Definition: lanai.h:85
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_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
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
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 RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
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_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
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")
char * dst
Definition: lz4.h:724
@ RZ_ABS
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
const char * name
Definition: op.c:541
RZ_API ut64 rz_reg_getv(RzReg *reg, const char *name)
Definition: reg.c:332
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
RZ_API RzRegItem * rz_reg_index_get(RzReg *reg, int idx)
Definition: reg.c:262
RZ_API const char * rz_reg_32_to_64(RzReg *reg, const char *rreg32)
Definition: reg.c:17
RZ_DEPRECATE struct rz_analysis_var_field_t RzAnalysisVarField
#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_META_TYPE_VARTYPE
Definition: rz_analysis.h:297
@ 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
RzAnalysisVarKind
Definition: rz_analysis.h:702
@ 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_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_LOAD
Definition: rz_analysis.h:416
@ 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_CMOV
Definition: rz_analysis.h:391
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_OR
Definition: rz_analysis.h:410
@ RZ_ANALYSIS_OP_TYPE_PUSH
Definition: rz_analysis.h:397
@ RZ_ANALYSIS_OP_TYPE_SHR
Definition: rz_analysis.h:406
@ RZ_ANALYSIS_OP_TYPE_POP
Definition: rz_analysis.h:398
@ RZ_ANALYSIS_OP_TYPE_DIV
Definition: rz_analysis.h:405
@ RZ_ANALYSIS_OP_TYPE_CAST
Definition: rz_analysis.h:426
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_SHL
Definition: rz_analysis.h:407
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
@ RZ_ANALYSIS_OP_TYPE_NOT
Definition: rz_analysis.h:414
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_LEA
Definition: rz_analysis.h:417
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_FLAGS_FS_IMPORTS
Definition: rz_core.h:59
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
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 const char * rz_str_constpool_get(RzStrConstPool *pool, const char *str)
Definition: str_constpool.c:19
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
Definition: strbuf.c:349
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
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 void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
@ RZ_BASE_TYPE_KIND_STRUCT
Definition: rz_type.h:73
@ 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
@ RZ_TYPE_KIND_IDENTIFIER
Definition: rz_type.h:128
@ RZ_TYPE_KIND_POINTER
Definition: rz_type.h:129
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_BORROW
Definition: rz_types.h:63
#define RZ_DEPRECATE
Definition: rz_types.h:66
#define RZ_ROUND(x, y)
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define ST32_MAX
Definition: rz_types_base.h:97
#define UT64_MAX
Definition: rz_types_base.h:86
#define ST64_MAX
Definition: rz_types_base.h:84
#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
RZ_API void rz_pvector_remove_data(RzPVector *vec, void *x)
Definition: vector.c:362
RZ_API void rz_vector_remove_at(RzVector *vec, size_t index, void *into)
Definition: vector.c:127
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
RZ_API void * rz_pvector_remove_at(RzPVector *vec, size_t index)
Definition: vector.c:355
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void ** rz_pvector_contains(RzPVector *vec, void *x)
Definition: vector.c:344
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
RZ_API RzVector * rz_vector_clone(RzVector *vec)
Definition: vector.c:101
RZ_API void rz_vector_clear(RzVector *vec)
Definition: vector.c:68
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
static bool rz_vector_empty(const RzVector *vec)
Definition: rz_vector.h:74
RZ_API void * rz_vector_insert(RzVector *vec, size_t index, void *x)
Definition: vector.c:151
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
#define isdigit(c)
Definition: safe-ctype.h:131
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
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define a(i)
Definition: sha256.c:41
Definition: z80asm.h:102
struct rz_analysis_t * analysis
Definition: rz_analysis.h:267
RzStrConstPool constpool
Definition: rz_analysis.h:620
struct rz_analysis_plugin_t * cur
Definition: rz_analysis.h:586
RzAnalysisOptions opt
Definition: rz_analysis.h:608
RzTypeDB * typedb
Definition: rz_analysis.h:602
RzCoreBind coreb
Definition: rz_analysis.h:580
RzAnalysisVarKind kind
Definition: rz_analysis.h:728
RzAnalysisFunction * fcn
Definition: rz_analysis.h:726
RzVector constraints
Definition: rz_analysis.h:734
RzBaseTypeStruct struct_data
Definition: rz_type.h:118
RzBaseTypeKind kind
Definition: rz_type.h:115
void * core
Definition: rz_bind.h:31
RzFlag * flags
Definition: rz_core.h:330
int size
in bits> 8,16,32,64 ... 128/256
Definition: rz_reg.h:120
int index
Index in register profile.
Definition: rz_reg.h:126
type constrained by the type conditions
Definition: rz_type.h:209
RzTypeCond cond
Definition: rz_type.h:210
RzTypeParser * parser
Definition: rz_type.h:37
RzTypeKind kind
Definition: rz_type.h:155
struct rz_type_t::@292::@294 identifier
size_t len
Definition: rz_vector.h:47
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 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_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_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_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 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 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 RZ_OWN RzType * rz_type_clone(RZ_BORROW RZ_NONNULL const RzType *type)
Creates an exact clone of the RzType.
Definition: type.c:1181
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
Definition: dis.c:32
static void var_free(RzAnalysisVar *var)
Definition: var.c:179
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_clear_accesses(RzAnalysisVar *var)
Definition: var.c:492
static int var_comparator(const RzAnalysisVar *a, const RzAnalysisVar *b)
Definition: var.c:1199
static bool var_same_kind(RzAnalysisVar *a, RzAnalysisVar *b)
Definition: var.c:67
RZ_API void rz_analysis_extract_rarg(RzAnalysis *analysis, RzAnalysisOp *op, RzAnalysisFunction *fcn, int *reg_set, int *count)
Definition: var.c:909
RZ_API void rz_analysis_fcn_vars_cache_fini(RzAnalysisFcnVarsCache *cache)
Definition: var.c:1223
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
RZ_API void rz_analysis_var_resolve_overlaps(RzAnalysisVar *var)
Definition: var.c:77
RZ_API void rz_analysis_function_delete_unused_vars(RzAnalysisFunction *fcn)
Definition: var.c:229
static void extract_arg(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op, const char *reg, const char *sign, char type)
Definition: var.c:669
RZ_API RZ_BORROW RzAnalysisVar * rz_analysis_function_get_var(RzAnalysisFunction *fcn, char kind, int delta)
Definition: var.c:259
static bool op_affect_dst(RzAnalysisOp *op)
Definition: var.c:831
RZ_API void rz_analysis_function_delete_all_vars(RzAnalysisFunction *fcn)
Definition: var.c:220
RZ_API int rz_analysis_var_count(RzAnalysis *a, RzAnalysisFunction *fcn, int kind, int type)
Definition: var.c:574
RZ_API void rz_analysis_extract_vars(RzAnalysis *analysis, RzAnalysisFunction *fcn, RzAnalysisOp *op)
Definition: var.c:1103
RZ_API ut64 rz_analysis_var_addr(RzAnalysisVar *var)
Definition: var.c:270
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 bool rz_analysis_function_rebase_vars(RzAnalysis *a, RzAnalysisFunction *fcn)
Definition: var.c:44
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
static int regvar_comparator(const RzAnalysisVar *a, const RzAnalysisVar *b)
Definition: var.c:1204
RZ_API void rz_analysis_var_remove_access_at(RzAnalysisVar *var, ut64 address)
Definition: var.c:476
RZ_API char * rz_analysis_var_get_constraints_readable(RzAnalysisVar *var)
Definition: var.c:528
#define ACCESS_CMP(x, y)
Definition: var.c:11
static void var_field_free(RzAnalysisVarField *field)
Definition: var.c:1158
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
RZ_API void rz_analysis_function_delete_vars_by_kind(RzAnalysisFunction *fcn, RzAnalysisVarKind kind)
Definition: var.c:206
RZ_API RZ_BORROW RzPVector * rz_analysis_function_get_vars_used_at(RzAnalysisFunction *fcn, ut64 op_addr)
Definition: var.c:393
static const char * __int_type_from_size(int size)
Definition: var.c:13
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_DEPRECATE RZ_API RzList * rz_analysis_var_all_list(RzAnalysis *analysis, RzAnalysisFunction *fcn)
Definition: var.c:1135
RZ_API void rz_analysis_var_add_constraint(RzAnalysisVar *var, RZ_BORROW RzTypeConstraint *constraint)
Definition: var.c:524
RZ_API st64 rz_analysis_function_get_var_stackptr_at(RzAnalysisFunction *fcn, st64 delta, ut64 addr)
Definition: var.c:284
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: var.c:1232
RZ_API bool rz_analysis_var_check_name(const char *name)
Definition: var.c:344
RZ_API void rz_analysis_fcn_vars_add_types(RzAnalysis *analysis, RZ_NONNULL RzAnalysisFunction *fcn)
Updates the types database for function arguments.
Definition: var.c:1383
RZ_API int rz_analysis_var_get_argnum(RzAnalysisVar *var)
Definition: var.c:369
RZ_API bool rz_analysis_var_rename(RzAnalysisVar *var, const char *new_name, bool verbose)
Definition: var.c:348
RZ_API RZ_BORROW RzAnalysisVar * rz_analysis_function_get_var_byname(RzAnalysisFunction *fcn, const char *name)
Definition: var.c:247
RZ_API void rz_analysis_var_delete(RzAnalysisVar *var)
Definition: var.c:192
RZ_API RzAnalysisVar * rz_analysis_var_get_dst_var(RzAnalysisVar *var)
Definition: var.c:417
static bool var_add_structure_fields_to_list(RzAnalysis *a, RzAnalysisVar *av, RzList *list)
Definition: var.c:593
RZ_API const char * rz_analysis_function_get_var_reg_at(RzAnalysisFunction *fcn, st64 delta, ut64 addr)
Definition: var.c:314
#define STR_EQUAL(s1, s2)
Definition: var.c:855
static RzAnalysisVar * get_stack_var(RzAnalysisFunction *fcn, int delta)
Definition: var.c:657
static bool var_overlap(RzAnalysisVar *a, RzAnalysisVar *b, ut64 a_size)
Definition: var.c:71
static const char * get_regname(RzAnalysis *analysis, RzAnalysisValue *value)
Definition: var.c:621
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
RZ_API void rz_analysis_var_set_type(RzAnalysisVar *var, RZ_OWN RzType *type, bool resolve_overlaps)
Definition: var.c:170
static RzList * var_generate_list(RzAnalysis *a, RzAnalysisFunction *fcn, int kind)
Definition: var.c:1117
RZ_API void rz_analysis_fcn_vars_cache_init(RzAnalysis *analysis, RzAnalysisFcnVarsCache *cache, RzAnalysisFunction *fcn)
Definition: var.c:1209
RZ_DEPRECATE RZ_API RzList * rz_analysis_function_get_var_fields(RzAnalysisFunction *fcn, int kind)
Definition: var.c:1166
RZ_DEPRECATE RZ_API RzAnalysisVar * rz_analysis_get_used_function_var(RzAnalysis *analysis, ut64 addr)
Definition: var.c:398
static st64 delta
Definition: vmenus.c:2425
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static char * regname(int reg)
Definition: dis.c:71
static int sp
Definition: z80asm.c:91
static int verbose
Definition: z80asm.c:73
static int comma
Definition: z80asm.c:76
static int addr
Definition: z80asm.c:58