symbol_demangle.cc Source File

Back to the index.

symbol_demangle.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * C++ symbol name demangling.
29  *
30  * For obvious performance reasons, the external c++filt utility cannot be
31  * used. Also, the host's version of this utility might be incompatible with
32  * the binary being emulated.
33  *
34  * TODO: Constructors, destructors, and lots of other stuff. See
35  * http://www.codesourcery.com/cxx-abi/abi.html#mangling for details.
36  */
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 
43 #include "symbol.h"
44 
45 
46 #define MAXLEN 1000
47 
48 
49 static void add_string(char *p, size_t *curlenp, const char *to_add)
50 {
51  size_t curlen = *curlenp;
52  while (curlen < MAXLEN && *to_add)
53  p[curlen++] = *to_add++;
54  *curlenp = curlen;
55 }
56 
57 
58 /*
59  * symbol_demangle_cplusplus_nested():
60  *
61  * Try to demangle a nested cplusplus name. name points to the first character
62  * after "_ZN".
63  */
64 static char *symbol_demangle_cplusplus_nested(const char *name)
65 {
66  char *result;
67  size_t result_len = 0, len;
68  int first = 1, type_added = 0, pointercounter, reference;
69 
70  CHECK_ALLOCATION(result = (char *) malloc(MAXLEN + 1));
71  result[0] = '\0';
72 
73  while (name[0] && name[0] != 'E' && result_len < MAXLEN) {
74  /* Read length of the next part: */
75  len = 0;
76  if (*name == '0') {
77  name ++;
78  } else {
79  while (isdigit((int)*name)) {
80  len *= 10;
81  len += (*name - '0');
82  name ++;
83  }
84  }
85 
86  /* Add :: */
87  if (!first)
88  add_string(result, &result_len, "::");
89 
90  /* Read the part itself: */
91  while (len-- >= 1 && result_len < MAXLEN)
92  result[result_len ++] = *name++;
93 
94  first = 0;
95  }
96 
97  if (name[0] != 'E')
98  goto fail;
99 
100  name ++;
101 
102  if (*name)
103  add_string(result, &result_len, "{");
104 
105  /* Type: */
106  pointercounter = reference = 0;
107  while (*name) {
108  int argument_done = 0;
109  char t = *name++;
110  switch (t) {
111  case 'c':
112  add_string(result, &result_len, "char");
113  argument_done = 1;
114  break;
115  case 'a':
116  add_string(result, &result_len, "signed char");
117  argument_done = 1;
118  break;
119  case 'h':
120  add_string(result, &result_len, "unsigned char");
121  argument_done = 1;
122  break;
123  case 'i':
124  add_string(result, &result_len, "int");
125  argument_done = 1;
126  break;
127  case 'j':
128  add_string(result, &result_len, "unsigned int");
129  argument_done = 1;
130  break;
131  case 'w':
132  add_string(result, &result_len, "wchar_t");
133  argument_done = 1;
134  break;
135  case 'b':
136  add_string(result, &result_len, "bool");
137  argument_done = 1;
138  break;
139  case 's':
140  add_string(result, &result_len, "short");
141  argument_done = 1;
142  break;
143  case 't':
144  add_string(result, &result_len, "unsigned short");
145  argument_done = 1;
146  break;
147  case 'l':
148  add_string(result, &result_len, "long");
149  argument_done = 1;
150  break;
151  case 'm':
152  add_string(result, &result_len, "unsigned long");
153  argument_done = 1;
154  break;
155  case 'x':
156  add_string(result, &result_len, "long long");
157  argument_done = 1;
158  break;
159  case 'y':
160  add_string(result, &result_len, "unsigned long long");
161  argument_done = 1;
162  break;
163  case 'n':
164  add_string(result, &result_len, "__int128");
165  argument_done = 1;
166  break;
167  case 'o':
168  add_string(result, &result_len, "unsigned __int128");
169  argument_done = 1;
170  break;
171  case 'f':
172  add_string(result, &result_len, "float");
173  argument_done = 1;
174  break;
175  case 'd':
176  add_string(result, &result_len, "double");
177  argument_done = 1;
178  break;
179  case 'e':
180  add_string(result, &result_len, "__float80");
181  argument_done = 1;
182  break;
183  case 'g':
184  add_string(result, &result_len, "__float128");
185  argument_done = 1;
186  break;
187  case 'z':
188  add_string(result, &result_len, "...");
189  argument_done = 1;
190  break;
191  case 'P':
192  pointercounter ++;
193  break;
194  case 'R':
195  reference ++;
196  break;
197  case 'v': /* void */
198  break;
199  default:/* Unknown */
200  goto fail;
201  }
202  if (argument_done) {
203  while (pointercounter-- > 0)
204  add_string(result, &result_len, "*");
205  while (reference-- > 0)
206  add_string(result, &result_len, "&");
207  if (*name)
208  add_string(result, &result_len, ",");
209  }
210  type_added = 1;
211  }
212 
213  if (type_added)
214  add_string(result, &result_len, "}");
215 
216  if (result_len == MAXLEN)
217  goto fail;
218 
219  result[result_len] = '\0';
220 
221  return result;
222 
223 fail:
224  free(result);
225  return NULL;
226 }
227 
228 
229 /*
230  * symbol_demangle_cplusplus():
231  *
232  * Try to demangle name. If name was not a valid/known C++ symbol, then NULL
233  * is returned. Otherwise, a newly allocated string is returned, containing
234  * the demangled name.
235  */
236 char *symbol_demangle_cplusplus(const char *name)
237 {
238  /* Only support _Z-style mangled names, for now: */
239  if (strlen(name) < 2 || name[0] != '_' || name[1] != 'Z')
240  return NULL;
241 
242  name += 2;
243 
244  switch (name[0]) {
245  case 'N':
246  return symbol_demangle_cplusplus_nested(name + 1);
247  break;
248  }
249 
250  return NULL;
251 }
252 
253 
254 
255 #ifdef TEST
256 
257 void test(char *mangled, char *result)
258 {
259  char *p = symbol_demangle_cplusplus(mangled);
260  if (p == NULL) {
261  if (result == NULL) {
262  return;
263  } else {
264  printf("FAILURE for %s!\n", mangled);
265  exit(1);
266  }
267  }
268  if (strcmp(p, result) == 0)
269  return;
270  printf("FAILURE for %s! (result = %s)\n", mangled, p);
271  exit(1);
272 }
273 
274 int main(int argc, char *argv[])
275 {
276  test("monkey", NULL);
277  test("_monkey", NULL);
278  test("_zmonkey", NULL);
279  test("_Zmonkey", NULL);
280  test("_ZQ5abcde", NULL);
281  test("_ZN3abc5defghE", "abc::defgh");
282  test("_ZN05defghEv", "::defgh{}");
283  test("_ZN5defghEv", "defgh{}");
284  test("_ZN3abc5defghEv", "abc::defgh{}");
285  test("_ZN3abc5defghEc", "abc::defgh{char}");
286  test("_ZN1a2bcEjij", "a::bc{unsigned int,int,unsigned int}");
287  printf("OK\n");
288  return 0;
289 }
290 
291 #endif
292 
main
int main(int argc, char *argv[])
Definition: experiment_arm_multi.cc:89
t
vmrs t
Definition: armreg.h:750
symbol::name
char * name
Definition: symbol.h:41
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition: cpu_arm_instr.cc:2333
symbol.h
symbol_demangle_cplusplus
char * symbol_demangle_cplusplus(const char *name)
Definition: symbol_demangle.cc:236
MAXLEN
#define MAXLEN
Definition: symbol_demangle.cc:46
symbol::len
uint64_t len
Definition: symbol.h:40
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17