Skip to content

Commit 3aa210b

Browse files
alvinhochuntru
authored andcommitted
[Symbolize][MinGW] Support demangling i386 call-conv-decorated C++ names
On i386 Windows, after C++ names have been Itanium-mangled, the C name mangling specific to its call convention may also be applied on top. This change teaches symbolizer to be able to demangle this type of mangled names. As part of this change, `demanglePE32ExternCFunc` has also been modified to fix unwanted stripping for vectorcall names when the demangled name is supposed to contain a leading `_`. Notice that the vectorcall mangling does not add either an `_` or `@` prefix. The old code always tries to strip the prefix first, which for Itanium mangled names in vectorcall, the leading underscore of the Itanium name gets stripped instead and breaks the Itanium demangler. Differential Revision: https://reviews.llvm.org/D144049 (cherry picked from commit e117fd2)
1 parent 0f02cdb commit 3aa210b

File tree

2 files changed

+144
-7
lines changed

2 files changed

+144
-7
lines changed

llvm/lib/DebugInfo/Symbolize/Symbolize.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -649,22 +649,29 @@ namespace {
649649
// vectorcall - foo@@12
650650
// These are all different linkage names for 'foo'.
651651
StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
652-
// Remove any '_' or '@' prefix.
653652
char Front = SymbolName.empty() ? '\0' : SymbolName[0];
654-
if (Front == '_' || Front == '@')
655-
SymbolName = SymbolName.drop_front();
656653

657654
// Remove any '@[0-9]+' suffix.
655+
bool HasAtNumSuffix = false;
658656
if (Front != '?') {
659657
size_t AtPos = SymbolName.rfind('@');
660658
if (AtPos != StringRef::npos &&
661-
all_of(drop_begin(SymbolName, AtPos + 1), isDigit))
659+
all_of(drop_begin(SymbolName, AtPos + 1), isDigit)) {
662660
SymbolName = SymbolName.substr(0, AtPos);
661+
HasAtNumSuffix = true;
662+
}
663663
}
664664

665665
// Remove any ending '@' for vectorcall.
666-
if (SymbolName.endswith("@"))
666+
bool IsVectorCall = false;
667+
if (HasAtNumSuffix && SymbolName.endswith("@")) {
667668
SymbolName = SymbolName.drop_back();
669+
IsVectorCall = true;
670+
}
671+
672+
// If not vectorcall, remove any '_' or '@' prefix.
673+
if (!IsVectorCall && (Front == '_' || Front == '@'))
674+
SymbolName = SymbolName.drop_front();
668675

669676
return SymbolName;
670677
}
@@ -692,8 +699,14 @@ LLVMSymbolizer::DemangleName(const std::string &Name,
692699
return Result;
693700
}
694701

695-
if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module())
696-
return std::string(demanglePE32ExternCFunc(Name));
702+
if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module()) {
703+
std::string DemangledCName(demanglePE32ExternCFunc(Name));
704+
// On i386 Windows, the C name mangling for different calling conventions
705+
// may also be applied on top of the Itanium or Rust name mangling.
706+
if (nonMicrosoftDemangle(DemangledCName.c_str(), Result))
707+
return Result;
708+
return DemangledCName;
709+
}
697710
return Name;
698711
}
699712

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# REQUIRES: x86-registered-target
2+
3+
# RUN: llvm-mc --filetype=obj --triple=i386-w64-windows-gnu %s -o %t.o -g
4+
5+
# RUN: llvm-symbolizer --obj=%t.o 0 1 2 3 4 5 6 7 8 9 10 | FileCheck %s
6+
7+
.def g
8+
.scl 2
9+
.type 32
10+
.endef
11+
g:
12+
nop
13+
# CHECK: {{^g$}}
14+
# CHECK-NEXT: symbolize-demangling-mingw32.s:12
15+
# CHECK-EMPTY:
16+
17+
.def baz
18+
.scl 2
19+
.type 32
20+
.endef
21+
baz:
22+
nop
23+
# CHECK-NEXT: {{^baz$}}
24+
# CHECK-NEXT: symbolize-demangling-mingw32.s:22
25+
# CHECK-EMPTY:
26+
27+
# extern "C" void c() {} // __cdecl
28+
.def _c
29+
.scl 2
30+
.type 32
31+
.endef
32+
_c:
33+
nop
34+
# CHECK-NEXT: {{^c$}}
35+
# CHECK-NEXT: symbolize-demangling-mingw32.s:33
36+
# CHECK-EMPTY:
37+
38+
# extern "C" void __stdcall c1() {}
39+
.def _c1@0
40+
.scl 2
41+
.type 32
42+
.endef
43+
_c1@0:
44+
nop
45+
# CHECK-NEXT: {{^c1$}}
46+
# CHECK-NEXT: symbolize-demangling-mingw32.s:44
47+
# CHECK-EMPTY:
48+
49+
# extern "C" void __fastcall c2(void) {}
50+
.def @c2@0
51+
.scl 2
52+
.type 32
53+
.endef
54+
@c2@0:
55+
nop
56+
# CHECK-NEXT: {{^c2$}}
57+
# CHECK-NEXT: symbolize-demangling-mingw32.s:55
58+
# CHECK-EMPTY:
59+
60+
# extern "C" void __vectorcall c3(void) {}
61+
.def c3@@0
62+
.scl 2
63+
.type 32
64+
.endef
65+
c3@@0:
66+
nop
67+
# CHECK-NEXT: {{^c3$}}
68+
# CHECK-NEXT: symbolize-demangling-mingw32.s:66
69+
# CHECK-EMPTY:
70+
71+
# void f() {} // __cdecl
72+
.def __Z1fv
73+
.scl 2
74+
.type 32
75+
.endef
76+
__Z1fv:
77+
nop
78+
# CHECK-NEXT: {{^f\(\)$}}
79+
# CHECK-NEXT: symbolize-demangling-mingw32.s:77
80+
# CHECK-EMPTY:
81+
82+
# void __stdcall f1() {}
83+
.def __Z2f1v@0
84+
.scl 2
85+
.type 32
86+
.endef
87+
__Z2f1v@0:
88+
nop
89+
# CHECK-NEXT: {{^f1\(\)$}}
90+
# CHECK-NEXT: symbolize-demangling-mingw32.s:88
91+
# CHECK-EMPTY:
92+
93+
# void __fastcall f2(void) {}
94+
.def @_Z2f2v@0
95+
.scl 2
96+
.type 32
97+
.endef
98+
@_Z2f2v@0:
99+
nop
100+
# CHECK-NEXT: {{^f2\(\)$}}
101+
# CHECK-NEXT: symbolize-demangling-mingw32.s:99
102+
# CHECK-EMPTY:
103+
104+
# void __vectorcall f3(void) {}
105+
.def _Z2f3v@@0
106+
.scl 2
107+
.type 32
108+
.endef
109+
_Z2f3v@@0:
110+
nop
111+
# CHECK-NEXT: {{^f3\(\)$}}
112+
# CHECK-NEXT: symbolize-demangling-mingw32.s:110
113+
# CHECK-EMPTY:
114+
115+
# Rust
116+
.def __RNvC1x1y
117+
.scl 2
118+
.type 32
119+
.endef
120+
__RNvC1x1y:
121+
nop
122+
# CHECK-NEXT: {{^x::y$}}
123+
# CHECK-NEXT: symbolize-demangling-mingw32.s:121
124+
# CHECK-EMPTY:

0 commit comments

Comments
 (0)