|
1 | 1 | /* radare - LGPL - Copyright 2013-2025 - pancake */ |
2 | 2 |
|
3 | | -#include <r_asm.h> |
4 | | -#include "c/tcc.h" |
5 | | -#include "c/tccgen.c" |
6 | | -#include "c/tccpp.c" |
7 | | -#include "c/libtcc.c" |
8 | | -#define USE_R2 1 |
9 | | -#include <spp/spp.h> |
| 3 | +#include <r_anal.h> |
10 | 4 |
|
11 | | -// used to pass anal and s1 to loader |
12 | | -typedef struct { |
13 | | - RAnal *anal; |
14 | | - TCCState *s1; |
15 | | -} LoadContext; |
16 | | - |
17 | | -extern int tcc_sym_push(TCCState *s1, char *typename, int typesize, int meta); |
18 | | - |
19 | | -/* parse C code and return it in key-value form */ |
20 | | - |
21 | | -static void __appendString(const char *msg, char **s) { |
22 | | - if (!s) { |
23 | | - printf ("%s\n", msg); |
24 | | - } else if (*s) { |
25 | | - char *p = malloc (strlen (msg) + strlen (*s) + 1); |
26 | | - if (p) { |
27 | | - strcpy (p, *s); |
28 | | - free (*s); |
29 | | - *s = p; |
30 | | - strcpy (p + strlen (p), msg); |
31 | | - } |
32 | | - } else { |
33 | | - *s = strdup (msg); |
34 | | - } |
35 | | -} |
| 5 | +R_IPI char* kvc_parse(const char* header_content, char **errmsg); |
36 | 6 |
|
37 | | -static bool __typeLoad(void *p, const char *k, const char *v) { |
38 | | - r_strf_buffer (128); |
39 | | - if (!p) { |
40 | | - return false; |
41 | | - } |
42 | | - int btype = 0; |
43 | | - LoadContext *loader = (LoadContext *)p; |
44 | | - RAnal *anal = loader->anal; |
45 | | - TCCState *s1 = loader->s1; |
46 | | - // TCCState *s1 = NULL; // XXX THIS WILL MAKE IT CRASH |
47 | | - //r_cons_printf (cons, "tk %s=%s\n", k, v); |
48 | | - // TODO: Add unions support |
49 | | - if (!strncmp (v, "struct", 6) && strncmp (k, "struct.", 7)) { |
50 | | - // structure |
51 | | - btype = VT_STRUCT; |
52 | | - const char *typename = k; |
53 | | - int typesize = 0; |
54 | | - // TODO: Add typesize here |
55 | | - char* query = r_strf ("struct.%s", k); |
56 | | - char *members = sdb_get (anal->sdb_types, query, 0); |
57 | | - char *next, *ptr = members; |
58 | | - if (members) { |
59 | | - do { |
60 | | - char *name = sdb_anext (ptr, &next); |
61 | | - if (!name) { |
62 | | - break; |
63 | | - } |
64 | | - query = r_strf ("struct.%s.%s", k, name); |
65 | | - char *subtype = sdb_get (anal->sdb_types, query, 0); |
66 | | - if (!subtype) { |
67 | | - break; |
| 7 | +static RAnalPlugin *resolve_plugin (RAnal *anal, int type) { |
| 8 | + RAnalPlugin *p; |
| 9 | + RListIter *iter; |
| 10 | + const char *tpp = anal->opt.tparser; |
| 11 | + r_list_foreach (anal->plugins, iter, p) { |
| 12 | + if (!strcmp (tpp, p->meta.name)) { |
| 13 | + switch (type) { |
| 14 | + case 0: |
| 15 | + if (p->tparse_text) { |
| 16 | + return p; |
68 | 17 | } |
69 | | - char *tmp = strchr (subtype, ','); |
70 | | - if (tmp) { |
71 | | - *tmp++ = 0; |
72 | | - tmp = strchr (tmp, ','); |
73 | | - if (tmp) { |
74 | | - *tmp++ = 0; |
75 | | - } |
76 | | - char *subname = tmp; |
77 | | - // TODO: Go recurse here |
78 | | - query = r_strf ("struct.%s.%s.meta", subtype, subname); |
79 | | - btype = sdb_num_get (anal->sdb_types, query, 0); |
80 | | - tcc_sym_push (s1, subtype, 0, btype); |
| 18 | + break; |
| 19 | + case 1: |
| 20 | + if (p->tparse_file) { |
| 21 | + return p; |
81 | 22 | } |
82 | | - free (subtype); |
83 | | - ptr = next; |
84 | | - } while (next); |
85 | | - free (members); |
86 | | - } |
87 | | - tcc_sym_push (s1, (char *)typename, typesize, btype); |
88 | | - } |
89 | | - return true; |
90 | | -} |
91 | | - |
92 | | -static void __errorFunc(void *opaque, const char *msg) { |
93 | | - __appendString (msg, opaque); |
94 | | - char **p = (char **)opaque; |
95 | | - if (p && *p) { |
96 | | - int n = strlen(*p); |
97 | | - char *ptr = malloc (n + 2); |
98 | | - if (!ptr) { |
99 | | - return; |
| 23 | + break; |
| 24 | + } |
100 | 25 | } |
101 | | - strcpy (ptr, *p); |
102 | | - ptr[n] = '\n'; |
103 | | - ptr[n + 1] = 0; |
104 | | - free (*p); |
105 | | - *p = ptr; |
106 | 26 | } |
| 27 | + return NULL; |
107 | 28 | } |
108 | 29 |
|
109 | | -R_IPI char* kvc_parse(const char* header_content, char **errmsg); |
110 | | - |
111 | 30 | R_API char *r_anal_cparse2(RAnal *anal, const char *code, char **error_msg) { |
112 | 31 | return kvc_parse (code, error_msg); |
113 | 32 | } |
114 | 33 |
|
115 | | -static TCCState *new_tcc(RAnal *anal) { |
116 | | - TCCState *ts = tcc_new (anal->config->arch, anal->config->bits, anal->config->os); |
117 | | - if (!ts) { |
118 | | - ts = tcc_new (R_SYS_ARCH, R_SYS_BITS, R_SYS_OS); |
119 | | - if (!ts) { |
120 | | - R_LOG_ERROR ("Cannot instantiate TCC for given arch (%s)", anal->config->arch); |
121 | | - return NULL; |
122 | | - } |
123 | | - } |
124 | | - return ts; |
125 | | -} |
126 | | - |
127 | 34 | R_API char *r_anal_cparse_file(RAnal *anal, const char *path, const char *dir, char **error_msg) { |
128 | | - if (anal->opt.newcparser) { |
129 | | - char *code = r_file_slurp (path, NULL); |
130 | | - if (code) { |
131 | | - char *res = r_anal_cparse2 (anal, code, error_msg); |
132 | | - free (code); |
133 | | - return res; |
134 | | - } |
135 | | - } |
136 | | - char *str = NULL; |
137 | | - TCCState *s1 = new_tcc (anal); |
138 | | - if (!s1) { |
139 | | - return NULL; |
140 | | - } |
141 | | - tcc_set_callback (s1, &__appendString, &str); |
142 | | - tcc_set_error_func (s1, (void *)error_msg, __errorFunc); |
143 | | - |
144 | | - // load saved types from sdb into the tcc context |
145 | | - LoadContext ctx = {anal, s1}; |
146 | | - sdb_foreach (anal->sdb_types, __typeLoad, (void *)&ctx); |
147 | | - |
148 | | - char *d = strdup (dir); |
149 | | - RList *dirs = r_str_split_list (d, ":", 0); |
150 | | - RListIter *iter; |
151 | | - char *di; |
152 | | - bool found = false; |
153 | | - r_list_foreach (dirs, iter, di) { |
154 | | - if (tcc_add_file (s1, path, di) != -1) { |
155 | | - found = true; |
156 | | - break; |
| 35 | + if (anal->opt.tparser) { |
| 36 | + RAnalPlugin *p = resolve_plugin (anal, 1); |
| 37 | + if (p) { |
| 38 | + return p->tparse_file (anal, path, dir); |
| 39 | + } else { |
| 40 | + RAnalPlugin *p = resolve_plugin (anal, 0); |
| 41 | + if (p) { |
| 42 | + char *text = r_file_slurp (path, NULL); |
| 43 | + char *res = p->tparse_text (anal, text); |
| 44 | + free (text); |
| 45 | + return res; |
| 46 | + } |
157 | 47 | } |
158 | 48 | } |
159 | | - if (!found) { |
160 | | - R_FREE (str); |
| 49 | + char *code = r_file_slurp (path, NULL); |
| 50 | + if (code) { |
| 51 | + char *res = r_anal_cparse2 (anal, code, error_msg); |
| 52 | + free (code); |
| 53 | + return res; |
161 | 54 | } |
162 | | - r_list_free (dirs); |
163 | | - free (d); |
164 | | - tcc_delete (s1); |
165 | | - return str; |
| 55 | + return NULL; |
166 | 56 | } |
167 | 57 |
|
168 | 58 | R_API char *r_anal_cparse(RAnal *anal, const char *code, char **error_msg) { |
169 | | - if (anal->opt.newcparser) { |
170 | | - return r_anal_cparse2 (anal, code, error_msg); |
171 | | - } |
172 | | - char *str = NULL; |
173 | | - TCCState *s1 = new_tcc (anal); |
174 | | - if (!s1) { |
175 | | - R_LOG_ERROR ("Cannot instantiate TCC for given arch (%s)", anal->config->arch); |
176 | | - return NULL; |
177 | | - } |
178 | | - tcc_set_callback (s1, &__appendString, &str); |
179 | | - tcc_set_error_func (s1, (void *)error_msg, __errorFunc); |
180 | | - |
181 | | - // load saved types from sdb into the tcc context |
182 | | - LoadContext ctx = {anal, s1}; |
183 | | - sdb_foreach (anal->sdb_types, __typeLoad, (void *)&ctx); |
184 | | - |
185 | | - if (tcc_compile_string (s1, code) != 0) { |
186 | | - R_FREE (str); |
| 59 | + if (anal->opt.tparser) { |
| 60 | + RAnalPlugin *p = resolve_plugin (anal, 0); |
| 61 | + if (p) { |
| 62 | + return p->tparse_text(anal, code); |
| 63 | + } |
187 | 64 | } |
188 | | - tcc_delete (s1); |
189 | | - return str; |
| 65 | + return r_anal_cparse2 (anal, code, error_msg); |
190 | 66 | } |
0 commit comments