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