1 /* radare - LGPL - Copyright 2013-2019 - pancake */
2 
3 #include <r_bin.h>
4 #include "../i/private.h"
5 #include "./cxx/demangle.h"
6 
r_bin_demangle_cxx(RBinFile * bf,const char * str,ut64 vaddr)7 R_API char *r_bin_demangle_cxx(RBinFile *bf, const char *str, ut64 vaddr) {
8 	// DMGL_TYPES | DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE
9 	// | DMGL_RET_POSTFIX | DMGL_TYPES;
10 	int i;
11 #if WITH_GPL
12 	int flags = DMGL_NO_OPTS | DMGL_PARAMS;
13 #endif
14 	const char *prefixes[] = {
15 		"__symbol_stub1_",
16 		"reloc.",
17 		"sym.imp.",
18 		"imp.",
19 		NULL
20 	};
21 	char *tmpstr = strdup (str);
22 	char *p = tmpstr;
23 
24 	if (p[0] == p[1] && *p == '_') {
25 		p++;
26 	}
27 	for (i = 0; prefixes[i]; i++) {
28 		int plen = strlen (prefixes[i]);
29 		if (!strncmp (p, prefixes[i], plen)) {
30 			p += plen;
31 			break;
32 		}
33 	}
34 	// remove CXXABI suffix
35 	char *cxxabi = strstr (p, "@@CXXABI");
36 	char *glibcxx = strstr (p, "@GLIBCXX");
37 	if (cxxabi) {
38 		*cxxabi = '\0';
39 	} else if (glibcxx) {
40 		if (p < glibcxx && glibcxx[-1] == '@') {
41 			glibcxx[-1] = '\0';
42 		} else {
43 			*glibcxx = '\0';
44 		}
45 	}
46 #if WITH_GPL
47 	char *out = cplus_demangle_v3 (p, flags);
48 #else
49 	/* TODO: implement a non-gpl alternative to c++v3 demangler */
50 	char *out = NULL;
51 #endif
52 	free (tmpstr);
53 	if (out) {
54 		char *sign = (char *)strchr (out, '(');
55 		if (sign) {
56 			char *str = out;
57 			char *ptr = NULL;
58 			char *nerd = NULL;
59 			for (;;) {
60 				ptr = strstr (str, "::");
61 				if (!ptr || ptr > sign) {
62 					break;
63 				}
64 				nerd = ptr;
65 				str = ptr + 1;
66 			}
67 			if (nerd && *nerd) {
68 				*nerd = 0;
69 				if (bf) {
70 					RBinSymbol *sym = r_bin_file_add_method (bf, out, nerd + 2, 0);
71 					if (sym) {
72 						if (sym->vaddr != 0 && sym->vaddr != vaddr) {
73 							if (bf && bf->rbin && bf->rbin->verbose) {
74 								eprintf ("Dupped method found: %s\n", sym->name);
75 							}
76 						}
77 						if (sym->vaddr == 0) {
78 							sym->vaddr = vaddr;
79 						}
80 					}
81 				}
82 				*nerd = ':';
83 			}
84 		}
85 	}
86 	return out;
87 }
88