1
2 /*--------------------------------------------------------------------*/
3 /*--- Demangling of C++ mangled names. demangle.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2013 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "pub_core_basics.h"
32 #include "pub_core_demangle.h"
33 #include "pub_core_libcassert.h"
34 #include "pub_core_libcbase.h"
35 #include "pub_core_libcprint.h"
36 #include "pub_core_mallocfree.h"
37 #include "pub_core_options.h"
38
39 #include "vg_libciface.h"
40 #include "demangle.h"
41
42 /* The demangler's job is to take a raw symbol name and turn it into
43 something a Human Bean can understand. There are two levels of
44 mangling.
45
46 1. First, C++ names are mangled by the compiler. So we'll have to
47 undo that.
48
49 2. Optionally, in relatively rare cases, the resulting name is then
50 itself encoded using Z-escaping (see pub_core_redir.h) so as to
51 become part of a redirect-specification.
52
53 Therefore, VG_(demangle) first tries to undo (2). If successful,
54 the soname part is discarded (humans don't want to see that).
55 Then, it tries to undo (1) (using demangling code from GNU/FSF).
56
57 Finally, change the name of all symbols which are known to be
58 functions below main() to "(below main)". This helps reduce
59 variability of stack traces, something which has been a problem for
60 the testsuite for a long time.
61
62 --------
63 If do_cxx_demangle == True, does all the above stages:
64 - undo (2) [Z-encoding]
65 - undo (1) [C++ mangling]
66 - do the below-main hack
67
68 If do_cxx_demangle == False, the middle stage is skipped:
69 - undo (2) [Z-encoding]
70 - do the below-main hack
71 */
72
73 /* Note that the C++ demangler is from GNU libiberty and is almost
74 completely unmodified. We use vg_libciface.h as a way to
75 impedance-match the libiberty code into our own framework.
76
77 The libiberty code included here was taken from the GCC repository
78 and is released under the LGPL 2.1 license, which AFAICT is compatible
79 with "GPL 2 or later" and so is OK for inclusion in Valgrind.
80
81 To update to a newer libiberty, use the "update-demangler" script
82 which is included in the valgrind repository. */
83
84 /* This is the main, standard demangler entry point. */
85
86 /* Upon return, *RESULT will point to the demangled name.
87 The memory buffer that holds the demangled name is allocated on the
88 heap and will be deallocated in the next invocation. Conceptually,
89 that buffer is owned by VG_(demangle). That means two things:
90 (1) Users of VG_(demangle) must not free that buffer.
91 (2) If the demangled name needs to be stashed away for later use,
92 the contents of the buffer needs to be copied. It is not sufficient
93 to just store the pointer as it will point to deallocated memory
94 after the next VG_(demangle) invocation. */
VG_(demangle)95 void VG_(demangle) ( Bool do_cxx_demangling, Bool do_z_demangling,
96 /* IN */ const HChar *orig,
97 /* OUT */ const HChar **result )
98 {
99 /* Possibly undo (2) */
100 /* Z-Demangling was requested.
101 The fastest way to see if it's a Z-mangled name is just to attempt
102 to Z-demangle it (with NULL for the soname buffer, since we're not
103 interested in that). */
104 if (do_z_demangling) {
105 const HChar *z_demangled;
106
107 if (VG_(maybe_Z_demangle)( orig, NULL, /*soname*/
108 &z_demangled, NULL, NULL, NULL )) {
109 orig = z_demangled;
110 }
111 }
112
113 /* Possibly undo (1) */
114 if (do_cxx_demangling && VG_(clo_demangle)) {
115 static HChar* demangled = NULL;
116
117 /* Free up previously demangled name */
118 if (demangled) VG_(arena_free) (VG_AR_DEMANGLE, demangled);
119
120 demangled = ML_(cplus_demangle) ( orig, DMGL_ANSI | DMGL_PARAMS );
121
122 *result = (demangled == NULL) ? orig : demangled;
123 } else {
124 *result = orig;
125 }
126
127 // 13 Mar 2005: We used to check here that the demangler wasn't leaking
128 // by calling the (now-removed) function VG_(is_empty_arena)(). But,
129 // very rarely (ie. I've heard of it twice in 3 years), the demangler
130 // does leak. But, we can't do much about it, and it's not a disaster,
131 // so we just let it slide without aborting or telling the user.
132 }
133
134
135 /*------------------------------------------------------------*/
136 /*--- DEMANGLE Z-ENCODED NAMES ---*/
137 /*------------------------------------------------------------*/
138
139 /* Demangle a Z-encoded name as described in pub_tool_redir.h.
140 Z-encoded names are used by Valgrind for doing function
141 interception/wrapping.
142
143 Demangle 'sym' into its soname and fnname parts, putting them in
144 the specified buffers. Returns a Bool indicating whether the
145 demangled failed or not. A failure can occur because the prefix
146 isn't recognised, the internal Z-escaping is wrong, or because one
147 or the other (or both) of the output buffers becomes full. Passing
148 'so' as NULL is acceptable if the caller is only interested in the
149 function name part. */
150
VG_(maybe_Z_demangle)151 Bool VG_(maybe_Z_demangle) ( const HChar* sym,
152 /*OUT*/const HChar** so,
153 /*OUT*/const HChar** fn,
154 /*OUT*/Bool* isWrap,
155 /*OUT*/Int* eclassTag,
156 /*OUT*/Int* eclassPrio )
157 {
158 static HChar *sobuf;
159 static HChar *fnbuf;
160 static SizeT buf_len = 0;
161
162 /* The length of the name after undoing Z-encoding is always smaller
163 than the mangled name. Making the soname and fnname buffers as large
164 as the demangled name is therefore always safe and overflow can never
165 occur. */
166 SizeT len = VG_(strlen)(sym) + 1;
167
168 if (buf_len < len) {
169 sobuf = VG_(arena_realloc)(VG_AR_DEMANGLE, "Z-demangle", sobuf, len);
170 fnbuf = VG_(arena_realloc)(VG_AR_DEMANGLE, "Z-demangle", fnbuf, len);
171 buf_len = len;
172 }
173 sobuf[0] = fnbuf[0] = '\0';
174
175 if (so)
176 *so = sobuf;
177 *fn = fnbuf;
178
179 # define EMITSO(ch) \
180 do { \
181 if (so) { \
182 sobuf[soi++] = ch; sobuf[soi] = 0; \
183 } \
184 } while (0)
185 # define EMITFN(ch) \
186 do { \
187 fnbuf[fni++] = ch; fnbuf[fni] = 0; \
188 } while (0)
189
190 Bool error, valid, fn_is_encoded, is_VG_Z_prefixed;
191 Int soi, fni, i;
192
193 error = False;
194 soi = 0;
195 fni = 0;
196
197 valid = sym[0] == '_'
198 && sym[1] == 'v'
199 && sym[2] == 'g'
200 && (sym[3] == 'r' || sym[3] == 'w')
201 && VG_(isdigit)(sym[4])
202 && VG_(isdigit)(sym[5])
203 && VG_(isdigit)(sym[6])
204 && VG_(isdigit)(sym[7])
205 && VG_(isdigit)(sym[8])
206 && sym[9] == 'Z'
207 && (sym[10] == 'Z' || sym[10] == 'U')
208 && sym[11] == '_';
209
210 if (valid
211 && sym[4] == '0' && sym[5] == '0' && sym[6] == '0' && sym[7] == '0'
212 && sym[8] != '0') {
213 /* If the eclass tag is 0000 (meaning "no eclass"), the priority
214 must be 0 too. */
215 valid = False;
216 }
217
218 if (!valid)
219 return False;
220
221 fn_is_encoded = sym[10] == 'Z';
222
223 if (isWrap)
224 *isWrap = sym[3] == 'w';
225
226 if (eclassTag) {
227 *eclassTag = 1000 * ((Int)sym[4] - '0')
228 + 100 * ((Int)sym[5] - '0')
229 + 10 * ((Int)sym[6] - '0')
230 + 1 * ((Int)sym[7] - '0');
231 vg_assert(*eclassTag >= 0 && *eclassTag <= 9999);
232 }
233
234 if (eclassPrio) {
235 *eclassPrio = ((Int)sym[8]) - '0';
236 vg_assert(*eclassPrio >= 0 && *eclassPrio <= 9);
237 }
238
239 /* Now check the soname prefix isn't "VG_Z_", as described in
240 pub_tool_redir.h. */
241 is_VG_Z_prefixed =
242 sym[12] == 'V' &&
243 sym[13] == 'G' &&
244 sym[14] == '_' &&
245 sym[15] == 'Z' &&
246 sym[16] == '_';
247 if (is_VG_Z_prefixed) {
248 vg_assert2(0, "symbol with a 'VG_Z_' prefix: %s.\n"
249 "see pub_tool_redir.h for an explanation.", sym);
250 }
251
252 /* Now scan the Z-encoded soname. */
253 i = 12;
254 while (True) {
255
256 if (sym[i] == '_')
257 /* Found the delimiter. Move on to the fnname loop. */
258 break;
259
260 if (sym[i] == 0) {
261 error = True;
262 goto out;
263 }
264
265 if (sym[i] != 'Z') {
266 EMITSO(sym[i]);
267 i++;
268 continue;
269 }
270
271 /* We've got a Z-escape. */
272 i++;
273 switch (sym[i]) {
274 case 'a': EMITSO('*'); break;
275 case 'c': EMITSO(':'); break;
276 case 'd': EMITSO('.'); break;
277 case 'h': EMITSO('-'); break;
278 case 'p': EMITSO('+'); break;
279 case 's': EMITSO(' '); break;
280 case 'u': EMITSO('_'); break;
281 case 'A': EMITSO('@'); break;
282 case 'D': EMITSO('$'); break;
283 case 'L': EMITSO('('); break;
284 case 'R': EMITSO(')'); break;
285 case 'Z': EMITSO('Z'); break;
286 default: error = True; goto out;
287 }
288 i++;
289 }
290
291 vg_assert(sym[i] == '_');
292 i++;
293
294 /* Now deal with the function name part. */
295 if (!fn_is_encoded) {
296
297 /* simple; just copy. */
298 while (True) {
299 if (sym[i] == 0)
300 break;
301 EMITFN(sym[i]);
302 i++;
303 }
304 goto out;
305
306 }
307
308 /* else use a Z-decoding loop like with soname */
309 while (True) {
310
311 if (sym[i] == 0)
312 break;
313
314 if (sym[i] != 'Z') {
315 EMITFN(sym[i]);
316 i++;
317 continue;
318 }
319
320 /* We've got a Z-escape. */
321 i++;
322 switch (sym[i]) {
323 case 'a': EMITFN('*'); break;
324 case 'c': EMITFN(':'); break;
325 case 'd': EMITFN('.'); break;
326 case 'h': EMITFN('-'); break;
327 case 'p': EMITFN('+'); break;
328 case 's': EMITFN(' '); break;
329 case 'u': EMITFN('_'); break;
330 case 'A': EMITFN('@'); break;
331 case 'D': EMITFN('$'); break;
332 case 'L': EMITFN('('); break;
333 case 'R': EMITFN(')'); break;
334 case 'Z': EMITFN('Z'); break;
335 default: error = True; goto out;
336 }
337 i++;
338 }
339
340 out:
341 EMITSO(0);
342 EMITFN(0);
343
344 if (error) {
345 /* Something's wrong. Give up. */
346 VG_(message)(Vg_UserMsg,
347 "m_demangle: error Z-demangling: %s\n", sym);
348 return False;
349 }
350
351 return True;
352 }
353
354
355 /*--------------------------------------------------------------------*/
356 /*--- end ---*/
357 /*--------------------------------------------------------------------*/
358