Rizin
unix-like reverse engineering framework and cli tools
carg.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2018 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_core.h>
5 
6 #define MAXSTRLEN 50
7 
13 RZ_DEPRECATE RZ_API ut64 rz_core_arg_get(RzCore *core, const char *cc, int num) {
15  if (!cc) {
17  }
18  if (rz_core_is_debug(core)) {
19  rz_debug_reg_sync(core->dbg, RZ_REG_TYPE_ANY, false);
20  }
21  if (!RZ_STR_ISEMPTY(cc)) {
22  if (!strcmp(cc, "stdcall") || !strcmp(cc, "pascal")) {
24  int bits = rz_core_is_debug(core) ? core->dbg->bits : core->analysis->bits;
25  if (bits) {
26  ut64 n64;
27  sp += 8; // skip return address, assume we are inside the call
28  sp += 8 * num;
29  // FIXME: honor endianness of platform
30  rz_io_read_at(core->io, sp, (ut8 *)&n64, sizeof(ut64));
31  return (ut64)n64;
32  } else {
33  sp += 4; // skip return address, assume we are inside the call
34  sp += 4 * num;
35  ut32 n32;
36  // FIXME: honor endianness of platform
37  rz_io_read_at(core->io, sp, (ut8 *)&n32, sizeof(ut32));
38  return (ut64)n32;
39  }
40  }
41  const char *rn = rz_analysis_cc_arg(core->analysis, cc, num);
42  if (rn) {
43  return rz_core_reg_getv_by_role_or_name(core, rn);
44  }
45  }
46  char reg[32];
47  return rz_core_reg_getv_by_role_or_name(core, rz_strf(reg, "A%d", num));
48 }
49 
55 RZ_DEPRECATE RZ_API bool rz_core_arg_set(RzCore *core, const char *cc, int num, ut64 val) {
56  rz_return_val_if_fail(core, false);
57  if (!RZ_STR_ISEMPTY(cc)) {
59  }
60  const char *rn = rz_analysis_cc_arg(core->analysis, cc, num);
61  if (rn) {
63  return true;
64  }
65  char reg[32];
67  return true;
68 }
69 
70 static void set_fcn_args_info(RzAnalysisFuncArg *arg, RzAnalysis *analysis, const char *fcn_name, const char *cc, int arg_num) {
71  if (!fcn_name || !arg || !analysis) {
72  return;
73  }
74  arg->name = rz_type_func_args_name(analysis->typedb, fcn_name, arg_num);
75  arg->orig_c_type = rz_type_func_args_type(analysis->typedb, fcn_name, arg_num);
76  if (!arg->name || !arg->orig_c_type) {
77  eprintf("Missing type for function argument (%s)\n", fcn_name);
78  return;
79  }
80  arg->c_type = arg->orig_c_type;
81  arg->fmt = rz_type_as_format(analysis->typedb, arg->c_type);
82  arg->size = rz_type_db_get_bitsize(analysis->typedb, arg->c_type) / 8;
83  arg->cc_source = rz_analysis_cc_arg(analysis, cc, arg_num);
84 }
85 
86 RZ_API char *resolve_fcn_name(RzAnalysis *analysis, const char *func_name) {
87  const char *str = func_name;
88  const char *name = func_name;
89  if (rz_type_func_exist(analysis->typedb, func_name)) {
90  return strdup(func_name);
91  }
92  while ((str = strchr(str, '.'))) {
93  name = str + 1;
94  str++;
95  }
96  if (rz_type_func_exist(analysis->typedb, name)) {
97  return strdup(name);
98  }
99  return rz_analysis_function_name_guess(analysis->typedb, (char *)func_name);
100 }
101 
102 static ut64 get_buf_val(ut8 *buf, int endian, int width) {
103  return (width == 8) ? rz_read_ble64(buf, endian) : (ut64)rz_read_ble32(buf, endian);
104 }
105 
106 static void print_arg_str(int argcnt, const char *name, bool color) {
107  if (color) {
108  rz_cons_printf(Color_BYELLOW " arg [%d]" Color_RESET " -" Color_BCYAN " %s" Color_RESET " : ",
109  argcnt, name);
110  } else {
111  rz_cons_printf(" arg [%d] - %s : ", argcnt, name);
112  }
113 }
114 
115 static void print_format_values(RzCore *core, const char *fmt, bool onstack, ut64 src, bool color) {
116  char opt;
117  ut64 bval = src;
118  int i;
119  int endian = core->print->big_endian;
120  int width = (core->analysis->bits == 64) ? 8 : 4;
121  int bsize = RZ_MIN(64, core->blocksize);
122 
123  ut8 *buf = malloc(bsize);
124  if (!buf) {
125  eprintf("Cannot allocate %d byte(s)\n", bsize);
126  free(buf);
127  return;
128  }
129  if (fmt) {
130  opt = *fmt;
131  } else {
132  opt = 'p'; // void *ptr
133  }
134  if (onstack || ((opt != 'd' && opt != 'x') && !onstack)) {
135  if (color) {
136  rz_cons_printf(Color_BGREEN "0x%08" PFMT64x Color_RESET " --> ", bval);
137  } else {
138  rz_cons_printf("0x%08" PFMT64x " --> ", bval);
139  }
140  rz_io_read_at(core->io, bval, buf, bsize);
141  }
142  if (onstack) { // Fetch value from stack
143  bval = get_buf_val(buf, endian, width);
144  if (opt != 'd' && opt != 'x') {
145  rz_io_read_at(core->io, bval, buf, bsize); // update buf with val from stack
146  }
147  }
148  rz_cons_print(color ? Color_BGREEN : "");
149  switch (opt) {
150  case 'z': // Null terminated string
151  rz_cons_print(color ? Color_RESET Color_BWHITE : "");
152  rz_cons_print("\"");
153  for (i = 0; i < MAXSTRLEN; i++) {
154  if (buf[i] == '\0') {
155  break;
156  }
157  ut8 b = buf[i];
158  if (IS_PRINTABLE(b)) {
159  rz_cons_printf("%c", b);
160  } else {
161  rz_cons_printf("\\x%02x", b);
162  }
163  if (i == MAXSTRLEN - 1) {
164  rz_cons_print("..."); // To show string is truncated
165  }
166  }
167  rz_cons_print("\"");
168  rz_cons_newline();
169  break;
170  case 'd': // integer
171  case 'x':
172  rz_cons_printf("0x%08" PFMT64x, bval);
173  rz_cons_newline();
174  break;
175  case 'c': // char
176  rz_cons_print("\'");
177  ut8 ch = buf[0];
178  if (IS_PRINTABLE(ch)) {
179  rz_cons_printf("%c", ch);
180  } else {
181  rz_cons_printf("\\x%02x", ch);
182  }
183  rz_cons_print("\'");
184  rz_cons_newline();
185  break;
186  case 'p': // pointer
187  {
188  // Try to deref the pointer once again
189  rz_cons_printf("0x%08" PFMT64x, get_buf_val(buf, endian, width));
190  rz_cons_newline();
191  break;
192  }
193  default:
194  // TODO: support types like structs and unions
195  rz_cons_println("unk_format");
196  }
197  rz_cons_print(Color_RESET);
198  free(buf);
199 }
200 
201 /* This function display list of arg with some colors */
202 
204  RzListIter *iter;
205  bool color = rz_config_get_i(core->config, "scr.color");
206  if (!core->analysis) {
207  return;
208  }
209  if (!core->analysis->reg) {
210  return;
211  }
212  const char *pc = rz_reg_get_name(core->analysis->reg, RZ_REG_NAME_PC);
213  ut64 cur_addr = rz_reg_getv(core->analysis->reg, pc);
215  if (!op) {
216  return;
217  }
218  if (op->type == RZ_ANALYSIS_OP_TYPE_CALL) {
219  RzAnalysisFunction *fcn;
221  bool onstack = false;
222  const char *fcn_name = NULL;
223  ut64 pcv = op->jump;
224  if (pcv == UT64_MAX) {
225  pcv = op->ptr;
226  }
227  fcn = rz_analysis_get_function_at(core->analysis, pcv);
228  if (fcn) {
229  fcn_name = fcn->name;
230  } else {
231  if (core->flags) {
232  RzFlagItem *item = rz_flag_get_i(core->flags, pcv);
233  if (item) {
234  fcn_name = item->name;
235  }
236  }
237  }
238  RzList *list = rz_core_get_func_args(core, fcn_name);
239  if (!rz_list_empty(list)) {
240  int argcnt = 0;
241  rz_list_foreach (list, iter, arg) {
242  if (arg->cc_source && !strncmp(arg->cc_source, "stack", 5)) {
243  onstack = true;
244  }
245  print_arg_str(argcnt, arg->name, color);
246  print_format_values(core, arg->fmt, onstack, arg->src, color);
247  argcnt++;
248  }
249  } else {
250  int nargs = 4; // TODO: use a correct value here when available
251  // if (nargs > 0) {
252  int i;
253  const char *cc = rz_analysis_cc_default(core->analysis); // or use "reg" ?
254  for (i = 0; i < nargs; i++) {
255  ut64 v = rz_core_arg_get(core, cc, i);
256  print_arg_str(i, "", color);
257  rz_cons_printf("0x%08" PFMT64x, v);
258  rz_cons_newline();
259  }
260  //} else {
261  // print_arg_str (0, "void", color);
262  //}
263  }
265  }
267 }
268 
270  if (!arg) {
271  return;
272  }
273  free(arg);
274 }
275 
276 RZ_API RZ_OWN RzList /*<RzAnalysisFuncArg *>*/ *rz_core_get_func_args(RzCore *core, const char *fcn_name) {
277  if (!fcn_name || !core->analysis) {
278  return NULL;
279  }
280  char *key = resolve_fcn_name(core->analysis, fcn_name);
281  if (!key) {
282  return NULL;
283  }
285  const char *sp = rz_reg_get_name(core->analysis->reg, RZ_REG_NAME_SP);
287  if (!rz_analysis_cc_func(core->analysis, key)) {
289  return NULL;
290  }
291  char *cc = strdup(rz_analysis_cc_func(core->analysis, key));
292  const char *src = rz_analysis_cc_arg(core->analysis, cc, 0); // src of first argument
293  if (!cc) {
294  // unsupported calling convention
295  free(key);
297  return NULL;
298  }
299  int i;
300  ut64 spv = rz_reg_getv(core->analysis->reg, sp);
301  ut64 s_width = (core->analysis->bits == 64) ? 8 : 4;
302  if (src && !strcmp(src, "stack_rev")) {
303  for (i = nargs - 1; i >= 0; i--) {
305  set_fcn_args_info(arg, core->analysis, key, cc, i);
306  arg->src = spv;
307  spv += arg->size ? arg->size : s_width;
309  }
310  } else {
311  for (i = 0; i < nargs; i++) {
313  if (!arg) {
314  free(cc);
316  return NULL;
317  }
318  set_fcn_args_info(arg, core->analysis, key, cc, i);
319  if (src && !strncmp(src, "stack", 5)) {
320  arg->src = spv;
321  if (!arg->size) {
322  arg->size = s_width;
323  }
324  spv += arg->size;
325  } else {
326  const char *cs = arg->cc_source;
327  if (!cs) {
329  }
330  if (cs) {
331  arg->src = rz_reg_getv(core->analysis->reg, cs);
332  }
333  }
335  }
336  }
337  free(key);
338  free(cc);
339  return list;
340 }
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 RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
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
ut16 val
Definition: armass64_const.h:6
int bits(struct state *s, int need)
Definition: blast.c:72
RZ_API RzAnalysisOp * rz_core_analysis_op(RzCore *core, ut64 addr, int mask)
Definition: canalysis.c:1033
static void print_arg_str(int argcnt, const char *name, bool color)
Definition: carg.c:106
RZ_API void rz_core_print_func_args(RzCore *core)
Definition: carg.c:203
static void print_format_values(RzCore *core, const char *fmt, bool onstack, ut64 src, bool color)
Definition: carg.c:115
RZ_DEPRECATE RZ_API bool rz_core_arg_set(RzCore *core, const char *cc, int num, ut64 val)
Set the value of the num-th argument in the current debug or emulation state.
Definition: carg.c:55
RZ_API RZ_OWN RzList * rz_core_get_func_args(RzCore *core, const char *fcn_name)
Definition: carg.c:276
static void set_fcn_args_info(RzAnalysisFuncArg *arg, RzAnalysis *analysis, const char *fcn_name, const char *cc, int arg_num)
Definition: carg.c:70
static ut64 get_buf_val(ut8 *buf, int endian, int width)
Definition: carg.c:102
static void rz_analysis_fcn_arg_free(RzAnalysisFuncArg *arg)
Definition: carg.c:269
RZ_DEPRECATE RZ_API ut64 rz_core_arg_get(RzCore *core, const char *cc, int num)
Get the value of the num-th argument from the current debug or emulation state.
Definition: carg.c:13
#define MAXSTRLEN
Definition: carg.c:6
RZ_API char * resolve_fcn_name(RzAnalysis *analysis, const char *func_name)
Definition: carg.c:86
RZ_API const char * rz_analysis_syscc_default(RzAnalysis *analysis)
Definition: cc.c:210
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_default(RzAnalysis *analysis)
Definition: cc.c:200
RZ_API bool rz_core_is_debug(RzCore *core)
Check whether the core is in debug mode (equivalent to cfg.debug)
Definition: cdebug.c:13
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
#define RZ_API
RZ_API RzReg * rz_core_reg_default(RzCore *core)
Get the currently relevant RzReg.
Definition: creg.c:17
RZ_API ut64 rz_core_reg_getv_by_role_or_name(RzCore *core, const char *name)
rz_reg_getv_by_role_or_name() on rz_core_reg_default()
Definition: creg.c:24
RZ_API bool rz_core_reg_set_by_role_or_name(RzCore *core, const char *name, ut64 num)
set on rz_core_reg_default()
Definition: creg.c:39
#define NULL
Definition: cris-opc.c:27
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 static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
uint32_t ut32
RZ_API int rz_debug_reg_sync(RzDebug *dbg, int type, int write)
Definition: dreg.c:9
const char * v
Definition: dsignal.c:12
RZ_API RzFlagItem * rz_flag_get_i(RzFlag *f, ut64 off)
Definition: flag.c:317
RZ_API RZ_OWN char * rz_type_as_format(const RzTypeDB *typedb, RZ_NONNULL RzType *type)
Represents the RzType as a pf format string.
Definition: format.c:3005
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
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_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
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
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_API bool rz_analysis_op_fini(RzAnalysisOp *op)
Definition: op.c:37
RZ_API ut64 rz_reg_getv(RzReg *reg, const char *name)
Definition: reg.c:332
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API ut64 rz_reg_get_value_by_role(RzReg *reg, RzRegisterId role)
Definition: rvalue.c:181
@ RZ_ANALYSIS_OP_MASK_BASIC
Definition: rz_analysis.h:440
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define Color_BCYAN
Definition: rz_cons.h:652
#define Color_BYELLOW
Definition: rz_cons.h:650
#define Color_RESET
Definition: rz_cons.h:617
#define Color_BWHITE
Definition: rz_cons.h:644
#define Color_BGREEN
Definition: rz_cons.h:646
static ut64 rz_read_ble64(const void *src, bool big_endian)
Definition: rz_endian.h:501
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
RZ_API bool rz_io_read_at(RzIO *io, ut64 addr, ut8 *buf, int len)
Definition: io.c:300
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
@ RZ_REG_NAME_SP
Definition: rz_reg.h:44
@ RZ_REG_NAME_PC
Definition: rz_reg.h:43
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define IS_PRINTABLE(x)
Definition: rz_str_util.h:10
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define PFMT64x
Definition: rz_types.h:393
#define RZ_DEPRECATE
Definition: rz_types.h:66
#define RZ_MIN(x, y)
#define UT64_MAX
Definition: rz_types_base.h:86
#define b(i)
Definition: sha256.c:42
const char * name
Definition: sparc-opc.c:1838
Definition: z80asm.h:102
RzTypeDB * typedb
Definition: rz_analysis.h:602
RzAnalysis * analysis
Definition: rz_core.h:322
RzDebug * dbg
Definition: rz_core.h:329
RzIO * io
Definition: rz_core.h:313
RzFlag * flags
Definition: rz_core.h:330
RzPrint * print
Definition: rz_core.h:327
ut32 blocksize
Definition: rz_core.h:303
RzConfig * config
Definition: rz_core.h:300
int bits
Definition: rz_debug.h:243
char * name
Definition: rz_flag.h:35
int big_endian
Definition: rz_print.h:124
int width
Definition: main.c:10
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 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 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
static int color
Definition: visual.c:20
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int sp
Definition: z80asm.c:91