/[gxemul]/upstream/0.4.6/src/symbol_demangle.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/0.4.6/src/symbol_demangle.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 43 - (hide annotations)
Mon Oct 8 16:22:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 7101 byte(s)
0.4.6
1 dpavlin 24 /*
2 dpavlin 34 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 dpavlin 24 *
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 dpavlin 42 * $Id: symbol_demangle.c,v 1.8 2007/06/15 17:02:38 debug Exp $
29 dpavlin 24 *
30     * C++ symbol name demangling.
31     *
32 dpavlin 32 * For obvious performance reasons, the external c++filt utility cannot be
33     * used. Also, the host's version of this utility might be incompatible with
34     * the binary being emulated.
35 dpavlin 24 *
36     * TODO: Constructors, destructors, and lots of other stuff. See
37     * http://www.codesourcery.com/cxx-abi/abi.html#mangling for details.
38     */
39    
40     #include <stdio.h>
41     #include <stdlib.h>
42     #include <string.h>
43     #include <ctype.h>
44    
45     #include "symbol.h"
46    
47    
48     #define MAXLEN 1000
49    
50    
51     static void add_string(char *p, size_t *curlenp, char *to_add)
52     {
53     size_t curlen = *curlenp;
54     while (curlen < MAXLEN && *to_add)
55     p[curlen++] = *to_add++;
56     *curlenp = curlen;
57     }
58    
59    
60     /*
61     * symbol_demangle_cplusplus_nested():
62     *
63     * Try to demangle a nested cplusplus name. name points to the first character
64     * after "_ZN".
65     */
66     static char *symbol_demangle_cplusplus_nested(char *name)
67     {
68 dpavlin 42 char *result;
69 dpavlin 24 size_t result_len = 0, len;
70     int first = 1, type_added = 0, pointercounter, reference;
71    
72 dpavlin 42 CHECK_ALLOCATION(result = malloc(MAXLEN + 1));
73 dpavlin 24 result[0] = '\0';
74    
75     while (name[0] && name[0] != 'E' && result_len < MAXLEN) {
76     /* Read length of the next part: */
77     len = 0;
78     if (*name == '0') {
79     name ++;
80     } else {
81     while (isdigit((int)*name)) {
82     len *= 10;
83     len += (*name - '0');
84     name ++;
85     }
86     }
87    
88     /* Add :: */
89     if (!first)
90     add_string(result, &result_len, "::");
91    
92     /* Read the part itself: */
93     while (len-- >= 1 && result_len < MAXLEN)
94     result[result_len ++] = *name++;
95    
96     first = 0;
97     }
98    
99     if (name[0] != 'E')
100     goto fail;
101    
102     name ++;
103    
104     if (*name)
105     add_string(result, &result_len, "{");
106    
107     /* Type: */
108     pointercounter = reference = 0;
109     while (*name) {
110     int argument_done = 0;
111     char t = *name++;
112     switch (t) {
113     case 'c':
114     add_string(result, &result_len, "char");
115     argument_done = 1;
116     break;
117     case 'a':
118     add_string(result, &result_len, "signed char");
119     argument_done = 1;
120     break;
121     case 'h':
122     add_string(result, &result_len, "unsigned char");
123     argument_done = 1;
124     break;
125     case 'i':
126     add_string(result, &result_len, "int");
127     argument_done = 1;
128     break;
129     case 'j':
130     add_string(result, &result_len, "unsigned int");
131     argument_done = 1;
132     break;
133     case 'w':
134     add_string(result, &result_len, "wchar_t");
135     argument_done = 1;
136     break;
137     case 'b':
138     add_string(result, &result_len, "bool");
139     argument_done = 1;
140     break;
141     case 's':
142     add_string(result, &result_len, "short");
143     argument_done = 1;
144     break;
145     case 't':
146     add_string(result, &result_len, "unsigned short");
147     argument_done = 1;
148     break;
149     case 'l':
150     add_string(result, &result_len, "long");
151     argument_done = 1;
152     break;
153     case 'm':
154     add_string(result, &result_len, "unsigned long");
155     argument_done = 1;
156     break;
157     case 'x':
158     add_string(result, &result_len, "long long");
159     argument_done = 1;
160     break;
161     case 'y':
162     add_string(result, &result_len, "unsigned long long");
163     argument_done = 1;
164     break;
165     case 'n':
166     add_string(result, &result_len, "__int128");
167     argument_done = 1;
168     break;
169     case 'o':
170     add_string(result, &result_len, "unsigned __int128");
171     argument_done = 1;
172     break;
173     case 'f':
174     add_string(result, &result_len, "float");
175     argument_done = 1;
176     break;
177     case 'd':
178     add_string(result, &result_len, "double");
179     argument_done = 1;
180     break;
181     case 'e':
182     add_string(result, &result_len, "__float80");
183     argument_done = 1;
184     break;
185     case 'g':
186     add_string(result, &result_len, "__float128");
187     argument_done = 1;
188     break;
189     case 'z':
190     add_string(result, &result_len, "...");
191     argument_done = 1;
192     break;
193     case 'P':
194     pointercounter ++;
195     break;
196     case 'R':
197     reference ++;
198     break;
199     case 'v': /* void */
200     break;
201     default:/* Unknown */
202     goto fail;
203     }
204     if (argument_done) {
205     while (pointercounter-- > 0)
206     add_string(result, &result_len, "*");
207     while (reference-- > 0)
208     add_string(result, &result_len, "&");
209     if (*name)
210     add_string(result, &result_len, ",");
211     }
212     type_added = 1;
213     }
214    
215     if (type_added)
216     add_string(result, &result_len, "}");
217    
218     if (result_len == MAXLEN)
219     goto fail;
220    
221     result[result_len] = '\0';
222    
223     return result;
224    
225     fail:
226     free(result);
227     return NULL;
228     }
229    
230    
231     /*
232     * symbol_demangle_cplusplus():
233     *
234     * Try to demangle name. If name was not a valid/known C++ symbol, then NULL
235     * is returned. Otherwise, a newly allocated string is returned, containing
236     * the demangled name.
237     */
238     char *symbol_demangle_cplusplus(char *name)
239     {
240     /* Only support _Z-style mangled names, for now: */
241     if (strlen(name) < 2 || name[0] != '_' || name[1] != 'Z')
242     return NULL;
243    
244     name += 2;
245    
246     switch (name[0]) {
247     case 'N':
248     return symbol_demangle_cplusplus_nested(name + 1);
249     break;
250     }
251    
252     return NULL;
253     }
254    
255    
256    
257     #ifdef TEST
258    
259     void test(char *mangled, char *result)
260     {
261     char *p = symbol_demangle_cplusplus(mangled);
262     if (p == NULL) {
263     if (result == NULL) {
264     return;
265     } else {
266     printf("FAILURE for %s!\n", mangled);
267     exit(1);
268     }
269     }
270     if (strcmp(p, result) == 0)
271     return;
272     printf("FAILURE for %s! (result = %s)\n", mangled, p);
273     exit(1);
274     }
275    
276     int main(int argc, char *argv[])
277     {
278     test("monkey", NULL);
279     test("_monkey", NULL);
280     test("_zmonkey", NULL);
281     test("_Zmonkey", NULL);
282     test("_ZQ5abcde", NULL);
283     test("_ZN3abc5defghE", "abc::defgh");
284     test("_ZN05defghEv", "::defgh{}");
285     test("_ZN5defghEv", "defgh{}");
286     test("_ZN3abc5defghEv", "abc::defgh{}");
287     test("_ZN3abc5defghEc", "abc::defgh{char}");
288     test("_ZN1a2bcEjij", "a::bc{unsigned int,int,unsigned int}");
289     printf("OK\n");
290     return 0;
291     }
292    
293     #endif
294    

  ViewVC Help
Powered by ViewVC 1.1.26