1 /* radare - LGPL - Copyright 2015-2016 - inisider */
2
3 #include "microsoft_demangle.h"
4 #include <ctype.h>
5 #include <r_cons.h>
6
7 #define _R_LIST_C
8 #include <r_list.h>
9
10 #define MICROSOFT_NAME_LEN (256)
11 #define MICROSOFR_CLASS_NAMESPACE_LEN (256)
12 #define IMPOSSIBLE_LEN (MICROSOFT_NAME_LEN + MICROSOFR_CLASS_NAMESPACE_LEN)
13
14 // TODO: it will be good to change this to some kind of map data structure
15 static RList *abbr_types = NULL;
16 static RList *abbr_names = NULL;
17
18 typedef enum EObjectType {
19 eObjectTypeStaticClassMember = 2,
20 eObjectTypeGlobal = 3,
21 eObjectTypeMax = 99
22 } EObjectType;
23
24 ///////////////////////////////////////////////////////////////////////////////
25 // State machine for parsing type codes data types
26 ///////////////////////////////////////////////////////////////////////////////
27 typedef enum ETCStateMachineErr {
28 eTCStateMachineErrOK,
29 eTCStateMachineErrUncorrectTypeCode,
30 eTCStateMachineErrUnsupportedTypeCode,
31 eTCStateMachineErrAlloc,
32 eTCStateMachineErrMax
33 } ETCStateMachineErr;
34
35 typedef enum ETCState { // TC - type code
36 eTCStateStart = 0, eTCStateEnd, eTCStateH, eTCStateX, eTCStateN, eTCStateD,
37 eTCStateC, eTCStateE, eTCStateF, eTCStateG, eTCStateI, eTCStateJ, eTCStateK,
38 eTCStateM, eTCStateZ, eTCState_, eTCStateT, eTCStateU, eTCStateW, eTCStateV,
39 eTCStateO, eTCStateS, eTCStateP, eTCStateR, eTCStateQ, eTCStateA, eTCState$,
40 eTCStateMax
41 } ETCState;
42
43 typedef struct STypeCodeStr {
44 char *type_str;
45 size_t type_str_len;
46 size_t curr_pos;
47 } STypeCodeStr;
48
49 struct SStateInfo;
50 typedef void (*state_func)(struct SStateInfo *, STypeCodeStr *type_code_str);
51
52 typedef struct SStateInfo {
53 ETCState state;
54 const char *buff_for_parsing;
55 size_t amount_of_read_chars;
56 ETCStateMachineErr err;
57 } SStateInfo;
58
59 typedef struct SStrInfo {
60 char *str_ptr;
61 size_t len;
62 } SStrInfo;
63
64 typedef struct SDataType {
65 char *left;
66 char *right;
67 } SDataType;
68
sstrinfo_free(SStrInfo * sstrinfo)69 static void sstrinfo_free(SStrInfo *sstrinfo) {
70 free (sstrinfo->str_ptr);
71 free (sstrinfo);
72 }
73
74 #define DECL_STATE_ACTION(action) static void tc_state_##action(SStateInfo *state, STypeCodeStr *type_code_str);
75 DECL_STATE_ACTION(start)
76 DECL_STATE_ACTION(end)
77 DECL_STATE_ACTION(X)
78 DECL_STATE_ACTION(N)
79 DECL_STATE_ACTION(D)
80 DECL_STATE_ACTION(C)
81 DECL_STATE_ACTION(E)
82 DECL_STATE_ACTION(F)
83 DECL_STATE_ACTION(G)
84 DECL_STATE_ACTION(H)
85 DECL_STATE_ACTION(I)
86 DECL_STATE_ACTION(J)
87 DECL_STATE_ACTION(K)
88 DECL_STATE_ACTION(M)
89 DECL_STATE_ACTION(Z)
90 DECL_STATE_ACTION(_)
91 DECL_STATE_ACTION(T)
92 DECL_STATE_ACTION(U)
93 DECL_STATE_ACTION(W)
94 DECL_STATE_ACTION(V)
95 DECL_STATE_ACTION(O)
96 DECL_STATE_ACTION(S)
97 DECL_STATE_ACTION(P)
98 DECL_STATE_ACTION(R)
99 DECL_STATE_ACTION(Q)
100 DECL_STATE_ACTION(A)
101 DECL_STATE_ACTION($)
102 #undef DECL_STATE_ACTION
103
104 #define NAME(action) tc_state_##action
105 static state_func const state_table[eTCStateMax] = {
106 NAME(start), NAME(end) , NAME(H), NAME(X), NAME(N), NAME(D), NAME(C), NAME(E),
107 NAME(F), NAME(G), NAME(I), NAME(J), NAME(K), NAME(M), NAME(Z), NAME(_),
108 NAME(T), NAME(U), NAME(W), NAME(V), NAME(O), NAME(S), NAME(P), NAME(R),
109 NAME(Q), NAME(A), NAME($)
110 };
111 #undef NAME
112 ///////////////////////////////////////////////////////////////////////////////
113 // End of data types for state machine which parse type codes
114 ///////////////////////////////////////////////////////////////////////////////
115
116 ///////////////////////////////////////////////////////////////////////////////
117 // State machine for parsing type codes functions
118 ///////////////////////////////////////////////////////////////////////////////
119
120 static void init_state_struct(SStateInfo *state, const char *buff_for_parsing);
121 static EDemanglerErr get_type_code_string(const char *sym, size_t *amount_of_read_chars, char **str_type_code);
122 static bool init_type_code_str_struct(STypeCodeStr *type_coder_str);
123 static void free_type_code_str_struct(STypeCodeStr *type_code_str);
124 static size_t get_template(const char *buf, SStrInfo *str_info, bool memorize);
125 static char *get_num(SStateInfo *state);
126 static EDemanglerErr parse_data_type(const char *sym, SDataType *demangled_type, size_t *len);
127 static size_t get_namespace_and_name(const char *buf, STypeCodeStr *type_code_str, size_t *amount_of_names, bool memorize);
128 static inline EDemanglerErr get_storage_class(const char encoded, const char **storage_class);
129 static inline size_t get_ptr_modifier(const char encoded, SDataType *ptr_modifier);
130 static EDemanglerErr parse_function(const char *sym, STypeCodeStr *type_code_str, char **demangled_function, size_t *chars_read);
131 static EDemanglerErr parse_microsoft_mangled_name(const char *sym, char **demangled_name, size_t *chars_read);
132 static EDemanglerErr parse_microsoft_rtti_mangled_name(const char *sym, char **demangled_name, size_t *chars_read);
133
run_state(SStateInfo * state_info,STypeCodeStr * type_code_str)134 static void run_state(SStateInfo *state_info, STypeCodeStr *type_code_str) {
135 state_table[state_info->state](state_info, type_code_str);
136 }
137
copy_string(STypeCodeStr * type_code_str,const char * str_for_copy,size_t copy_len)138 static int copy_string(STypeCodeStr *type_code_str, const char *str_for_copy, size_t copy_len) {
139 int res = 1; // all is OK
140 size_t str_for_copy_len = (copy_len == 0 && str_for_copy) ? strlen (str_for_copy) : copy_len;
141 size_t free_space = type_code_str->type_str_len - type_code_str->curr_pos - 1;
142
143 if (free_space < str_for_copy_len) {
144 int newlen = type_code_str->type_str_len + (str_for_copy_len << 1) + 1;
145 if (newlen < 1) {
146 R_FREE (type_code_str->type_str);
147 goto copy_string_err;
148 }
149 type_code_str->type_str_len = newlen;
150 char *type_str = (char *) realloc (type_code_str->type_str, newlen);
151 if (!type_str) {
152 R_FREE (type_code_str->type_str);
153 goto copy_string_err;
154 }
155 type_code_str->type_str = type_str;
156 if (!type_code_str->type_str) {
157 res = 0;
158 goto copy_string_err;
159 }
160 }
161
162 char *dst = type_code_str->type_str + type_code_str->curr_pos;
163 if (!dst) {
164 return 0;
165 }
166
167 if (str_for_copy) {
168 r_str_ncpy (dst, str_for_copy, str_for_copy_len + 1);
169 } else {
170 memset (dst, 0, str_for_copy_len);
171 }
172 type_code_str->curr_pos += str_for_copy_len;
173 if (type_code_str->type_str) {
174 type_code_str->type_str[type_code_str->curr_pos] = '\0';
175 }
176
177 copy_string_err:
178 return res;
179 }
180
get_template_params(const char * sym,size_t * amount_of_read_chars,char ** str_type_code)181 static int get_template_params(const char *sym, size_t *amount_of_read_chars, char **str_type_code) {
182 SStateInfo state;
183 init_state_struct (&state, sym);
184 const char template_param[] = "template-parameter-";
185 char *tmp, *res = NULL;
186 const char *const start_sym = sym;
187 if (!strncmp (sym, "?", 1)) {
188 // anonymous template param
189 state.amount_of_read_chars += 1;
190 state.buff_for_parsing += 1;
191 res = get_num (&state);
192 if (res) {
193 tmp = r_str_newf("%s%s", template_param, res);
194 free (res);
195 res = tmp;
196 }
197 } else {
198 if (strncmp (sym, "$", 1)) {
199 return eDemanglerErrUncorrectMangledSymbol;
200 }
201 sym++;
202 state.amount_of_read_chars += 2;
203 state.buff_for_parsing += 2;
204 char *a, *b, *c;
205 switch (*sym) {
206 case '0':
207 // Signed integer
208 a = get_num (&state);
209 if (a) {
210 int signed_a = atoi (a);
211 res = r_str_newf ("%d", signed_a);
212 free (a);
213 }
214 break;
215 case '1': {
216 STypeCodeStr str;
217 EDemanglerErr err;
218 if (!init_type_code_str_struct (&str)) {
219 return eDemanglerErrMemoryAllocation;
220 }
221 sym += 2;
222 size_t ret = get_namespace_and_name (sym, &str, NULL, true);
223 if (!ret) {
224 free_type_code_str_struct (&str);
225 return eDemanglerErrUncorrectMangledSymbol;
226 }
227 sym += ret + 1;
228 SDataType data_type;
229 if (isdigit ((unsigned char)*sym)) {
230 err = parse_data_type (sym, &data_type, &ret);
231 *str_type_code = r_str_newf ("&%s %s%s", data_type.left, str.type_str, data_type.right);
232 free (data_type.left);
233 free (data_type.right);
234 } else {
235 char *tmp = NULL;
236 err = parse_function (sym, &str, &tmp, &ret);
237 *str_type_code = r_str_newf ("&%s", tmp);
238 free (tmp);
239 }
240 sym += ret;
241 *amount_of_read_chars = sym - start_sym;
242 free_type_code_str_struct (&str);
243 return err;
244 }
245 case '2':
246 // real value a ^ b
247 a = get_num (&state);
248 b = get_num (&state);
249 if (a && b) {
250 int signed_b = atoi (b);
251 res = r_str_newf ("%sE%d", a, signed_b);
252 }
253 free (a);
254 free (b);
255 break;
256 case 'D':
257 // anonymous template param
258 res = get_num (&state);
259 if (res) {
260 tmp = r_str_newf ("%s%s", template_param, res);
261 free (res);
262 res = tmp;
263 }
264 break;
265 case 'F':
266 // Signed {a, b}
267 a = get_num (&state);
268 b = get_num (&state);
269 if (a && b) {
270 int signed_a = atoi (a);
271 int signed_b = atoi (b);
272 res = r_str_newf ("{%d, %d}", signed_a, signed_b);
273 }
274 free (a);
275 free (b);
276 break;
277 case 'G':
278 // Signed {a, b, c}
279 a = get_num (&state);
280 b = get_num (&state);
281 c = get_num (&state);
282 if (a && b && c) {
283 int signed_a = atoi (a);
284 int signed_b = atoi (b);
285 int signed_c = atoi (c);
286 res = r_str_newf ("{%d, %d, %d}", signed_a, signed_b, signed_c);
287 }
288 free (a);
289 free (b);
290 free (c);
291 break;
292 case 'H':
293 // Unsigned integer
294 res = get_num (&state);
295 break;
296 case 'I':
297 // Unsigned {x, y}
298 a = get_num (&state);
299 b = get_num (&state);
300 if (a && b) {
301 res = r_str_newf ("{%s, %s}", a, b);
302 }
303 free (a);
304 free (b);
305 break;
306 case 'J':
307 // Unsigned {x, y, z}
308 a = get_num (&state);
309 b = get_num (&state);
310 c = get_num (&state);
311 if (a && b && c) {
312 res = r_str_newf ("{%s, %s, %s}", a, b, c);
313 }
314 free (a);
315 free (b);
316 free (c);
317 break;
318 case 'Q':
319 // anonymous non-type template parameter
320 res = get_num (&state);
321 if (res) {
322 tmp = r_str_newf("non-type-%s%s", template_param, res);
323 free (res);
324 res = tmp;
325 }
326 break;
327 default:
328 break;
329 }
330 }
331
332 if (!res) {
333 return eDemanglerErrUnsupportedMangling;
334 }
335
336 *str_type_code = res;
337 *amount_of_read_chars = state.amount_of_read_chars;
338
339 return eDemanglerErrOK;
340 }
341
get_operator_code(const char * buf,RList * names_l,bool memorize)342 static size_t get_operator_code(const char *buf, RList *names_l, bool memorize) {
343 // C++ operator code (one character, or two if the first is '_')
344 #define SET_OPERATOR_CODE(str) { \
345 str_info = malloc (sizeof (SStrInfo)); \
346 if (!str_info) break; \
347 str_info->len = strlen (str); \
348 str_info->str_ptr = strdup (str); \
349 r_list_append (names_l, str_info); \
350 }
351 SStrInfo *str_info;
352 size_t read_len = 1;
353 switch (*++buf) {
354 case '0': SET_OPERATOR_CODE("constructor"); break;
355 case '1': SET_OPERATOR_CODE("~destructor"); break;
356 case '2': SET_OPERATOR_CODE("operator new"); break;
357 case '3': SET_OPERATOR_CODE("operator delete"); break;
358 case '4': SET_OPERATOR_CODE("operator="); break;
359 case '5': SET_OPERATOR_CODE("operator>>"); break;
360 case '6': SET_OPERATOR_CODE("operator<<"); break;
361 case '7': SET_OPERATOR_CODE("operator!"); break;
362 case '8': SET_OPERATOR_CODE("operator=="); break;
363 case '9': SET_OPERATOR_CODE("operator!="); break;
364 case 'A': SET_OPERATOR_CODE("operator[]"); break;
365 case 'B': SET_OPERATOR_CODE("operator #{return_type}"); break;
366 case 'C': SET_OPERATOR_CODE("operator->"); break;
367 case 'D': SET_OPERATOR_CODE("operator*"); break;
368 case 'E': SET_OPERATOR_CODE("operator++"); break;
369 case 'F': SET_OPERATOR_CODE("operator--"); break;
370 case 'G': SET_OPERATOR_CODE("operator-"); break;
371 case 'H': SET_OPERATOR_CODE("operator+"); break;
372 case 'I': SET_OPERATOR_CODE("operator&"); break;
373 case 'J': SET_OPERATOR_CODE("operator->*"); break;
374 case 'K': SET_OPERATOR_CODE("operator/"); break;
375 case 'L': SET_OPERATOR_CODE("operator%"); break;
376 case 'M': SET_OPERATOR_CODE("operator<"); break;
377 case 'N': SET_OPERATOR_CODE("operator<="); break;
378 case 'O': SET_OPERATOR_CODE("operator>"); break;
379 case 'P': SET_OPERATOR_CODE("operator>="); break;
380 case 'Q': SET_OPERATOR_CODE("operator,"); break;
381 case 'R': SET_OPERATOR_CODE("operator()"); break;
382 case 'S': SET_OPERATOR_CODE("operator~"); break;
383 case 'T': SET_OPERATOR_CODE("operator^"); break;
384 case 'U': SET_OPERATOR_CODE("operator|"); break;
385 case 'V': SET_OPERATOR_CODE("operator&"); break;
386 case 'W': SET_OPERATOR_CODE("operator||"); break;
387 case 'X': SET_OPERATOR_CODE("operator*="); break;
388 case 'Y': SET_OPERATOR_CODE("operator+="); break;
389 case 'Z': SET_OPERATOR_CODE("operator-="); break;
390 case '$':
391 {
392 str_info = malloc (sizeof (SStrInfo));
393 if (!str_info) {
394 break;
395 }
396 size_t i = get_template (buf + 1, str_info, memorize);
397 if (!i) {
398 R_FREE (str_info);
399 return 0;
400 }
401 r_list_append (names_l, str_info);
402 read_len += i;
403 break;
404 }
405 case '_':
406 switch (*++buf) {
407 case '0': SET_OPERATOR_CODE ("operator/="); break;
408 case '1': SET_OPERATOR_CODE ("operator%="); break;
409 case '2': SET_OPERATOR_CODE ("operator>>="); break;
410 case '3': SET_OPERATOR_CODE ("operator<<="); break;
411 case '4': SET_OPERATOR_CODE ("operator&="); break;
412 case '5': SET_OPERATOR_CODE ("operator|="); break;
413 case '6': SET_OPERATOR_CODE ("operator^="); break;
414 case '7': SET_OPERATOR_CODE ("vftable"); break;
415 case '8': SET_OPERATOR_CODE ("vbtable"); break;
416 case '9': SET_OPERATOR_CODE ("vcall"); break;
417 case 'A': SET_OPERATOR_CODE ("typeof"); break;
418 case 'B': SET_OPERATOR_CODE ("local_static_guard"); break;
419 case 'C': SET_OPERATOR_CODE ("string"); break;
420 case 'D': SET_OPERATOR_CODE ("vbase_dtor"); break;
421 case 'E': SET_OPERATOR_CODE ("vector_dtor"); break;
422 case 'G': SET_OPERATOR_CODE ("scalar_dtor"); break;
423 case 'H': SET_OPERATOR_CODE ("vector_ctor_iter"); break;
424 case 'I': SET_OPERATOR_CODE ("vector_dtor_iter"); break;
425 case 'J': SET_OPERATOR_CODE ("vector_vbase_ctor_iter"); break;
426 case 'L': SET_OPERATOR_CODE ("eh_vector_ctor_iter"); break;
427 case 'M': SET_OPERATOR_CODE ("eh_vector_dtor_iter"); break;
428 case 'N': SET_OPERATOR_CODE ("eh_vector_vbase_ctor_iter"); break;
429 case 'O': SET_OPERATOR_CODE ("copy_ctor_closure"); break;
430 case 'R':
431 switch (*++buf) {
432 case '0': {
433 size_t len;
434 char *str = NULL;
435 if (parse_microsoft_rtti_mangled_name (buf + 2, &str, &len) != eDemanglerErrOK) {
436 r_list_free (names_l);
437 return 0;
438 }
439 read_len += len + 2;
440 str = r_str_append (str, " `RTTI Type Descriptor'");
441 SET_OPERATOR_CODE (str);
442 free (str);
443 break;
444 }
445 case '1': {
446 SStateInfo state;
447 init_state_struct (&state, buf + 1);
448 char *a = get_num (&state);
449 char *b = get_num (&state);
450 char *c = get_num (&state);
451 char *d = get_num (&state);
452 if (!a || !b || !c || !d) {
453 r_list_free (names_l);
454 return 0;
455 }
456 read_len += state.amount_of_read_chars + 1;
457 r_str_newf ("`RTTI Base Class Descriptor at (%s,%s,%s,%s)'", a, b, c, d);
458 break;
459 }
460 case '2': SET_OPERATOR_CODE ("`RTTI Base Class Array'"); break;
461 case '3': SET_OPERATOR_CODE ("`RTTI Class Hierarchy Descriptor'"); break;
462 case '4': SET_OPERATOR_CODE ("`RTTI Complete Object Locator'"); break;
463 default: return 0;
464 }
465 break;
466 case 'S': SET_OPERATOR_CODE ("local_vftable"); break;
467 case 'T': SET_OPERATOR_CODE ("local_vftable_ctor_closure"); break;
468 case 'U': SET_OPERATOR_CODE ("operator new[]"); break;
469 case 'V': SET_OPERATOR_CODE ("operator delete[]"); break;
470 case 'X': SET_OPERATOR_CODE ("placement_new_closure"); break;
471 case 'Y': SET_OPERATOR_CODE ("placement_delete_closure"); break;
472 default:
473 r_list_free (names_l);
474 return 0;
475 }
476 read_len++;
477 break;
478 default:
479 r_list_free (names_l);
480 return 0;
481 }
482 read_len++;
483 return read_len;
484 #undef SET_OPERATOR_CODE
485 }
486
487 ///////////////////////////////////////////////////////////////////////////////
get_template(const char * buf,SStrInfo * str_info,bool memorize)488 static size_t get_template(const char *buf, SStrInfo *str_info, bool memorize) {
489 size_t len = 0;
490 char *str_type_code = NULL;
491 STypeCodeStr type_code_str;
492 // RListIter *it = NULL;
493 RList *saved_abbr_names = abbr_names; // save current abbr names, this
494 RList *new_abbr_names = r_list_newf (free);
495
496 if (!init_type_code_str_struct(&type_code_str)) {
497 goto get_template_err;
498 }
499
500 if (*buf == '?') {
501 RList *names_l = r_list_newf ((RListFree)sstrinfo_free);
502 if (!names_l) {
503 return 0;
504 }
505 size_t i = get_operator_code (buf, names_l, memorize);
506 if (!i) {
507 return 0;
508 }
509 len += i;
510 buf += i;
511 SStrInfo *name = r_list_head (names_l)->data;
512 copy_string (&type_code_str, name->str_ptr, name->len);
513 r_list_free (names_l);
514 } else {
515 char *tmp = strchr(buf, '@');
516 if (!tmp) {
517 goto get_template_err;
518 }
519
520 // get/copy template len/name
521 len += (tmp - buf + 1);
522 copy_string (&type_code_str, buf, len - 1);
523 r_list_append (new_abbr_names, r_str_ndup (buf, len - 1));
524 buf += len;
525 }
526
527 if (*buf != '@') {
528 copy_string (&type_code_str, "<", 0);
529 }
530
531 abbr_names = new_abbr_names;
532
533 // get identifier
534 size_t i = 0;
535 while (*buf != '@') {
536 if (i) {
537 copy_string (&type_code_str, ", ", 0);
538 }
539 if (get_type_code_string (buf, &i, &str_type_code) != eDemanglerErrOK) {
540 if (get_template_params (buf, &i, &str_type_code) != eDemanglerErrOK) {
541 len = 0;
542 goto get_template_err;
543 }
544 }
545 copy_string (&type_code_str, str_type_code, 0);
546 buf += i;
547 len += i;
548 R_FREE (str_type_code);
549 }
550 if (*buf != '@') {
551 len = 0;
552 goto get_template_err;
553 }
554 if (i) {
555 copy_string (&type_code_str, ">", 0);
556 }
557 buf++;
558 len++;
559
560 str_info->str_ptr = type_code_str.type_str;
561 str_info->len = type_code_str.curr_pos;
562
563 get_template_err:
564 r_list_free (new_abbr_names);
565 abbr_names = saved_abbr_names; // restore global list with name abbr.
566
567 if (memorize) {
568 r_list_append (abbr_names, strdup (type_code_str.type_str));
569 }
570
571 // will be free at a caller function
572 // free_type_code_str_struct(&type_code_str);
573 return len;
574 }
575
576 ///////////////////////////////////////////////////////////////////////////////
577 /// \brief get_namespace_and_name
578 /// \param buf Current buffer position with mangled name
579 /// \param type_code_str String with got name and namespaces
580 /// \param amount_of_names Amount of names that was in list
581 /// \return Return amount of processed chars
582 ///
get_namespace_and_name(const char * buf,STypeCodeStr * type_code_str,size_t * amount_of_names,bool memorize)583 static size_t get_namespace_and_name(const char *buf, STypeCodeStr *type_code_str, size_t *amount_of_names, bool memorize) {
584 const char *curr_pos = NULL, *prev_pos = NULL, *tmp = NULL;
585 RList /* <SStrInfo *> */ *names_l = NULL;
586 RListIter *it = NULL;
587 SStrInfo *str_info = NULL;
588
589 size_t len = 0, read_len = 0, tmp_len = 0;
590
591 names_l = r_list_newf ((RListFree)sstrinfo_free);
592
593 if (*buf == '?') {
594 size_t res = get_operator_code (buf, names_l, memorize);
595 if (!res) {
596 return 0;
597 }
598 memorize = true;
599 buf += res;
600 read_len += res;
601 }
602
603 prev_pos = buf;
604 curr_pos = strchr (buf, '@');
605
606 // hack for nested templates
607 // think about how better to fix this...
608 len = curr_pos - prev_pos;
609 if (len == 0) {
610 goto get_namespace_and_name_err;
611 }
612
613 while (curr_pos != NULL) {
614 len = curr_pos - prev_pos;
615 tmp = prev_pos;
616
617 if ((len == 0) && (*(curr_pos) == '@')) {
618 break;
619 }
620
621 // TODO:maybe add check of name correctness? like name can not start
622 // with number
623 if ((len <= 0) || (len >= MICROSOFT_NAME_LEN)) {
624 goto get_namespace_and_name_err;
625 }
626
627 str_info = malloc (sizeof (SStrInfo));
628 if (!str_info) {
629 break;
630 }
631
632 // check is it teamplate???
633 if ((*tmp == '?') && (*(tmp + 1) == '$')) {
634 size_t i = 0;
635 i = get_template (tmp + 2, str_info, memorize);
636 if (!i) {
637 R_FREE (str_info);
638 goto get_namespace_and_name_err;
639 }
640 r_list_append (names_l, str_info);
641
642 prev_pos = tmp + i + 2;
643 curr_pos = strchr (prev_pos, '@');
644 read_len += i + 2;
645 // if (curr_pos)
646 // read_len++;
647 continue;
648 }
649
650 if ((*tmp == '?') && (*(tmp + 1) == 'Q')) {
651 STypeCodeStr str;
652 if (!init_type_code_str_struct (&str)) {
653 break;
654 }
655 size_t i = get_namespace_and_name (tmp + 2, &str, NULL, true);
656 if (!i) {
657 break;
658 }
659 prev_pos = tmp + i + 3;
660 curr_pos = strchr (prev_pos, '@');
661 read_len += i + 3;
662 str_info->str_ptr = r_str_newf ("[%s]", str.type_str);
663 str_info->len = strlen (str_info->str_ptr);
664 r_list_append (names_l, str_info);
665 free (str.type_str);
666 continue;
667 }
668
669 // Nested name
670 if (*tmp == '?') {
671 read_len++;
672 // Optional sequence number
673 char *num = NULL;
674 if (*(tmp + 1) != '?') {
675 SStateInfo state;
676 init_state_struct (&state, tmp + 1);
677 num = get_num (&state);
678 tmp += state.amount_of_read_chars + 1;
679 read_len += state.amount_of_read_chars + 1;
680 }
681 char *demangled;
682 if (parse_microsoft_mangled_name (tmp + 2, &demangled, &len) != eDemanglerErrOK) {
683 break;
684 }
685 read_len += len + 1;
686 if (num) {
687 str_info->str_ptr = r_str_newf ("`%s'::`%s'", demangled, num);
688 free (num);
689 } else {
690 str_info->str_ptr = r_str_newf ("`%s'", demangled);
691 }
692
693 str_info->len = strlen (str_info->str_ptr);
694 r_list_append (names_l, str_info);
695 r_list_append (abbr_names, strdup (str_info->str_ptr));
696 free (demangled);
697 break;
698 }
699
700 if (isdigit ((ut8)*tmp)) {
701 tmp = r_list_get_n (abbr_names, *tmp - '0');
702 if (!tmp) {
703 break;
704 }
705 len = 1;
706 } else {
707 char *tmpname = malloc (len + 1);
708 memset (tmpname, 0, len + 1);
709 memcpy (tmpname, prev_pos, len);
710 r_list_append (abbr_names, tmpname);
711 tmp = tmpname;
712 }
713
714 str_info->str_ptr = strdup (tmp);
715 str_info->len = strlen (tmp);
716
717 r_list_append (names_l, str_info);
718
719 memorize = true;
720
721 read_len += len;
722 if (len == 1) {
723 if (*(prev_pos + 1) == '@') {
724 prev_pos = curr_pos;
725 } else {
726 prev_pos++;
727 }
728 } else {
729 prev_pos = curr_pos + 1;
730 curr_pos = strchr (curr_pos + 1, '@');
731 if (curr_pos) {
732 read_len++;
733 }
734 }
735 }
736
737 get_namespace_and_name_err:
738 tmp_len = r_list_length (names_l);
739 if (amount_of_names) {
740 *amount_of_names = tmp_len;
741 }
742 r_list_foreach_prev (names_l, it, str_info) {
743 copy_string (type_code_str, str_info->str_ptr, str_info->len);
744
745 if (--tmp_len) {
746 copy_string (type_code_str, "::", 0);
747 }
748 }
749 r_list_free (names_l);
750 return read_len;
751 }
752
753 #define SINGLEQUOTED_U 'U'
754 #define SINGLEQUOTED_X 'X'
755 #define SINGLEQUOTED_D 'D'
756 #define SINGLEQUOTED_C 'C'
757 #define SINGLEQUOTED_E 'E'
758 #define SINGLEQUOTED_F 'F'
759 #define SINGLEQUOTED_G 'G'
760 #define SINGLEQUOTED_H 'H'
761 #define SINGLEQUOTED_I 'I'
762 #define SINGLEQUOTED_J 'J'
763 #define SINGLEQUOTED_K 'K'
764 #define SINGLEQUOTED_M 'M'
765 #define SINGLEQUOTED_N 'N'
766 #define SINGLEQUOTED_T 'T'
767 #define SINGLEQUOTED_Z 'Z'
768 #define SINGLEQUOTED_W 'W'
769 #define SINGLEQUOTED_V 'V'
770 #define SINGLEQUOTED_O 'O'
771 #define SINGLEQUOTED_S 'S'
772 #define SINGLEQUOTED_P 'P'
773 #define SINGLEQUOTED_R 'R'
774 #define SINGLEQUOTED_Q 'Q'
775 #define SINGLEQUOTED_A 'A'
776 #define SINGLEQUOTED__ '_'
777 #define SINGLEQUOTED_$ '$'
778 #define CHAR_WITH_QUOTES(letter) (SINGLEQUOTED_##letter)
779
780 #define DEF_STATE_ACTION(action) static void tc_state_##action(SStateInfo *state, STypeCodeStr *type_code_str)
781 #define GO_TO_NEXT_STATE(state, new_state) { \
782 (state)->amount_of_read_chars++; \
783 (state)->buff_for_parsing++; \
784 (state)->state = eTCStateEnd; \
785 }
786 #define ONE_LETTER_ACTIION(action, type) \
787 static void tc_state_##action(SStateInfo *state, STypeCodeStr *type_code_str) \
788 { \
789 if (copy_string(type_code_str, type, 0) == 0) { \
790 state->err = eTCStateMachineErrAlloc; \
791 } \
792 state->state = eTCStateEnd; \
793 } \
794
795 ONE_LETTER_ACTIION(X, "void")
796 ONE_LETTER_ACTIION(D, "char")
797 ONE_LETTER_ACTIION(C, "signed char")
798 ONE_LETTER_ACTIION(E, "unsigned char")
799 ONE_LETTER_ACTIION(F, "short int")
800 ONE_LETTER_ACTIION(G, "unsigned short int")
801 ONE_LETTER_ACTIION(H, "int")
802 ONE_LETTER_ACTIION(I, "unsigned int")
803 ONE_LETTER_ACTIION(J, "long int")
804 ONE_LETTER_ACTIION(K, "unsigned long int")
805 ONE_LETTER_ACTIION(M, "float")
806 ONE_LETTER_ACTIION(N, "double")
807 ONE_LETTER_ACTIION(Z, "varargs ...")
808 ONE_LETTER_ACTIION(O, "long double")
809
DEF_STATE_ACTION(_)810 DEF_STATE_ACTION(_)
811 {
812 #define PROCESS_CASE(letter, type_str) \
813 case CHAR_WITH_QUOTES(letter): \
814 copy_string(type_code_str, type_str, 0); \
815 break;
816
817 switch(*(state->buff_for_parsing)) {
818 PROCESS_CASE (J, "long long(__int64)")
819 PROCESS_CASE (K, "unsigned long long(unsigned __int64)")
820 PROCESS_CASE (T, "long double(80 bit precision)")
821 PROCESS_CASE (Z, "long double(64 bit precision)")
822 PROCESS_CASE (W, "wchar_t")
823 PROCESS_CASE (N, "bool")
824 default:
825 state->err = eTCStateMachineErrUncorrectTypeCode;
826 break;
827 }
828
829 state->amount_of_read_chars++;
830 state->buff_for_parsing++;
831 state->state = eTCStateEnd;
832 #undef PROCESS_CASE
833 }
834
835 ///////////////////////////////////////////////////////////////////////////////
836 // isdigit need to check is it need to do deabbreviation of names
837 // +2 -> skipp @@ ( the end of class, union,...
838 // or +2 -> skip abbreviated_num + '@'
839 #define GET_USER_DEF_TYPE_NAME(data_struct_str) { \
840 copy_string (type_code_str, data_struct_str, 0); \
841 \
842 check_len = get_namespace_and_name (state->buff_for_parsing, type_code_str, NULL, true); \
843 if (check_len) { \
844 state->amount_of_read_chars += check_len; \
845 state->buff_for_parsing += check_len; \
846 if (*state->buff_for_parsing) { \
847 state->buff_for_parsing++; \
848 state->amount_of_read_chars++; \
849 } \
850 } else { \
851 state->err = eTCStateMachineErrUncorrectTypeCode; \
852 } \
853 }
854
DEF_STATE_ACTION(T)855 DEF_STATE_ACTION(T)
856 {
857 #define PROCESS_CASE(case_string, type_str) { \
858 check_len = strlen (case_string); \
859 if ((check_len < buff_len) && \
860 (strncmp (state->buff_for_parsing, case_string, check_len) == 0)) { \
861 copy_string (type_code_str, type_str, 0); \
862 state->buff_for_parsing += check_len; \
863 state->amount_of_read_chars += check_len; \
864 return; \
865 } \
866 }
867
868 size_t buff_len = strlen (state->buff_for_parsing);
869 size_t check_len = 0;
870
871 state->state = eTCStateEnd;
872
873 PROCESS_CASE ("__m64@@", "__m64");
874 PROCESS_CASE ("__m128@@", "__m128");
875 PROCESS_CASE ("__m128i@@", "__m128i");
876 PROCESS_CASE ("__m256@@", "__m256");
877 PROCESS_CASE ("__m256i@@", "__m256i");
878 PROCESS_CASE ("__m512@@", "__m512");
879 PROCESS_CASE ("__m512i@@", "__m512i");
880
881 GET_USER_DEF_TYPE_NAME ("union ");
882 #undef PROCESS_CASE
883 }
884
DEF_STATE_ACTION(U)885 DEF_STATE_ACTION(U)
886 {
887 #define PROCESS_CASE(case_string, type_str) { \
888 check_len = strlen (case_string); \
889 if ((check_len < buff_len) && \
890 (strncmp (state->buff_for_parsing, case_string, check_len) == 0)) { \
891 copy_string (type_code_str, type_str, 0); \
892 state->amount_of_read_chars += check_len; \
893 state->buff_for_parsing += check_len; \
894 return; \
895 } \
896 }
897
898 size_t buff_len = strlen (state->buff_for_parsing);
899 size_t check_len = 0;
900
901 state->state = eTCStateEnd;
902
903 PROCESS_CASE ("__m128d@@", "__m128d");
904 PROCESS_CASE ("__m256d@@", "__m256d");
905 PROCESS_CASE ("__m512d@@", "__m512d");
906
907 GET_USER_DEF_TYPE_NAME ("struct ");
908 #undef PROCESS_CASE
909 }
910
DEF_STATE_ACTION(W)911 DEF_STATE_ACTION(W)
912 {
913 //W4X@@ -> enum X, W4X@Y@@ -> enum Y::X
914 size_t check_len = 0;
915 state->state = eTCStateEnd;
916
917 if (*state->buff_for_parsing != '4') {
918 state->err = eTCStateMachineErrUncorrectTypeCode;
919 }
920
921 state->buff_for_parsing++;
922 state->amount_of_read_chars++;
923
924 GET_USER_DEF_TYPE_NAME("enum ");
925 }
926
DEF_STATE_ACTION(V)927 DEF_STATE_ACTION(V)
928 {
929 // VX@@ -> class X
930 size_t check_len = 0;
931 state->state = eTCStateEnd;
932
933 GET_USER_DEF_TYPE_NAME("class ");
934 }
935
936 #undef GET_USER_DEF_TYPE_NAME
937
get_num(SStateInfo * state)938 static char *get_num(SStateInfo *state) {
939 char *ptr = NULL;
940 if (*state->buff_for_parsing >= '0' && *state->buff_for_parsing <= '8') {
941 ptr = malloc (2);
942 if (!ptr) {
943 return NULL;
944 }
945 ptr[0] = *state->buff_for_parsing + 1;
946 ptr[1] = '\0';
947 state->buff_for_parsing++;
948 state->amount_of_read_chars++;
949 } else if (*state->buff_for_parsing == '9') {
950 ptr = strdup ("10");
951 state->buff_for_parsing++;
952 state->amount_of_read_chars++;
953 } else if (*state->buff_for_parsing >= 'A' && *state->buff_for_parsing <= 'P') {
954 ut32 ret = 0;
955
956 while (*state->buff_for_parsing >= 'A' && *state->buff_for_parsing <= 'P') {
957 ret *= 16;
958 ret += *state->buff_for_parsing - 'A';
959 state->buff_for_parsing++;
960 state->amount_of_read_chars++;
961 }
962
963 if (*state->buff_for_parsing != '@') {
964 return NULL;
965 }
966
967 ptr = r_str_newf ("%u", ret);
968 state->buff_for_parsing++;
969 state->amount_of_read_chars++;
970 }
971
972 return ptr;
973 }
974
parse_type_modifier(SStateInfo * state,STypeCodeStr * type_code_str,const char * modifier_str)975 static inline void parse_type_modifier(SStateInfo *state, STypeCodeStr *type_code_str, const char *modifier_str) {
976 size_t i = 0;
977 EDemanglerErr err = eDemanglerErrOK;
978 char *tmp = NULL;
979 STypeCodeStr tmp_str;
980 STypeCodeStr modifier;
981 bool is_pin_ptr = false;
982 char clr_type = '\0';
983
984 state->state = eTCStateEnd;
985
986 if (!init_type_code_str_struct (&tmp_str)) {
987 state->err = eTCStateMachineErrAlloc;
988 return;
989 }
990 if (!init_type_code_str_struct (&modifier)) {
991 free_type_code_str_struct (&tmp_str);
992 state->err = eTCStateMachineErrAlloc;
993 return;
994 }
995
996 if (*state->buff_for_parsing == '$') {
997 if (state->buff_for_parsing[1] == '0') {
998 // TODO: no idea what this means
999 state->buff_for_parsing += 3;
1000 state->amount_of_read_chars += 3;
1001 }
1002 }
1003
1004 SDataType mod;
1005 i = get_ptr_modifier (*state->buff_for_parsing, &mod);
1006 state->buff_for_parsing += i;
1007 state->amount_of_read_chars += i;
1008
1009 if (*state->buff_for_parsing == '$') {
1010 state->buff_for_parsing++;
1011 switch (*state->buff_for_parsing++) {
1012 case 'A':
1013 clr_type = '^';
1014 break;
1015 case 'B': // cli::pin_ptr<T>
1016 is_pin_ptr = true;
1017 break;
1018 case 'C':
1019 clr_type = '%';
1020 break;
1021 default:
1022 state->err = eTCStateMachineErrUnsupportedTypeCode;
1023 break;
1024 }
1025 state->amount_of_read_chars += 2;
1026 }
1027
1028 SDataType mod2;
1029 i = get_ptr_modifier (*state->buff_for_parsing, &mod2);
1030 state->buff_for_parsing += i;
1031 state->amount_of_read_chars += i;
1032
1033 const char *storage_class;
1034 if (get_storage_class (*state->buff_for_parsing, &storage_class) != eDemanglerErrOK) {
1035 state->err = eTCStateMachineErrUnsupportedTypeCode;
1036 goto MODIFIER_err;
1037 }
1038 if (storage_class) {
1039 copy_string (&modifier, storage_class, 0);
1040 copy_string (&modifier, " ", 1);
1041 }
1042 copy_string (&modifier, mod2.left, 0);
1043
1044 state->buff_for_parsing++;
1045 state->amount_of_read_chars++;
1046
1047 if (*state->buff_for_parsing == 'Y') {
1048 char *n1;
1049 int num;
1050
1051 state->buff_for_parsing++;
1052 state->amount_of_read_chars++;
1053 if (!(n1 = get_num (state))) {
1054 goto MODIFIER_err;
1055 }
1056 num = atoi (n1);
1057 R_FREE (n1);
1058
1059 copy_string (&tmp_str, " ", 0);
1060 copy_string (&tmp_str, "(", 0);
1061 copy_string (&tmp_str, modifier.type_str, modifier.curr_pos);
1062 copy_string (&tmp_str, modifier_str, 0);
1063 copy_string (&tmp_str, ")", 0);
1064
1065 while (num--) {
1066 n1 = get_num (state);
1067 copy_string (&tmp_str, "[", 0);
1068 copy_string (&tmp_str, n1, 0);
1069 copy_string (&tmp_str, "]", 0);
1070 R_FREE (n1);
1071 }
1072 }
1073
1074 if (tmp_str.curr_pos == 0) {
1075 copy_string (&tmp_str, " ", 0);
1076 copy_string (&tmp_str, modifier.type_str, modifier.curr_pos);
1077 copy_string (&tmp_str, mod.left, 0);
1078 if (clr_type) {
1079 char *str = strdup (modifier_str);
1080 if (!str) {
1081 state->err = eTCStateMachineErrAlloc;
1082 goto MODIFIER_err;
1083 }
1084 *str = clr_type;
1085 copy_string (&tmp_str, str, 0);
1086 free (str);
1087 } else {
1088 if (is_pin_ptr) {
1089 while (*++modifier_str == ' ') {};
1090 }
1091 copy_string (&tmp_str, modifier_str, 0);
1092 }
1093 copy_string (&tmp_str, mod2.right, 0);
1094 }
1095
1096 if (!strncmp (state->buff_for_parsing, "__Z", 3)) {
1097 // TODO: no idea what this means
1098 state->buff_for_parsing += 3;
1099 state->amount_of_read_chars += 3;
1100 }
1101
1102 err = get_type_code_string (state->buff_for_parsing, &i, &tmp);
1103 if (err != eDemanglerErrOK) {
1104 state->err = eTCStateMachineErrUnsupportedTypeCode;
1105 goto MODIFIER_err;
1106 }
1107
1108 state->amount_of_read_chars += i;
1109 state->buff_for_parsing += i;
1110 if (is_pin_ptr) {
1111 copy_string (type_code_str, "cli::pin_ptr<", 0);
1112 }
1113 copy_string (type_code_str, tmp, 0);
1114 copy_string (type_code_str, tmp_str.type_str, tmp_str.curr_pos);
1115 if (is_pin_ptr) {
1116 copy_string (type_code_str, ">", 0);
1117 }
1118 copy_string (type_code_str, mod.right, 0);
1119
1120 MODIFIER_err:
1121 R_FREE (tmp);
1122 free_type_code_str_struct (&tmp_str);
1123 free_type_code_str_struct (&modifier);
1124 }
1125
DEF_STATE_ACTION(S)1126 DEF_STATE_ACTION(S)
1127 {
1128 parse_type_modifier (state, type_code_str, "* const volatile");
1129 }
1130
get_calling_convention(char calling_convention)1131 static inline const char *get_calling_convention(char calling_convention) {
1132 switch (calling_convention) {
1133 case 'A': return "__cdecl";
1134 case 'B': return "__cdecl __declspec(dllexport)";
1135 case 'C': return "__pascal";
1136 case 'D': return "__pascal __declspec(dllexport)";
1137 case 'E': return "__thiscall";
1138 case 'F': return "__thiscall __declspec(dllexport)";
1139 case 'G': return "__stdcall";
1140 case 'H': return "__stdcall __declspec(dllexport)";
1141 case 'I': return "__fastcall";
1142 case 'J': return "__fastcall __declspec(dllexport)";
1143 case 'K': return "default (none given)";
1144 case 'L': return "default (none given) __declspec(dllexport)";
1145 case 'M': return "__clrcall";
1146 default: return NULL;
1147 }
1148 }
1149
parse_function_args(const char * sym,char ** demangled_args,size_t * read_chars)1150 static EDemanglerErr parse_function_args(const char *sym, char **demangled_args, size_t *read_chars) {
1151 EDemanglerErr err = eDemanglerErrOK;
1152 const char *curr_pos = sym;
1153 size_t len = 0;
1154
1155 STypeCodeStr func_str;
1156 if (!init_type_code_str_struct (&func_str)) {
1157 return eDemanglerErrMemoryAllocation;
1158 }
1159
1160 copy_string (&func_str, "(", 0);
1161
1162 // Function arguments
1163 while (*curr_pos && *curr_pos != 'Z') {
1164 if (*curr_pos != '@') {
1165 char *tmp;
1166 bool is_abbr_type = false;
1167 if (len) {
1168 copy_string (&func_str, ", ", 0);
1169 }
1170 err = get_type_code_string (curr_pos, &len, &tmp);
1171 if (err != eDemanglerErrOK) {
1172 // abbreviation of type processing
1173 if ((*curr_pos >= '0') && (*curr_pos <= '9')) {
1174 free (tmp);
1175 tmp = r_list_get_n (abbr_types, (ut32)(*curr_pos - '0'));
1176 if (!tmp) {
1177 err = eDemanglerErrUncorrectMangledSymbol;
1178 break;
1179 }
1180 err = eDemanglerErrOK;
1181 len = 1;
1182 is_abbr_type = true;
1183 } else {
1184 err = eDemanglerErrUncorrectMangledSymbol;
1185 free (tmp);
1186 break;
1187 }
1188 }
1189 curr_pos += len;
1190
1191 if (len > 1) {
1192 r_list_append (abbr_types, strdup (tmp));
1193 }
1194
1195 copy_string (&func_str, tmp, 0);
1196
1197 if (!strcmp (tmp, "void")) {
1198 // arguments list is void
1199 if (!is_abbr_type) {
1200 free (tmp);
1201 }
1202 break;
1203 }
1204 if (!is_abbr_type) {
1205 free (tmp);
1206 }
1207 } else {
1208 curr_pos++;
1209 }
1210 }
1211
1212 while (*curr_pos == '@') {
1213 curr_pos++;
1214 }
1215
1216 if (*curr_pos != 'Z') {
1217 err = eDemanglerErrUncorrectMangledSymbol;
1218 }
1219
1220 copy_string (&func_str, ")", 0);
1221
1222 if (demangled_args) {
1223 *demangled_args = strdup (func_str.type_str);
1224 }
1225
1226 free_type_code_str_struct (&func_str);
1227
1228 if (read_chars) {
1229 *read_chars = curr_pos - sym + 1;
1230 }
1231
1232 return err;
1233 }
1234
1235 // TODO: use parse_function() instead
pf(SStateInfo * state,STypeCodeStr * type_code_str,const char * pointer_str)1236 static void pf(SStateInfo *state, STypeCodeStr *type_code_str, const char *pointer_str) {
1237 const char *call_conv = NULL;
1238 const char *storage = NULL;
1239 char *ret_type = NULL;
1240 size_t i = 0;
1241 EDemanglerErr err;
1242
1243 state->state = eTCStateEnd;
1244
1245 // Calling convention
1246 call_conv = get_calling_convention (*state->buff_for_parsing++);
1247 if (!call_conv) {
1248 // XXX unify error messages into a single enum
1249 state->err = (ETCStateMachineErr)eDemanglerErrUncorrectMangledSymbol;
1250 }
1251
1252 state->amount_of_read_chars += 2; // '6' + call_conv
1253
1254 // return type
1255 if (*state->buff_for_parsing == '?') {
1256 err = get_storage_class (*++state->buff_for_parsing, &storage);
1257 if (err != eDemanglerErrOK) {
1258 state->err = eTCStateMachineErrUncorrectTypeCode;
1259 return;
1260 }
1261 state->buff_for_parsing++;
1262 state->amount_of_read_chars += 2;
1263 }
1264 err = get_type_code_string (state->buff_for_parsing, &i, &ret_type);
1265 if (err != eDemanglerErrOK) {
1266 state->err = eTCStateMachineErrUnsupportedTypeCode;
1267 return;
1268 }
1269
1270 copy_string (type_code_str, ret_type, 0);
1271 if (storage) {
1272 copy_string (type_code_str, " ", 1);
1273 copy_string (type_code_str, storage, 0);
1274 }
1275 copy_string (type_code_str, " (", 0);
1276 R_FREE (ret_type);
1277
1278 copy_string (type_code_str, call_conv, 0);
1279 copy_string (type_code_str, " ", 1);
1280 copy_string (type_code_str, pointer_str, 0);
1281 copy_string (type_code_str, ")", 1);
1282
1283 state->amount_of_read_chars += i;
1284 state->buff_for_parsing += i;
1285
1286 char *demangled_args;
1287 if (parse_function_args (state->buff_for_parsing, &demangled_args, &i) != eDemanglerErrOK) {
1288 state->err = eTCStateMachineErrUncorrectTypeCode;
1289 return;
1290 }
1291 state->amount_of_read_chars += i;
1292 state->buff_for_parsing += i;
1293 copy_string (type_code_str, demangled_args, 0);
1294 free (demangled_args);
1295 return;
1296 }
1297
parse_pointer(SStateInfo * state,STypeCodeStr * type_code_str,const char * pointer_str)1298 static void parse_pointer(SStateInfo *state, STypeCodeStr *type_code_str, const char *pointer_str) {
1299 if (isdigit ((ut8)*state->buff_for_parsing)) {
1300 ut8 digit = *state->buff_for_parsing++;
1301 if (digit == '6' || digit == '7') {
1302 pf (state, type_code_str, pointer_str);
1303 return;
1304 } else if (digit == '8' || digit == '9') {
1305 STypeCodeStr func_str;
1306 if (!init_type_code_str_struct (&func_str)) {
1307 state->err = eTCStateMachineErrAlloc;
1308 return;
1309 };
1310 size_t read = get_namespace_and_name (state->buff_for_parsing, &func_str, NULL, true) + 1;
1311 state->amount_of_read_chars += read;
1312 state->buff_for_parsing += read;
1313 copy_string (&func_str, "::", 2);
1314 copy_string (&func_str, pointer_str, 0);
1315 pf (state, type_code_str, func_str.type_str);
1316 free_type_code_str_struct (&func_str);
1317 state->state = eTCStateEnd;
1318 return;
1319 }
1320 }
1321 parse_type_modifier (state, type_code_str, pointer_str);
1322 }
1323
1324 #define PARSE_POINTER(pointer_str) parse_pointer (state, type_code_str, pointer_str)
1325
1326
DEF_STATE_ACTION(P)1327 DEF_STATE_ACTION(P) {
1328 PARSE_POINTER ("*");
1329 }
1330
DEF_STATE_ACTION(R)1331 DEF_STATE_ACTION(R) {
1332 PARSE_POINTER ("* volatile");
1333 }
1334
DEF_STATE_ACTION(Q)1335 DEF_STATE_ACTION(Q) {
1336 PARSE_POINTER ("* const");
1337 }
1338
DEF_STATE_ACTION(A)1339 DEF_STATE_ACTION(A) {
1340 PARSE_POINTER ("&");
1341 }
1342
DEF_STATE_ACTION($)1343 DEF_STATE_ACTION($) {
1344 if (*(state->buff_for_parsing++) != '$') {
1345 state->err = eTCStateMachineErrUncorrectTypeCode;
1346 return;
1347 }
1348 state->amount_of_read_chars += 2;
1349 switch (*state->buff_for_parsing++) {
1350 case 'A':
1351 state->state = eTCStateP;
1352 break;
1353 case 'B':
1354 parse_type_modifier (state, type_code_str, "");
1355 break;
1356 case 'C':
1357 parse_type_modifier (state, type_code_str, "");
1358 break;
1359 case 'F':
1360 state->state = eTCStateP;
1361 break;
1362 case 'Q':
1363 parse_type_modifier (state, type_code_str, "&&");
1364 state->state = eTCStateEnd;
1365 break;
1366 case 'R':
1367 parse_type_modifier (state, type_code_str, "&& volatile");
1368 state->state = eTCStateEnd;
1369 break;
1370 case 'T':
1371 copy_string (type_code_str, "std::nullptr_t", 15);
1372 state->state = eTCStateEnd;
1373 break;
1374 case 'V':
1375 state->state = eTCStateEnd;
1376 break;
1377 case 'Z':
1378 state->state = eTCStateEnd;
1379 break;
1380 default:
1381 state->err = eTCStateMachineErrUncorrectTypeCode;
1382 break;
1383 }
1384 }
1385
1386 #undef ONE_LETTER_ACTION
1387 #undef GO_TO_NEXT_STATE
1388 #undef DEF_STATE_ACTION
1389
tc_state_start(SStateInfo * state,STypeCodeStr * type_code_str)1390 static void tc_state_start(SStateInfo *state, STypeCodeStr *type_code_str) {
1391 #define ONE_LETTER_STATE(letter) \
1392 case CHAR_WITH_QUOTES(letter): \
1393 state->state = eTCState##letter; \
1394 break; \
1395
1396 switch (*(state->buff_for_parsing)) {
1397 ONE_LETTER_STATE (X)
1398 ONE_LETTER_STATE (D)
1399 ONE_LETTER_STATE (C)
1400 ONE_LETTER_STATE (E)
1401 ONE_LETTER_STATE (F)
1402 ONE_LETTER_STATE (G)
1403 ONE_LETTER_STATE (H)
1404 ONE_LETTER_STATE (I)
1405 ONE_LETTER_STATE (J)
1406 ONE_LETTER_STATE (K)
1407 ONE_LETTER_STATE (M)
1408 ONE_LETTER_STATE (N)
1409 ONE_LETTER_STATE (Z)
1410 ONE_LETTER_STATE (_)
1411 ONE_LETTER_STATE (T)
1412 ONE_LETTER_STATE (U)
1413 ONE_LETTER_STATE (W)
1414 ONE_LETTER_STATE (V)
1415 ONE_LETTER_STATE (O)
1416 ONE_LETTER_STATE (S)
1417 ONE_LETTER_STATE (P)
1418 ONE_LETTER_STATE (R)
1419 ONE_LETTER_STATE (Q)
1420 ONE_LETTER_STATE (A)
1421 ONE_LETTER_STATE ($)
1422 default:
1423 //eprintf("[uncorrect type] error while parsing type\n");
1424
1425 state->state = eTCStateEnd;
1426 state->err = eTCStateMachineErrUncorrectTypeCode;
1427 break;
1428 }
1429
1430 state->amount_of_read_chars++;
1431 state->buff_for_parsing++;
1432 #undef ONE_LETTER_STATE
1433 }
1434
tc_state_end(SStateInfo * state,STypeCodeStr * type_code_str)1435 static void tc_state_end(SStateInfo *state, STypeCodeStr *type_code_str) {
1436 return;
1437 }
1438
init_state_struct(SStateInfo * state,const char * buff_for_parsing)1439 static void init_state_struct(SStateInfo *state, const char *buff_for_parsing) {
1440 state->state = eTCStateStart;
1441 state->buff_for_parsing = buff_for_parsing;
1442 state->amount_of_read_chars = 0;
1443 state->err = eTCStateMachineErrOK;
1444 }
1445
init_type_code_str_struct(STypeCodeStr * type_coder_str)1446 static bool init_type_code_str_struct(STypeCodeStr *type_coder_str) {
1447 #define TYPE_STR_LEN 1024
1448 // 1 - initialization finish with success, else - 0
1449
1450 type_coder_str->type_str_len = TYPE_STR_LEN;
1451
1452 type_coder_str->type_str = (char *) calloc (TYPE_STR_LEN, sizeof (char));
1453 if (!type_coder_str->type_str) {
1454 return false;
1455 }
1456 memset (type_coder_str->type_str, 0, TYPE_STR_LEN * sizeof(char));
1457
1458 type_coder_str->curr_pos = 0; // strlen ("unknown type");
1459 // strncpy(type_coder_str->type_str, "unknown_type", type_coder_str->curr_pos);
1460
1461 return true;
1462 #undef TYPE_STR_LEN
1463 }
1464
free_type_code_str_struct(STypeCodeStr * type_code_str)1465 static void free_type_code_str_struct(STypeCodeStr *type_code_str) {
1466 if (type_code_str->type_str) {
1467 R_FREE (type_code_str->type_str);
1468 }
1469 type_code_str->type_str_len = 0;
1470 }
1471
1472 ///////////////////////////////////////////////////////////////////////////////
1473 // End of machine functions for parsing type codes
1474 ///////////////////////////////////////////////////////////////////////////////
1475
get_type_code_string(const char * sym,size_t * amount_of_read_chars,char ** str_type_code)1476 static EDemanglerErr get_type_code_string(const char *sym, size_t *amount_of_read_chars, char **str_type_code) {
1477 EDemanglerErr err = eDemanglerErrOK;
1478 char *tmp_sym = strdup (sym);
1479 STypeCodeStr type_code_str;
1480 SStateInfo state;
1481
1482 if (!init_type_code_str_struct (&type_code_str)) {
1483 err = eDemanglerErrMemoryAllocation;
1484 goto get_type_code_string_err;
1485 }
1486
1487 init_state_struct (&state, tmp_sym);
1488
1489 while (state.state != eTCStateEnd) {
1490 run_state (&state, &type_code_str);
1491 if (state.err != eTCStateMachineErrOK) {
1492 *str_type_code = NULL;
1493 *amount_of_read_chars = 0;
1494 switch (state.err) {
1495 case eTCStateMachineErrUncorrectTypeCode:
1496 err = eDemanglerErrUncorrectMangledSymbol;
1497 break;
1498 case eTCStateMachineErrUnsupportedTypeCode:
1499 err = eDemanglerErrUnsupportedMangling;
1500 default:
1501 break;
1502 }
1503 goto get_type_code_string_err;
1504 }
1505 }
1506
1507 *str_type_code = strdup (type_code_str.type_str);
1508 *amount_of_read_chars = state.amount_of_read_chars;
1509
1510 get_type_code_string_err:
1511 R_FREE (tmp_sym);
1512 free_type_code_str_struct (&type_code_str);
1513 return err;
1514 }
1515
get_ptr_modifier(const char encoded,SDataType * ptr_modifier)1516 static inline size_t get_ptr_modifier(const char encoded, SDataType *ptr_modifier) {
1517 size_t read = 0;
1518 #define SET_PTR_MODIFIER(letter, modifier_left, modifier_right) \
1519 case letter: \
1520 ptr_modifier->left = modifier_left; \
1521 ptr_modifier->right = modifier_right; \
1522 read++; \
1523 break;
1524
1525 switch (encoded) {
1526 SET_PTR_MODIFIER ('E', "", " __ptr64")
1527 SET_PTR_MODIFIER ('F', "__unaligned ", "")
1528 SET_PTR_MODIFIER ('G', "", " &")
1529 SET_PTR_MODIFIER ('H', "", " &&")
1530 SET_PTR_MODIFIER ('I', "", " __restrict")
1531 default:
1532 ptr_modifier->left = ptr_modifier->right = "";
1533 }
1534 #undef SET_PTR_MODIFIER
1535 return read;
1536 }
1537
get_storage_class(const char encoded,const char ** storage_class)1538 static inline EDemanglerErr get_storage_class(const char encoded, const char **storage_class) {
1539 switch (encoded) {
1540 case 'A':
1541 *storage_class = NULL;
1542 break; // non-const
1543 case 'B':
1544 case 'J':
1545 *storage_class = "const";
1546 break;
1547 case 'C':
1548 case 'G':
1549 case 'K':
1550 *storage_class = "volatile";
1551 break;
1552 case 'D':
1553 case 'H':
1554 case 'L':
1555 *storage_class = "const volatile";
1556 break;
1557 default:
1558 return eDemanglerErrUncorrectMangledSymbol;
1559 }
1560 return eDemanglerErrOK;
1561 }
1562
parse_data_type(const char * sym,SDataType * data_type,size_t * len)1563 static EDemanglerErr parse_data_type(const char *sym, SDataType *data_type, size_t *len) {
1564 EDemanglerErr err = eDemanglerErrOK;
1565 size_t i;
1566 const char *curr_pos = sym;
1567 SDataType modifier;
1568 const char *storage_class = NULL;
1569 char *tmp;
1570 if (len) {
1571 *len = 0;
1572 }
1573 data_type->left = data_type->right = NULL;
1574 // Data type and access level
1575 switch (*curr_pos++) {
1576 // Data
1577 case '0': // Private static member
1578 case '1': // Protected static member
1579 case '2': // Public static member
1580 case '3': // Normal variable
1581 case '4': // Normal variable
1582 case '5': // Normal variable
1583 i = 0;
1584 err = get_type_code_string (curr_pos, &i, &tmp);
1585 if (err != eDemanglerErrOK) {
1586 return err;
1587 }
1588
1589 curr_pos += i;
1590 curr_pos += get_ptr_modifier (*curr_pos, &modifier);
1591 if (get_storage_class (*curr_pos, &storage_class) != eDemanglerErrOK) {
1592 free (tmp);
1593 return eDemanglerErrUncorrectMangledSymbol;
1594 }
1595 curr_pos++;
1596
1597 if (data_type) {
1598 data_type->right = strdup ("");
1599 if (!storage_class) {
1600 data_type->left = r_str_newf ("%s%s%s", modifier.left, tmp, modifier.right);
1601 } else {
1602 data_type->left = r_str_newf ("%s%s %s%s", modifier.left, tmp, storage_class, modifier.right);
1603 }
1604 free (tmp);
1605 }
1606 break;
1607 case '6': // compiler generated static
1608 case '7': // compiler generated static
1609 if (data_type) {
1610 curr_pos += get_ptr_modifier (*curr_pos, &modifier);
1611 if (get_storage_class (*curr_pos, &storage_class) != eDemanglerErrOK) {
1612 return eDemanglerErrUncorrectMangledSymbol;
1613 }
1614 curr_pos++;
1615
1616 data_type->left = r_str_newf ("%s%s%s", storage_class, modifier.left , modifier.right);
1617 if (*curr_pos != '@') {
1618 STypeCodeStr str;
1619 if (!init_type_code_str_struct (&str)) {
1620 return eDemanglerErrMemoryAllocation;
1621 }
1622 size_t i = get_namespace_and_name (curr_pos, &str, NULL, true);
1623 if (!i) {
1624 free_type_code_str_struct (&str);
1625 return eDemanglerErrUncorrectMangledSymbol;
1626 }
1627 curr_pos += i;
1628 if (*(curr_pos + 1) != '@') {
1629 STypeCodeStr str2;
1630 if (!init_type_code_str_struct (&str2)) {
1631 free_type_code_str_struct (&str);
1632 return eDemanglerErrMemoryAllocation;
1633 }
1634 i = get_namespace_and_name (curr_pos + 1, &str2, NULL, true);
1635 if (!i) {
1636 free_type_code_str_struct (&str);
1637 free_type_code_str_struct (&str2);
1638 return eDemanglerErrUncorrectMangledSymbol;
1639 }
1640 curr_pos += i + 1;
1641 data_type->right = r_str_newf ("{for `%s's `%s'}", str.type_str, str2.type_str);
1642 free_type_code_str_struct (&str2);
1643 } else {
1644 data_type->right = r_str_newf ("{for `%s'}", str.type_str);
1645 }
1646 free_type_code_str_struct (&str);
1647 } else {
1648 data_type->right = strdup ("");
1649 }
1650 }
1651 break;
1652 }
1653 if (len) {
1654 *len = curr_pos - sym;
1655 }
1656 return eDemanglerErrOK;
1657 }
1658
parse_function_type(const char * sym,SDataType * data_type,size_t * len,bool * is_static,bool * is_implicit_this_pointer)1659 static EDemanglerErr parse_function_type(const char *sym, SDataType *data_type,
1660 size_t *len, bool *is_static, bool *is_implicit_this_pointer) {
1661 const char *curr_pos = sym;
1662 data_type->left = data_type->right = "";
1663 *is_static = *is_implicit_this_pointer = false;
1664 #define SET_THUNK_MODIFIER(letter, modifier_str) \
1665 case letter: { \
1666 SStateInfo state; \
1667 init_state_struct (&state, curr_pos); \
1668 char *num = get_num (&state); \
1669 if (!num) {\
1670 return eDemanglerErrUncorrectMangledSymbol; \
1671 } \
1672 data_type->left = modifier_str; \
1673 data_type->right = r_str_newf ("`adjustor{%s}'", num); \
1674 free (num);\
1675 *is_implicit_this_pointer = true; \
1676 curr_pos += state.amount_of_read_chars; \
1677 break; \
1678 }
1679
1680 #define SET_ACCESS_MODIFIER(letter, flag_set, modifier_str) \
1681 case letter: \
1682 data_type->left = modifier_str; \
1683 *flag_set = true; \
1684 break; \
1685
1686 /* Functions */
1687 switch (*curr_pos++) {
1688 SET_ACCESS_MODIFIER ('A', is_implicit_this_pointer, "private");
1689 SET_ACCESS_MODIFIER ('B', is_implicit_this_pointer, "private");
1690 SET_ACCESS_MODIFIER ('C', is_static, "private: static");
1691 SET_ACCESS_MODIFIER ('D', is_static, "private: static");
1692 SET_ACCESS_MODIFIER ('E', is_implicit_this_pointer, "private virtual");
1693 SET_ACCESS_MODIFIER ('F', is_implicit_this_pointer, "private virtual");
1694 SET_THUNK_MODIFIER ('G', "[thunk]:private virtual");
1695 SET_THUNK_MODIFIER ('H', "[thunk]:private virtual");
1696 SET_ACCESS_MODIFIER ('I', is_implicit_this_pointer, "protected");
1697 SET_ACCESS_MODIFIER ('J', is_implicit_this_pointer, "protected");
1698 SET_ACCESS_MODIFIER ('K', is_static, "protected: static");
1699 SET_ACCESS_MODIFIER ('L', is_static, "protected: static");
1700 SET_ACCESS_MODIFIER ('M', is_implicit_this_pointer, "protected virtual");
1701 SET_ACCESS_MODIFIER ('N', is_implicit_this_pointer, "protected virtual");
1702 SET_THUNK_MODIFIER ('O', "[thunk]:protected virtual");
1703 SET_THUNK_MODIFIER ('P', "[thunk]:protected virtual");
1704 SET_ACCESS_MODIFIER ('Q', is_implicit_this_pointer, "public");
1705 SET_ACCESS_MODIFIER ('R', is_implicit_this_pointer, "public");
1706 SET_ACCESS_MODIFIER ('S', is_static, "public: static");
1707 SET_ACCESS_MODIFIER ('T', is_static, "public: static");
1708 SET_ACCESS_MODIFIER ('U', is_implicit_this_pointer, "public virtual");
1709 SET_ACCESS_MODIFIER ('V', is_implicit_this_pointer, "public virtual");
1710 SET_THUNK_MODIFIER ('W', "[thunk]:public virtual");
1711 SET_THUNK_MODIFIER ('X', "[thunk]:public virtual");
1712 case 'Y': // near
1713 case 'Z': // far
1714 break;
1715 default:
1716 return eDemanglerErrUncorrectMangledSymbol;
1717 }
1718 #undef SET_ACCESS_MODIFIER
1719 if (len) {
1720 *len = curr_pos - sym;
1721 }
1722 return eDemanglerErrOK;
1723 }
1724
parse_function(const char * sym,STypeCodeStr * type_code_str,char ** demangled_function,size_t * chars_read)1725 static EDemanglerErr parse_function(const char *sym, STypeCodeStr *type_code_str, char **demangled_function, size_t *chars_read) {
1726 EDemanglerErr err = eDemanglerErrOK;
1727 bool is_implicit_this_pointer;
1728 bool is_static;
1729 const char *memb_func_access_code = NULL;
1730 const char *call_conv = NULL;
1731 const char *storage_class_code_for_ret = NULL;
1732 char *demangled_args;
1733 char *ret_type = NULL;
1734 const char *curr_pos = sym;
1735 SDataType data_type;
1736 const char *__64ptr = NULL;
1737 size_t len;
1738
1739 STypeCodeStr func_str;
1740 if (!init_type_code_str_struct (&func_str)) {
1741 err = eDemanglerErrMemoryAllocation;
1742 goto parse_function_err;
1743 }
1744
1745 if (!strncmp (curr_pos, "$$F", 3)) {
1746 // Managed function (Managed C++ or C++/CLI)
1747 curr_pos += 3;
1748 }
1749
1750 err = parse_function_type (curr_pos, &data_type, &len, &is_static, &is_implicit_this_pointer);
1751 if (err != eDemanglerErrOK) {
1752 goto parse_function_err;
1753 }
1754
1755 curr_pos += len;
1756
1757 if (*curr_pos == 'E') {
1758 __64ptr = "__ptr64";
1759 curr_pos++;
1760 }
1761
1762 if (*curr_pos == '$') {
1763 curr_pos += 2;
1764 }
1765
1766 // member function access code
1767 if (is_implicit_this_pointer) {
1768 err = get_storage_class (*curr_pos++, &memb_func_access_code);
1769 if (err != eDemanglerErrOK) {
1770 goto parse_function_err;
1771 }
1772 }
1773
1774 // currently does not use because I can not find real example of
1775 // where to use this
1776 // just read in http://www.agner.org/optimize/calling_conventions.pdf
1777 // that this is possible
1778 // when some find the case where it is used please remove this (void)*
1779 // lines
1780 (void)is_static;
1781
1782 // Calling convention
1783 call_conv = get_calling_convention (*curr_pos++);
1784 if (!call_conv) {
1785 err = eDemanglerErrUncorrectMangledSymbol;
1786 goto parse_function_err;
1787 }
1788
1789 // get storage class code for return
1790 if (*curr_pos == '?') {
1791 err = get_storage_class (*++curr_pos, &memb_func_access_code);
1792 if (err != eDemanglerErrOK) {
1793 goto parse_function_err;
1794 }
1795 curr_pos++;
1796 }
1797
1798 // Return type, or @ if 'void'
1799 if (*curr_pos == '@') {
1800 ret_type = strdup ("void");
1801 curr_pos++;
1802 } else {
1803 err = get_type_code_string (curr_pos, &len, &ret_type);
1804 if (err != eDemanglerErrOK) {
1805 err = eDemanglerErrUncorrectMangledSymbol;
1806 goto parse_function_err;
1807 }
1808
1809 curr_pos += len;
1810 }
1811
1812 err = parse_function_args (curr_pos, &demangled_args, &len);
1813 if (err != eDemanglerErrOK) {
1814 goto parse_function_err;
1815 }
1816
1817 curr_pos += len;
1818
1819 if (*data_type.left) {
1820 copy_string (&func_str, data_type.left, 0);
1821 if (!strstr (data_type.left, "static")) {
1822 copy_string (&func_str, ": ", 0);
1823 } else {
1824 copy_string (&func_str, " ", 0);
1825 }
1826 }
1827
1828 if (storage_class_code_for_ret) {
1829 copy_string (&func_str, storage_class_code_for_ret, 0);
1830 copy_string (&func_str, " ", 0);
1831 }
1832
1833 if (ret_type) {
1834 copy_string (&func_str, ret_type, 0);
1835 copy_string (&func_str, " ", 0);
1836 }
1837
1838 if (call_conv) {
1839 copy_string (&func_str, call_conv, 0);
1840 copy_string (&func_str, " ", 0);
1841 }
1842
1843 if (type_code_str->type_str) {
1844 copy_string (&func_str, type_code_str->type_str, type_code_str->curr_pos);
1845 }
1846
1847 if (*data_type.right) {
1848 copy_string (&func_str, data_type.right, 0);
1849 free (data_type.right);
1850 }
1851
1852 copy_string (&func_str, demangled_args, 0);
1853 free (demangled_args);
1854
1855 if (memb_func_access_code) {
1856 copy_string (&func_str, memb_func_access_code, 0);
1857 }
1858
1859 if (__64ptr) {
1860 copy_string (&func_str, " ", 0);
1861 copy_string (&func_str, __64ptr, 0);
1862 }
1863
1864 if (ret_type) {
1865 if (strstr (func_str.type_str, "#{return_type}")) {
1866 func_str.type_str = r_str_replace (func_str.type_str, "#{return_type}", ret_type, 0);
1867 func_str.curr_pos -= strlen ("#{return_type}") - strlen (ret_type);
1868 }
1869 }
1870
1871 // need to be free by user
1872 if (func_str.type_str) {
1873 *demangled_function = strdup (func_str.type_str);
1874 }
1875
1876 parse_function_err:
1877 if (chars_read) {
1878 *chars_read = curr_pos - sym;
1879 }
1880 free_type_code_str_struct (&func_str);
1881 free (ret_type);
1882 return err;
1883 }
1884
1885 ///////////////////////////////////////////////////////////////////////////////
1886 /// public mangled name of global object:
1887 /// <public name> ::= ?<name>@[<namespace>@](0->inf)@3<type><storage class>
1888 /// mangled name of a static class member object:
1889 /// <public name> ::= ?<name>@[<classname>@](1->inf)@2<type><storage class>
1890 ///////////////////////////////////////////////////////////////////////////////
parse_microsoft_mangled_name(const char * sym,char ** demangled_name,size_t * chars_read)1891 static EDemanglerErr parse_microsoft_mangled_name(const char *sym, char **demangled_name, size_t *chars_read) {
1892 STypeCodeStr type_code_str;
1893 EDemanglerErr err = eDemanglerErrOK;
1894
1895 SDataType data_type;
1896
1897 const char *curr_pos = sym;
1898
1899 if (!init_type_code_str_struct (&type_code_str)) {
1900 err = eDemanglerErrMemoryAllocation;
1901 goto parse_microsoft_mangled_name_err;
1902 }
1903 size_t i;
1904 size_t len = get_namespace_and_name (curr_pos, &type_code_str, &i, false);
1905 if (!len) {
1906 err = eDemanglerErrUncorrectMangledSymbol;
1907 goto parse_microsoft_mangled_name_err;
1908 }
1909
1910 curr_pos += len + 1;
1911
1912 if (!strncmp (curr_pos, "$$F", 3)) {
1913 // Managed function (Managed C++ or C++/CLI)
1914 curr_pos += 3;
1915 }
1916
1917 if (curr_pos[0] == '_') {
1918 // TODO: __based()
1919 curr_pos++;
1920 }
1921
1922 if (isdigit ((unsigned char)*curr_pos)) {
1923 err = parse_data_type (curr_pos, &data_type, &len);
1924 if (err != eDemanglerErrOK) {
1925 goto parse_microsoft_mangled_name_err;
1926 }
1927 curr_pos += len;
1928 *demangled_name = NULL;
1929 if (data_type.left) {
1930 *demangled_name = r_str_newf ("%s ", data_type.left);
1931 }
1932 *demangled_name = r_str_append (*demangled_name, type_code_str.type_str);
1933 *demangled_name = r_str_append (*demangled_name, data_type.right);
1934 free (data_type.left);
1935 free (data_type.right);
1936 } else if (isalpha ((unsigned char)*curr_pos)) {
1937 err = parse_function (curr_pos, &type_code_str, demangled_name, &len);
1938 curr_pos += len;
1939 } else {
1940 err = eDemanglerErrUncorrectMangledSymbol;
1941 }
1942
1943 parse_microsoft_mangled_name_err:
1944 free_type_code_str_struct (&type_code_str);
1945 if (chars_read) {
1946 *chars_read = curr_pos - sym;
1947 }
1948 return err;
1949 }
1950
parse_microsoft_rtti_mangled_name(const char * sym,char ** demangled_name,size_t * chars_read)1951 static EDemanglerErr parse_microsoft_rtti_mangled_name(const char *sym, char **demangled_name, size_t *chars_read) {
1952 EDemanglerErr err = eDemanglerErrOK;
1953 char *type = NULL;
1954 const char *storage = NULL;
1955 if (chars_read) {
1956 *chars_read = 0;
1957 }
1958 err = get_storage_class (*sym++, &storage);
1959 if (err != eDemanglerErrOK) {
1960 return err;
1961 }
1962 size_t len;
1963 err = get_type_code_string (sym, &len, &type);
1964 if (err != eDemanglerErrOK) {
1965 return err;
1966 }
1967 if (storage) {
1968 *demangled_name = r_str_newf ("%s %s", type, storage);
1969 } else {
1970 *demangled_name = r_str_newf ("%s", type);
1971 }
1972 if (chars_read) {
1973 *chars_read = len + 1;
1974 }
1975 free (type);
1976 return err;
1977 }
1978
1979 ///////////////////////////////////////////////////////////////////////////////
microsoft_demangle(SDemangler * demangler,char ** demangled_name)1980 EDemanglerErr microsoft_demangle(SDemangler *demangler, char **demangled_name) {
1981 EDemanglerErr err = eDemanglerErrOK;
1982 // RListIter *it = NULL;
1983 // char *tmp = NULL;
1984
1985 // TODO: need refactor... maybe remove the static variable somewhere?
1986 abbr_types = r_list_newf (free);
1987 abbr_names = r_list_newf (free);
1988
1989 if (!demangler || !demangled_name) {
1990 err = eDemanglerErrMemoryAllocation;
1991 goto microsoft_demangle_err;
1992 }
1993
1994 if (!strncmp (demangler->symbol, ".?", 2)) {
1995 err = parse_microsoft_rtti_mangled_name (demangler->symbol + 2, demangled_name, NULL);
1996 } else {
1997 err = parse_microsoft_mangled_name (demangler->symbol + 1, demangled_name, NULL);
1998 }
1999
2000 microsoft_demangle_err:
2001 r_list_free (abbr_names);
2002 r_list_free (abbr_types);
2003 return err;
2004 }
2005