1 #!/usr/bin/perl -w /* -*- indent-tabs-mode: nil -*- */
3 # Version: MPL 1.1 / GPLv3+ / LGPLv3+
5 # The contents of this file are subject to the Mozilla Public License Version
6 # 1.1 (the "License"); you may not use this file except in compliance with
7 # the License. You may obtain a copy of the License at
8 # http://www.mozilla.org/MPL/
10 # Software distributed under the License is distributed on an "AS IS" basis,
11 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 # for the specific language governing rights and limitations under the
15 # The Initial Developer of the Original Code is
17 # Portions created by the Initial Developer are Copyright (C) 2011 Novell,
18 # Inc. All Rights Reserved.
20 # Contributor(s): Tor Lillqvist <tml@iki.fi>
22 # Alternatively, the contents of this file may be used under the terms of
23 # either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 # the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 # in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 # instead of those above.
28 # Change MSVC mangled C++ names from 32-bit form to the corresponding
29 # 64-bit form. Each line of input can contain at most one mangled
32 # Based on experimentation with MSVC2008 and the following web pages:
34 # http://www.geoffchappell.com/viewer.htm?doc=studies/msvc/language/decoration/index.htm
35 # Thorough but incomplete. Still, describes details the below sources
38 # http://cvs.winehq.com/cvsweb/wine/dlls/msvcrt/undname.c
39 # Wine's __unDname function, presumably the most complete, although
40 # not really written to act as "documentation"
42 # http://mearie.org/documents/mscmangle/
43 # Relatively complete but a bit badly structured and terse.
45 # http://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B_Name_Mangling
46 # seems to be mostly a ripoff on the mearie.org page
48 # Example transformation:
49 # ??0ORealDynamicLoader@salhelper@@IAE@PAPAV01@ABVOUString@rtl@@1PAX2@Z =>
50 # ??0ORealDynamicLoader@salhelper@@IEAA@PEAPEAV01@AEBVOUString@rtl@@1PEAX2@Z
52 # It should be relatively easy to remove the modification parts of the
53 # below code and use the regex for some other task on MSVC mangled
56 # The regular expression below accepts also nonsensical mangled names,
57 # so it should not be used to verify correctness of mangled names.
67 return $num + 1 if ($num eq '0' || ($num ge '1' && $num le '9'));
69 $num =~ tr/ABCDEFGHIJKLMNOP@/0123456789ABCDEF /;
77 return $num - 1 if ($num <= 10);
79 $num = sprintf("%X", $num);
80 $num =~ tr/0123456789ABCDEF/ABCDEFGHIJKLMNOP/;
86 my ($number, $position) = @_;
88 my $bytes = parse_number
($number);
90 push(@opstack, 'r '.($position - length($number)).' '.length($number).' '.format_number
($bytes));
96 # Named subpattern definitions. I use names of the form
97 # __CamelCase__ for the named subpatters so that they are easier
101 \??
([0-9] | [A
-P
]+@
)
103 (?
<__32BitChecksum__
>
106 (?
<__CallingConvention__
>
111 (?
{ push(@opstack, 'r '.(pos()-1).' 1 A cdecl'); })
114 (?
<__StringLiteralText__
>
124 [_a
-zA
-Z\
$][_a
-zA
-Z0
-9\
$]*@
126 (?
<__ArgsZTerminated__
>
127 (?
&__DataTypeInArgs__
)+ @? Z
129 (?
<__ArgsNonZTerminated__
>
130 (?
&__DataTypeInArgs__
)+ @?
133 (?
&__Identifier__
) (?
&__ArgsNonZTerminated__
)
139 \?\
$ (?
&__TemplateName__
)
144 (?
<__DataTypeCommon__
>
146 # extended types like _int64, bool and wchar_t
152 # class, struct, union, cointerface
157 (?
{ push(@opstack, 'i '.pos().' E reference'); })
162 (?
{ push(@opstack, 'i '.pos().' E pointer'); })
168 6 (?
&__CallingConvention__
) (?
&__DataTypeNotInArgs__
) (?
&__ArgsZTerminated__
)
171 (?
{ push(@opstack, 'i '.pos().' E pointer'); })
186 \
$ [ABCD
] (?
&__DataTypeNotInArgs__
)
193 # multidimensional array
196 (?
&__DataTypeNotInArgs__
)
198 (?
<__DataTypeInArgs__
>
200 (?
&__DataTypeCommon__
)
206 (?
<__DataTypeNotInArgs__
>
208 (?
&__DataTypeCommon__
)
210 \? (?
&__ModifiedType__
)
215 # All mangled names start with a question mark
218 # Ctors, dtors, operators etc have separate a priori defined
219 # special mangled names like the very simple ?0 for constructor
220 # and ?_R16789 for "RTTI Base Class Descriptor at (6,7,8,9)"
221 # whatever that might mean.
227 # C is for string literals, see below
228 # R is RTTI, see immediately below
231 R0
(?
&__DataTypeNotInArgs__
)
246 # Static members and normal variables
248 (?
&__DataTypeNotInArgs__
)
251 # Compiler-generated static
260 # Non-static Methods, implicit 'this'
263 (?
{ push(@opstack, 'i '.(pos()-1).' E this'); })
264 (?
&__CallingConvention__
)
268 (?
&__DataTypeNotInArgs__
)
270 (?
&__ArgsZTerminated__
)
274 (?
&__CallingConvention__
)
278 (?
&__DataTypeNotInArgs__
)
280 (?
&__ArgsZTerminated__
)
285 (?
{ double_thunk
($^N
, pos()); })
287 (?
{ push(@opstack, 'i '.(pos()-1).' E this'); })
288 (?
&__CallingConvention__
)
292 (?
&__DataTypeNotInArgs__
)
294 (?
&__ArgsZTerminated__
)
298 (?
&__CallingConvention__
)
302 (?
&__DataTypeNotInArgs__
)
304 (?
&__ArgsZTerminated__
)
307 \
$ (?
&__Identifier__
) (?
&__ArgsNonZTerminated__
)
310 # pooled string literals
311 \?_C\
@_[01](?
&__Number__
)(?
&__32BitChecksum__
)(?
&__StringLiteralText__
)@
315 while (my $op = pop(@opstack))
317 # print STDERR "op=$op\n";
318 my @a = split (' ', $op);
320 substr($_,$a[1],0) = $a[2];
321 } elsif ($a[0] eq 'r') {
322 substr($_,$a[1],$a[2]) = $a[3];