1 /* radare - LGPL - Copyright 2013-2020 - pancake, oddcoder, sivaramaaa */
2 
3 #include <r_util.h>
4 
r_type_set(Sdb * TDB,ut64 at,const char * field,ut64 val)5 R_API int r_type_set(Sdb *TDB, ut64 at, const char *field, ut64 val) {
6 	const char *kind;
7 	char var[128];
8 	sprintf (var, "link.%08"PFMT64x, at);
9 	kind = sdb_const_get (TDB, var, NULL);
10 	if (kind) {
11 		const char *p = sdb_const_get (TDB, kind, NULL);
12 		if (p) {
13 			snprintf (var, sizeof (var), "%s.%s.%s", p, kind, field);
14 			int off = sdb_array_get_num (TDB, var, 1, NULL);
15 			//int siz = sdb_array_get_num (DB, var, 2, NULL);
16 			eprintf ("wv 0x%08"PFMT64x" @ 0x%08"PFMT64x, val, at + off);
17 			return true;
18 		}
19 		eprintf ("Invalid kind of type\n");
20 	}
21 	return false;
22 }
23 
r_type_kind(Sdb * TDB,const char * name)24 R_API int r_type_kind(Sdb *TDB, const char *name) {
25 	if (!name) {
26 		return -1;
27 	}
28 	const char *type = sdb_const_get (TDB, name, 0);
29 	if (!type) {
30 		return -1;
31 	}
32 	if (!strcmp (type, "enum")) {
33 		return R_TYPE_ENUM;
34 	}
35 	if (!strcmp (type, "struct")) {
36 		return R_TYPE_STRUCT;
37 	}
38 	if (!strcmp (type, "union")) {
39 		return R_TYPE_UNION;
40 	}
41 	if (!strcmp (type, "type")) {
42 		return R_TYPE_BASIC;
43 	}
44 	if (!strcmp (type, "typedef")) {
45 		return R_TYPE_TYPEDEF;
46 	}
47 	return -1;
48 }
49 
r_type_get_enum(Sdb * TDB,const char * name)50 R_API RList* r_type_get_enum (Sdb *TDB, const char *name) {
51 	char *p, var[130];
52 	int n;
53 
54 	if (r_type_kind (TDB, name) != R_TYPE_ENUM) {
55 		return NULL;
56 	}
57 	RList *res = r_list_new ();
58 	snprintf (var, sizeof (var), "enum.%s", name);
59 	for (n = 0; (p = sdb_array_get (TDB, var, n, NULL)); n++) {
60 		RTypeEnum *member = R_NEW0 (RTypeEnum);
61 		if (member) {
62 			char *var2 = r_str_newf ("%s.%s", var, p);
63 			if (var2) {
64 				char *val = sdb_array_get (TDB, var2, 0, NULL);
65 				if (val) {
66 					member->name = p;
67 					member->val = val;
68 					r_list_append (res, member);
69 				} else {
70 					free (member);
71 					free (var2);
72 				}
73 			} else {
74 				free (member);
75 			}
76 		}
77 	}
78 	return res;
79 }
80 
r_type_enum_member(Sdb * TDB,const char * name,const char * member,ut64 val)81 R_API char *r_type_enum_member(Sdb *TDB, const char *name, const char *member, ut64 val) {
82 	if (r_type_kind (TDB, name) != R_TYPE_ENUM) {
83 		return NULL;
84 	}
85 	const char *q = member
86 		? sdb_fmt ("enum.%s.%s", name, member)
87 		: sdb_fmt ("enum.%s.0x%"PFMT64x, name, val);
88 	return sdb_get (TDB, q, 0);
89 }
90 
r_type_enum_getbitfield(Sdb * TDB,const char * name,ut64 val)91 R_API char *r_type_enum_getbitfield(Sdb *TDB, const char *name, ut64 val) {
92 	char *q, *ret = NULL;
93 	const char *res;
94 	int i;
95 
96 	if (r_type_kind (TDB, name) != R_TYPE_ENUM) {
97 		return NULL;
98 	}
99 	bool isFirst = true;
100 	ret = r_str_appendf (ret, "0x%08"PFMT64x" : ", val);
101 	for (i = 0; i < 32; i++) {
102 		ut32 n = 1ULL << i;
103 		if (!(val & n)) {
104 			continue;
105 		}
106 		q = sdb_fmt ("enum.%s.0x%x", name, n);
107 		res = sdb_const_get (TDB, q, 0);
108 		if (isFirst) {
109 			isFirst = false;
110 		} else {
111 			ret = r_str_append (ret, " | ");
112 		}
113 		if (res) {
114 			ret = r_str_append (ret, res);
115 		} else {
116 			ret = r_str_appendf (ret, "0x%x", n);
117 		}
118 	}
119 	return ret;
120 }
121 
r_type_get_bitsize(Sdb * TDB,const char * type)122 R_API ut64 r_type_get_bitsize(Sdb *TDB, const char *type) {
123 	char *query;
124 	/* Filter out the structure keyword if type looks like "struct mystruc" */
125 	const char *tmptype;
126 	if (!strncmp (type, "struct ", 7)) {
127 		tmptype = type + 7;
128 	} else if (!strncmp (type, "union ", 6)) {
129 		tmptype = type + 6;
130 	} else {
131 		tmptype = type;
132 	}
133 	if ((strstr (type, "*(") || strstr (type, " *")) && strncmp (type, "char *", 7)) {
134 		return 32;
135 	}
136 	const char *t = sdb_const_get (TDB, tmptype, 0);
137 	if (!t) {
138 		if (!strncmp (tmptype, "enum ", 5)) {
139 			//XXX: Need a proper way to determine size of enum
140 			return 32;
141 		}
142 		return 0;
143 	}
144 	if (!strcmp (t, "type")){
145 		query = r_str_newf ("type.%s.size", tmptype);
146 		ut64 r = sdb_num_get (TDB, query, 0); // returns size in bits
147 		free (query);
148 		return r;
149 	}
150 	if (!strcmp (t, "struct") || !strcmp (t, "union")) {
151 		query = r_str_newf ("%s.%s", t, tmptype);
152 		char *members = sdb_get (TDB, query, 0);
153 		char *next, *ptr = members;
154 		ut64 ret = 0;
155 		if (members) {
156 			do {
157 				char *name = sdb_anext (ptr, &next);
158 				if (!name) {
159 					break;
160 				}
161 				free (query);
162 				query = r_str_newf ("%s.%s.%s", t, tmptype, name);
163 				char *subtype = sdb_get (TDB, query, 0);
164 				R_FREE (query);
165 				if (!subtype) {
166 					break;
167 				}
168 				char *tmp = strchr (subtype, ',');
169 				if (tmp) {
170 					*tmp++ = 0;
171 					tmp = strchr (tmp, ',');
172 					if (tmp) {
173 						*tmp++ = 0;
174 					}
175 					int elements = r_num_math (NULL, tmp);
176 					if (elements == 0) {
177 						elements = 1;
178 					}
179 					if (!strcmp (t, "struct")) {
180 						ret += r_type_get_bitsize (TDB, subtype) * elements;
181 					} else {
182 						ut64 sz = r_type_get_bitsize (TDB, subtype) * elements;
183 						ret = sz > ret ? sz : ret;
184 					}
185 				}
186 				free (subtype);
187 				ptr = next;
188 			} while (next);
189 			free (members);
190 		}
191 		free (query);
192 		return ret;
193 	}
194 	return 0;
195 }
196 
r_type_get_struct_memb(Sdb * TDB,const char * type,int offset)197 R_API char *r_type_get_struct_memb(Sdb *TDB, const char *type, int offset) {
198 	int i, cur_offset, next_offset = 0;
199 	char *res = NULL;
200 
201 	if (offset < 0) {
202 		return NULL;
203 	}
204 	char* query = sdb_fmt ("struct.%s", type);
205 	char *members = sdb_get (TDB, query, 0);
206 	if (!members) {
207 		//eprintf ("%s is not a struct\n", type);
208 		return NULL;
209 	}
210 	int nargs = r_str_split (members, ',');
211 	for (i = 0; i < nargs ; i++) {
212 		const char *name = r_str_word_get0 (members, i);
213 		if (!name) {
214 			break;
215 		}
216 		query = sdb_fmt ("struct.%s.%s", type, name);
217 		char *subtype = sdb_get (TDB, query, 0);
218 		if (!subtype) {
219 			break;
220 		}
221 		int len = r_str_split (subtype, ',');
222 		if (len < 3) {
223 			free (subtype);
224 			break;
225 		}
226 		cur_offset = r_num_math (NULL, r_str_word_get0 (subtype, len - 2));
227 		if (cur_offset > 0 && cur_offset < next_offset) {
228 			free (subtype);
229 			break;
230 		}
231 		if (!cur_offset) {
232 			cur_offset = next_offset;
233 		}
234 		if (cur_offset == offset) {
235 			res = r_str_newf ("%s.%s", type, name);
236 			free (subtype);
237 			break;
238 		}
239 		int arrsz = r_num_math (NULL, r_str_word_get0 (subtype, len - 1));
240 		int fsize = (r_type_get_bitsize (TDB, subtype) * (arrsz ? arrsz : 1)) / 8;
241 		if (!fsize) {
242 			free (subtype);
243 			break;
244 		}
245 		next_offset = cur_offset + fsize;
246 		// Handle nested structs
247 		if (offset > cur_offset && offset < next_offset) {
248 			char *nested_type = (char *)r_str_word_get0 (subtype, 0);
249 			if (r_str_startswith (nested_type, "struct ") && !r_str_endswith (nested_type, " *")) {
250 				len = r_str_split (nested_type, ' ');
251 				if (len < 2) {
252 					free (subtype);
253 					break;
254 				}
255 				nested_type = (char *)r_str_word_get0 (nested_type, 1);
256 				char *nested_res = r_type_get_struct_memb (TDB, nested_type, offset - cur_offset);
257 				if (nested_res) {
258 					len = r_str_split(nested_res, '.');
259 					res = r_str_newf ("%s.%s.%s", type, name, r_str_word_get0 (nested_res, len - 1));
260 					free (nested_res);
261 					free (subtype);
262 					break;
263 				}
264 			}
265 		}
266 		free (subtype);
267 	}
268 	free (members);
269 	return res;
270 }
271 
272 // XXX this function is slow!
r_type_get_by_offset(Sdb * TDB,ut64 offset)273 R_API RList* r_type_get_by_offset(Sdb *TDB, ut64 offset) {
274 	RList *offtypes = r_list_new ();
275 	SdbList *ls = sdb_foreach_list (TDB, true);
276 	SdbListIter *lsi;
277 	SdbKv *kv;
278 	ls_foreach (ls, lsi, kv) {
279 		// TODO: Add unions support
280 		if (!strncmp (sdbkv_value (kv), "struct", 6) && strncmp (sdbkv_key (kv), "struct.", 7)) {
281 			char *res = r_type_get_struct_memb (TDB, sdbkv_key (kv), offset);
282 			if (res) {
283 				r_list_append (offtypes, res);
284 			}
285 		}
286 	}
287 	ls_free (ls);
288 	return offtypes;
289 }
290 
291 // XXX 12 is the maxstructsizedelta
292 #define TYPE_RANGE_BASE(x) ((x)>>16)
293 
types_range_list(Sdb * db,ut64 addr)294 static RList *types_range_list(Sdb *db, ut64 addr) {
295 	RList *list = NULL;
296 	ut64 base = TYPE_RANGE_BASE (addr);
297 	char *s = r_str_newf ("range.%"PFMT64x, base);
298 	if (s) {
299 		char *r = sdb_get (db, s, 0);
300 		if (r) {
301 			list = r_str_split_list (r, " ", -1);
302 		}
303 		free (s);
304 	}
305 	return list;
306 }
307 
types_range_del(Sdb * db,ut64 addr)308 static void types_range_del(Sdb *db, ut64 addr) {
309 	ut64 base = TYPE_RANGE_BASE (addr);
310 	const char *k = sdb_fmt ("range.%"PFMT64x, base);
311 	char valstr[SDB_NUM_BUFSZ];
312 	const char *v = sdb_itoa (addr, valstr, SDB_NUM_BASE);
313 	sdb_array_remove (db, k, v, 0);
314 }
315 
types_range_add(Sdb * db,ut64 addr)316 static void types_range_add(Sdb *db, ut64 addr) {
317 	ut64 base = TYPE_RANGE_BASE (addr);
318 	const char *k = sdb_fmt ("range.%"PFMT64x, base);
319 	(void)sdb_array_add_num (db, k, addr, 0);
320 }
321 
r_type_link_at(Sdb * TDB,ut64 addr)322 R_API char *r_type_link_at(Sdb *TDB, ut64 addr) {
323 	if (addr == UT64_MAX) {
324 		return NULL;
325 	}
326 	const char *query = sdb_fmt ("link.%08"PFMT64x, addr);
327 	char *res = sdb_get (TDB, query, 0);
328 	if (!res) { // resolve struct memb if possible for given addr
329 		RList *list = types_range_list (TDB, addr);
330 		RListIter *iter;
331 		const char *s;
332 		r_list_foreach (list, iter, s) {
333 			ut64 laddr = r_num_get (NULL, s);
334 			if (addr > laddr) {
335 				int delta = addr - laddr;
336 				const char *lk = sdb_fmt ("link.%08"PFMT64x, laddr);
337 				char *k = sdb_get (TDB, lk, 0);
338 				res = r_type_get_struct_memb (TDB, k, delta);
339 				if (res) {
340 					break;
341 				}
342 				free (k);
343 			}
344 		}
345 	}
346 	return res;
347 }
348 
r_type_set_link(Sdb * TDB,const char * type,ut64 addr)349 R_API int r_type_set_link(Sdb *TDB, const char *type, ut64 addr) {
350 	if (sdb_const_get (TDB, type, 0)) {
351 		char *laddr = r_str_newf ("link.%08"PFMT64x, addr);
352 		sdb_set (TDB, laddr, type, 0);
353 		types_range_add (TDB, addr);
354 		free (laddr);
355 		return true;
356 	}
357 	return false;
358 }
359 
r_type_link_offset(Sdb * TDB,const char * type,ut64 addr)360 R_API int r_type_link_offset(Sdb *TDB, const char *type, ut64 addr) {
361 	if (sdb_const_get (TDB, type, 0)) {
362 		char *laddr = r_str_newf ("offset.%08"PFMT64x, addr);
363 		sdb_set (TDB, laddr, type, 0);
364 		free (laddr);
365 		return true;
366 	}
367 	return false;
368 }
369 
r_type_unlink(Sdb * TDB,ut64 addr)370 R_API int r_type_unlink(Sdb *TDB, ut64 addr) {
371 	char *laddr = sdb_fmt ("link.%08"PFMT64x, addr);
372 	sdb_unset (TDB, laddr, 0);
373 	types_range_del (TDB, addr);
374 	return true;
375 }
376 
fmt_struct_union(Sdb * TDB,char * var,bool is_typedef)377 static char *fmt_struct_union(Sdb *TDB, char *var, bool is_typedef) {
378 	// assumes var list is sorted by offset.. should do more checks here
379 	char *p = NULL, *vars = NULL, var2[132], *fmt = NULL;
380 	size_t n;
381 	char *fields = r_str_newf ("%s.fields", var);
382 	char *nfields = (is_typedef) ? fields : var;
383 	for (n = 0; (p = sdb_array_get (TDB, nfields, n, NULL)); n++) {
384 		char *struct_name = NULL;
385 		const char *tfmt = NULL;
386 		bool isStruct = false;
387 		bool isEnum = false;
388 		bool isfp = false;
389 		snprintf (var2, sizeof (var2), "%s.%s", var, p);
390 		size_t alen = sdb_array_size (TDB, var2);
391 		int elements = sdb_array_get_num (TDB, var2, alen - 1, NULL);
392 		char *type = sdb_array_get (TDB, var2, 0, NULL);
393 		if (type) {
394 			char var3[128] = {0};
395 			// Handle general pointers except for char *
396 			if ((strstr (type, "*(") || strstr (type, " *")) && strncmp (type, "char *", 7)) {
397 				isfp = true;
398 			} else if (r_str_startswith (type, "struct ")) {
399 				struct_name = type + 7;
400 				// TODO: iterate over all the struct fields, and format the format and vars
401 				snprintf (var3, sizeof (var3), "struct.%s", struct_name);
402 				tfmt = sdb_const_get (TDB, var3, NULL);
403 				isStruct = true;
404 			} else {
405 				// special case for char[]. Use char* format type without *
406 				if (!strcmp (type, "char") && elements > 0) {
407 					tfmt = sdb_const_get (TDB, "type.char *", NULL);
408 					if (tfmt && *tfmt == '*') {
409 						tfmt++;
410 					}
411 				} else {
412 					if (r_str_startswith (type, "enum ")) {
413 						snprintf (var3, sizeof (var3), "%s", type + 5);
414 						isEnum = true;
415 					} else {
416 						snprintf (var3, sizeof (var3), "type.%s", type);
417 					}
418 					tfmt = sdb_const_get (TDB, var3, NULL);
419 				}
420 
421 			}
422 			if (isfp) {
423 				// consider function pointer as void * for printing
424 				fmt = r_str_append (fmt, "p");
425 				vars = r_str_append (vars, p);
426 				vars = r_str_append (vars, " ");
427 			} else if (tfmt) {
428 				(void) r_str_replace_ch (type, ' ', '_', true);
429 				if (elements > 0) {
430 					fmt = r_str_appendf (fmt, "[%d]", elements);
431 				}
432 				if (isStruct) {
433 					fmt = r_str_append (fmt, "?");
434 					if (struct_name) {
435 						vars = r_str_appendf (vars, "(%s)%s", struct_name, p);
436 					}
437 					vars = r_str_append (vars, " ");
438 				} else if (isEnum) {
439 					fmt = r_str_append (fmt, "E");
440 					vars = r_str_appendf (vars, "(%s)%s", type + 5, p);
441 					vars = r_str_append (vars, " ");
442 				} else {
443 					fmt = r_str_append (fmt, tfmt);
444 					vars = r_str_append (vars, p);
445 					vars = r_str_append (vars, " ");
446 				}
447 			} else {
448 				eprintf ("Cannot resolve type '%s'\n", var3);
449 			}
450 			free (type);
451 		}
452 		free (p);
453 	}
454 	free (fields);
455 	fmt = r_str_append (fmt, " ");
456 	fmt = r_str_append (fmt, vars);
457 	free (vars);
458 	return fmt;
459 }
460 
r_type_format(Sdb * TDB,const char * t)461 R_API char *r_type_format(Sdb *TDB, const char *t) {
462 	char var[130], var2[132];
463 	const char *kind = sdb_const_get (TDB, t, NULL);
464 	if (!kind) {
465 		return NULL;
466 	}
467 	// only supports struct atm
468 	snprintf (var, sizeof (var), "%s.%s", kind, t);
469 	if (!strcmp (kind, "type")) {
470 		const char *fmt = sdb_const_get (TDB, var, NULL);
471 		if (fmt) {
472 			return strdup (fmt);
473 		}
474 	} else if (!strcmp (kind, "struct") || !strcmp (kind, "union")) {
475 		return fmt_struct_union(TDB, var, false);
476 	}
477 	if (!strcmp (kind, "typedef")) {
478 		snprintf (var2, sizeof (var2), "typedef.%s", t);
479 		const char *type = sdb_const_get (TDB, var2, NULL);
480 		// only supports struct atm
481 		if (type && !strcmp (type, "struct")) {
482 			return fmt_struct_union (TDB, var, true);
483 		}
484 	}
485 	return NULL;
486 }
487 
r_type_del(Sdb * TDB,const char * name)488 R_API void r_type_del(Sdb *TDB, const char *name) {
489 	const char *kind = sdb_const_get (TDB, name, 0);
490 	if (!kind) {
491 		return;
492 	}
493 	if (!strcmp (kind, "type")) {
494 		sdb_unset (TDB, sdb_fmt ("type.%s", name), 0);
495 		sdb_unset (TDB, sdb_fmt ("type.%s.size", name), 0);
496 		sdb_unset (TDB, sdb_fmt ("type.%s.meta", name), 0);
497 		sdb_unset (TDB, name, 0);
498 	} else if (!strcmp (kind, "struct") || !strcmp (kind, "union")) {
499 		int i, n = sdb_array_length(TDB, sdb_fmt ("%s.%s", kind, name));
500 		char *elements_key = r_str_newf ("%s.%s", kind, name);
501 		for (i = 0; i< n; i++) {
502 			char *p = sdb_array_get (TDB, elements_key, i, NULL);
503 			sdb_unset (TDB, sdb_fmt ("%s.%s", elements_key, p), 0);
504 			free (p);
505 		}
506 		sdb_unset (TDB, elements_key, 0);
507 		sdb_unset (TDB, name, 0);
508 		free (elements_key);
509 	} else if (!strcmp (kind, "func")) {
510 		int i, n = sdb_num_get (TDB, sdb_fmt ("func.%s.args", name), 0);
511 		for (i = 0; i < n; i++) {
512 			sdb_unset (TDB, sdb_fmt ("func.%s.arg.%d", name, i), 0);
513 		}
514 		sdb_unset (TDB, sdb_fmt ("func.%s.ret", name), 0);
515 		sdb_unset (TDB, sdb_fmt ("func.%s.cc", name), 0);
516 		sdb_unset (TDB, sdb_fmt ("func.%s.noreturn", name), 0);
517 		sdb_unset (TDB, sdb_fmt ("func.%s.args", name), 0);
518 		sdb_unset (TDB, name, 0);
519 	} else if (!strcmp (kind, "enum")) {
520 		RList *list = r_type_get_enum (TDB, name);
521 		RTypeEnum *member;
522 		RListIter *iter;
523 		r_list_foreach (list, iter, member) {
524 			sdb_unset (TDB, sdb_fmt ("enum.%s.%s", name, member->name), 0);
525 			sdb_unset (TDB, sdb_fmt ("enum.%s.%s", name, member->val), 0);
526 		}
527 		sdb_unset (TDB, name, 0);
528 		r_list_free (list);
529 	} else if (!strcmp (kind, "typedef")) {
530 		RStrBuf buf;
531 		r_strbuf_init (&buf);
532 		r_strbuf_setf (&buf, "typedef.%s", name);
533 		sdb_unset (TDB, r_strbuf_get (&buf), 0);
534 		r_strbuf_fini (&buf);
535 		sdb_unset (TDB, name, 0);
536 	} else {
537 		eprintf ("Unrecognized type kind \"%s\"\n", kind);
538 	}
539 }
540 
541 // Function prototypes api
r_type_func_exist(Sdb * TDB,const char * func_name)542 R_API int r_type_func_exist(Sdb *TDB, const char *func_name) {
543 	const char *fcn = sdb_const_get (TDB, func_name, 0);
544 	return fcn && !strcmp (fcn, "func");
545 }
546 
r_type_func_ret(Sdb * TDB,const char * func_name)547 R_API const char *r_type_func_ret(Sdb *TDB, const char *func_name){
548 	const char *query = sdb_fmt ("func.%s.ret", func_name);
549 	return sdb_const_get (TDB, query, 0);
550 }
551 
r_type_func_args_count(Sdb * TDB,const char * func_name)552 R_API int r_type_func_args_count(Sdb *TDB, const char *func_name) {
553 	const char *query = sdb_fmt ("func.%s.args", func_name);
554 	return sdb_num_get (TDB, query, 0);
555 }
556 
r_type_func_args_type(Sdb * TDB,R_NONNULL const char * func_name,int i)557 R_API R_OWN char *r_type_func_args_type(Sdb *TDB, R_NONNULL const char *func_name, int i) {
558 	const char *query = sdb_fmt ("func.%s.arg.%d", func_name, i);
559 	char *ret = sdb_get (TDB, query, 0);
560 	if (ret) {
561 		char *comma = strchr (ret, ',');
562 		if (comma) {
563 			*comma = 0;
564 			return ret;
565 		}
566 		free (ret);
567 	}
568 	return NULL;
569 }
570 
r_type_func_args_name(Sdb * TDB,R_NONNULL const char * func_name,int i)571 R_API const char *r_type_func_args_name(Sdb *TDB, R_NONNULL const char *func_name, int i) {
572 	const char *query = sdb_fmt ("func.%s.arg.%d", func_name, i);
573 	const char *get = sdb_const_get (TDB, query, 0);
574 	if (get) {
575 		char *ret = strchr (get, ',');
576 		return ret == 0 ? ret : ret + 1;
577 	}
578 	return NULL;
579 }
580 
581 #define MIN_MATCH_LEN 4
582 
is_function(const char * name)583 static inline bool is_function(const char *name) {
584 	return name && !strcmp("func", name);
585 }
586 
type_func_try_guess(Sdb * TDB,R_NONNULL char * name)587 static R_OWN char *type_func_try_guess(Sdb *TDB, R_NONNULL char *name) {
588 	if (strlen(name) < MIN_MATCH_LEN) {
589 		return NULL;
590 	}
591 
592 	const char *res = sdb_const_get(TDB, name, NULL);
593 	if (is_function(res)) {
594 		return strdup(name);
595 	}
596 
597 	return NULL;
598 }
599 
is_auto_named(char * func_name,size_t slen)600 static inline bool is_auto_named(char *func_name, size_t slen) {
601 	return slen > 4 && (r_str_startswith (func_name, "fcn.") || r_str_startswith (func_name, "loc."));
602 }
603 
has_r_prefixes(char * func_name,int offset,size_t slen)604 static inline bool has_r_prefixes(char *func_name, int offset, size_t slen) {
605 	return slen > 4 && (offset + 3 < slen) && func_name[offset + 3] == '.';
606 }
607 
strip_r_prefixes(char * func_name,size_t slen)608 static char *strip_r_prefixes(char *func_name, size_t slen) {
609 	// strip r2 prefixes (sym, sym.imp, etc')
610 	int offset = 0;
611 
612 	while (has_r_prefixes(func_name, offset, slen)) {
613 		offset += 4;
614 	}
615 
616 	return func_name + offset;
617 }
618 
strip_common_prefixes_stdlib(char * func_name)619 static char *strip_common_prefixes_stdlib(char *func_name) {
620 	// strip common prefixes from standard lib functions
621 	if (r_str_startswith (func_name, "__isoc99_")) {
622 		func_name += 9;
623 	} else if (r_str_startswith (func_name, "__libc_") && !strstr(func_name, "_main")) {
624 		func_name += 7;
625 	} else if (r_str_startswith (func_name, "__GI_")) {
626 		func_name += 5;
627 	}
628 
629 	return func_name;
630 }
631 
strip_dll_prefix(char * func_name)632 static char *strip_dll_prefix(char *func_name) {
633 	char *tmp = strstr(func_name, "dll_");
634 	if (tmp) {
635 		return tmp + 3;
636 	}
637 
638 	return func_name;
639 }
640 
clean_function_name(char * func_name)641 static void clean_function_name(char *func_name) {
642 	char *last = (char *)r_str_lchr (func_name, '_');
643 	if (!last || !r_str_isnumber(last + 1)) {
644 		return;
645 	}
646 
647 	*last = '\0';
648 }
649 
650 // TODO:
651 // - symbol names are long and noisy, some of them might not be matched due
652 //	 to additional information added around name
r_type_func_guess(Sdb * TDB,R_NONNULL char * func_name)653 R_API R_OWN char *r_type_func_guess(Sdb *TDB, R_NONNULL char *func_name) {
654 	char *str = func_name;
655 	char *result = NULL;
656 	r_return_val_if_fail (TDB, false);
657 	r_return_val_if_fail (func_name, false);
658 
659 	size_t slen = strlen (str);
660 	if (slen < MIN_MATCH_LEN || is_auto_named(str, slen)) {
661 		return NULL;
662 	}
663 
664 	str = strip_r_prefixes(str, slen);
665 	str = strip_common_prefixes_stdlib(str);
666 	str = strip_dll_prefix(str);
667 
668 	if ((result = type_func_try_guess (TDB, str))) {
669 		return result;
670 	}
671 
672 	str = strdup (str);
673 	clean_function_name(str);
674 
675 	if (*str == '_' && (result = type_func_try_guess (TDB, str + 1))) {
676 		free (str);
677 		return result;
678 	}
679 
680 	free (str);
681 	return result;
682 }
683