1 /* radare - LGPL - Copyright 2009-2018 - pancake */
2
3 #include <r_core.h>
4
5 #define MAXSTRLEN 50
6
set_fcn_args_info(RAnalFuncArg * arg,RAnal * anal,const char * fcn_name,const char * cc,int arg_num)7 static void set_fcn_args_info(RAnalFuncArg *arg, RAnal *anal, const char *fcn_name, const char *cc, int arg_num) {
8 if (!fcn_name || !arg || !anal) {
9 return;
10 }
11 Sdb *TDB = anal->sdb_types;
12 arg->name = r_type_func_args_name (TDB, fcn_name, arg_num);
13 arg->orig_c_type = r_type_func_args_type (TDB, fcn_name, arg_num);
14 if (!arg->name || !arg->orig_c_type) {
15 eprintf ("Missing type for function argument (%s)\n", fcn_name);
16 return;
17 }
18 if (!strncmp ("const ", arg->orig_c_type, 6)) {
19 arg->c_type = arg->orig_c_type + 6;
20 } else {
21 arg->c_type = arg->orig_c_type;
22 }
23 const char *query = sdb_fmt ("type.%s", arg->c_type);
24 arg->fmt = sdb_const_get (TDB, query, 0);
25 const char *t_query = sdb_fmt ("type.%s.size", arg->c_type);
26 arg->size = sdb_num_get (TDB, t_query, 0) / 8;
27 arg->cc_source = r_anal_cc_arg (anal, cc, arg_num);
28 }
29
resolve_fcn_name(RAnal * anal,const char * func_name)30 R_API char *resolve_fcn_name(RAnal *anal, const char *func_name) {
31 const char *str = func_name;
32 const char *name = func_name;
33 if (r_type_func_exist (anal->sdb_types, func_name)) {
34 return strdup (func_name);
35 }
36 while ((str = strchr (str, '.'))) {
37 name = str + 1;
38 str++;
39 }
40 if (r_type_func_exist (anal->sdb_types, name)) {
41 return strdup (name);
42 }
43 return r_type_func_guess (anal->sdb_types, (char*)func_name);
44 }
45
get_buf_val(ut8 * buf,int endian,int width)46 static ut64 get_buf_val(ut8 *buf, int endian, int width) {
47 return (width == 8)? r_read_ble64 (buf, endian) : (ut64) r_read_ble32 (buf,endian);
48 }
49
print_arg_str(int argcnt,const char * name,bool color)50 static void print_arg_str(int argcnt, const char *name, bool color) {
51 if (color) {
52 r_cons_printf (Color_BYELLOW" arg [%d]"Color_RESET" -"Color_BCYAN" %s"Color_RESET" : ",
53 argcnt, name);
54 } else {
55 r_cons_printf (" arg [%d] - %s : ", argcnt, name);
56 }
57 }
58
print_format_values(RCore * core,const char * fmt,bool onstack,ut64 src,bool color)59 static void print_format_values(RCore *core, const char *fmt, bool onstack, ut64 src, bool color) {
60 char opt;
61 ut64 bval = src;
62 int i;
63 int endian = core->print->big_endian;
64 int width = (core->anal->bits == 64)? 8: 4;
65 int bsize = R_MIN (64, core->blocksize);
66
67 ut8 *buf = malloc (bsize);
68 if (!buf) {
69 eprintf ("Cannot allocate %d byte(s)\n", bsize);
70 free (buf);
71 return;
72 }
73 if (fmt) {
74 opt = *fmt;
75 } else {
76 opt = 'p'; // void *ptr
77 }
78 if (onstack || ((opt != 'd' && opt != 'x') && !onstack)) {
79 if (color) {
80 r_cons_printf (Color_BGREEN"0x%08"PFMT64x Color_RESET" --> ", bval);
81 } else {
82 r_cons_printf ("0x%08"PFMT64x" --> ", bval);
83 }
84 r_io_read_at (core->io, bval, buf, bsize);
85 }
86 if (onstack) { // Fetch value from stack
87 bval = get_buf_val (buf, endian, width);
88 if (opt != 'd' && opt != 'x') {
89 r_io_read_at (core->io, bval, buf, bsize); // update buf with val from stack
90 }
91 }
92 r_cons_print (color? Color_BGREEN: "");
93 switch (opt) {
94 case 'z' : // Null terminated string
95 r_cons_print (color ?Color_RESET Color_BWHITE:"");
96 r_cons_print ("\"");
97 for (i = 0; i < MAXSTRLEN; i++) {
98 if (buf[i] == '\0') {
99 break;
100 }
101 ut8 b = buf[i];
102 if (IS_PRINTABLE (b)) {
103 r_cons_printf ("%c", b);
104 } else {
105 r_cons_printf ("\\x%02x", b);
106 }
107 if (i == MAXSTRLEN - 1) {
108 r_cons_print ("..."); // To show string is truncated
109 }
110 }
111 r_cons_print ("\"");
112 r_cons_newline ();
113 break;
114 case 'd' : // integer
115 case 'x' :
116 r_cons_printf ("0x%08" PFMT64x, bval);
117 r_cons_newline ();
118 break;
119 case 'c' : // char
120 r_cons_print ("\'");
121 ut8 ch = buf[0];
122 if (IS_PRINTABLE (ch)) {
123 r_cons_printf ("%c", ch);
124 } else {
125 r_cons_printf ("\\x%02x", ch);
126 }
127 r_cons_print ("\'");
128 r_cons_newline ();
129 break;
130 case 'p' : // pointer
131 {
132 // Try to deref the pointer once again
133 r_cons_printf ("0x%08"PFMT64x, get_buf_val (buf, endian, width));
134 r_cons_newline ();
135 break;
136 }
137 default:
138 //TODO: support types like structs and unions
139 r_cons_println ("unk_format");
140 }
141 r_cons_print (Color_RESET);
142 free (buf);
143 }
144
145 /* This function display list of arg with some colors */
146
r_core_print_func_args(RCore * core)147 R_API void r_core_print_func_args(RCore *core) {
148 RListIter *iter;
149 bool color = r_config_get_i (core->config, "scr.color");
150 if (!core->anal) {
151 return;
152 }
153 if (!core->anal->reg) {
154 return;
155 }
156 const char *pc = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
157 ut64 cur_addr = r_reg_getv (core->anal->reg, pc);
158 RAnalOp *op = r_core_anal_op (core, cur_addr, R_ANAL_OP_MASK_BASIC);
159 if (!op) {
160 return;
161 }
162 if (op->type == R_ANAL_OP_TYPE_CALL) {
163 RAnalFunction *fcn;
164 RAnalFuncArg *arg;
165 bool onstack = false;
166 const char *fcn_name = NULL;
167 ut64 pcv = op->jump;
168 if (pcv == UT64_MAX) {
169 pcv = op->ptr;
170 }
171 fcn = r_anal_get_function_at (core->anal, pcv);
172 if (fcn) {
173 fcn_name = fcn->name;
174 } else {
175 if (core->flags) {
176 RFlagItem *item = r_flag_get_i (core->flags, pcv);
177 if (item) {
178 fcn_name = item->name;
179 }
180 }
181 }
182 RList *list = r_core_get_func_args (core, fcn_name);
183 if (!r_list_empty (list)) {
184 int argcnt = 0;
185 r_list_foreach (list, iter, arg) {
186 if (arg->cc_source && !strncmp (arg->cc_source, "stack", 5)) {
187 onstack = true;
188 }
189 print_arg_str (argcnt, arg->name, color);
190 print_format_values (core, arg->fmt, onstack, arg->src, color);
191 argcnt++;
192 }
193 } else {
194 int nargs = 4; // TODO: use a correct value here when available
195 //if (nargs > 0) {
196 int i;
197 const char *cc = r_anal_cc_default (core->anal); // or use "reg" ?
198 for (i = 0; i < nargs; i++) {
199 ut64 v = r_debug_arg_get (core->dbg, cc, i);
200 print_arg_str (i, "", color);
201 r_cons_printf ("0x%08" PFMT64x, v);
202 r_cons_newline ();
203 }
204 //} else {
205 // print_arg_str (0, "void", color);
206 //}
207 }
208 }
209 r_anal_op_fini (op);
210 }
211
r_anal_fcn_arg_free(RAnalFuncArg * arg)212 static void r_anal_fcn_arg_free(RAnalFuncArg *arg) {
213 if (!arg) {
214 return;
215 }
216 free (arg->orig_c_type);
217 free (arg);
218 }
219
220 /* Returns a list of RAnalFuncArg */
r_core_get_func_args(RCore * core,const char * fcn_name)221 R_API RList *r_core_get_func_args(RCore *core, const char *fcn_name) {
222 if (!fcn_name || !core->anal) {
223 return NULL;
224 }
225 Sdb *TDB = core->anal->sdb_types;
226 char *key = resolve_fcn_name (core->anal, fcn_name);
227 if (!key) {
228 return NULL;
229 }
230 const char *sp = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
231 int nargs = r_type_func_args_count (TDB, key);
232 if (!r_anal_cc_func (core->anal, key)){
233 return NULL;
234 }
235 char *cc = strdup (r_anal_cc_func (core->anal, key));
236 const char *src = r_anal_cc_arg (core->anal, cc, 0); // src of first argument
237 if (!cc) {
238 // unsupported calling convention
239 free (key);
240 return NULL;
241 }
242 RList *list = r_list_newf ((RListFree)r_anal_fcn_arg_free);
243 int i;
244 ut64 spv = r_reg_getv (core->anal->reg, sp);
245 ut64 s_width = (core->anal->bits == 64)? 8: 4;
246 if (src && !strcmp (src, "stack_rev")) {
247 for (i = nargs - 1; i >= 0; i--) {
248 RAnalFuncArg *arg = R_NEW0 (RAnalFuncArg);
249 set_fcn_args_info (arg, core->anal, key, cc, i);
250 arg->src = spv;
251 spv += arg->size? arg->size : s_width;
252 r_list_append (list, arg);
253 }
254 } else {
255 for (i = 0; i < nargs; i++) {
256 RAnalFuncArg *arg = R_NEW0 (RAnalFuncArg);
257 if (!arg) {
258 r_list_free (list);
259 return NULL;
260 }
261 set_fcn_args_info (arg, core->anal, key, cc, i);
262 if (src && !strncmp (src, "stack", 5)) {
263 arg->src = spv;
264 if (!arg->size) {
265 arg->size = s_width;
266 }
267 spv += arg->size;
268 } else {
269 const char *cs = arg->cc_source;
270 if (!cs) {
271 cs = r_anal_cc_default (core->anal);
272 }
273 if (cs) {
274 arg->src = r_reg_getv (core->anal->reg, cs);
275 }
276 }
277 r_list_append (list, arg);
278 }
279 }
280 free (key);
281 free (cc);
282 return list;
283 }
284