clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name MicrosoftDemangle.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -D PIC -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -D_RET_PROTECTOR -ret-protector -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Demangle/MicrosoftDemangle.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | #include "llvm/Demangle/MicrosoftDemangle.h" |
17 | #include "llvm/Demangle/Demangle.h" |
18 | #include "llvm/Demangle/MicrosoftDemangleNodes.h" |
19 | |
20 | #include "llvm/Demangle/DemangleConfig.h" |
21 | #include "llvm/Demangle/StringView.h" |
22 | #include "llvm/Demangle/Utility.h" |
23 | |
24 | #include <array> |
25 | #include <cctype> |
26 | #include <cstdio> |
27 | #include <tuple> |
28 | |
29 | using namespace llvm; |
30 | using namespace ms_demangle; |
31 | |
32 | static bool startsWithDigit(StringView S) { |
33 | return !S.empty() && std::isdigit(S.front()); |
34 | } |
35 | |
36 | |
37 | struct NodeList { |
38 | Node *N = nullptr; |
39 | NodeList *Next = nullptr; |
40 | }; |
41 | |
42 | static bool isMemberPointer(StringView MangledName, bool &Error) { |
43 | Error = false; |
44 | switch (MangledName.popFront()) { |
45 | case '$': |
46 | |
47 | |
48 | return false; |
49 | case 'A': |
50 | |
51 | |
52 | return false; |
53 | case 'P': |
54 | case 'Q': |
55 | case 'R': |
56 | case 'S': |
57 | |
58 | |
59 | break; |
60 | default: |
61 | |
62 | |
63 | DEMANGLE_UNREACHABLE; |
64 | } |
65 | |
66 | |
67 | |
68 | if (startsWithDigit(MangledName)) { |
69 | if (MangledName[0] != '6' && MangledName[0] != '8') { |
70 | Error = true; |
71 | return false; |
72 | } |
73 | return (MangledName[0] == '8'); |
74 | } |
75 | |
76 | |
77 | |
78 | MangledName.consumeFront('E'); |
79 | MangledName.consumeFront('I'); |
80 | MangledName.consumeFront('F'); |
81 | |
82 | if (MangledName.empty()) { |
83 | Error = true; |
84 | return false; |
85 | } |
86 | |
87 | |
88 | switch (MangledName.front()) { |
89 | case 'A': |
90 | case 'B': |
91 | case 'C': |
92 | case 'D': |
93 | return false; |
94 | case 'Q': |
95 | case 'R': |
96 | case 'S': |
97 | case 'T': |
98 | return true; |
99 | default: |
100 | Error = true; |
101 | return false; |
102 | } |
103 | } |
104 | |
105 | static SpecialIntrinsicKind |
106 | consumeSpecialIntrinsicKind(StringView &MangledName) { |
107 | if (MangledName.consumeFront("?_7")) |
108 | return SpecialIntrinsicKind::Vftable; |
109 | if (MangledName.consumeFront("?_8")) |
110 | return SpecialIntrinsicKind::Vbtable; |
111 | if (MangledName.consumeFront("?_9")) |
112 | return SpecialIntrinsicKind::VcallThunk; |
113 | if (MangledName.consumeFront("?_A")) |
114 | return SpecialIntrinsicKind::Typeof; |
115 | if (MangledName.consumeFront("?_B")) |
116 | return SpecialIntrinsicKind::LocalStaticGuard; |
117 | if (MangledName.consumeFront("?_C")) |
118 | return SpecialIntrinsicKind::StringLiteralSymbol; |
119 | if (MangledName.consumeFront("?_P")) |
120 | return SpecialIntrinsicKind::UdtReturning; |
121 | if (MangledName.consumeFront("?_R0")) |
122 | return SpecialIntrinsicKind::RttiTypeDescriptor; |
123 | if (MangledName.consumeFront("?_R1")) |
124 | return SpecialIntrinsicKind::RttiBaseClassDescriptor; |
125 | if (MangledName.consumeFront("?_R2")) |
126 | return SpecialIntrinsicKind::RttiBaseClassArray; |
127 | if (MangledName.consumeFront("?_R3")) |
128 | return SpecialIntrinsicKind::RttiClassHierarchyDescriptor; |
129 | if (MangledName.consumeFront("?_R4")) |
130 | return SpecialIntrinsicKind::RttiCompleteObjLocator; |
131 | if (MangledName.consumeFront("?_S")) |
132 | return SpecialIntrinsicKind::LocalVftable; |
133 | if (MangledName.consumeFront("?__E")) |
134 | return SpecialIntrinsicKind::DynamicInitializer; |
135 | if (MangledName.consumeFront("?__F")) |
136 | return SpecialIntrinsicKind::DynamicAtexitDestructor; |
137 | if (MangledName.consumeFront("?__J")) |
138 | return SpecialIntrinsicKind::LocalStaticThreadGuard; |
139 | return SpecialIntrinsicKind::None; |
140 | } |
141 | |
142 | static bool startsWithLocalScopePattern(StringView S) { |
143 | if (!S.consumeFront('?')) |
144 | return false; |
145 | |
146 | size_t End = S.find('?'); |
147 | if (End == StringView::npos) |
148 | return false; |
149 | StringView Candidate = S.substr(0, End); |
150 | if (Candidate.empty()) |
151 | return false; |
152 | |
153 | |
154 | |
155 | if (Candidate.size() == 1) |
156 | return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9'); |
157 | |
158 | |
159 | if (Candidate.back() != '@') |
160 | return false; |
161 | Candidate = Candidate.dropBack(); |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | if (Candidate[0] < 'B' || Candidate[0] > 'P') |
170 | return false; |
171 | Candidate = Candidate.dropFront(); |
172 | while (!Candidate.empty()) { |
173 | if (Candidate[0] < 'A' || Candidate[0] > 'P') |
174 | return false; |
175 | Candidate = Candidate.dropFront(); |
176 | } |
177 | |
178 | return true; |
179 | } |
180 | |
181 | static bool isTagType(StringView S) { |
182 | switch (S.front()) { |
183 | case 'T': |
184 | case 'U': |
185 | case 'V': |
186 | case 'W': |
187 | return true; |
188 | } |
189 | return false; |
190 | } |
191 | |
192 | static bool isCustomType(StringView S) { return S[0] == '?'; } |
193 | |
194 | static bool isPointerType(StringView S) { |
195 | if (S.startsWith("$$Q")) |
196 | return true; |
197 | |
198 | switch (S.front()) { |
199 | case 'A': |
200 | case 'P': |
201 | case 'Q': |
202 | case 'R': |
203 | case 'S': |
204 | return true; |
205 | } |
206 | return false; |
207 | } |
208 | |
209 | static bool isArrayType(StringView S) { return S[0] == 'Y'; } |
210 | |
211 | static bool isFunctionType(StringView S) { |
212 | return S.startsWith("$$A8@@") || S.startsWith("$$A6"); |
213 | } |
214 | |
215 | static FunctionRefQualifier |
216 | demangleFunctionRefQualifier(StringView &MangledName) { |
217 | if (MangledName.consumeFront('G')) |
218 | return FunctionRefQualifier::Reference; |
219 | else if (MangledName.consumeFront('H')) |
220 | return FunctionRefQualifier::RValueReference; |
221 | return FunctionRefQualifier::None; |
222 | } |
223 | |
224 | static std::pair<Qualifiers, PointerAffinity> |
225 | demanglePointerCVQualifiers(StringView &MangledName) { |
226 | if (MangledName.consumeFront("$$Q")) |
227 | return std::make_pair(Q_None, PointerAffinity::RValueReference); |
228 | |
229 | switch (MangledName.popFront()) { |
230 | case 'A': |
231 | return std::make_pair(Q_None, PointerAffinity::Reference); |
232 | case 'P': |
233 | return std::make_pair(Q_None, PointerAffinity::Pointer); |
234 | case 'Q': |
235 | return std::make_pair(Q_Const, PointerAffinity::Pointer); |
236 | case 'R': |
237 | return std::make_pair(Q_Volatile, PointerAffinity::Pointer); |
238 | case 'S': |
239 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), |
240 | PointerAffinity::Pointer); |
241 | } |
242 | |
243 | |
244 | DEMANGLE_UNREACHABLE; |
245 | } |
246 | |
247 | StringView Demangler::copyString(StringView Borrowed) { |
248 | char *Stable = Arena.allocUnalignedBuffer(Borrowed.size() + 1); |
249 | std::strcpy(Stable, Borrowed.begin()); |
250 | |
251 | return {Stable, Borrowed.size()}; |
252 | } |
253 | |
254 | SpecialTableSymbolNode * |
255 | Demangler::demangleSpecialTableSymbolNode(StringView &MangledName, |
256 | SpecialIntrinsicKind K) { |
257 | NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>(); |
258 | switch (K) { |
259 | case SpecialIntrinsicKind::Vftable: |
260 | NI->Name = "`vftable'"; |
261 | break; |
262 | case SpecialIntrinsicKind::Vbtable: |
263 | NI->Name = "`vbtable'"; |
264 | break; |
265 | case SpecialIntrinsicKind::LocalVftable: |
266 | NI->Name = "`local vftable'"; |
267 | break; |
268 | case SpecialIntrinsicKind::RttiCompleteObjLocator: |
269 | NI->Name = "`RTTI Complete Object Locator'"; |
270 | break; |
271 | default: |
272 | DEMANGLE_UNREACHABLE; |
273 | } |
274 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI); |
275 | SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>(); |
276 | STSN->Name = QN; |
277 | bool IsMember = false; |
278 | if (MangledName.empty()) { |
279 | Error = true; |
280 | return nullptr; |
281 | } |
282 | char Front = MangledName.popFront(); |
283 | if (Front != '6' && Front != '7') { |
284 | Error = true; |
285 | return nullptr; |
286 | } |
287 | |
288 | std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName); |
289 | if (!MangledName.consumeFront('@')) |
290 | STSN->TargetName = demangleFullyQualifiedTypeName(MangledName); |
291 | return STSN; |
292 | } |
293 | |
294 | LocalStaticGuardVariableNode * |
295 | Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) { |
296 | LocalStaticGuardIdentifierNode *LSGI = |
297 | Arena.alloc<LocalStaticGuardIdentifierNode>(); |
298 | LSGI->IsThread = IsThread; |
299 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI); |
300 | LocalStaticGuardVariableNode *LSGVN = |
301 | Arena.alloc<LocalStaticGuardVariableNode>(); |
302 | LSGVN->Name = QN; |
303 | |
304 | if (MangledName.consumeFront("4IA")) |
305 | LSGVN->IsVisible = false; |
306 | else if (MangledName.consumeFront("5")) |
307 | LSGVN->IsVisible = true; |
308 | else { |
309 | Error = true; |
310 | return nullptr; |
311 | } |
312 | |
313 | if (!MangledName.empty()) |
314 | LSGI->ScopeIndex = demangleUnsigned(MangledName); |
315 | return LSGVN; |
316 | } |
317 | |
318 | static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena, |
319 | StringView Name) { |
320 | NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>(); |
321 | Id->Name = Name; |
322 | return Id; |
323 | } |
324 | |
325 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, |
326 | IdentifierNode *Identifier) { |
327 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); |
328 | QN->Components = Arena.alloc<NodeArrayNode>(); |
329 | QN->Components->Count = 1; |
330 | QN->Components->Nodes = Arena.allocArray<Node *>(1); |
| 11 | | Calling 'ArenaAllocator::allocArray' | |
|
331 | QN->Components->Nodes[0] = Identifier; |
332 | return QN; |
333 | } |
334 | |
335 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, |
336 | StringView Name) { |
337 | NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name); |
338 | return synthesizeQualifiedName(Arena, Id); |
| 10 | | Calling 'synthesizeQualifiedName' | |
|
339 | } |
340 | |
341 | static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena, |
342 | TypeNode *Type, |
343 | StringView VariableName) { |
344 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
345 | VSN->Type = Type; |
346 | VSN->Name = synthesizeQualifiedName(Arena, VariableName); |
347 | return VSN; |
348 | } |
349 | |
350 | VariableSymbolNode *Demangler::demangleUntypedVariable( |
351 | ArenaAllocator &Arena, StringView &MangledName, StringView VariableName) { |
352 | NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName); |
353 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI); |
354 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
355 | VSN->Name = QN; |
356 | if (MangledName.consumeFront("8")) |
357 | return VSN; |
358 | |
359 | Error = true; |
360 | return nullptr; |
361 | } |
362 | |
363 | VariableSymbolNode * |
364 | Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, |
365 | StringView &MangledName) { |
366 | RttiBaseClassDescriptorNode *RBCDN = |
367 | Arena.alloc<RttiBaseClassDescriptorNode>(); |
368 | RBCDN->NVOffset = demangleUnsigned(MangledName); |
369 | RBCDN->VBPtrOffset = demangleSigned(MangledName); |
370 | RBCDN->VBTableOffset = demangleUnsigned(MangledName); |
371 | RBCDN->Flags = demangleUnsigned(MangledName); |
372 | if (Error) |
373 | return nullptr; |
374 | |
375 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
376 | VSN->Name = demangleNameScopeChain(MangledName, RBCDN); |
377 | MangledName.consumeFront('8'); |
378 | return VSN; |
379 | } |
380 | |
381 | FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, |
382 | bool IsDestructor) { |
383 | DynamicStructorIdentifierNode *DSIN = |
384 | Arena.alloc<DynamicStructorIdentifierNode>(); |
385 | DSIN->IsDestructor = IsDestructor; |
386 | |
387 | bool IsKnownStaticDataMember = false; |
388 | if (MangledName.consumeFront('?')) |
389 | IsKnownStaticDataMember = true; |
390 | |
391 | SymbolNode *Symbol = demangleDeclarator(MangledName); |
392 | if (Error) |
393 | return nullptr; |
394 | |
395 | FunctionSymbolNode *FSN = nullptr; |
396 | |
397 | if (Symbol->kind() == NodeKind::VariableSymbol) { |
398 | DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol); |
399 | |
400 | |
401 | |
402 | |
403 | |
404 | int AtCount = IsKnownStaticDataMember ? 2 : 1; |
405 | for (int I = 0; I < AtCount; ++I) { |
406 | if (MangledName.consumeFront('@')) |
407 | continue; |
408 | Error = true; |
409 | return nullptr; |
410 | } |
411 | |
412 | FSN = demangleFunctionEncoding(MangledName); |
413 | if (FSN) |
414 | FSN->Name = synthesizeQualifiedName(Arena, DSIN); |
415 | } else { |
416 | if (IsKnownStaticDataMember) { |
417 | |
418 | Error = true; |
419 | return nullptr; |
420 | } |
421 | |
422 | FSN = static_cast<FunctionSymbolNode *>(Symbol); |
423 | DSIN->Name = Symbol->Name; |
424 | FSN->Name = synthesizeQualifiedName(Arena, DSIN); |
425 | } |
426 | |
427 | return FSN; |
428 | } |
429 | |
430 | SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) { |
431 | SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName); |
432 | |
433 | switch (SIK) { |
434 | case SpecialIntrinsicKind::None: |
435 | return nullptr; |
436 | case SpecialIntrinsicKind::StringLiteralSymbol: |
437 | return demangleStringLiteral(MangledName); |
438 | case SpecialIntrinsicKind::Vftable: |
439 | case SpecialIntrinsicKind::Vbtable: |
440 | case SpecialIntrinsicKind::LocalVftable: |
441 | case SpecialIntrinsicKind::RttiCompleteObjLocator: |
442 | return demangleSpecialTableSymbolNode(MangledName, SIK); |
443 | case SpecialIntrinsicKind::VcallThunk: |
444 | return demangleVcallThunkNode(MangledName); |
445 | case SpecialIntrinsicKind::LocalStaticGuard: |
446 | return demangleLocalStaticGuard(MangledName, false); |
447 | case SpecialIntrinsicKind::LocalStaticThreadGuard: |
448 | return demangleLocalStaticGuard(MangledName, true); |
449 | case SpecialIntrinsicKind::RttiTypeDescriptor: { |
450 | TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); |
451 | if (Error) |
452 | break; |
453 | if (!MangledName.consumeFront("@8")) |
454 | break; |
455 | if (!MangledName.empty()) |
456 | break; |
457 | return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'"); |
458 | } |
459 | case SpecialIntrinsicKind::RttiBaseClassArray: |
460 | return demangleUntypedVariable(Arena, MangledName, |
461 | "`RTTI Base Class Array'"); |
462 | case SpecialIntrinsicKind::RttiClassHierarchyDescriptor: |
463 | return demangleUntypedVariable(Arena, MangledName, |
464 | "`RTTI Class Hierarchy Descriptor'"); |
465 | case SpecialIntrinsicKind::RttiBaseClassDescriptor: |
466 | return demangleRttiBaseClassDescriptorNode(Arena, MangledName); |
467 | case SpecialIntrinsicKind::DynamicInitializer: |
468 | return demangleInitFiniStub(MangledName, false); |
469 | case SpecialIntrinsicKind::DynamicAtexitDestructor: |
470 | return demangleInitFiniStub(MangledName, true); |
471 | case SpecialIntrinsicKind::Typeof: |
472 | case SpecialIntrinsicKind::UdtReturning: |
473 | |
474 | |
475 | break; |
476 | case SpecialIntrinsicKind::Unknown: |
477 | DEMANGLE_UNREACHABLE; |
478 | } |
479 | Error = true; |
480 | return nullptr; |
481 | } |
482 | |
483 | IdentifierNode * |
484 | Demangler::demangleFunctionIdentifierCode(StringView &MangledName) { |
485 | assert(MangledName.startsWith('?')); |
486 | MangledName = MangledName.dropFront(); |
487 | if (MangledName.empty()) { |
488 | Error = true; |
489 | return nullptr; |
490 | } |
491 | |
492 | if (MangledName.consumeFront("__")) |
493 | return demangleFunctionIdentifierCode( |
494 | MangledName, FunctionIdentifierCodeGroup::DoubleUnder); |
495 | if (MangledName.consumeFront("_")) |
496 | return demangleFunctionIdentifierCode(MangledName, |
497 | FunctionIdentifierCodeGroup::Under); |
498 | return demangleFunctionIdentifierCode(MangledName, |
499 | FunctionIdentifierCodeGroup::Basic); |
500 | } |
501 | |
502 | StructorIdentifierNode * |
503 | Demangler::demangleStructorIdentifier(StringView &MangledName, |
504 | bool IsDestructor) { |
505 | StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>(); |
506 | N->IsDestructor = IsDestructor; |
507 | return N; |
508 | } |
509 | |
510 | ConversionOperatorIdentifierNode * |
511 | Demangler::demangleConversionOperatorIdentifier(StringView &MangledName) { |
512 | ConversionOperatorIdentifierNode *N = |
513 | Arena.alloc<ConversionOperatorIdentifierNode>(); |
514 | return N; |
515 | } |
516 | |
517 | LiteralOperatorIdentifierNode * |
518 | Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) { |
519 | LiteralOperatorIdentifierNode *N = |
520 | Arena.alloc<LiteralOperatorIdentifierNode>(); |
521 | N->Name = demangleSimpleString(MangledName, false); |
522 | return N; |
523 | } |
524 | |
525 | IntrinsicFunctionKind |
526 | Demangler::translateIntrinsicFunctionCode(char CH, |
527 | FunctionIdentifierCodeGroup Group) { |
528 | using IFK = IntrinsicFunctionKind; |
529 | if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) { |
530 | Error = true; |
531 | return IFK::None; |
532 | } |
533 | |
534 | |
535 | |
536 | |
537 | static IFK Basic[36] = { |
538 | IFK::None, |
539 | IFK::None, |
540 | IFK::New, |
541 | IFK::Delete, |
542 | IFK::Assign, |
543 | IFK::RightShift, |
544 | IFK::LeftShift, |
545 | IFK::LogicalNot, |
546 | IFK::Equals, |
547 | IFK::NotEquals, |
548 | IFK::ArraySubscript, |
549 | IFK::None, |
550 | IFK::Pointer, |
551 | IFK::Dereference, |
552 | IFK::Increment, |
553 | IFK::Decrement, |
554 | IFK::Minus, |
555 | IFK::Plus, |
556 | IFK::BitwiseAnd, |
557 | IFK::MemberPointer, |
558 | IFK::Divide, |
559 | IFK::Modulus, |
560 | IFK::LessThan, |
561 | IFK::LessThanEqual, |
562 | IFK::GreaterThan, |
563 | IFK::GreaterThanEqual, |
564 | IFK::Comma, |
565 | IFK::Parens, |
566 | IFK::BitwiseNot, |
567 | IFK::BitwiseXor, |
568 | IFK::BitwiseOr, |
569 | IFK::LogicalAnd, |
570 | IFK::LogicalOr, |
571 | IFK::TimesEqual, |
572 | IFK::PlusEqual, |
573 | IFK::MinusEqual, |
574 | }; |
575 | static IFK Under[36] = { |
576 | IFK::DivEqual, |
577 | IFK::ModEqual, |
578 | IFK::RshEqual, |
579 | IFK::LshEqual, |
580 | IFK::BitwiseAndEqual, |
581 | IFK::BitwiseOrEqual, |
582 | IFK::BitwiseXorEqual, |
583 | IFK::None, |
584 | IFK::None, |
585 | IFK::None, |
586 | IFK::None, |
587 | IFK::None, |
588 | IFK::None, |
589 | IFK::VbaseDtor, |
590 | IFK::VecDelDtor, |
591 | IFK::DefaultCtorClosure, |
592 | IFK::ScalarDelDtor, |
593 | IFK::VecCtorIter, |
594 | IFK::VecDtorIter, |
595 | IFK::VecVbaseCtorIter, |
596 | IFK::VdispMap, |
597 | IFK::EHVecCtorIter, |
598 | IFK::EHVecDtorIter, |
599 | IFK::EHVecVbaseCtorIter, |
600 | IFK::CopyCtorClosure, |
601 | IFK::None, |
602 | IFK::None, |
603 | IFK::None, |
604 | IFK::None, |
605 | IFK::LocalVftableCtorClosure, |
606 | IFK::ArrayNew, |
607 | IFK::ArrayDelete, |
608 | IFK::None, |
609 | IFK::None, |
610 | IFK::None, |
611 | IFK::None, |
612 | }; |
613 | static IFK DoubleUnder[36] = { |
614 | IFK::None, |
615 | IFK::None, |
616 | IFK::None, |
617 | IFK::None, |
618 | IFK::None, |
619 | IFK::None, |
620 | IFK::None, |
621 | IFK::None, |
622 | IFK::None, |
623 | IFK::None, |
624 | IFK::ManVectorCtorIter, |
625 | IFK::ManVectorDtorIter, |
626 | IFK::EHVectorCopyCtorIter, |
627 | IFK::EHVectorVbaseCopyCtorIter, |
628 | IFK::None, |
629 | IFK::None, |
630 | IFK::VectorCopyCtorIter, |
631 | IFK::VectorVbaseCopyCtorIter, |
632 | IFK::ManVectorVbaseCopyCtorIter, |
633 | |
634 | IFK::None, |
635 | IFK::None, |
636 | IFK::CoAwait, |
637 | IFK::Spaceship, |
638 | IFK::None, |
639 | IFK::None, |
640 | IFK::None, |
641 | IFK::None, |
642 | IFK::None, |
643 | IFK::None, |
644 | IFK::None, |
645 | IFK::None, |
646 | IFK::None, |
647 | IFK::None, |
648 | IFK::None, |
649 | IFK::None, |
650 | IFK::None, |
651 | }; |
652 | |
653 | int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10); |
654 | switch (Group) { |
655 | case FunctionIdentifierCodeGroup::Basic: |
656 | return Basic[Index]; |
657 | case FunctionIdentifierCodeGroup::Under: |
658 | return Under[Index]; |
659 | case FunctionIdentifierCodeGroup::DoubleUnder: |
660 | return DoubleUnder[Index]; |
661 | } |
662 | DEMANGLE_UNREACHABLE; |
663 | } |
664 | |
665 | IdentifierNode * |
666 | Demangler::demangleFunctionIdentifierCode(StringView &MangledName, |
667 | FunctionIdentifierCodeGroup Group) { |
668 | if (MangledName.empty()) { |
669 | Error = true; |
670 | return nullptr; |
671 | } |
672 | switch (Group) { |
673 | case FunctionIdentifierCodeGroup::Basic: |
674 | switch (char CH = MangledName.popFront()) { |
675 | case '0': |
676 | case '1': |
677 | return demangleStructorIdentifier(MangledName, CH == '1'); |
678 | case 'B': |
679 | return demangleConversionOperatorIdentifier(MangledName); |
680 | default: |
681 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( |
682 | translateIntrinsicFunctionCode(CH, Group)); |
683 | } |
684 | case FunctionIdentifierCodeGroup::Under: |
685 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( |
686 | translateIntrinsicFunctionCode(MangledName.popFront(), Group)); |
687 | case FunctionIdentifierCodeGroup::DoubleUnder: |
688 | switch (char CH = MangledName.popFront()) { |
689 | case 'K': |
690 | return demangleLiteralOperatorIdentifier(MangledName); |
691 | default: |
692 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( |
693 | translateIntrinsicFunctionCode(CH, Group)); |
694 | } |
695 | } |
696 | |
697 | DEMANGLE_UNREACHABLE; |
698 | } |
699 | |
700 | SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName, |
701 | QualifiedNameNode *Name) { |
702 | if (MangledName.empty()) { |
703 | Error = true; |
704 | return nullptr; |
705 | } |
706 | |
707 | |
708 | switch (MangledName.front()) { |
709 | case '0': |
710 | case '1': |
711 | case '2': |
712 | case '3': |
713 | case '4': { |
714 | StorageClass SC = demangleVariableStorageClass(MangledName); |
715 | return demangleVariableEncoding(MangledName, SC); |
716 | } |
717 | } |
718 | FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName); |
719 | |
720 | IdentifierNode *UQN = Name->getUnqualifiedIdentifier(); |
721 | if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { |
722 | ConversionOperatorIdentifierNode *COIN = |
723 | static_cast<ConversionOperatorIdentifierNode *>(UQN); |
724 | if (FSN) |
725 | COIN->TargetType = FSN->Signature->ReturnType; |
726 | } |
727 | return FSN; |
728 | } |
729 | |
730 | SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) { |
731 | |
732 | |
733 | QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); |
734 | if (Error) |
735 | return nullptr; |
736 | |
737 | SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN); |
738 | if (Error) |
739 | return nullptr; |
740 | Symbol->Name = QN; |
741 | |
742 | IdentifierNode *UQN = QN->getUnqualifiedIdentifier(); |
743 | if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { |
744 | ConversionOperatorIdentifierNode *COIN = |
745 | static_cast<ConversionOperatorIdentifierNode *>(UQN); |
746 | if (!COIN->TargetType) { |
747 | Error = true; |
748 | return nullptr; |
749 | } |
750 | } |
751 | return Symbol; |
752 | } |
753 | |
754 | SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) { |
755 | assert(MangledName.startsWith("??@")); |
756 | |
757 | |
758 | |
759 | size_t MD5Last = MangledName.find('@', strlen("??@")); |
760 | if (MD5Last == StringView::npos) { |
| 7 | | Assuming 'MD5Last' is not equal to 'npos' | |
|
| |
761 | Error = true; |
762 | return nullptr; |
763 | } |
764 | const char *Start = MangledName.begin(); |
765 | MangledName = MangledName.dropFront(MD5Last + 1); |
766 | |
767 | |
768 | |
769 | |
770 | |
771 | |
772 | |
773 | |
774 | |
775 | |
776 | |
777 | MangledName.consumeFront("??_R4@"); |
778 | |
779 | StringView MD5(Start, MangledName.begin()); |
780 | SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol); |
781 | S->Name = synthesizeQualifiedName(Arena, MD5); |
| 9 | | Calling 'synthesizeQualifiedName' | |
|
782 | |
783 | return S; |
784 | } |
785 | |
786 | SymbolNode *Demangler::demangleTypeinfoName(StringView &MangledName) { |
787 | assert(MangledName.startsWith('.')); |
788 | MangledName.consumeFront('.'); |
789 | |
790 | TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); |
791 | if (Error || !MangledName.empty()) { |
792 | Error = true; |
793 | return nullptr; |
794 | } |
795 | return synthesizeVariable(Arena, T, "`RTTI Type Descriptor Name'"); |
796 | } |
797 | |
798 | |
799 | SymbolNode *Demangler::parse(StringView &MangledName) { |
800 | |
801 | |
802 | |
803 | if (MangledName.startsWith('.')) |
| 2 | | Assuming the condition is false | |
|
| |
804 | return demangleTypeinfoName(MangledName); |
805 | |
806 | if (MangledName.startsWith("??@")) |
| 4 | | Assuming the condition is true | |
|
| |
807 | return demangleMD5Name(MangledName); |
| 6 | | Calling 'Demangler::demangleMD5Name' | |
|
808 | |
809 | |
810 | if (!MangledName.startsWith('?')) { |
811 | Error = true; |
812 | return nullptr; |
813 | } |
814 | |
815 | MangledName.consumeFront('?'); |
816 | |
817 | |
818 | |
819 | if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName)) |
820 | return SI; |
821 | |
822 | return demangleDeclarator(MangledName); |
823 | } |
824 | |
825 | TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) { |
826 | if (!MangledName.consumeFront(".?A")) |
827 | return nullptr; |
828 | MangledName.consumeFront(".?A"); |
829 | if (MangledName.empty()) |
830 | return nullptr; |
831 | |
832 | return demangleClassType(MangledName); |
833 | } |
834 | |
835 | |
836 | |
837 | |
838 | |
839 | |
840 | |
841 | |
842 | VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName, |
843 | StorageClass SC) { |
844 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
845 | |
846 | VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop); |
847 | VSN->SC = SC; |
848 | |
849 | if (Error) |
850 | return nullptr; |
851 | |
852 | |
853 | |
854 | switch (VSN->Type->kind()) { |
855 | case NodeKind::PointerType: { |
856 | PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type); |
857 | |
858 | Qualifiers ExtraChildQuals = Q_None; |
859 | PTN->Quals = Qualifiers(VSN->Type->Quals | |
860 | demanglePointerExtQualifiers(MangledName)); |
861 | |
862 | bool IsMember = false; |
863 | std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName); |
864 | |
865 | if (PTN->ClassParent) { |
866 | QualifiedNameNode *BackRefName = |
867 | demangleFullyQualifiedTypeName(MangledName); |
868 | (void)BackRefName; |
869 | } |
870 | PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals); |
871 | |
872 | break; |
873 | } |
874 | default: |
875 | VSN->Type->Quals = demangleQualifiers(MangledName).first; |
876 | break; |
877 | } |
878 | |
879 | return VSN; |
880 | } |
881 | |
882 | |
883 | |
884 | |
885 | |
886 | |
887 | |
888 | |
889 | |
890 | |
891 | |
892 | |
893 | std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) { |
894 | bool IsNegative = MangledName.consumeFront('?'); |
895 | |
896 | if (startsWithDigit(MangledName)) { |
897 | uint64_t Ret = MangledName[0] - '0' + 1; |
898 | MangledName = MangledName.dropFront(1); |
899 | return {Ret, IsNegative}; |
900 | } |
901 | |
902 | uint64_t Ret = 0; |
903 | for (size_t i = 0; i < MangledName.size(); ++i) { |
904 | char C = MangledName[i]; |
905 | if (C == '@') { |
906 | MangledName = MangledName.dropFront(i + 1); |
907 | return {Ret, IsNegative}; |
908 | } |
909 | if ('A' <= C && C <= 'P') { |
910 | Ret = (Ret << 4) + (C - 'A'); |
911 | continue; |
912 | } |
913 | break; |
914 | } |
915 | |
916 | Error = true; |
917 | return {0ULL, false}; |
918 | } |
919 | |
920 | uint64_t Demangler::demangleUnsigned(StringView &MangledName) { |
921 | bool IsNegative = false; |
922 | uint64_t Number = 0; |
923 | std::tie(Number, IsNegative) = demangleNumber(MangledName); |
924 | if (IsNegative) |
925 | Error = true; |
926 | return Number; |
927 | } |
928 | |
929 | int64_t Demangler::demangleSigned(StringView &MangledName) { |
930 | bool IsNegative = false; |
931 | uint64_t Number = 0; |
932 | std::tie(Number, IsNegative) = demangleNumber(MangledName); |
933 | if (Number > INT64_MAX) |
934 | Error = true; |
935 | int64_t I = static_cast<int64_t>(Number); |
936 | return IsNegative ? -I : I; |
937 | } |
938 | |
939 | |
940 | |
941 | void Demangler::memorizeString(StringView S) { |
942 | if (Backrefs.NamesCount >= BackrefContext::Max) |
943 | return; |
944 | for (size_t i = 0; i < Backrefs.NamesCount; ++i) |
945 | if (S == Backrefs.Names[i]->Name) |
946 | return; |
947 | NamedIdentifierNode *N = Arena.alloc<NamedIdentifierNode>(); |
948 | N->Name = S; |
949 | Backrefs.Names[Backrefs.NamesCount++] = N; |
950 | } |
951 | |
952 | NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) { |
953 | assert(startsWithDigit(MangledName)); |
954 | |
955 | size_t I = MangledName[0] - '0'; |
956 | if (I >= Backrefs.NamesCount) { |
957 | Error = true; |
958 | return nullptr; |
959 | } |
960 | |
961 | MangledName = MangledName.dropFront(); |
962 | return Backrefs.Names[I]; |
963 | } |
964 | |
965 | void Demangler::memorizeIdentifier(IdentifierNode *Identifier) { |
966 | |
967 | |
968 | OutputStream OS; |
969 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) |
970 | |
971 | std::terminate(); |
972 | Identifier->output(OS, OF_Default); |
973 | OS << '\0'; |
974 | char *Name = OS.getBuffer(); |
975 | |
976 | StringView Owned = copyString(Name); |
977 | memorizeString(Owned); |
978 | std::free(Name); |
979 | } |
980 | |
981 | IdentifierNode * |
982 | Demangler::demangleTemplateInstantiationName(StringView &MangledName, |
983 | NameBackrefBehavior NBB) { |
984 | assert(MangledName.startsWith("?$")); |
985 | MangledName.consumeFront("?$"); |
986 | |
987 | BackrefContext OuterContext; |
988 | std::swap(OuterContext, Backrefs); |
989 | |
990 | IdentifierNode *Identifier = |
991 | demangleUnqualifiedSymbolName(MangledName, NBB_Simple); |
992 | if (!Error) |
993 | Identifier->TemplateParams = demangleTemplateParameterList(MangledName); |
994 | |
995 | std::swap(OuterContext, Backrefs); |
996 | if (Error) |
997 | return nullptr; |
998 | |
999 | if (NBB & NBB_Template) { |
1000 | |
1001 | |
1002 | |
1003 | if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier || |
1004 | Identifier->kind() == NodeKind::StructorIdentifier) { |
1005 | Error = true; |
1006 | return nullptr; |
1007 | } |
1008 | |
1009 | memorizeIdentifier(Identifier); |
1010 | } |
1011 | |
1012 | return Identifier; |
1013 | } |
1014 | |
1015 | NamedIdentifierNode *Demangler::demangleSimpleName(StringView &MangledName, |
1016 | bool Memorize) { |
1017 | StringView S = demangleSimpleString(MangledName, Memorize); |
1018 | if (Error) |
1019 | return nullptr; |
1020 | |
1021 | NamedIdentifierNode *Name = Arena.alloc<NamedIdentifierNode>(); |
1022 | Name->Name = S; |
1023 | return Name; |
1024 | } |
1025 | |
1026 | static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); } |
1027 | |
1028 | static uint8_t rebasedHexDigitToNumber(char C) { |
1029 | assert(isRebasedHexDigit(C)); |
1030 | return (C <= 'J') ? (C - 'A') : (10 + C - 'K'); |
1031 | } |
1032 | |
1033 | uint8_t Demangler::demangleCharLiteral(StringView &MangledName) { |
1034 | assert(!MangledName.empty()); |
1035 | if (!MangledName.startsWith('?')) |
1036 | return MangledName.popFront(); |
1037 | |
1038 | MangledName = MangledName.dropFront(); |
1039 | if (MangledName.empty()) |
1040 | goto CharLiteralError; |
1041 | |
1042 | if (MangledName.consumeFront('$')) { |
1043 | |
1044 | if (MangledName.size() < 2) |
1045 | goto CharLiteralError; |
1046 | StringView Nibbles = MangledName.substr(0, 2); |
1047 | if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1])) |
1048 | goto CharLiteralError; |
1049 | |
1050 | uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]); |
1051 | uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]); |
1052 | MangledName = MangledName.dropFront(2); |
1053 | return (C1 << 4) | C2; |
1054 | } |
1055 | |
1056 | if (startsWithDigit(MangledName)) { |
1057 | const char *Lookup = ",/\\:. \n\t'-"; |
1058 | char C = Lookup[MangledName[0] - '0']; |
1059 | MangledName = MangledName.dropFront(); |
1060 | return C; |
1061 | } |
1062 | |
1063 | if (MangledName[0] >= 'a' && MangledName[0] <= 'z') { |
1064 | char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', |
1065 | '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', |
1066 | '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', |
1067 | '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'}; |
1068 | char C = Lookup[MangledName[0] - 'a']; |
1069 | MangledName = MangledName.dropFront(); |
1070 | return C; |
1071 | } |
1072 | |
1073 | if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') { |
1074 | char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', |
1075 | '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', |
1076 | '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', |
1077 | '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'}; |
1078 | char C = Lookup[MangledName[0] - 'A']; |
1079 | MangledName = MangledName.dropFront(); |
1080 | return C; |
1081 | } |
1082 | |
1083 | CharLiteralError: |
1084 | Error = true; |
1085 | return '\0'; |
1086 | } |
1087 | |
1088 | wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) { |
1089 | uint8_t C1, C2; |
1090 | |
1091 | C1 = demangleCharLiteral(MangledName); |
1092 | if (Error || MangledName.empty()) |
1093 | goto WCharLiteralError; |
1094 | C2 = demangleCharLiteral(MangledName); |
1095 | if (Error) |
1096 | goto WCharLiteralError; |
1097 | |
1098 | return ((wchar_t)C1 << 8) | (wchar_t)C2; |
1099 | |
1100 | WCharLiteralError: |
1101 | Error = true; |
1102 | return L'\0'; |
1103 | } |
1104 | |
1105 | static void writeHexDigit(char *Buffer, uint8_t Digit) { |
1106 | assert(Digit <= 15); |
1107 | *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10); |
1108 | } |
1109 | |
1110 | static void outputHex(OutputStream &OS, unsigned C) { |
1111 | assert (C != 0); |
1112 | |
1113 | |
1114 | |
1115 | |
1116 | |
1117 | |
1118 | char TempBuffer[17]; |
1119 | |
1120 | ::memset(TempBuffer, 0, sizeof(TempBuffer)); |
1121 | constexpr int MaxPos = sizeof(TempBuffer) - 1; |
1122 | |
1123 | int Pos = MaxPos - 1; |
1124 | while (C != 0) { |
1125 | for (int I = 0; I < 2; ++I) { |
1126 | writeHexDigit(&TempBuffer[Pos--], C % 16); |
1127 | C /= 16; |
1128 | } |
1129 | } |
1130 | TempBuffer[Pos--] = 'x'; |
1131 | assert(Pos >= 0); |
1132 | TempBuffer[Pos--] = '\\'; |
1133 | OS << StringView(&TempBuffer[Pos + 1]); |
1134 | } |
1135 | |
1136 | static void outputEscapedChar(OutputStream &OS, unsigned C) { |
1137 | switch (C) { |
1138 | case '\0': |
1139 | OS << "\\0"; |
1140 | return; |
1141 | case '\'': |
1142 | OS << "\\\'"; |
1143 | return; |
1144 | case '\"': |
1145 | OS << "\\\""; |
1146 | return; |
1147 | case '\\': |
1148 | OS << "\\\\"; |
1149 | return; |
1150 | case '\a': |
1151 | OS << "\\a"; |
1152 | return; |
1153 | case '\b': |
1154 | OS << "\\b"; |
1155 | return; |
1156 | case '\f': |
1157 | OS << "\\f"; |
1158 | return; |
1159 | case '\n': |
1160 | OS << "\\n"; |
1161 | return; |
1162 | case '\r': |
1163 | OS << "\\r"; |
1164 | return; |
1165 | case '\t': |
1166 | OS << "\\t"; |
1167 | return; |
1168 | case '\v': |
1169 | OS << "\\v"; |
1170 | return; |
1171 | default: |
1172 | break; |
1173 | } |
1174 | |
1175 | if (C > 0x1F && C < 0x7F) { |
1176 | |
1177 | OS << (char)C; |
1178 | return; |
1179 | } |
1180 | |
1181 | outputHex(OS, C); |
1182 | } |
1183 | |
1184 | static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) { |
1185 | const uint8_t *End = StringBytes + Length - 1; |
1186 | unsigned Count = 0; |
1187 | while (Length > 0 && *End == 0) { |
1188 | --Length; |
1189 | --End; |
1190 | ++Count; |
1191 | } |
1192 | return Count; |
1193 | } |
1194 | |
1195 | static unsigned countEmbeddedNulls(const uint8_t *StringBytes, |
1196 | unsigned Length) { |
1197 | unsigned Result = 0; |
1198 | for (unsigned I = 0; I < Length; ++I) { |
1199 | if (*StringBytes++ == 0) |
1200 | ++Result; |
1201 | } |
1202 | return Result; |
1203 | } |
1204 | |
1205 | |
1206 | |
1207 | |
1208 | static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars, |
1209 | uint64_t NumBytes) { |
1210 | assert(NumBytes > 0); |
1211 | |
1212 | |
1213 | if (NumBytes % 2 == 1) |
1214 | return 1; |
1215 | |
1216 | |
1217 | |
1218 | |
1219 | if (NumBytes < 32) { |
1220 | unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars); |
1221 | if (TrailingNulls >= 4 && NumBytes % 4 == 0) |
1222 | return 4; |
1223 | if (TrailingNulls >= 2) |
1224 | return 2; |
1225 | return 1; |
1226 | } |
1227 | |
1228 | |
1229 | |
1230 | |
1231 | |
1232 | |
1233 | |
1234 | unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars); |
1235 | if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0) |
1236 | return 4; |
1237 | if (Nulls >= NumChars / 3) |
1238 | return 2; |
1239 | return 1; |
1240 | } |
1241 | |
1242 | static unsigned decodeMultiByteChar(const uint8_t *StringBytes, |
1243 | unsigned CharIndex, unsigned CharBytes) { |
1244 | assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4); |
1245 | unsigned Offset = CharIndex * CharBytes; |
1246 | unsigned Result = 0; |
1247 | StringBytes = StringBytes + Offset; |
1248 | for (unsigned I = 0; I < CharBytes; ++I) { |
1249 | unsigned C = static_cast<unsigned>(StringBytes[I]); |
1250 | Result |= C << (8 * I); |
1251 | } |
1252 | return Result; |
1253 | } |
1254 | |
1255 | FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) { |
1256 | FunctionSymbolNode *FSN = Arena.alloc<FunctionSymbolNode>(); |
1257 | VcallThunkIdentifierNode *VTIN = Arena.alloc<VcallThunkIdentifierNode>(); |
1258 | FSN->Signature = Arena.alloc<ThunkSignatureNode>(); |
1259 | FSN->Signature->FunctionClass = FC_NoParameterList; |
1260 | |
1261 | FSN->Name = demangleNameScopeChain(MangledName, VTIN); |
1262 | if (!Error) |
1263 | Error = !MangledName.consumeFront("$B"); |
1264 | if (!Error) |
1265 | VTIN->OffsetInVTable = demangleUnsigned(MangledName); |
1266 | if (!Error) |
1267 | Error = !MangledName.consumeFront('A'); |
1268 | if (!Error) |
1269 | FSN->Signature->CallConvention = demangleCallingConvention(MangledName); |
1270 | return (Error) ? nullptr : FSN; |
1271 | } |
1272 | |
1273 | EncodedStringLiteralNode * |
1274 | Demangler::demangleStringLiteral(StringView &MangledName) { |
1275 | |
1276 | OutputStream OS; |
1277 | StringView CRC; |
1278 | uint64_t StringByteSize; |
1279 | bool IsWcharT = false; |
1280 | bool IsNegative = false; |
1281 | size_t CrcEndPos = 0; |
1282 | char *ResultBuffer = nullptr; |
1283 | |
1284 | EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>(); |
1285 | |
1286 | |
1287 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) |
1288 | |
1289 | std::terminate(); |
1290 | |
1291 | |
1292 | if (!MangledName.consumeFront("@_")) |
1293 | goto StringLiteralError; |
1294 | if (MangledName.empty()) |
1295 | goto StringLiteralError; |
1296 | |
1297 | |
1298 | switch (MangledName.popFront()) { |
1299 | case '1': |
1300 | IsWcharT = true; |
1301 | DEMANGLE_FALLTHROUGH; |
1302 | case '0': |
1303 | break; |
1304 | default: |
1305 | goto StringLiteralError; |
1306 | } |
1307 | |
1308 | |
1309 | std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName); |
1310 | if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1)) |
1311 | goto StringLiteralError; |
1312 | |
1313 | |
1314 | CrcEndPos = MangledName.find('@'); |
1315 | if (CrcEndPos == StringView::npos) |
1316 | goto StringLiteralError; |
1317 | CRC = MangledName.substr(0, CrcEndPos); |
1318 | MangledName = MangledName.dropFront(CrcEndPos + 1); |
1319 | if (MangledName.empty()) |
1320 | goto StringLiteralError; |
1321 | |
1322 | if (IsWcharT) { |
1323 | Result->Char = CharKind::Wchar; |
1324 | if (StringByteSize > 64) |
1325 | Result->IsTruncated = true; |
1326 | |
1327 | while (!MangledName.consumeFront('@')) { |
1328 | if (MangledName.size() < 2) |
1329 | goto StringLiteralError; |
1330 | wchar_t W = demangleWcharLiteral(MangledName); |
1331 | if (StringByteSize != 2 || Result->IsTruncated) |
1332 | outputEscapedChar(OS, W); |
1333 | StringByteSize -= 2; |
1334 | if (Error) |
1335 | goto StringLiteralError; |
1336 | } |
1337 | } else { |
1338 | |
1339 | |
1340 | constexpr unsigned MaxStringByteLength = 32 * 4; |
1341 | uint8_t StringBytes[MaxStringByteLength]; |
1342 | |
1343 | unsigned BytesDecoded = 0; |
1344 | while (!MangledName.consumeFront('@')) { |
1345 | if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength) |
1346 | goto StringLiteralError; |
1347 | StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName); |
1348 | } |
1349 | |
1350 | if (StringByteSize > BytesDecoded) |
1351 | Result->IsTruncated = true; |
1352 | |
1353 | unsigned CharBytes = |
1354 | guessCharByteSize(StringBytes, BytesDecoded, StringByteSize); |
1355 | assert(StringByteSize % CharBytes == 0); |
1356 | switch (CharBytes) { |
1357 | case 1: |
1358 | Result->Char = CharKind::Char; |
1359 | break; |
1360 | case 2: |
1361 | Result->Char = CharKind::Char16; |
1362 | break; |
1363 | case 4: |
1364 | Result->Char = CharKind::Char32; |
1365 | break; |
1366 | default: |
1367 | DEMANGLE_UNREACHABLE; |
1368 | } |
1369 | const unsigned NumChars = BytesDecoded / CharBytes; |
1370 | for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) { |
1371 | unsigned NextChar = |
1372 | decodeMultiByteChar(StringBytes, CharIndex, CharBytes); |
1373 | if (CharIndex + 1 < NumChars || Result->IsTruncated) |
1374 | outputEscapedChar(OS, NextChar); |
1375 | } |
1376 | } |
1377 | |
1378 | OS << '\0'; |
1379 | ResultBuffer = OS.getBuffer(); |
1380 | Result->DecodedString = copyString(ResultBuffer); |
1381 | std::free(ResultBuffer); |
1382 | return Result; |
1383 | |
1384 | StringLiteralError: |
1385 | Error = true; |
1386 | std::free(OS.getBuffer()); |
1387 | return nullptr; |
1388 | } |
1389 | |
1390 | |
1391 | |
1392 | StringView Demangler::demangleSimpleString(StringView &MangledName, |
1393 | bool Memorize) { |
1394 | StringView S; |
1395 | for (size_t i = 0; i < MangledName.size(); ++i) { |
1396 | if (MangledName[i] != '@') |
1397 | continue; |
1398 | if (i == 0) |
1399 | break; |
1400 | S = MangledName.substr(0, i); |
1401 | MangledName = MangledName.dropFront(i + 1); |
1402 | |
1403 | if (Memorize) |
1404 | memorizeString(S); |
1405 | return S; |
1406 | } |
1407 | |
1408 | Error = true; |
1409 | return {}; |
1410 | } |
1411 | |
1412 | NamedIdentifierNode * |
1413 | Demangler::demangleAnonymousNamespaceName(StringView &MangledName) { |
1414 | assert(MangledName.startsWith("?A")); |
1415 | MangledName.consumeFront("?A"); |
1416 | |
1417 | NamedIdentifierNode *Node = Arena.alloc<NamedIdentifierNode>(); |
1418 | Node->Name = "`anonymous namespace'"; |
1419 | size_t EndPos = MangledName.find('@'); |
1420 | if (EndPos == StringView::npos) { |
1421 | Error = true; |
1422 | return nullptr; |
1423 | } |
1424 | StringView NamespaceKey = MangledName.substr(0, EndPos); |
1425 | memorizeString(NamespaceKey); |
1426 | MangledName = MangledName.substr(EndPos + 1); |
1427 | return Node; |
1428 | } |
1429 | |
1430 | NamedIdentifierNode * |
1431 | Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) { |
1432 | assert(startsWithLocalScopePattern(MangledName)); |
1433 | |
1434 | NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>(); |
1435 | MangledName.consumeFront('?'); |
1436 | uint64_t Number = 0; |
1437 | bool IsNegative = false; |
1438 | std::tie(Number, IsNegative) = demangleNumber(MangledName); |
1439 | assert(!IsNegative); |
1440 | |
1441 | |
1442 | MangledName.consumeFront('?'); |
1443 | |
1444 | assert(!Error); |
1445 | Node *Scope = parse(MangledName); |
1446 | if (Error) |
1447 | return nullptr; |
1448 | |
1449 | |
1450 | OutputStream OS; |
1451 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) |
1452 | |
1453 | std::terminate(); |
1454 | OS << '`'; |
1455 | Scope->output(OS, OF_Default); |
1456 | OS << '\''; |
1457 | OS << "::`" << Number << "'"; |
1458 | OS << '\0'; |
1459 | char *Result = OS.getBuffer(); |
1460 | Identifier->Name = copyString(Result); |
1461 | std::free(Result); |
1462 | return Identifier; |
1463 | } |
1464 | |
1465 | |
1466 | QualifiedNameNode * |
1467 | Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) { |
1468 | IdentifierNode *Identifier = |
1469 | demangleUnqualifiedTypeName(MangledName, true); |
1470 | if (Error) |
1471 | return nullptr; |
1472 | assert(Identifier); |
1473 | |
1474 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier); |
1475 | if (Error) |
1476 | return nullptr; |
1477 | assert(QN); |
1478 | return QN; |
1479 | } |
1480 | |
1481 | |
1482 | |
1483 | |
1484 | QualifiedNameNode * |
1485 | Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) { |
1486 | |
1487 | |
1488 | |
1489 | |
1490 | |
1491 | IdentifierNode *Identifier = |
1492 | demangleUnqualifiedSymbolName(MangledName, NBB_Simple); |
1493 | if (Error) |
1494 | return nullptr; |
1495 | |
1496 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier); |
1497 | if (Error) |
1498 | return nullptr; |
1499 | |
1500 | if (Identifier->kind() == NodeKind::StructorIdentifier) { |
1501 | if (QN->Components->Count < 2) { |
1502 | Error = true; |
1503 | return nullptr; |
1504 | } |
1505 | StructorIdentifierNode *SIN = |
1506 | static_cast<StructorIdentifierNode *>(Identifier); |
1507 | Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2]; |
1508 | SIN->Class = static_cast<IdentifierNode *>(ClassNode); |
1509 | } |
1510 | assert(QN); |
1511 | return QN; |
1512 | } |
1513 | |
1514 | IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName, |
1515 | bool Memorize) { |
1516 | |
1517 | |
1518 | |
1519 | |
1520 | if (startsWithDigit(MangledName)) |
1521 | return demangleBackRefName(MangledName); |
1522 | |
1523 | if (MangledName.startsWith("?$")) |
1524 | return demangleTemplateInstantiationName(MangledName, NBB_Template); |
1525 | |
1526 | return demangleSimpleName(MangledName, Memorize); |
1527 | } |
1528 | |
1529 | IdentifierNode * |
1530 | Demangler::demangleUnqualifiedSymbolName(StringView &MangledName, |
1531 | NameBackrefBehavior NBB) { |
1532 | if (startsWithDigit(MangledName)) |
1533 | return demangleBackRefName(MangledName); |
1534 | if (MangledName.startsWith("?$")) |
1535 | return demangleTemplateInstantiationName(MangledName, NBB); |
1536 | if (MangledName.startsWith('?')) |
1537 | return demangleFunctionIdentifierCode(MangledName); |
1538 | return demangleSimpleName(MangledName, (NBB & NBB_Simple) != 0); |
1539 | } |
1540 | |
1541 | IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) { |
1542 | if (startsWithDigit(MangledName)) |
1543 | return demangleBackRefName(MangledName); |
1544 | |
1545 | if (MangledName.startsWith("?$")) |
1546 | return demangleTemplateInstantiationName(MangledName, NBB_Template); |
1547 | |
1548 | if (MangledName.startsWith("?A")) |
1549 | return demangleAnonymousNamespaceName(MangledName); |
1550 | |
1551 | if (startsWithLocalScopePattern(MangledName)) |
1552 | return demangleLocallyScopedNamePiece(MangledName); |
1553 | |
1554 | return demangleSimpleName(MangledName, true); |
1555 | } |
1556 | |
1557 | static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, |
1558 | size_t Count) { |
1559 | NodeArrayNode *N = Arena.alloc<NodeArrayNode>(); |
1560 | N->Count = Count; |
1561 | N->Nodes = Arena.allocArray<Node *>(Count); |
1562 | for (size_t I = 0; I < Count; ++I) { |
1563 | N->Nodes[I] = Head->N; |
1564 | Head = Head->Next; |
1565 | } |
1566 | return N; |
1567 | } |
1568 | |
1569 | QualifiedNameNode * |
1570 | Demangler::demangleNameScopeChain(StringView &MangledName, |
1571 | IdentifierNode *UnqualifiedName) { |
1572 | NodeList *Head = Arena.alloc<NodeList>(); |
1573 | |
1574 | Head->N = UnqualifiedName; |
1575 | |
1576 | size_t Count = 1; |
1577 | while (!MangledName.consumeFront("@")) { |
1578 | ++Count; |
1579 | NodeList *NewHead = Arena.alloc<NodeList>(); |
1580 | NewHead->Next = Head; |
1581 | Head = NewHead; |
1582 | |
1583 | if (MangledName.empty()) { |
1584 | Error = true; |
1585 | return nullptr; |
1586 | } |
1587 | |
1588 | assert(!Error); |
1589 | IdentifierNode *Elem = demangleNameScopePiece(MangledName); |
1590 | if (Error) |
1591 | return nullptr; |
1592 | |
1593 | Head->N = Elem; |
1594 | } |
1595 | |
1596 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); |
1597 | QN->Components = nodeListToNodeArray(Arena, Head, Count); |
1598 | return QN; |
1599 | } |
1600 | |
1601 | FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { |
1602 | switch (MangledName.popFront()) { |
1603 | case '9': |
1604 | return FuncClass(FC_ExternC | FC_NoParameterList); |
1605 | case 'A': |
1606 | return FC_Private; |
1607 | case 'B': |
1608 | return FuncClass(FC_Private | FC_Far); |
1609 | case 'C': |
1610 | return FuncClass(FC_Private | FC_Static); |
1611 | case 'D': |
1612 | return FuncClass(FC_Private | FC_Static | FC_Far); |
1613 | case 'E': |
1614 | return FuncClass(FC_Private | FC_Virtual); |
1615 | case 'F': |
1616 | return FuncClass(FC_Private | FC_Virtual | FC_Far); |
1617 | case 'G': |
1618 | return FuncClass(FC_Private | FC_StaticThisAdjust); |
1619 | case 'H': |
1620 | return FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far); |
1621 | case 'I': |
1622 | return FuncClass(FC_Protected); |
1623 | case 'J': |
1624 | return FuncClass(FC_Protected | FC_Far); |
1625 | case 'K': |
1626 | return FuncClass(FC_Protected | FC_Static); |
1627 | case 'L': |
1628 | return FuncClass(FC_Protected | FC_Static | FC_Far); |
1629 | case 'M': |
1630 | return FuncClass(FC_Protected | FC_Virtual); |
1631 | case 'N': |
1632 | return FuncClass(FC_Protected | FC_Virtual | FC_Far); |
1633 | case 'O': |
1634 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust); |
1635 | case 'P': |
1636 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far); |
1637 | case 'Q': |
1638 | return FuncClass(FC_Public); |
1639 | case 'R': |
1640 | return FuncClass(FC_Public | FC_Far); |
1641 | case 'S': |
1642 | return FuncClass(FC_Public | FC_Static); |
1643 | case 'T': |
1644 | return FuncClass(FC_Public | FC_Static | FC_Far); |
1645 | case 'U': |
1646 | return FuncClass(FC_Public | FC_Virtual); |
1647 | case 'V': |
1648 | return FuncClass(FC_Public | FC_Virtual | FC_Far); |
1649 | case 'W': |
1650 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust); |
1651 | case 'X': |
1652 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far); |
1653 | case 'Y': |
1654 | return FuncClass(FC_Global); |
1655 | case 'Z': |
1656 | return FuncClass(FC_Global | FC_Far); |
1657 | case '$': { |
1658 | FuncClass VFlag = FC_VirtualThisAdjust; |
1659 | if (MangledName.consumeFront('R')) |
1660 | VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx); |
1661 | if (MangledName.empty()) |
1662 | break; |
1663 | switch (MangledName.popFront()) { |
1664 | case '0': |
1665 | return FuncClass(FC_Private | FC_Virtual | VFlag); |
1666 | case '1': |
1667 | return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far); |
1668 | case '2': |
1669 | return FuncClass(FC_Protected | FC_Virtual | VFlag); |
1670 | case '3': |
1671 | return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far); |
1672 | case '4': |
1673 | return FuncClass(FC_Public | FC_Virtual | VFlag); |
1674 | case '5': |
1675 | return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far); |
1676 | } |
1677 | } |
1678 | } |
1679 | |
1680 | Error = true; |
1681 | return FC_Public; |
1682 | } |
1683 | |
1684 | CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { |
1685 | if (MangledName.empty()) { |
1686 | Error = true; |
1687 | return CallingConv::None; |
1688 | } |
1689 | |
1690 | switch (MangledName.popFront()) { |
1691 | case 'A': |
1692 | case 'B': |
1693 | return CallingConv::Cdecl; |
1694 | case 'C': |
1695 | case 'D': |
1696 | return CallingConv::Pascal; |
1697 | case 'E': |
1698 | case 'F': |
1699 | return CallingConv::Thiscall; |
1700 | case 'G': |
1701 | case 'H': |
1702 | return CallingConv::Stdcall; |
1703 | case 'I': |
1704 | case 'J': |
1705 | return CallingConv::Fastcall; |
1706 | case 'M': |
1707 | case 'N': |
1708 | return CallingConv::Clrcall; |
1709 | case 'O': |
1710 | case 'P': |
1711 | return CallingConv::Eabi; |
1712 | case 'Q': |
1713 | return CallingConv::Vectorcall; |
1714 | case 'S': |
1715 | return CallingConv::Swift; |
1716 | case 'W': |
1717 | return CallingConv::SwiftAsync; |
1718 | } |
1719 | |
1720 | return CallingConv::None; |
1721 | } |
1722 | |
1723 | StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) { |
1724 | assert(MangledName.front() >= '0' && MangledName.front() <= '4'); |
1725 | |
1726 | switch (MangledName.popFront()) { |
1727 | case '0': |
1728 | return StorageClass::PrivateStatic; |
1729 | case '1': |
1730 | return StorageClass::ProtectedStatic; |
1731 | case '2': |
1732 | return StorageClass::PublicStatic; |
1733 | case '3': |
1734 | return StorageClass::Global; |
1735 | case '4': |
1736 | return StorageClass::FunctionLocalStatic; |
1737 | } |
1738 | DEMANGLE_UNREACHABLE; |
1739 | } |
1740 | |
1741 | std::pair<Qualifiers, bool> |
1742 | Demangler::demangleQualifiers(StringView &MangledName) { |
1743 | if (MangledName.empty()) { |
1744 | Error = true; |
1745 | return std::make_pair(Q_None, false); |
1746 | } |
1747 | |
1748 | switch (MangledName.popFront()) { |
1749 | |
1750 | case 'Q': |
1751 | return std::make_pair(Q_None, true); |
1752 | case 'R': |
1753 | return std::make_pair(Q_Const, true); |
1754 | case 'S': |
1755 | return std::make_pair(Q_Volatile, true); |
1756 | case 'T': |
1757 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true); |
1758 | |
1759 | case 'A': |
1760 | return std::make_pair(Q_None, false); |
1761 | case 'B': |
1762 | return std::make_pair(Q_Const, false); |
1763 | case 'C': |
1764 | return std::make_pair(Q_Volatile, false); |
1765 | case 'D': |
1766 | return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false); |
1767 | } |
1768 | Error = true; |
1769 | return std::make_pair(Q_None, false); |
1770 | } |
1771 | |
1772 | |
1773 | |
1774 | TypeNode *Demangler::demangleType(StringView &MangledName, |
1775 | QualifierMangleMode QMM) { |
1776 | Qualifiers Quals = Q_None; |
1777 | bool IsMember = false; |
1778 | if (QMM == QualifierMangleMode::Mangle) { |
1779 | std::tie(Quals, IsMember) = demangleQualifiers(MangledName); |
1780 | } else if (QMM == QualifierMangleMode::Result) { |
1781 | if (MangledName.consumeFront('?')) |
1782 | std::tie(Quals, IsMember) = demangleQualifiers(MangledName); |
1783 | } |
1784 | |
1785 | if (MangledName.empty()) { |
1786 | Error = true; |
1787 | return nullptr; |
1788 | } |
1789 | |
1790 | TypeNode *Ty = nullptr; |
1791 | if (isTagType(MangledName)) |
1792 | Ty = demangleClassType(MangledName); |
1793 | else if (isPointerType(MangledName)) { |
1794 | if (isMemberPointer(MangledName, Error)) |
1795 | Ty = demangleMemberPointerType(MangledName); |
1796 | else if (!Error) |
1797 | Ty = demanglePointerType(MangledName); |
1798 | else |
1799 | return nullptr; |
1800 | } else if (isArrayType(MangledName)) |
1801 | Ty = demangleArrayType(MangledName); |
1802 | else if (isFunctionType(MangledName)) { |
1803 | if (MangledName.consumeFront("$$A8@@")) |
1804 | Ty = demangleFunctionType(MangledName, true); |
1805 | else { |
1806 | assert(MangledName.startsWith("$$A6")); |
1807 | MangledName.consumeFront("$$A6"); |
1808 | Ty = demangleFunctionType(MangledName, false); |
1809 | } |
1810 | } else if (isCustomType(MangledName)) { |
1811 | Ty = demangleCustomType(MangledName); |
1812 | } else { |
1813 | Ty = demanglePrimitiveType(MangledName); |
1814 | } |
1815 | |
1816 | if (!Ty || Error) |
1817 | return Ty; |
1818 | Ty->Quals = Qualifiers(Ty->Quals | Quals); |
1819 | return Ty; |
1820 | } |
1821 | |
1822 | bool Demangler::demangleThrowSpecification(StringView &MangledName) { |
1823 | if (MangledName.consumeFront("_E")) |
1824 | return true; |
1825 | if (MangledName.consumeFront('Z')) |
1826 | return false; |
1827 | |
1828 | Error = true; |
1829 | return false; |
1830 | } |
1831 | |
1832 | FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName, |
1833 | bool HasThisQuals) { |
1834 | FunctionSignatureNode *FTy = Arena.alloc<FunctionSignatureNode>(); |
1835 | |
1836 | if (HasThisQuals) { |
1837 | FTy->Quals = demanglePointerExtQualifiers(MangledName); |
1838 | FTy->RefQualifier = demangleFunctionRefQualifier(MangledName); |
1839 | FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first); |
1840 | } |
1841 | |
1842 | |
1843 | FTy->CallConvention = demangleCallingConvention(MangledName); |
1844 | |
1845 | |
1846 | |
1847 | bool IsStructor = MangledName.consumeFront('@'); |
1848 | if (!IsStructor) |
1849 | FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result); |
1850 | |
1851 | FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic); |
1852 | |
1853 | FTy->IsNoexcept = demangleThrowSpecification(MangledName); |
1854 | |
1855 | return FTy; |
1856 | } |
1857 | |
1858 | FunctionSymbolNode * |
1859 | Demangler::demangleFunctionEncoding(StringView &MangledName) { |
1860 | FuncClass ExtraFlags = FC_None; |
1861 | if (MangledName.consumeFront("$$J0")) |
1862 | ExtraFlags = FC_ExternC; |
1863 | |
1864 | if (MangledName.empty()) { |
1865 | Error = true; |
1866 | return nullptr; |
1867 | } |
1868 | |
1869 | FuncClass FC = demangleFunctionClass(MangledName); |
1870 | FC = FuncClass(ExtraFlags | FC); |
1871 | |
1872 | FunctionSignatureNode *FSN = nullptr; |
1873 | ThunkSignatureNode *TTN = nullptr; |
1874 | if (FC & FC_StaticThisAdjust) { |
1875 | TTN = Arena.alloc<ThunkSignatureNode>(); |
1876 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); |
1877 | } else if (FC & FC_VirtualThisAdjust) { |
1878 | TTN = Arena.alloc<ThunkSignatureNode>(); |
1879 | if (FC & FC_VirtualThisAdjustEx) { |
1880 | TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName); |
1881 | TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName); |
1882 | } |
1883 | TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName); |
1884 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); |
1885 | } |
1886 | |
1887 | if (FC & FC_NoParameterList) { |
1888 | |
1889 | |
1890 | |
1891 | FSN = Arena.alloc<FunctionSignatureNode>(); |
1892 | } else { |
1893 | bool HasThisQuals = !(FC & (FC_Global | FC_Static)); |
1894 | FSN = demangleFunctionType(MangledName, HasThisQuals); |
1895 | } |
1896 | |
1897 | if (Error) |
1898 | return nullptr; |
1899 | |
1900 | if (TTN) { |
1901 | *static_cast<FunctionSignatureNode *>(TTN) = *FSN; |
1902 | FSN = TTN; |
1903 | } |
1904 | FSN->FunctionClass = FC; |
1905 | |
1906 | FunctionSymbolNode *Symbol = Arena.alloc<FunctionSymbolNode>(); |
1907 | Symbol->Signature = FSN; |
1908 | return Symbol; |
1909 | } |
1910 | |
1911 | CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) { |
1912 | assert(MangledName.startsWith('?')); |
1913 | MangledName.popFront(); |
1914 | |
1915 | CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>(); |
1916 | CTN->Identifier = demangleUnqualifiedTypeName(MangledName, true); |
1917 | if (!MangledName.consumeFront('@')) |
1918 | Error = true; |
1919 | if (Error) |
1920 | return nullptr; |
1921 | return CTN; |
1922 | } |
1923 | |
1924 | |
1925 | PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) { |
1926 | if (MangledName.consumeFront("$$T")) |
1927 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr); |
1928 | |
1929 | switch (MangledName.popFront()) { |
1930 | case 'X': |
1931 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Void); |
1932 | case 'D': |
1933 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char); |
1934 | case 'C': |
1935 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Schar); |
1936 | case 'E': |
1937 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uchar); |
1938 | case 'F': |
1939 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Short); |
1940 | case 'G': |
1941 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ushort); |
1942 | case 'H': |
1943 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int); |
1944 | case 'I': |
1945 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint); |
1946 | case 'J': |
1947 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Long); |
1948 | case 'K': |
1949 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ulong); |
1950 | case 'M': |
1951 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Float); |
1952 | case 'N': |
1953 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Double); |
1954 | case 'O': |
1955 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ldouble); |
1956 | case '_': { |
1957 | if (MangledName.empty()) { |
1958 | Error = true; |
1959 | return nullptr; |
1960 | } |
1961 | switch (MangledName.popFront()) { |
1962 | case 'N': |
1963 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Bool); |
1964 | case 'J': |
1965 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int64); |
1966 | case 'K': |
1967 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64); |
1968 | case 'W': |
1969 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar); |
1970 | case 'Q': |
1971 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char8); |
1972 | case 'S': |
1973 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16); |
1974 | case 'U': |
1975 | return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char32); |
1976 | } |
1977 | break; |
1978 | } |
1979 | } |
1980 | Error = true; |
1981 | return nullptr; |
1982 | } |
1983 | |
1984 | TagTypeNode *Demangler::demangleClassType(StringView &MangledName) { |
1985 | TagTypeNode *TT = nullptr; |
1986 | |
1987 | switch (MangledName.popFront()) { |
1988 | case 'T': |
1989 | TT = Arena.alloc<TagTypeNode>(TagKind::Union); |
1990 | break; |
1991 | case 'U': |
1992 | TT = Arena.alloc<TagTypeNode>(TagKind::Struct); |
1993 | break; |
1994 | case 'V': |
1995 | TT = Arena.alloc<TagTypeNode>(TagKind::Class); |
1996 | break; |
1997 | case 'W': |
1998 | if (!MangledName.consumeFront('4')) { |
1999 | Error = true; |
2000 | return nullptr; |
2001 | } |
2002 | TT = Arena.alloc<TagTypeNode>(TagKind::Enum); |
2003 | break; |
2004 | default: |
2005 | assert(false); |
2006 | } |
2007 | |
2008 | TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName); |
2009 | return TT; |
2010 | } |
2011 | |
2012 | |
2013 | |
2014 | PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) { |
2015 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); |
2016 | |
2017 | std::tie(Pointer->Quals, Pointer->Affinity) = |
2018 | demanglePointerCVQualifiers(MangledName); |
2019 | |
2020 | if (MangledName.consumeFront("6")) { |
2021 | Pointer->Pointee = demangleFunctionType(MangledName, false); |
2022 | return Pointer; |
2023 | } |
2024 | |
2025 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); |
2026 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); |
2027 | |
2028 | Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle); |
2029 | return Pointer; |
2030 | } |
2031 | |
2032 | PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { |
2033 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); |
2034 | |
2035 | std::tie(Pointer->Quals, Pointer->Affinity) = |
2036 | demanglePointerCVQualifiers(MangledName); |
2037 | assert(Pointer->Affinity == PointerAffinity::Pointer); |
2038 | |
2039 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); |
2040 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); |
2041 | |
2042 | |
2043 | |
2044 | if (MangledName.consumeFront("8")) { |
2045 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); |
2046 | Pointer->Pointee = demangleFunctionType(MangledName, true); |
2047 | } else { |
2048 | Qualifiers PointeeQuals = Q_None; |
2049 | bool IsMember = false; |
2050 | std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName); |
2051 | assert(IsMember || Error); |
2052 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); |
2053 | |
2054 | Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop); |
2055 | if (Pointer->Pointee) |
2056 | Pointer->Pointee->Quals = PointeeQuals; |
2057 | } |
2058 | |
2059 | return Pointer; |
2060 | } |
2061 | |
2062 | Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) { |
2063 | Qualifiers Quals = Q_None; |
2064 | if (MangledName.consumeFront('E')) |
2065 | Quals = Qualifiers(Quals | Q_Pointer64); |
2066 | if (MangledName.consumeFront('I')) |
2067 | Quals = Qualifiers(Quals | Q_Restrict); |
2068 | if (MangledName.consumeFront('F')) |
2069 | Quals = Qualifiers(Quals | Q_Unaligned); |
2070 | |
2071 | return Quals; |
2072 | } |
2073 | |
2074 | ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) { |
2075 | assert(MangledName.front() == 'Y'); |
2076 | MangledName.popFront(); |
2077 | |
2078 | uint64_t Rank = 0; |
2079 | bool IsNegative = false; |
2080 | std::tie(Rank, IsNegative) = demangleNumber(MangledName); |
2081 | if (IsNegative || Rank == 0) { |
2082 | Error = true; |
2083 | return nullptr; |
2084 | } |
2085 | |
2086 | ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>(); |
2087 | NodeList *Head = Arena.alloc<NodeList>(); |
2088 | NodeList *Tail = Head; |
2089 | |
2090 | for (uint64_t I = 0; I < Rank; ++I) { |
2091 | uint64_t D = 0; |
2092 | std::tie(D, IsNegative) = demangleNumber(MangledName); |
2093 | if (Error || IsNegative) { |
2094 | Error = true; |
2095 | return nullptr; |
2096 | } |
2097 | Tail->N = Arena.alloc<IntegerLiteralNode>(D, IsNegative); |
2098 | if (I + 1 < Rank) { |
2099 | Tail->Next = Arena.alloc<NodeList>(); |
2100 | Tail = Tail->Next; |
2101 | } |
2102 | } |
2103 | ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank); |
2104 | |
2105 | if (MangledName.consumeFront("$$C")) { |
2106 | bool IsMember = false; |
2107 | std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName); |
2108 | if (IsMember) { |
2109 | Error = true; |
2110 | return nullptr; |
2111 | } |
2112 | } |
2113 | |
2114 | ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop); |
2115 | return ATy; |
2116 | } |
2117 | |
2118 | |
2119 | NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName, |
2120 | bool &IsVariadic) { |
2121 | |
2122 | if (MangledName.consumeFront('X')) |
2123 | return nullptr; |
2124 | |
2125 | NodeList *Head = Arena.alloc<NodeList>(); |
2126 | NodeList **Current = &Head; |
2127 | size_t Count = 0; |
2128 | while (!Error && !MangledName.startsWith('@') && |
2129 | !MangledName.startsWith('Z')) { |
2130 | ++Count; |
2131 | |
2132 | if (startsWithDigit(MangledName)) { |
2133 | size_t N = MangledName[0] - '0'; |
2134 | if (N >= Backrefs.FunctionParamCount) { |
2135 | Error = true; |
2136 | return nullptr; |
2137 | } |
2138 | MangledName = MangledName.dropFront(); |
2139 | |
2140 | *Current = Arena.alloc<NodeList>(); |
2141 | (*Current)->N = Backrefs.FunctionParams[N]; |
2142 | Current = &(*Current)->Next; |
2143 | continue; |
2144 | } |
2145 | |
2146 | size_t OldSize = MangledName.size(); |
2147 | |
2148 | *Current = Arena.alloc<NodeList>(); |
2149 | TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop); |
2150 | if (!TN || Error) |
2151 | return nullptr; |
2152 | |
2153 | (*Current)->N = TN; |
2154 | |
2155 | size_t CharsConsumed = OldSize - MangledName.size(); |
2156 | assert(CharsConsumed != 0); |
2157 | |
2158 | |
2159 | |
2160 | if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1) |
2161 | Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN; |
2162 | |
2163 | Current = &(*Current)->Next; |
2164 | } |
2165 | |
2166 | if (Error) |
2167 | return nullptr; |
2168 | |
2169 | NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count); |
2170 | |
2171 | |
2172 | |
2173 | if (MangledName.consumeFront('@')) |
2174 | return NA; |
2175 | |
2176 | if (MangledName.consumeFront('Z')) { |
2177 | IsVariadic = true; |
2178 | return NA; |
2179 | } |
2180 | |
2181 | DEMANGLE_UNREACHABLE; |
2182 | } |
2183 | |
2184 | NodeArrayNode * |
2185 | Demangler::demangleTemplateParameterList(StringView &MangledName) { |
2186 | NodeList *Head = nullptr; |
2187 | NodeList **Current = &Head; |
2188 | size_t Count = 0; |
2189 | |
2190 | while (!MangledName.startsWith('@')) { |
2191 | if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || |
2192 | MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) { |
2193 | |
2194 | continue; |
2195 | } |
2196 | |
2197 | ++Count; |
2198 | |
2199 | |
2200 | *Current = Arena.alloc<NodeList>(); |
2201 | |
2202 | NodeList &TP = **Current; |
2203 | |
2204 | TemplateParameterReferenceNode *TPRN = nullptr; |
2205 | if (MangledName.consumeFront("$$Y")) { |
2206 | |
2207 | TP.N = demangleFullyQualifiedTypeName(MangledName); |
2208 | } else if (MangledName.consumeFront("$$B")) { |
2209 | |
2210 | TP.N = demangleType(MangledName, QualifierMangleMode::Drop); |
2211 | } else if (MangledName.consumeFront("$$C")) { |
2212 | |
2213 | TP.N = demangleType(MangledName, QualifierMangleMode::Mangle); |
2214 | } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") || |
2215 | MangledName.startsWith("$I") || MangledName.startsWith("$J")) { |
2216 | |
2217 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); |
2218 | TPRN->IsMemberPointer = true; |
2219 | |
2220 | MangledName = MangledName.dropFront(); |
2221 | |
2222 | |
2223 | |
2224 | |
2225 | char InheritanceSpecifier = MangledName.popFront(); |
2226 | SymbolNode *S = nullptr; |
2227 | if (MangledName.startsWith('?')) { |
2228 | S = parse(MangledName); |
2229 | if (Error || !S->Name) { |
2230 | Error = true; |
2231 | return nullptr; |
2232 | } |
2233 | memorizeIdentifier(S->Name->getUnqualifiedIdentifier()); |
2234 | } |
2235 | |
2236 | switch (InheritanceSpecifier) { |
2237 | case 'J': |
2238 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2239 | demangleSigned(MangledName); |
2240 | DEMANGLE_FALLTHROUGH; |
2241 | case 'I': |
2242 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2243 | demangleSigned(MangledName); |
2244 | DEMANGLE_FALLTHROUGH; |
2245 | case 'H': |
2246 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2247 | demangleSigned(MangledName); |
2248 | DEMANGLE_FALLTHROUGH; |
2249 | case '1': |
2250 | break; |
2251 | default: |
2252 | DEMANGLE_UNREACHABLE; |
2253 | } |
2254 | TPRN->Affinity = PointerAffinity::Pointer; |
2255 | TPRN->Symbol = S; |
2256 | } else if (MangledName.startsWith("$E?")) { |
2257 | MangledName.consumeFront("$E"); |
2258 | |
2259 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); |
2260 | TPRN->Symbol = parse(MangledName); |
2261 | TPRN->Affinity = PointerAffinity::Reference; |
2262 | } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) { |
2263 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); |
2264 | |
2265 | |
2266 | MangledName = MangledName.dropFront(); |
2267 | char InheritanceSpecifier = MangledName.popFront(); |
2268 | |
2269 | switch (InheritanceSpecifier) { |
2270 | case 'G': |
2271 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2272 | demangleSigned(MangledName); |
2273 | DEMANGLE_FALLTHROUGH; |
2274 | case 'F': |
2275 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2276 | demangleSigned(MangledName); |
2277 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2278 | demangleSigned(MangledName); |
2279 | break; |
2280 | default: |
2281 | DEMANGLE_UNREACHABLE; |
2282 | } |
2283 | TPRN->IsMemberPointer = true; |
2284 | |
2285 | } else if (MangledName.consumeFront("$0")) { |
2286 | |
2287 | bool IsNegative = false; |
2288 | uint64_t Value = 0; |
2289 | std::tie(Value, IsNegative) = demangleNumber(MangledName); |
2290 | |
2291 | TP.N = Arena.alloc<IntegerLiteralNode>(Value, IsNegative); |
2292 | } else { |
2293 | TP.N = demangleType(MangledName, QualifierMangleMode::Drop); |
2294 | } |
2295 | if (Error) |
2296 | return nullptr; |
2297 | |
2298 | Current = &TP.Next; |
2299 | } |
2300 | |
2301 | |
2302 | assert(!Error); |
2303 | |
2304 | |
2305 | |
2306 | assert(MangledName.startsWith('@')); |
2307 | MangledName.consumeFront('@'); |
2308 | return nodeListToNodeArray(Arena, Head, Count); |
2309 | } |
2310 | |
2311 | void Demangler::dumpBackReferences() { |
2312 | std::printf("%d function parameter backreferences\n", |
2313 | (int)Backrefs.FunctionParamCount); |
2314 | |
2315 | |
2316 | OutputStream OS; |
2317 | if (!initializeOutputStream(nullptr, nullptr, OS, 1024)) |
2318 | std::terminate(); |
2319 | for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) { |
2320 | OS.setCurrentPosition(0); |
2321 | |
2322 | TypeNode *T = Backrefs.FunctionParams[I]; |
2323 | T->output(OS, OF_Default); |
2324 | |
2325 | std::printf(" [%d] - %.*s\n", (int)I, (int)OS.getCurrentPosition(), |
2326 | OS.getBuffer()); |
2327 | } |
2328 | std::free(OS.getBuffer()); |
2329 | |
2330 | if (Backrefs.FunctionParamCount > 0) |
2331 | std::printf("\n"); |
2332 | std::printf("%d name backreferences\n", (int)Backrefs.NamesCount); |
2333 | for (size_t I = 0; I < Backrefs.NamesCount; ++I) { |
2334 | std::printf(" [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(), |
2335 | Backrefs.Names[I]->Name.begin()); |
2336 | } |
2337 | if (Backrefs.NamesCount > 0) |
2338 | std::printf("\n"); |
2339 | } |
2340 | |
2341 | char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled, |
2342 | char *Buf, size_t *N, |
2343 | int *Status, MSDemangleFlags Flags) { |
2344 | Demangler D; |
2345 | OutputStream S; |
2346 | |
2347 | StringView Name{MangledName}; |
2348 | SymbolNode *AST = D.parse(Name); |
| 1 | Calling 'Demangler::parse' | |
|
2349 | if (!D.Error && NMangled) |
2350 | *NMangled = Name.begin() - MangledName; |
2351 | |
2352 | if (Flags & MSDF_DumpBackrefs) |
2353 | D.dumpBackReferences(); |
2354 | |
2355 | OutputFlags OF = OF_Default; |
2356 | if (Flags & MSDF_NoCallingConvention) |
2357 | OF = OutputFlags(OF | OF_NoCallingConvention); |
2358 | if (Flags & MSDF_NoAccessSpecifier) |
2359 | OF = OutputFlags(OF | OF_NoAccessSpecifier); |
2360 | if (Flags & MSDF_NoReturnType) |
2361 | OF = OutputFlags(OF | OF_NoReturnType); |
2362 | if (Flags & MSDF_NoMemberType) |
2363 | OF = OutputFlags(OF | OF_NoMemberType); |
2364 | |
2365 | int InternalStatus = demangle_success; |
2366 | if (D.Error) |
2367 | InternalStatus = demangle_invalid_mangled_name; |
2368 | else if (!initializeOutputStream(Buf, N, S, 1024)) |
2369 | InternalStatus = demangle_memory_alloc_failure; |
2370 | else { |
2371 | AST->output(S, OF); |
2372 | S += '\0'; |
2373 | if (N != nullptr) |
2374 | *N = S.getCurrentPosition(); |
2375 | Buf = S.getBuffer(); |
2376 | } |
2377 | |
2378 | if (Status) |
2379 | *Status = InternalStatus; |
2380 | return InternalStatus == demangle_success ? Buf : nullptr; |
2381 | } |