1 /* radare - LGPL - Copyright 2013-2019 - pancake */
2 
3 #include "r_util.h"
4 #include "r_types.h"
5 #include "r_parse.h"
6 #include "tcc.h"
7 
8 extern int tcc_sym_push(char *typename, int typesize, int meta);
9 
10 /* parse C code and return it in key-value form */
11 
__appendString(const char * msg,char ** s)12 static void __appendString(const char *msg, char **s) {
13 	if (!s) {
14 		printf ("%s\n", msg);
15 	} else if (*s) {
16 		char *p = malloc (strlen (msg) + strlen (*s) + 1);
17 		if (p) {
18 			strcpy (p, *s);
19 			free (*s);
20 			*s = p;
21 			strcpy (p + strlen (p), msg);
22 		}
23 	} else {
24 		*s = strdup (msg);
25 	}
26 }
27 
__typeLoad(void * p,const char * k,const char * v)28 static bool __typeLoad(void *p, const char *k, const char *v) {
29 	if (!p) {
30 		return false;
31 	}
32 	int btype = 0;
33 	RAnal *anal = (RAnal*)p;
34 	//r_cons_printf ("tk %s=%s\n", k, v);
35 	// TODO: Add unions support
36 	if (!strncmp (v, "struct", 6) && strncmp (k, "struct.", 7)) {
37 		// structure
38 		btype = VT_STRUCT;
39 		const char *typename = k;
40 		int typesize = 0;
41 		// TODO: Add typesize here
42 		char* query = sdb_fmt ("struct.%s", k);
43 		char *members = sdb_get (anal->sdb_types, query, 0);
44 		char *next, *ptr = members;
45 		if (members) {
46 			do {
47 				char *name = sdb_anext (ptr, &next);
48 				if (!name) {
49 					break;
50 				}
51 				query = sdb_fmt ("struct.%s.%s", k, name);
52 				char *subtype = sdb_get (anal->sdb_types, query, 0);
53 				if (!subtype) {
54 					break;
55 				}
56 				char *tmp = strchr (subtype, ',');
57 				if (tmp) {
58 					*tmp++ = 0;
59 					tmp = strchr (tmp, ',');
60 					if (tmp) {
61 						*tmp++ = 0;
62 					}
63 					char *subname = tmp;
64 					// TODO: Go recurse here
65 					query = sdb_fmt ("struct.%s.%s.meta", subtype, subname);
66 					btype = sdb_num_get (anal->sdb_types, query, 0);
67 					tcc_sym_push (subtype, 0, btype);
68 				}
69 				free (subtype);
70 				ptr = next;
71 			} while (next);
72 			free (members);
73 		}
74 		tcc_sym_push ((char *)typename, typesize, btype);
75 	}
76 	return true;
77 }
78 
__errorFunc(void * opaque,const char * msg)79 static void __errorFunc(void *opaque, const char *msg) {
80 	__appendString (msg, opaque);
81 	char **p = (char **)opaque;
82 	if (p && *p) {
83 		int n = strlen(*p);
84 		char *ptr = malloc (n + 2);
85 		if (!ptr) {
86 			return;
87 		}
88 		strcpy (ptr, *p);
89 		ptr[n] = '\n';
90 		ptr[n + 1] = 0;
91 		free (*p);
92 		*p = ptr;
93 	}
94 }
95 
r_parse_c_file(RAnal * anal,const char * path,const char * dir,char ** error_msg)96 R_API char *r_parse_c_file(RAnal *anal, const char *path, const char *dir, char **error_msg) {
97 	char *str = NULL;
98 	TCCState *T = tcc_new (anal->cpu, anal->bits, anal->os);
99 	if (!T) {
100 		return NULL;
101 	}
102 	tcc_set_callback (T, &__appendString, &str);
103 	tcc_set_error_func (T, (void *)error_msg, __errorFunc);
104 	sdb_foreach (anal->sdb_types, __typeLoad, anal);
105 	if (tcc_add_file (T, path, dir) == -1) {
106 		free (str);
107 		str = NULL;
108 	}
109 	tcc_delete (T);
110 	return str;
111 }
112 
r_parse_c_string(RAnal * anal,const char * code,char ** error_msg)113 R_API char *r_parse_c_string(RAnal *anal, const char *code, char **error_msg) {
114 	char *str = NULL;
115 	TCCState *T = tcc_new (anal->cpu, anal->bits, anal->os);
116 	if (!T) {
117 		return NULL;
118 	}
119 	tcc_set_callback (T, &__appendString, &str);
120 	tcc_set_error_func (T, (void *)error_msg, __errorFunc);
121 	sdb_foreach (anal->sdb_types, __typeLoad, NULL);
122 	if (tcc_compile_string (T, code) != 0) {
123 		free (str);
124 		str = NULL;
125 	}
126 	tcc_delete (T);
127 	return str;
128 }
129 
130 // XXX do not use globals
r_parse_c_reset(RParse * p)131 R_API void r_parse_c_reset(RParse *p) {
132 	anon_sym = SYM_FIRST_ANOM;
133 }
134