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