1 | //===- MicrosoftDemangle.cpp ----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines a demangler for MSVC-style mangled symbols. |
10 | // |
11 | // This file has no dependencies on the rest of LLVM so that it can be |
12 | // easily reused in other programs such as libcxxabi. |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #include "llvm/Demangle/MicrosoftDemangle.h" |
17 | |
18 | #include "llvm/Demangle/Demangle.h" |
19 | #include "llvm/Demangle/DemangleConfig.h" |
20 | #include "llvm/Demangle/MicrosoftDemangleNodes.h" |
21 | #include "llvm/Demangle/StringViewExtras.h" |
22 | #include "llvm/Demangle/Utility.h" |
23 | |
24 | #include <array> |
25 | #include <cctype> |
26 | #include <cstdio> |
27 | #include <optional> |
28 | #include <string_view> |
29 | #include <tuple> |
30 | |
31 | using namespace llvm; |
32 | using namespace ms_demangle; |
33 | |
34 | static bool startsWithDigit(std::string_view S) { |
35 | return !S.empty() && std::isdigit(S.front()); |
36 | } |
37 | |
38 | struct NodeList { |
39 | Node *N = nullptr; |
40 | NodeList *Next = nullptr; |
41 | }; |
42 | |
43 | static bool consumeFront(std::string_view &S, char C) { |
44 | if (!llvm::itanium_demangle::starts_with(self: S, C)) |
45 | return false; |
46 | S.remove_prefix(n: 1); |
47 | return true; |
48 | } |
49 | |
50 | static bool consumeFront(std::string_view &S, std::string_view C) { |
51 | if (!llvm::itanium_demangle::starts_with(haystack: S, needle: C)) |
52 | return false; |
53 | S.remove_prefix(n: C.size()); |
54 | return true; |
55 | } |
56 | |
57 | static bool consumeFront(std::string_view &S, std::string_view PrefixA, |
58 | std::string_view PrefixB, bool A) { |
59 | const std::string_view &Prefix = A ? PrefixA : PrefixB; |
60 | return consumeFront(S, C: Prefix); |
61 | } |
62 | |
63 | static bool startsWith(std::string_view S, std::string_view PrefixA, |
64 | std::string_view PrefixB, bool A) { |
65 | const std::string_view &Prefix = A ? PrefixA : PrefixB; |
66 | return llvm::itanium_demangle::starts_with(haystack: S, needle: Prefix); |
67 | } |
68 | |
69 | bool Demangler::isMemberPointer(std::string_view MangledName, bool &Error) { |
70 | Error = false; |
71 | const char F = MangledName.front(); |
72 | MangledName.remove_prefix(n: 1); |
73 | switch (F) { |
74 | case '$': |
75 | // This is probably an rvalue reference (e.g. $$Q), and you cannot have an |
76 | // rvalue reference to a member. |
77 | return false; |
78 | case 'A': |
79 | // 'A' indicates a reference, and you cannot have a reference to a member |
80 | // function or member. |
81 | return false; |
82 | case 'P': |
83 | case 'Q': |
84 | case 'R': |
85 | case 'S': |
86 | // These 4 values indicate some kind of pointer, but we still don't know |
87 | // what. |
88 | break; |
89 | default: |
90 | // isMemberPointer() is called only if isPointerType() returns true, |
91 | // and it rejects other prefixes. |
92 | DEMANGLE_UNREACHABLE; |
93 | } |
94 | |
95 | // If it starts with a number, then 6 indicates a non-member function |
96 | // pointer, and 8 indicates a member function pointer. |
97 | if (startsWithDigit(S: MangledName)) { |
98 | if (MangledName[0] != '6' && MangledName[0] != '8') { |
99 | Error = true; |
100 | return false; |
101 | } |
102 | return (MangledName[0] == '8'); |
103 | } |
104 | |
105 | // Remove ext qualifiers since those can appear on either type and are |
106 | // therefore not indicative. |
107 | consumeFront(S&: MangledName, C: 'E'); // 64-bit |
108 | consumeFront(S&: MangledName, C: 'I'); // restrict |
109 | consumeFront(S&: MangledName, C: 'F'); // unaligned |
110 | demanglePointerAuthQualifier(MangledName); |
111 | |
112 | if (MangledName.empty()) { |
113 | Error = true; |
114 | return false; |
115 | } |
116 | |
117 | // The next value should be either ABCD (non-member) or QRST (member). |
118 | switch (MangledName.front()) { |
119 | case 'A': |
120 | case 'B': |
121 | case 'C': |
122 | case 'D': |
123 | return false; |
124 | case 'Q': |
125 | case 'R': |
126 | case 'S': |
127 | case 'T': |
128 | return true; |
129 | default: |
130 | Error = true; |
131 | return false; |
132 | } |
133 | } |
134 | |
135 | static SpecialIntrinsicKind |
136 | consumeSpecialIntrinsicKind(std::string_view &MangledName) { |
137 | if (consumeFront(S&: MangledName, C: "?_7" )) |
138 | return SpecialIntrinsicKind::Vftable; |
139 | if (consumeFront(S&: MangledName, C: "?_8" )) |
140 | return SpecialIntrinsicKind::Vbtable; |
141 | if (consumeFront(S&: MangledName, C: "?_9" )) |
142 | return SpecialIntrinsicKind::VcallThunk; |
143 | if (consumeFront(S&: MangledName, C: "?_A" )) |
144 | return SpecialIntrinsicKind::Typeof; |
145 | if (consumeFront(S&: MangledName, C: "?_B" )) |
146 | return SpecialIntrinsicKind::LocalStaticGuard; |
147 | if (consumeFront(S&: MangledName, C: "?_C" )) |
148 | return SpecialIntrinsicKind::StringLiteralSymbol; |
149 | if (consumeFront(S&: MangledName, C: "?_P" )) |
150 | return SpecialIntrinsicKind::UdtReturning; |
151 | if (consumeFront(S&: MangledName, C: "?_R0" )) |
152 | return SpecialIntrinsicKind::RttiTypeDescriptor; |
153 | if (consumeFront(S&: MangledName, C: "?_R1" )) |
154 | return SpecialIntrinsicKind::RttiBaseClassDescriptor; |
155 | if (consumeFront(S&: MangledName, C: "?_R2" )) |
156 | return SpecialIntrinsicKind::RttiBaseClassArray; |
157 | if (consumeFront(S&: MangledName, C: "?_R3" )) |
158 | return SpecialIntrinsicKind::RttiClassHierarchyDescriptor; |
159 | if (consumeFront(S&: MangledName, C: "?_R4" )) |
160 | return SpecialIntrinsicKind::RttiCompleteObjLocator; |
161 | if (consumeFront(S&: MangledName, C: "?_S" )) |
162 | return SpecialIntrinsicKind::LocalVftable; |
163 | if (consumeFront(S&: MangledName, C: "?__E" )) |
164 | return SpecialIntrinsicKind::DynamicInitializer; |
165 | if (consumeFront(S&: MangledName, C: "?__F" )) |
166 | return SpecialIntrinsicKind::DynamicAtexitDestructor; |
167 | if (consumeFront(S&: MangledName, C: "?__J" )) |
168 | return SpecialIntrinsicKind::LocalStaticThreadGuard; |
169 | return SpecialIntrinsicKind::None; |
170 | } |
171 | |
172 | static bool startsWithLocalScopePattern(std::string_view S) { |
173 | if (!consumeFront(S, C: '?')) |
174 | return false; |
175 | |
176 | size_t End = S.find(c: '?'); |
177 | if (End == std::string_view::npos) |
178 | return false; |
179 | std::string_view Candidate = S.substr(pos: 0, n: End); |
180 | if (Candidate.empty()) |
181 | return false; |
182 | |
183 | // \?[0-9]\? |
184 | // ?@? is the discriminator 0. |
185 | if (Candidate.size() == 1) |
186 | return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9'); |
187 | |
188 | // If it's not 0-9, then it's an encoded number terminated with an @ |
189 | if (Candidate.back() != '@') |
190 | return false; |
191 | Candidate.remove_suffix(n: 1); |
192 | |
193 | // An encoded number starts with B-P and all subsequent digits are in A-P. |
194 | // Note that the reason the first digit cannot be A is two fold. First, it |
195 | // would create an ambiguity with ?A which delimits the beginning of an |
196 | // anonymous namespace. Second, A represents 0, and you don't start a multi |
197 | // digit number with a leading 0. Presumably the anonymous namespace |
198 | // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J. |
199 | if (Candidate[0] < 'B' || Candidate[0] > 'P') |
200 | return false; |
201 | Candidate.remove_prefix(n: 1); |
202 | while (!Candidate.empty()) { |
203 | if (Candidate[0] < 'A' || Candidate[0] > 'P') |
204 | return false; |
205 | Candidate.remove_prefix(n: 1); |
206 | } |
207 | |
208 | return true; |
209 | } |
210 | |
211 | static bool isTagType(std::string_view S) { |
212 | switch (S.front()) { |
213 | case 'T': // union |
214 | case 'U': // struct |
215 | case 'V': // class |
216 | case 'W': // enum |
217 | return true; |
218 | } |
219 | return false; |
220 | } |
221 | |
222 | static bool isCustomType(std::string_view S) { return S[0] == '?'; } |
223 | |
224 | static bool isPointerType(std::string_view S) { |
225 | if (llvm::itanium_demangle::starts_with(haystack: S, needle: "$$Q" )) // foo && |
226 | return true; |
227 | |
228 | switch (S.front()) { |
229 | case 'A': // foo & |
230 | case 'P': // foo * |
231 | case 'Q': // foo *const |
232 | case 'R': // foo *volatile |
233 | case 'S': // foo *const volatile |
234 | return true; |
235 | } |
236 | return false; |
237 | } |
238 | |
239 | static bool isArrayType(std::string_view S) { return S[0] == 'Y'; } |
240 | |
241 | static bool isFunctionType(std::string_view S) { |
242 | return llvm::itanium_demangle::starts_with(haystack: S, needle: "$$A8@@" ) || |
243 | llvm::itanium_demangle::starts_with(haystack: S, needle: "$$A6" ); |
244 | } |
245 | |
246 | static FunctionRefQualifier |
247 | demangleFunctionRefQualifier(std::string_view &MangledName) { |
248 | if (consumeFront(S&: MangledName, C: 'G')) |
249 | return FunctionRefQualifier::Reference; |
250 | else if (consumeFront(S&: MangledName, C: 'H')) |
251 | return FunctionRefQualifier::RValueReference; |
252 | return FunctionRefQualifier::None; |
253 | } |
254 | |
255 | static std::pair<Qualifiers, PointerAffinity> |
256 | demanglePointerCVQualifiers(std::string_view &MangledName) { |
257 | if (consumeFront(S&: MangledName, C: "$$Q" )) |
258 | return std::make_pair(x: Q_None, y: PointerAffinity::RValueReference); |
259 | |
260 | const char F = MangledName.front(); |
261 | MangledName.remove_prefix(n: 1); |
262 | switch (F) { |
263 | case 'A': |
264 | return std::make_pair(x: Q_None, y: PointerAffinity::Reference); |
265 | case 'P': |
266 | return std::make_pair(x: Q_None, y: PointerAffinity::Pointer); |
267 | case 'Q': |
268 | return std::make_pair(x: Q_Const, y: PointerAffinity::Pointer); |
269 | case 'R': |
270 | return std::make_pair(x: Q_Volatile, y: PointerAffinity::Pointer); |
271 | case 'S': |
272 | return std::make_pair(x: Qualifiers(Q_Const | Q_Volatile), |
273 | y: PointerAffinity::Pointer); |
274 | } |
275 | // This function is only called if isPointerType() returns true, |
276 | // and it only returns true for the six cases listed above. |
277 | DEMANGLE_UNREACHABLE; |
278 | } |
279 | |
280 | std::string_view Demangler::copyString(std::string_view Borrowed) { |
281 | char *Stable = Arena.allocUnalignedBuffer(Size: Borrowed.size()); |
282 | // This is not a micro-optimization, it avoids UB, should Borrowed be an null |
283 | // buffer. |
284 | if (Borrowed.size()) |
285 | std::memcpy(dest: Stable, src: Borrowed.data(), n: Borrowed.size()); |
286 | |
287 | return {Stable, Borrowed.size()}; |
288 | } |
289 | |
290 | SpecialTableSymbolNode * |
291 | Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName, |
292 | SpecialIntrinsicKind K) { |
293 | NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>(); |
294 | switch (K) { |
295 | case SpecialIntrinsicKind::Vftable: |
296 | NI->Name = "`vftable'" ; |
297 | break; |
298 | case SpecialIntrinsicKind::Vbtable: |
299 | NI->Name = "`vbtable'" ; |
300 | break; |
301 | case SpecialIntrinsicKind::LocalVftable: |
302 | NI->Name = "`local vftable'" ; |
303 | break; |
304 | case SpecialIntrinsicKind::RttiCompleteObjLocator: |
305 | NI->Name = "`RTTI Complete Object Locator'" ; |
306 | break; |
307 | default: |
308 | DEMANGLE_UNREACHABLE; |
309 | } |
310 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, UnqualifiedName: NI); |
311 | SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>(); |
312 | STSN->Name = QN; |
313 | bool IsMember = false; |
314 | if (MangledName.empty()) { |
315 | Error = true; |
316 | return nullptr; |
317 | } |
318 | char Front = MangledName.front(); |
319 | MangledName.remove_prefix(n: 1); |
320 | if (Front != '6' && Front != '7') { |
321 | Error = true; |
322 | return nullptr; |
323 | } |
324 | |
325 | std::tie(args&: STSN->Quals, args&: IsMember) = demangleQualifiers(MangledName); |
326 | if (!consumeFront(S&: MangledName, C: '@')) |
327 | STSN->TargetName = demangleFullyQualifiedTypeName(MangledName); |
328 | return STSN; |
329 | } |
330 | |
331 | LocalStaticGuardVariableNode * |
332 | Demangler::demangleLocalStaticGuard(std::string_view &MangledName, |
333 | bool IsThread) { |
334 | LocalStaticGuardIdentifierNode *LSGI = |
335 | Arena.alloc<LocalStaticGuardIdentifierNode>(); |
336 | LSGI->IsThread = IsThread; |
337 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, UnqualifiedName: LSGI); |
338 | LocalStaticGuardVariableNode *LSGVN = |
339 | Arena.alloc<LocalStaticGuardVariableNode>(); |
340 | LSGVN->Name = QN; |
341 | |
342 | if (consumeFront(S&: MangledName, C: "4IA" )) |
343 | LSGVN->IsVisible = false; |
344 | else if (consumeFront(S&: MangledName, C: "5" )) |
345 | LSGVN->IsVisible = true; |
346 | else { |
347 | Error = true; |
348 | return nullptr; |
349 | } |
350 | |
351 | if (!MangledName.empty()) |
352 | LSGI->ScopeIndex = demangleUnsigned(MangledName); |
353 | return LSGVN; |
354 | } |
355 | |
356 | static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena, |
357 | std::string_view Name) { |
358 | NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>(); |
359 | Id->Name = Name; |
360 | return Id; |
361 | } |
362 | |
363 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, |
364 | IdentifierNode *Identifier) { |
365 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); |
366 | QN->Components = Arena.alloc<NodeArrayNode>(); |
367 | QN->Components->Count = 1; |
368 | QN->Components->Nodes = Arena.allocArray<Node *>(Count: 1); |
369 | QN->Components->Nodes[0] = Identifier; |
370 | return QN; |
371 | } |
372 | |
373 | static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, |
374 | std::string_view Name) { |
375 | NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name); |
376 | return synthesizeQualifiedName(Arena, Identifier: Id); |
377 | } |
378 | |
379 | static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena, |
380 | TypeNode *Type, |
381 | std::string_view VariableName) { |
382 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
383 | VSN->Type = Type; |
384 | VSN->Name = synthesizeQualifiedName(Arena, Name: VariableName); |
385 | return VSN; |
386 | } |
387 | |
388 | VariableSymbolNode * |
389 | Demangler::demangleUntypedVariable(ArenaAllocator &Arena, |
390 | std::string_view &MangledName, |
391 | std::string_view VariableName) { |
392 | NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, Name: VariableName); |
393 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, UnqualifiedName: NI); |
394 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
395 | VSN->Name = QN; |
396 | if (consumeFront(S&: MangledName, C: "8" )) |
397 | return VSN; |
398 | |
399 | Error = true; |
400 | return nullptr; |
401 | } |
402 | |
403 | VariableSymbolNode * |
404 | Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, |
405 | std::string_view &MangledName) { |
406 | RttiBaseClassDescriptorNode *RBCDN = |
407 | Arena.alloc<RttiBaseClassDescriptorNode>(); |
408 | RBCDN->NVOffset = demangleUnsigned(MangledName); |
409 | RBCDN->VBPtrOffset = demangleSigned(MangledName); |
410 | RBCDN->VBTableOffset = demangleUnsigned(MangledName); |
411 | RBCDN->Flags = demangleUnsigned(MangledName); |
412 | if (Error) |
413 | return nullptr; |
414 | |
415 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
416 | VSN->Name = demangleNameScopeChain(MangledName, UnqualifiedName: RBCDN); |
417 | consumeFront(S&: MangledName, C: '8'); |
418 | return VSN; |
419 | } |
420 | |
421 | FunctionSymbolNode * |
422 | Demangler::demangleInitFiniStub(std::string_view &MangledName, |
423 | bool IsDestructor) { |
424 | DynamicStructorIdentifierNode *DSIN = |
425 | Arena.alloc<DynamicStructorIdentifierNode>(); |
426 | DSIN->IsDestructor = IsDestructor; |
427 | |
428 | bool IsKnownStaticDataMember = false; |
429 | if (consumeFront(S&: MangledName, C: '?')) |
430 | IsKnownStaticDataMember = true; |
431 | |
432 | SymbolNode *Symbol = demangleDeclarator(MangledName); |
433 | if (Error) |
434 | return nullptr; |
435 | |
436 | FunctionSymbolNode *FSN = nullptr; |
437 | |
438 | if (Symbol->kind() == NodeKind::VariableSymbol) { |
439 | DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol); |
440 | |
441 | // Older versions of clang mangled this type of symbol incorrectly. They |
442 | // would omit the leading ? and they would only emit a single @ at the end. |
443 | // The correct mangling is a leading ? and 2 trailing @ signs. Handle |
444 | // both cases. |
445 | int AtCount = IsKnownStaticDataMember ? 2 : 1; |
446 | for (int I = 0; I < AtCount; ++I) { |
447 | if (consumeFront(S&: MangledName, C: '@')) |
448 | continue; |
449 | Error = true; |
450 | return nullptr; |
451 | } |
452 | |
453 | FSN = demangleFunctionEncoding(MangledName); |
454 | if (FSN) |
455 | FSN->Name = synthesizeQualifiedName(Arena, Identifier: DSIN); |
456 | } else { |
457 | if (IsKnownStaticDataMember) { |
458 | // This was supposed to be a static data member, but we got a function. |
459 | Error = true; |
460 | return nullptr; |
461 | } |
462 | |
463 | FSN = static_cast<FunctionSymbolNode *>(Symbol); |
464 | DSIN->Name = Symbol->Name; |
465 | FSN->Name = synthesizeQualifiedName(Arena, Identifier: DSIN); |
466 | } |
467 | |
468 | return FSN; |
469 | } |
470 | |
471 | SymbolNode *Demangler::demangleSpecialIntrinsic(std::string_view &MangledName) { |
472 | SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName); |
473 | |
474 | switch (SIK) { |
475 | case SpecialIntrinsicKind::None: |
476 | return nullptr; |
477 | case SpecialIntrinsicKind::StringLiteralSymbol: |
478 | return demangleStringLiteral(MangledName); |
479 | case SpecialIntrinsicKind::Vftable: |
480 | case SpecialIntrinsicKind::Vbtable: |
481 | case SpecialIntrinsicKind::LocalVftable: |
482 | case SpecialIntrinsicKind::RttiCompleteObjLocator: |
483 | return demangleSpecialTableSymbolNode(MangledName, K: SIK); |
484 | case SpecialIntrinsicKind::VcallThunk: |
485 | return demangleVcallThunkNode(MangledName); |
486 | case SpecialIntrinsicKind::LocalStaticGuard: |
487 | return demangleLocalStaticGuard(MangledName, /*IsThread=*/false); |
488 | case SpecialIntrinsicKind::LocalStaticThreadGuard: |
489 | return demangleLocalStaticGuard(MangledName, /*IsThread=*/true); |
490 | case SpecialIntrinsicKind::RttiTypeDescriptor: { |
491 | TypeNode *T = demangleType(MangledName, QMM: QualifierMangleMode::Result); |
492 | if (Error) |
493 | break; |
494 | if (!consumeFront(S&: MangledName, C: "@8" )) |
495 | break; |
496 | if (!MangledName.empty()) |
497 | break; |
498 | return synthesizeVariable(Arena, Type: T, VariableName: "`RTTI Type Descriptor'" ); |
499 | } |
500 | case SpecialIntrinsicKind::RttiBaseClassArray: |
501 | return demangleUntypedVariable(Arena, MangledName, |
502 | VariableName: "`RTTI Base Class Array'" ); |
503 | case SpecialIntrinsicKind::RttiClassHierarchyDescriptor: |
504 | return demangleUntypedVariable(Arena, MangledName, |
505 | VariableName: "`RTTI Class Hierarchy Descriptor'" ); |
506 | case SpecialIntrinsicKind::RttiBaseClassDescriptor: |
507 | return demangleRttiBaseClassDescriptorNode(Arena, MangledName); |
508 | case SpecialIntrinsicKind::DynamicInitializer: |
509 | return demangleInitFiniStub(MangledName, /*IsDestructor=*/false); |
510 | case SpecialIntrinsicKind::DynamicAtexitDestructor: |
511 | return demangleInitFiniStub(MangledName, /*IsDestructor=*/true); |
512 | case SpecialIntrinsicKind::Typeof: |
513 | case SpecialIntrinsicKind::UdtReturning: |
514 | // It's unclear which tools produces these manglings, so demangling |
515 | // support is not (yet?) implemented. |
516 | break; |
517 | case SpecialIntrinsicKind::Unknown: |
518 | DEMANGLE_UNREACHABLE; // Never returned by consumeSpecialIntrinsicKind. |
519 | } |
520 | Error = true; |
521 | return nullptr; |
522 | } |
523 | |
524 | IdentifierNode * |
525 | Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName) { |
526 | assert(llvm::itanium_demangle::starts_with(MangledName, '?')); |
527 | MangledName.remove_prefix(n: 1); |
528 | if (MangledName.empty()) { |
529 | Error = true; |
530 | return nullptr; |
531 | } |
532 | |
533 | if (consumeFront(S&: MangledName, C: "__" )) |
534 | return demangleFunctionIdentifierCode( |
535 | MangledName, Group: FunctionIdentifierCodeGroup::DoubleUnder); |
536 | if (consumeFront(S&: MangledName, C: "_" )) |
537 | return demangleFunctionIdentifierCode(MangledName, |
538 | Group: FunctionIdentifierCodeGroup::Under); |
539 | return demangleFunctionIdentifierCode(MangledName, |
540 | Group: FunctionIdentifierCodeGroup::Basic); |
541 | } |
542 | |
543 | StructorIdentifierNode * |
544 | Demangler::demangleStructorIdentifier(std::string_view &MangledName, |
545 | bool IsDestructor) { |
546 | StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>(); |
547 | N->IsDestructor = IsDestructor; |
548 | return N; |
549 | } |
550 | |
551 | ConversionOperatorIdentifierNode * |
552 | Demangler::demangleConversionOperatorIdentifier(std::string_view &MangledName) { |
553 | ConversionOperatorIdentifierNode *N = |
554 | Arena.alloc<ConversionOperatorIdentifierNode>(); |
555 | return N; |
556 | } |
557 | |
558 | LiteralOperatorIdentifierNode * |
559 | Demangler::demangleLiteralOperatorIdentifier(std::string_view &MangledName) { |
560 | LiteralOperatorIdentifierNode *N = |
561 | Arena.alloc<LiteralOperatorIdentifierNode>(); |
562 | N->Name = demangleSimpleString(MangledName, /*Memorize=*/false); |
563 | return N; |
564 | } |
565 | |
566 | IntrinsicFunctionKind |
567 | Demangler::translateIntrinsicFunctionCode(char CH, |
568 | FunctionIdentifierCodeGroup Group) { |
569 | using IFK = IntrinsicFunctionKind; |
570 | if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) { |
571 | Error = true; |
572 | return IFK::None; |
573 | } |
574 | |
575 | // Not all ? identifiers are intrinsics *functions*. This function only maps |
576 | // operator codes for the special functions, all others are handled elsewhere, |
577 | // hence the IFK::None entries in the table. |
578 | static IFK Basic[36] = { |
579 | IFK::None, // ?0 # Foo::Foo() |
580 | IFK::None, // ?1 # Foo::~Foo() |
581 | IFK::New, // ?2 # operator new |
582 | IFK::Delete, // ?3 # operator delete |
583 | IFK::Assign, // ?4 # operator= |
584 | IFK::RightShift, // ?5 # operator>> |
585 | IFK::LeftShift, // ?6 # operator<< |
586 | IFK::LogicalNot, // ?7 # operator! |
587 | IFK::Equals, // ?8 # operator== |
588 | IFK::NotEquals, // ?9 # operator!= |
589 | IFK::ArraySubscript, // ?A # operator[] |
590 | IFK::None, // ?B # Foo::operator <type>() |
591 | IFK::Pointer, // ?C # operator-> |
592 | IFK::Dereference, // ?D # operator* |
593 | IFK::Increment, // ?E # operator++ |
594 | IFK::Decrement, // ?F # operator-- |
595 | IFK::Minus, // ?G # operator- |
596 | IFK::Plus, // ?H # operator+ |
597 | IFK::BitwiseAnd, // ?I # operator& |
598 | IFK::MemberPointer, // ?J # operator->* |
599 | IFK::Divide, // ?K # operator/ |
600 | IFK::Modulus, // ?L # operator% |
601 | IFK::LessThan, // ?M operator< |
602 | IFK::LessThanEqual, // ?N operator<= |
603 | IFK::GreaterThan, // ?O operator> |
604 | IFK::GreaterThanEqual, // ?P operator>= |
605 | IFK::Comma, // ?Q operator, |
606 | IFK::Parens, // ?R operator() |
607 | IFK::BitwiseNot, // ?S operator~ |
608 | IFK::BitwiseXor, // ?T operator^ |
609 | IFK::BitwiseOr, // ?U operator| |
610 | IFK::LogicalAnd, // ?V operator&& |
611 | IFK::LogicalOr, // ?W operator|| |
612 | IFK::TimesEqual, // ?X operator*= |
613 | IFK::PlusEqual, // ?Y operator+= |
614 | IFK::MinusEqual, // ?Z operator-= |
615 | }; |
616 | static IFK Under[36] = { |
617 | IFK::DivEqual, // ?_0 operator/= |
618 | IFK::ModEqual, // ?_1 operator%= |
619 | IFK::RshEqual, // ?_2 operator>>= |
620 | IFK::LshEqual, // ?_3 operator<<= |
621 | IFK::BitwiseAndEqual, // ?_4 operator&= |
622 | IFK::BitwiseOrEqual, // ?_5 operator|= |
623 | IFK::BitwiseXorEqual, // ?_6 operator^= |
624 | IFK::None, // ?_7 # vftable |
625 | IFK::None, // ?_8 # vbtable |
626 | IFK::None, // ?_9 # vcall |
627 | IFK::None, // ?_A # typeof |
628 | IFK::None, // ?_B # local static guard |
629 | IFK::None, // ?_C # string literal |
630 | IFK::VbaseDtor, // ?_D # vbase destructor |
631 | IFK::VecDelDtor, // ?_E # vector deleting destructor |
632 | IFK::DefaultCtorClosure, // ?_F # default constructor closure |
633 | IFK::ScalarDelDtor, // ?_G # scalar deleting destructor |
634 | IFK::VecCtorIter, // ?_H # vector constructor iterator |
635 | IFK::VecDtorIter, // ?_I # vector destructor iterator |
636 | IFK::VecVbaseCtorIter, // ?_J # vector vbase constructor iterator |
637 | IFK::VdispMap, // ?_K # virtual displacement map |
638 | IFK::EHVecCtorIter, // ?_L # eh vector constructor iterator |
639 | IFK::EHVecDtorIter, // ?_M # eh vector destructor iterator |
640 | IFK::EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator |
641 | IFK::CopyCtorClosure, // ?_O # copy constructor closure |
642 | IFK::None, // ?_P<name> # udt returning <name> |
643 | IFK::None, // ?_Q # <unknown> |
644 | IFK::None, // ?_R0 - ?_R4 # RTTI Codes |
645 | IFK::None, // ?_S # local vftable |
646 | IFK::LocalVftableCtorClosure, // ?_T # local vftable constructor closure |
647 | IFK::ArrayNew, // ?_U operator new[] |
648 | IFK::ArrayDelete, // ?_V operator delete[] |
649 | IFK::None, // ?_W <unused> |
650 | IFK::None, // ?_X <unused> |
651 | IFK::None, // ?_Y <unused> |
652 | IFK::None, // ?_Z <unused> |
653 | }; |
654 | static IFK DoubleUnder[36] = { |
655 | IFK::None, // ?__0 <unused> |
656 | IFK::None, // ?__1 <unused> |
657 | IFK::None, // ?__2 <unused> |
658 | IFK::None, // ?__3 <unused> |
659 | IFK::None, // ?__4 <unused> |
660 | IFK::None, // ?__5 <unused> |
661 | IFK::None, // ?__6 <unused> |
662 | IFK::None, // ?__7 <unused> |
663 | IFK::None, // ?__8 <unused> |
664 | IFK::None, // ?__9 <unused> |
665 | IFK::ManVectorCtorIter, // ?__A managed vector ctor iterator |
666 | IFK::ManVectorDtorIter, // ?__B managed vector dtor iterator |
667 | IFK::EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator |
668 | IFK::EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iter |
669 | IFK::None, // ?__E dynamic initializer for `T' |
670 | IFK::None, // ?__F dynamic atexit destructor for `T' |
671 | IFK::VectorCopyCtorIter, // ?__G vector copy constructor iter |
672 | IFK::VectorVbaseCopyCtorIter, // ?__H vector vbase copy ctor iter |
673 | IFK::ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy ctor |
674 | // iter |
675 | IFK::None, // ?__J local static thread guard |
676 | IFK::None, // ?__K operator ""_name |
677 | IFK::CoAwait, // ?__L operator co_await |
678 | IFK::Spaceship, // ?__M operator<=> |
679 | IFK::None, // ?__N <unused> |
680 | IFK::None, // ?__O <unused> |
681 | IFK::None, // ?__P <unused> |
682 | IFK::None, // ?__Q <unused> |
683 | IFK::None, // ?__R <unused> |
684 | IFK::None, // ?__S <unused> |
685 | IFK::None, // ?__T <unused> |
686 | IFK::None, // ?__U <unused> |
687 | IFK::None, // ?__V <unused> |
688 | IFK::None, // ?__W <unused> |
689 | IFK::None, // ?__X <unused> |
690 | IFK::None, // ?__Y <unused> |
691 | IFK::None, // ?__Z <unused> |
692 | }; |
693 | |
694 | int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10); |
695 | switch (Group) { |
696 | case FunctionIdentifierCodeGroup::Basic: |
697 | return Basic[Index]; |
698 | case FunctionIdentifierCodeGroup::Under: |
699 | return Under[Index]; |
700 | case FunctionIdentifierCodeGroup::DoubleUnder: |
701 | return DoubleUnder[Index]; |
702 | } |
703 | DEMANGLE_UNREACHABLE; |
704 | } |
705 | |
706 | IdentifierNode * |
707 | Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName, |
708 | FunctionIdentifierCodeGroup Group) { |
709 | if (MangledName.empty()) { |
710 | Error = true; |
711 | return nullptr; |
712 | } |
713 | const char CH = MangledName.front(); |
714 | switch (Group) { |
715 | case FunctionIdentifierCodeGroup::Basic: |
716 | MangledName.remove_prefix(n: 1); |
717 | switch (CH) { |
718 | case '0': |
719 | case '1': |
720 | return demangleStructorIdentifier(MangledName, IsDestructor: CH == '1'); |
721 | case 'B': |
722 | return demangleConversionOperatorIdentifier(MangledName); |
723 | default: |
724 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( |
725 | ConstructorArgs: translateIntrinsicFunctionCode(CH, Group)); |
726 | } |
727 | case FunctionIdentifierCodeGroup::Under: |
728 | MangledName.remove_prefix(n: 1); |
729 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( |
730 | ConstructorArgs: translateIntrinsicFunctionCode(CH, Group)); |
731 | case FunctionIdentifierCodeGroup::DoubleUnder: |
732 | MangledName.remove_prefix(n: 1); |
733 | switch (CH) { |
734 | case 'K': |
735 | return demangleLiteralOperatorIdentifier(MangledName); |
736 | default: |
737 | return Arena.alloc<IntrinsicFunctionIdentifierNode>( |
738 | ConstructorArgs: translateIntrinsicFunctionCode(CH, Group)); |
739 | } |
740 | } |
741 | |
742 | DEMANGLE_UNREACHABLE; |
743 | } |
744 | |
745 | SymbolNode *Demangler::demangleEncodedSymbol(std::string_view &MangledName, |
746 | QualifiedNameNode *Name) { |
747 | if (MangledName.empty()) { |
748 | Error = true; |
749 | return nullptr; |
750 | } |
751 | |
752 | // Read a variable. |
753 | switch (MangledName.front()) { |
754 | case '0': |
755 | case '1': |
756 | case '2': |
757 | case '3': |
758 | case '4': { |
759 | StorageClass SC = demangleVariableStorageClass(MangledName); |
760 | return demangleVariableEncoding(MangledName, SC); |
761 | } |
762 | } |
763 | FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName); |
764 | |
765 | IdentifierNode *UQN = Name->getUnqualifiedIdentifier(); |
766 | if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { |
767 | ConversionOperatorIdentifierNode *COIN = |
768 | static_cast<ConversionOperatorIdentifierNode *>(UQN); |
769 | if (FSN) |
770 | COIN->TargetType = FSN->Signature->ReturnType; |
771 | } |
772 | return FSN; |
773 | } |
774 | |
775 | SymbolNode *Demangler::demangleDeclarator(std::string_view &MangledName) { |
776 | // What follows is a main symbol name. This may include namespaces or class |
777 | // back references. |
778 | QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); |
779 | if (Error) |
780 | return nullptr; |
781 | |
782 | SymbolNode *Symbol = demangleEncodedSymbol(MangledName, Name: QN); |
783 | if (Error) |
784 | return nullptr; |
785 | Symbol->Name = QN; |
786 | |
787 | IdentifierNode *UQN = QN->getUnqualifiedIdentifier(); |
788 | if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) { |
789 | ConversionOperatorIdentifierNode *COIN = |
790 | static_cast<ConversionOperatorIdentifierNode *>(UQN); |
791 | if (!COIN->TargetType) { |
792 | Error = true; |
793 | return nullptr; |
794 | } |
795 | } |
796 | return Symbol; |
797 | } |
798 | |
799 | SymbolNode *Demangler::demangleMD5Name(std::string_view &MangledName) { |
800 | assert(llvm::itanium_demangle::starts_with(MangledName, "??@" )); |
801 | // This is an MD5 mangled name. We can't demangle it, just return the |
802 | // mangled name. |
803 | // An MD5 mangled name is ??@ followed by 32 characters and a terminating @. |
804 | size_t MD5Last = MangledName.find(c: '@', pos: strlen(s: "??@" )); |
805 | if (MD5Last == std::string_view::npos) { |
806 | Error = true; |
807 | return nullptr; |
808 | } |
809 | const char *Start = MangledName.data(); |
810 | const size_t StartSize = MangledName.size(); |
811 | MangledName.remove_prefix(n: MD5Last + 1); |
812 | |
813 | // There are two additional special cases for MD5 names: |
814 | // 1. For complete object locators where the object name is long enough |
815 | // for the object to have an MD5 name, the complete object locator is |
816 | // called ??@...@??_R4@ (with a trailing "??_R4@" instead of the usual |
817 | // leading "??_R4". This is handled here. |
818 | // 2. For catchable types, in versions of MSVC before 2015 (<1900) or after |
819 | // 2017.2 (>= 1914), the catchable type mangling is _CT??@...@??@...@8 |
820 | // instead of_CT??@...@8 with just one MD5 name. Since we don't yet |
821 | // demangle catchable types anywhere, this isn't handled for MD5 names |
822 | // either. |
823 | consumeFront(S&: MangledName, C: "??_R4@" ); |
824 | |
825 | assert(MangledName.size() < StartSize); |
826 | const size_t Count = StartSize - MangledName.size(); |
827 | std::string_view MD5(Start, Count); |
828 | SymbolNode *S = Arena.alloc<SymbolNode>(ConstructorArgs: NodeKind::Md5Symbol); |
829 | S->Name = synthesizeQualifiedName(Arena, Name: MD5); |
830 | |
831 | return S; |
832 | } |
833 | |
834 | SymbolNode *Demangler::demangleTypeinfoName(std::string_view &MangledName) { |
835 | assert(llvm::itanium_demangle::starts_with(MangledName, '.')); |
836 | consumeFront(S&: MangledName, C: '.'); |
837 | |
838 | TypeNode *T = demangleType(MangledName, QMM: QualifierMangleMode::Result); |
839 | if (Error || !MangledName.empty()) { |
840 | Error = true; |
841 | return nullptr; |
842 | } |
843 | return synthesizeVariable(Arena, Type: T, VariableName: "`RTTI Type Descriptor Name'" ); |
844 | } |
845 | |
846 | // Parser entry point. |
847 | SymbolNode *Demangler::parse(std::string_view &MangledName) { |
848 | // Typeinfo names are strings stored in RTTI data. They're not symbol names. |
849 | // It's still useful to demangle them. They're the only demangled entity |
850 | // that doesn't start with a "?" but a ".". |
851 | if (llvm::itanium_demangle::starts_with(self: MangledName, C: '.')) |
852 | return demangleTypeinfoName(MangledName); |
853 | |
854 | if (llvm::itanium_demangle::starts_with(haystack: MangledName, needle: "??@" )) |
855 | return demangleMD5Name(MangledName); |
856 | |
857 | // MSVC-style mangled symbols must start with '?'. |
858 | if (!llvm::itanium_demangle::starts_with(self: MangledName, C: '?')) { |
859 | Error = true; |
860 | return nullptr; |
861 | } |
862 | |
863 | consumeFront(S&: MangledName, C: '?'); |
864 | |
865 | // ?$ is a template instantiation, but all other names that start with ? are |
866 | // operators / special names. |
867 | if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName)) |
868 | return SI; |
869 | |
870 | return demangleDeclarator(MangledName); |
871 | } |
872 | |
873 | TagTypeNode *Demangler::parseTagUniqueName(std::string_view &MangledName) { |
874 | if (!consumeFront(S&: MangledName, C: ".?A" )) { |
875 | Error = true; |
876 | return nullptr; |
877 | } |
878 | consumeFront(S&: MangledName, C: ".?A" ); |
879 | if (MangledName.empty()) { |
880 | Error = true; |
881 | return nullptr; |
882 | } |
883 | |
884 | return demangleClassType(MangledName); |
885 | } |
886 | |
887 | // <type-encoding> ::= <storage-class> <variable-type> |
888 | // <storage-class> ::= 0 # private static member |
889 | // ::= 1 # protected static member |
890 | // ::= 2 # public static member |
891 | // ::= 3 # global |
892 | // ::= 4 # static local |
893 | |
894 | VariableSymbolNode * |
895 | Demangler::demangleVariableEncoding(std::string_view &MangledName, |
896 | StorageClass SC) { |
897 | VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); |
898 | |
899 | VSN->Type = demangleType(MangledName, QMM: QualifierMangleMode::Drop); |
900 | VSN->SC = SC; |
901 | |
902 | if (Error) |
903 | return nullptr; |
904 | |
905 | // <variable-type> ::= <type> <cvr-qualifiers> |
906 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references |
907 | switch (VSN->Type->kind()) { |
908 | case NodeKind::PointerType: { |
909 | PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type); |
910 | |
911 | Qualifiers = Q_None; |
912 | PTN->Quals = Qualifiers(VSN->Type->Quals | |
913 | demanglePointerExtQualifiers(MangledName)); |
914 | |
915 | bool IsMember = false; |
916 | std::tie(args&: ExtraChildQuals, args&: IsMember) = demangleQualifiers(MangledName); |
917 | |
918 | if (PTN->ClassParent) { |
919 | QualifiedNameNode *BackRefName = |
920 | demangleFullyQualifiedTypeName(MangledName); |
921 | (void)BackRefName; |
922 | } |
923 | PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals); |
924 | |
925 | break; |
926 | } |
927 | default: |
928 | VSN->Type->Quals = demangleQualifiers(MangledName).first; |
929 | break; |
930 | } |
931 | |
932 | return VSN; |
933 | } |
934 | |
935 | // Sometimes numbers are encoded in mangled symbols. For example, |
936 | // "int (*x)[20]" is a valid C type (x is a pointer to an array of |
937 | // length 20), so we need some way to embed numbers as part of symbols. |
938 | // This function parses it. |
939 | // |
940 | // <number> ::= [?] <non-negative integer> |
941 | // |
942 | // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10 |
943 | // ::= <hex digit>+ @ # when Number == 0 or >= 10 |
944 | // |
945 | // <hex-digit> ::= [A-P] # A = 0, B = 1, ... |
946 | std::pair<uint64_t, bool> |
947 | Demangler::demangleNumber(std::string_view &MangledName) { |
948 | bool IsNegative = consumeFront(S&: MangledName, C: '?'); |
949 | |
950 | if (startsWithDigit(S: MangledName)) { |
951 | uint64_t Ret = MangledName[0] - '0' + 1; |
952 | MangledName.remove_prefix(n: 1); |
953 | return {Ret, IsNegative}; |
954 | } |
955 | |
956 | uint64_t Ret = 0; |
957 | for (size_t i = 0; i < MangledName.size(); ++i) { |
958 | char C = MangledName[i]; |
959 | if (C == '@') { |
960 | MangledName.remove_prefix(n: i + 1); |
961 | return {Ret, IsNegative}; |
962 | } |
963 | if ('A' <= C && C <= 'P') { |
964 | Ret = (Ret << 4) + (C - 'A'); |
965 | continue; |
966 | } |
967 | break; |
968 | } |
969 | |
970 | Error = true; |
971 | return {0ULL, false}; |
972 | } |
973 | |
974 | uint64_t Demangler::demangleUnsigned(std::string_view &MangledName) { |
975 | bool IsNegative = false; |
976 | uint64_t Number = 0; |
977 | std::tie(args&: Number, args&: IsNegative) = demangleNumber(MangledName); |
978 | if (IsNegative) |
979 | Error = true; |
980 | return Number; |
981 | } |
982 | |
983 | int64_t Demangler::demangleSigned(std::string_view &MangledName) { |
984 | bool IsNegative = false; |
985 | uint64_t Number = 0; |
986 | std::tie(args&: Number, args&: IsNegative) = demangleNumber(MangledName); |
987 | if (Number > INT64_MAX) |
988 | Error = true; |
989 | int64_t I = static_cast<int64_t>(Number); |
990 | return IsNegative ? -I : I; |
991 | } |
992 | |
993 | // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9. |
994 | // Memorize it. |
995 | void Demangler::memorizeString(std::string_view S) { |
996 | if (Backrefs.NamesCount >= BackrefContext::Max) |
997 | return; |
998 | for (size_t i = 0; i < Backrefs.NamesCount; ++i) |
999 | if (S == Backrefs.Names[i]->Name) |
1000 | return; |
1001 | NamedIdentifierNode *N = Arena.alloc<NamedIdentifierNode>(); |
1002 | N->Name = S; |
1003 | Backrefs.Names[Backrefs.NamesCount++] = N; |
1004 | } |
1005 | |
1006 | NamedIdentifierNode * |
1007 | Demangler::demangleBackRefName(std::string_view &MangledName) { |
1008 | assert(startsWithDigit(MangledName)); |
1009 | |
1010 | size_t I = MangledName[0] - '0'; |
1011 | if (I >= Backrefs.NamesCount) { |
1012 | Error = true; |
1013 | return nullptr; |
1014 | } |
1015 | |
1016 | MangledName.remove_prefix(n: 1); |
1017 | return Backrefs.Names[I]; |
1018 | } |
1019 | |
1020 | void Demangler::memorizeIdentifier(IdentifierNode *Identifier) { |
1021 | // Render this class template name into a string buffer so that we can |
1022 | // memorize it for the purpose of back-referencing. |
1023 | OutputBuffer OB; |
1024 | Identifier->output(OB, Flags: OF_Default); |
1025 | std::string_view Owned = copyString(Borrowed: OB); |
1026 | memorizeString(S: Owned); |
1027 | std::free(ptr: OB.getBuffer()); |
1028 | } |
1029 | |
1030 | IdentifierNode * |
1031 | Demangler::demangleTemplateInstantiationName(std::string_view &MangledName, |
1032 | NameBackrefBehavior NBB) { |
1033 | assert(llvm::itanium_demangle::starts_with(MangledName, "?$" )); |
1034 | consumeFront(S&: MangledName, C: "?$" ); |
1035 | |
1036 | BackrefContext OuterContext; |
1037 | std::swap(a&: OuterContext, b&: Backrefs); |
1038 | |
1039 | IdentifierNode *Identifier = |
1040 | demangleUnqualifiedSymbolName(MangledName, NBB: NBB_Simple); |
1041 | if (!Error) |
1042 | Identifier->TemplateParams = demangleTemplateParameterList(MangledName); |
1043 | |
1044 | std::swap(a&: OuterContext, b&: Backrefs); |
1045 | if (Error) |
1046 | return nullptr; |
1047 | |
1048 | if (NBB & NBB_Template) { |
1049 | // NBB_Template is only set for types and non-leaf names ("a::" in "a::b"). |
1050 | // Structors and conversion operators only makes sense in a leaf name, so |
1051 | // reject them in NBB_Template contexts. |
1052 | if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier || |
1053 | Identifier->kind() == NodeKind::StructorIdentifier) { |
1054 | Error = true; |
1055 | return nullptr; |
1056 | } |
1057 | |
1058 | memorizeIdentifier(Identifier); |
1059 | } |
1060 | |
1061 | return Identifier; |
1062 | } |
1063 | |
1064 | NamedIdentifierNode * |
1065 | Demangler::demangleSimpleName(std::string_view &MangledName, bool Memorize) { |
1066 | std::string_view S = demangleSimpleString(MangledName, Memorize); |
1067 | if (Error) |
1068 | return nullptr; |
1069 | |
1070 | NamedIdentifierNode *Name = Arena.alloc<NamedIdentifierNode>(); |
1071 | Name->Name = S; |
1072 | return Name; |
1073 | } |
1074 | |
1075 | static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); } |
1076 | |
1077 | static uint8_t rebasedHexDigitToNumber(char C) { |
1078 | assert(isRebasedHexDigit(C)); |
1079 | return (C <= 'J') ? (C - 'A') : (10 + C - 'K'); |
1080 | } |
1081 | |
1082 | uint8_t Demangler::demangleCharLiteral(std::string_view &MangledName) { |
1083 | assert(!MangledName.empty()); |
1084 | if (!llvm::itanium_demangle::starts_with(self: MangledName, C: '?')) { |
1085 | const uint8_t F = MangledName.front(); |
1086 | MangledName.remove_prefix(n: 1); |
1087 | return F; |
1088 | } |
1089 | |
1090 | MangledName.remove_prefix(n: 1); |
1091 | if (MangledName.empty()) |
1092 | goto CharLiteralError; |
1093 | |
1094 | if (consumeFront(S&: MangledName, C: '$')) { |
1095 | // Two hex digits |
1096 | if (MangledName.size() < 2) |
1097 | goto CharLiteralError; |
1098 | std::string_view Nibbles = MangledName.substr(pos: 0, n: 2); |
1099 | if (!isRebasedHexDigit(C: Nibbles[0]) || !isRebasedHexDigit(C: Nibbles[1])) |
1100 | goto CharLiteralError; |
1101 | // Don't append the null terminator. |
1102 | uint8_t C1 = rebasedHexDigitToNumber(C: Nibbles[0]); |
1103 | uint8_t C2 = rebasedHexDigitToNumber(C: Nibbles[1]); |
1104 | MangledName.remove_prefix(n: 2); |
1105 | return (C1 << 4) | C2; |
1106 | } |
1107 | |
1108 | if (startsWithDigit(S: MangledName)) { |
1109 | const char *Lookup = ",/\\:. \n\t'-" ; |
1110 | char C = Lookup[MangledName[0] - '0']; |
1111 | MangledName.remove_prefix(n: 1); |
1112 | return C; |
1113 | } |
1114 | |
1115 | if (MangledName[0] >= 'a' && MangledName[0] <= 'z') { |
1116 | char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7', |
1117 | '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE', |
1118 | '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', |
1119 | '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'}; |
1120 | char C = Lookup[MangledName[0] - 'a']; |
1121 | MangledName.remove_prefix(n: 1); |
1122 | return C; |
1123 | } |
1124 | |
1125 | if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') { |
1126 | char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7', |
1127 | '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE', |
1128 | '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', |
1129 | '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'}; |
1130 | char C = Lookup[MangledName[0] - 'A']; |
1131 | MangledName.remove_prefix(n: 1); |
1132 | return C; |
1133 | } |
1134 | |
1135 | CharLiteralError: |
1136 | Error = true; |
1137 | return '\0'; |
1138 | } |
1139 | |
1140 | wchar_t Demangler::demangleWcharLiteral(std::string_view &MangledName) { |
1141 | uint8_t C1, C2; |
1142 | |
1143 | C1 = demangleCharLiteral(MangledName); |
1144 | if (Error || MangledName.empty()) |
1145 | goto WCharLiteralError; |
1146 | C2 = demangleCharLiteral(MangledName); |
1147 | if (Error) |
1148 | goto WCharLiteralError; |
1149 | |
1150 | return ((wchar_t)C1 << 8) | (wchar_t)C2; |
1151 | |
1152 | WCharLiteralError: |
1153 | Error = true; |
1154 | return L'\0'; |
1155 | } |
1156 | |
1157 | static void writeHexDigit(char *Buffer, uint8_t Digit) { |
1158 | assert(Digit <= 15); |
1159 | *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10); |
1160 | } |
1161 | |
1162 | static void outputHex(OutputBuffer &OB, unsigned C) { |
1163 | assert (C != 0); |
1164 | |
1165 | // It's easier to do the math if we can work from right to left, but we need |
1166 | // to print the numbers from left to right. So render this into a temporary |
1167 | // buffer first, then output the temporary buffer. Each byte is of the form |
1168 | // \xAB, which means that each byte needs 4 characters. Since there are at |
1169 | // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer. |
1170 | char TempBuffer[17]; |
1171 | |
1172 | ::memset(s: TempBuffer, c: 0, n: sizeof(TempBuffer)); |
1173 | constexpr int MaxPos = sizeof(TempBuffer) - 1; |
1174 | |
1175 | int Pos = MaxPos - 1; // TempBuffer[MaxPos] is the terminating \0. |
1176 | while (C != 0) { |
1177 | for (int I = 0; I < 2; ++I) { |
1178 | writeHexDigit(Buffer: &TempBuffer[Pos--], Digit: C % 16); |
1179 | C /= 16; |
1180 | } |
1181 | } |
1182 | TempBuffer[Pos--] = 'x'; |
1183 | assert(Pos >= 0); |
1184 | TempBuffer[Pos--] = '\\'; |
1185 | OB << std::string_view(&TempBuffer[Pos + 1]); |
1186 | } |
1187 | |
1188 | static void outputEscapedChar(OutputBuffer &OB, unsigned C) { |
1189 | switch (C) { |
1190 | case '\0': // nul |
1191 | OB << "\\0" ; |
1192 | return; |
1193 | case '\'': // single quote |
1194 | OB << "\\\'" ; |
1195 | return; |
1196 | case '\"': // double quote |
1197 | OB << "\\\"" ; |
1198 | return; |
1199 | case '\\': // backslash |
1200 | OB << "\\\\" ; |
1201 | return; |
1202 | case '\a': // bell |
1203 | OB << "\\a" ; |
1204 | return; |
1205 | case '\b': // backspace |
1206 | OB << "\\b" ; |
1207 | return; |
1208 | case '\f': // form feed |
1209 | OB << "\\f" ; |
1210 | return; |
1211 | case '\n': // new line |
1212 | OB << "\\n" ; |
1213 | return; |
1214 | case '\r': // carriage return |
1215 | OB << "\\r" ; |
1216 | return; |
1217 | case '\t': // tab |
1218 | OB << "\\t" ; |
1219 | return; |
1220 | case '\v': // vertical tab |
1221 | OB << "\\v" ; |
1222 | return; |
1223 | default: |
1224 | break; |
1225 | } |
1226 | |
1227 | if (C > 0x1F && C < 0x7F) { |
1228 | // Standard ascii char. |
1229 | OB << (char)C; |
1230 | return; |
1231 | } |
1232 | |
1233 | outputHex(OB, C); |
1234 | } |
1235 | |
1236 | static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) { |
1237 | const uint8_t *End = StringBytes + Length - 1; |
1238 | unsigned Count = 0; |
1239 | while (Length > 0 && *End == 0) { |
1240 | --Length; |
1241 | --End; |
1242 | ++Count; |
1243 | } |
1244 | return Count; |
1245 | } |
1246 | |
1247 | static unsigned countEmbeddedNulls(const uint8_t *StringBytes, |
1248 | unsigned Length) { |
1249 | unsigned Result = 0; |
1250 | for (unsigned I = 0; I < Length; ++I) { |
1251 | if (*StringBytes++ == 0) |
1252 | ++Result; |
1253 | } |
1254 | return Result; |
1255 | } |
1256 | |
1257 | // A mangled (non-wide) string literal stores the total length of the string it |
1258 | // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text |
1259 | // (passed in StringBytes, NumChars). |
1260 | static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars, |
1261 | uint64_t NumBytes) { |
1262 | assert(NumBytes > 0); |
1263 | |
1264 | // If the number of bytes is odd, this is guaranteed to be a char string. |
1265 | if (NumBytes % 2 == 1) |
1266 | return 1; |
1267 | |
1268 | // All strings can encode at most 32 bytes of data. If it's less than that, |
1269 | // then we encoded the entire string. In this case we check for a 1-byte, |
1270 | // 2-byte, or 4-byte null terminator. |
1271 | if (NumBytes < 32) { |
1272 | unsigned TrailingNulls = countTrailingNullBytes(StringBytes, Length: NumChars); |
1273 | if (TrailingNulls >= 4 && NumBytes % 4 == 0) |
1274 | return 4; |
1275 | if (TrailingNulls >= 2) |
1276 | return 2; |
1277 | return 1; |
1278 | } |
1279 | |
1280 | // The whole string was not able to be encoded. Try to look at embedded null |
1281 | // terminators to guess. The heuristic is that we count all embedded null |
1282 | // terminators. If more than 2/3 are null, it's a char32. If more than 1/3 |
1283 | // are null, it's a char16. Otherwise it's a char8. This obviously isn't |
1284 | // perfect and is biased towards languages that have ascii alphabets, but this |
1285 | // was always going to be best effort since the encoding is lossy. |
1286 | unsigned Nulls = countEmbeddedNulls(StringBytes, Length: NumChars); |
1287 | if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0) |
1288 | return 4; |
1289 | if (Nulls >= NumChars / 3) |
1290 | return 2; |
1291 | return 1; |
1292 | } |
1293 | |
1294 | static unsigned decodeMultiByteChar(const uint8_t *StringBytes, |
1295 | unsigned CharIndex, unsigned CharBytes) { |
1296 | assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4); |
1297 | unsigned Offset = CharIndex * CharBytes; |
1298 | unsigned Result = 0; |
1299 | StringBytes = StringBytes + Offset; |
1300 | for (unsigned I = 0; I < CharBytes; ++I) { |
1301 | unsigned C = static_cast<unsigned>(StringBytes[I]); |
1302 | Result |= C << (8 * I); |
1303 | } |
1304 | return Result; |
1305 | } |
1306 | |
1307 | FunctionSymbolNode * |
1308 | Demangler::demangleVcallThunkNode(std::string_view &MangledName) { |
1309 | FunctionSymbolNode *FSN = Arena.alloc<FunctionSymbolNode>(); |
1310 | VcallThunkIdentifierNode *VTIN = Arena.alloc<VcallThunkIdentifierNode>(); |
1311 | FSN->Signature = Arena.alloc<ThunkSignatureNode>(); |
1312 | FSN->Signature->FunctionClass = FC_NoParameterList; |
1313 | |
1314 | FSN->Name = demangleNameScopeChain(MangledName, UnqualifiedName: VTIN); |
1315 | if (!Error) |
1316 | Error = !consumeFront(S&: MangledName, C: "$B" ); |
1317 | if (!Error) |
1318 | VTIN->OffsetInVTable = demangleUnsigned(MangledName); |
1319 | if (!Error) |
1320 | Error = !consumeFront(S&: MangledName, C: 'A'); |
1321 | if (!Error) |
1322 | FSN->Signature->CallConvention = demangleCallingConvention(MangledName); |
1323 | return (Error) ? nullptr : FSN; |
1324 | } |
1325 | |
1326 | EncodedStringLiteralNode * |
1327 | Demangler::demangleStringLiteral(std::string_view &MangledName) { |
1328 | // This function uses goto, so declare all variables up front. |
1329 | OutputBuffer OB; |
1330 | std::string_view CRC; |
1331 | uint64_t StringByteSize; |
1332 | bool IsWcharT = false; |
1333 | bool IsNegative = false; |
1334 | size_t CrcEndPos = 0; |
1335 | char F; |
1336 | |
1337 | EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>(); |
1338 | |
1339 | // Prefix indicating the beginning of a string literal |
1340 | if (!consumeFront(S&: MangledName, C: "@_" )) |
1341 | goto StringLiteralError; |
1342 | if (MangledName.empty()) |
1343 | goto StringLiteralError; |
1344 | |
1345 | // Char Type (regular or wchar_t) |
1346 | F = MangledName.front(); |
1347 | MangledName.remove_prefix(n: 1); |
1348 | switch (F) { |
1349 | case '1': |
1350 | IsWcharT = true; |
1351 | DEMANGLE_FALLTHROUGH; |
1352 | case '0': |
1353 | break; |
1354 | default: |
1355 | goto StringLiteralError; |
1356 | } |
1357 | |
1358 | // Encoded Length |
1359 | std::tie(args&: StringByteSize, args&: IsNegative) = demangleNumber(MangledName); |
1360 | if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1)) |
1361 | goto StringLiteralError; |
1362 | |
1363 | // CRC 32 (always 8 characters plus a terminator) |
1364 | CrcEndPos = MangledName.find(c: '@'); |
1365 | if (CrcEndPos == std::string_view::npos) |
1366 | goto StringLiteralError; |
1367 | CRC = MangledName.substr(pos: 0, n: CrcEndPos); |
1368 | MangledName.remove_prefix(n: CrcEndPos + 1); |
1369 | if (MangledName.empty()) |
1370 | goto StringLiteralError; |
1371 | |
1372 | if (IsWcharT) { |
1373 | Result->Char = CharKind::Wchar; |
1374 | if (StringByteSize > 64) |
1375 | Result->IsTruncated = true; |
1376 | |
1377 | while (!consumeFront(S&: MangledName, C: '@')) { |
1378 | // For a wide string StringByteSize has to have an even length. |
1379 | if (StringByteSize % 2 != 0) |
1380 | goto StringLiteralError; |
1381 | if (StringByteSize == 0) |
1382 | goto StringLiteralError; |
1383 | if (MangledName.size() < 2) |
1384 | goto StringLiteralError; |
1385 | wchar_t W = demangleWcharLiteral(MangledName); |
1386 | if (StringByteSize != 2 || Result->IsTruncated) |
1387 | outputEscapedChar(OB, C: W); |
1388 | StringByteSize -= 2; |
1389 | if (Error) |
1390 | goto StringLiteralError; |
1391 | } |
1392 | } else { |
1393 | // The max byte length is actually 32, but some compilers mangled strings |
1394 | // incorrectly, so we have to assume it can go higher. |
1395 | constexpr unsigned MaxStringByteLength = 32 * 4; |
1396 | uint8_t StringBytes[MaxStringByteLength]; |
1397 | |
1398 | unsigned BytesDecoded = 0; |
1399 | while (!consumeFront(S&: MangledName, C: '@')) { |
1400 | if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength) |
1401 | goto StringLiteralError; |
1402 | StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName); |
1403 | } |
1404 | |
1405 | if (StringByteSize > BytesDecoded) |
1406 | Result->IsTruncated = true; |
1407 | |
1408 | unsigned CharBytes = |
1409 | guessCharByteSize(StringBytes, NumChars: BytesDecoded, NumBytes: StringByteSize); |
1410 | assert(StringByteSize % CharBytes == 0); |
1411 | switch (CharBytes) { |
1412 | case 1: |
1413 | Result->Char = CharKind::Char; |
1414 | break; |
1415 | case 2: |
1416 | Result->Char = CharKind::Char16; |
1417 | break; |
1418 | case 4: |
1419 | Result->Char = CharKind::Char32; |
1420 | break; |
1421 | default: |
1422 | DEMANGLE_UNREACHABLE; |
1423 | } |
1424 | const unsigned NumChars = BytesDecoded / CharBytes; |
1425 | for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) { |
1426 | unsigned NextChar = |
1427 | decodeMultiByteChar(StringBytes, CharIndex, CharBytes); |
1428 | if (CharIndex + 1 < NumChars || Result->IsTruncated) |
1429 | outputEscapedChar(OB, C: NextChar); |
1430 | } |
1431 | } |
1432 | |
1433 | Result->DecodedString = copyString(Borrowed: OB); |
1434 | std::free(ptr: OB.getBuffer()); |
1435 | return Result; |
1436 | |
1437 | StringLiteralError: |
1438 | Error = true; |
1439 | std::free(ptr: OB.getBuffer()); |
1440 | return nullptr; |
1441 | } |
1442 | |
1443 | // Returns MangledName's prefix before the first '@', or an error if |
1444 | // MangledName contains no '@' or the prefix has length 0. |
1445 | std::string_view Demangler::demangleSimpleString(std::string_view &MangledName, |
1446 | bool Memorize) { |
1447 | std::string_view S; |
1448 | for (size_t i = 0; i < MangledName.size(); ++i) { |
1449 | if (MangledName[i] != '@') |
1450 | continue; |
1451 | if (i == 0) |
1452 | break; |
1453 | S = MangledName.substr(pos: 0, n: i); |
1454 | MangledName.remove_prefix(n: i + 1); |
1455 | |
1456 | if (Memorize) |
1457 | memorizeString(S); |
1458 | return S; |
1459 | } |
1460 | |
1461 | Error = true; |
1462 | return {}; |
1463 | } |
1464 | |
1465 | NamedIdentifierNode * |
1466 | Demangler::demangleAnonymousNamespaceName(std::string_view &MangledName) { |
1467 | assert(llvm::itanium_demangle::starts_with(MangledName, "?A" )); |
1468 | consumeFront(S&: MangledName, C: "?A" ); |
1469 | |
1470 | NamedIdentifierNode *Node = Arena.alloc<NamedIdentifierNode>(); |
1471 | Node->Name = "`anonymous namespace'" ; |
1472 | size_t EndPos = MangledName.find(c: '@'); |
1473 | if (EndPos == std::string_view::npos) { |
1474 | Error = true; |
1475 | return nullptr; |
1476 | } |
1477 | std::string_view NamespaceKey = MangledName.substr(pos: 0, n: EndPos); |
1478 | memorizeString(S: NamespaceKey); |
1479 | MangledName = MangledName.substr(pos: EndPos + 1); |
1480 | return Node; |
1481 | } |
1482 | |
1483 | NamedIdentifierNode * |
1484 | Demangler::demangleLocallyScopedNamePiece(std::string_view &MangledName) { |
1485 | assert(startsWithLocalScopePattern(MangledName)); |
1486 | |
1487 | NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>(); |
1488 | consumeFront(S&: MangledName, C: '?'); |
1489 | uint64_t Number = 0; |
1490 | bool IsNegative = false; |
1491 | std::tie(args&: Number, args&: IsNegative) = demangleNumber(MangledName); |
1492 | assert(!IsNegative); |
1493 | |
1494 | // One ? to terminate the number |
1495 | consumeFront(S&: MangledName, C: '?'); |
1496 | |
1497 | assert(!Error); |
1498 | Node *Scope = parse(MangledName); |
1499 | if (Error) |
1500 | return nullptr; |
1501 | |
1502 | // Render the parent symbol's name into a buffer. |
1503 | OutputBuffer OB; |
1504 | OB << '`'; |
1505 | Scope->output(OB, Flags: OF_Default); |
1506 | OB << '\''; |
1507 | OB << "::`" << Number << "'" ; |
1508 | |
1509 | Identifier->Name = copyString(Borrowed: OB); |
1510 | std::free(ptr: OB.getBuffer()); |
1511 | return Identifier; |
1512 | } |
1513 | |
1514 | // Parses a type name in the form of A@B@C@@ which represents C::B::A. |
1515 | QualifiedNameNode * |
1516 | Demangler::demangleFullyQualifiedTypeName(std::string_view &MangledName) { |
1517 | IdentifierNode *Identifier = |
1518 | demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true); |
1519 | if (Error) |
1520 | return nullptr; |
1521 | assert(Identifier); |
1522 | |
1523 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, UnqualifiedName: Identifier); |
1524 | if (Error) |
1525 | return nullptr; |
1526 | assert(QN); |
1527 | return QN; |
1528 | } |
1529 | |
1530 | // Parses a symbol name in the form of A@B@C@@ which represents C::B::A. |
1531 | // Symbol names have slightly different rules regarding what can appear |
1532 | // so we separate out the implementations for flexibility. |
1533 | QualifiedNameNode * |
1534 | Demangler::demangleFullyQualifiedSymbolName(std::string_view &MangledName) { |
1535 | // This is the final component of a symbol name (i.e. the leftmost component |
1536 | // of a mangled name. Since the only possible template instantiation that |
1537 | // can appear in this context is a function template, and since those are |
1538 | // not saved for the purposes of name backreferences, only backref simple |
1539 | // names. |
1540 | IdentifierNode *Identifier = |
1541 | demangleUnqualifiedSymbolName(MangledName, NBB: NBB_Simple); |
1542 | if (Error) |
1543 | return nullptr; |
1544 | |
1545 | QualifiedNameNode *QN = demangleNameScopeChain(MangledName, UnqualifiedName: Identifier); |
1546 | if (Error) |
1547 | return nullptr; |
1548 | |
1549 | if (Identifier->kind() == NodeKind::StructorIdentifier) { |
1550 | if (QN->Components->Count < 2) { |
1551 | Error = true; |
1552 | return nullptr; |
1553 | } |
1554 | StructorIdentifierNode *SIN = |
1555 | static_cast<StructorIdentifierNode *>(Identifier); |
1556 | Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2]; |
1557 | SIN->Class = static_cast<IdentifierNode *>(ClassNode); |
1558 | } |
1559 | assert(QN); |
1560 | return QN; |
1561 | } |
1562 | |
1563 | IdentifierNode * |
1564 | Demangler::demangleUnqualifiedTypeName(std::string_view &MangledName, |
1565 | bool Memorize) { |
1566 | // An inner-most name can be a back-reference, because a fully-qualified name |
1567 | // (e.g. Scope + Inner) can contain other fully qualified names inside of |
1568 | // them (for example template parameters), and these nested parameters can |
1569 | // refer to previously mangled types. |
1570 | if (startsWithDigit(S: MangledName)) |
1571 | return demangleBackRefName(MangledName); |
1572 | |
1573 | if (llvm::itanium_demangle::starts_with(haystack: MangledName, needle: "?$" )) |
1574 | return demangleTemplateInstantiationName(MangledName, NBB: NBB_Template); |
1575 | |
1576 | return demangleSimpleName(MangledName, Memorize); |
1577 | } |
1578 | |
1579 | IdentifierNode * |
1580 | Demangler::demangleUnqualifiedSymbolName(std::string_view &MangledName, |
1581 | NameBackrefBehavior NBB) { |
1582 | if (startsWithDigit(S: MangledName)) |
1583 | return demangleBackRefName(MangledName); |
1584 | if (llvm::itanium_demangle::starts_with(haystack: MangledName, needle: "?$" )) |
1585 | return demangleTemplateInstantiationName(MangledName, NBB); |
1586 | if (llvm::itanium_demangle::starts_with(self: MangledName, C: '?')) |
1587 | return demangleFunctionIdentifierCode(MangledName); |
1588 | return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0); |
1589 | } |
1590 | |
1591 | IdentifierNode * |
1592 | Demangler::demangleNameScopePiece(std::string_view &MangledName) { |
1593 | if (startsWithDigit(S: MangledName)) |
1594 | return demangleBackRefName(MangledName); |
1595 | |
1596 | if (llvm::itanium_demangle::starts_with(haystack: MangledName, needle: "?$" )) |
1597 | return demangleTemplateInstantiationName(MangledName, NBB: NBB_Template); |
1598 | |
1599 | if (llvm::itanium_demangle::starts_with(haystack: MangledName, needle: "?A" )) |
1600 | return demangleAnonymousNamespaceName(MangledName); |
1601 | |
1602 | if (startsWithLocalScopePattern(S: MangledName)) |
1603 | return demangleLocallyScopedNamePiece(MangledName); |
1604 | |
1605 | return demangleSimpleName(MangledName, /*Memorize=*/true); |
1606 | } |
1607 | |
1608 | static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, |
1609 | size_t Count) { |
1610 | NodeArrayNode *N = Arena.alloc<NodeArrayNode>(); |
1611 | N->Count = Count; |
1612 | N->Nodes = Arena.allocArray<Node *>(Count); |
1613 | for (size_t I = 0; I < Count; ++I) { |
1614 | N->Nodes[I] = Head->N; |
1615 | Head = Head->Next; |
1616 | } |
1617 | return N; |
1618 | } |
1619 | |
1620 | QualifiedNameNode * |
1621 | Demangler::demangleNameScopeChain(std::string_view &MangledName, |
1622 | IdentifierNode *UnqualifiedName) { |
1623 | NodeList *Head = Arena.alloc<NodeList>(); |
1624 | |
1625 | Head->N = UnqualifiedName; |
1626 | |
1627 | size_t Count = 1; |
1628 | while (!consumeFront(S&: MangledName, C: "@" )) { |
1629 | ++Count; |
1630 | NodeList *NewHead = Arena.alloc<NodeList>(); |
1631 | NewHead->Next = Head; |
1632 | Head = NewHead; |
1633 | |
1634 | if (MangledName.empty()) { |
1635 | Error = true; |
1636 | return nullptr; |
1637 | } |
1638 | |
1639 | assert(!Error); |
1640 | IdentifierNode *Elem = demangleNameScopePiece(MangledName); |
1641 | if (Error) |
1642 | return nullptr; |
1643 | |
1644 | Head->N = Elem; |
1645 | } |
1646 | |
1647 | QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>(); |
1648 | QN->Components = nodeListToNodeArray(Arena, Head, Count); |
1649 | return QN; |
1650 | } |
1651 | |
1652 | FuncClass Demangler::demangleFunctionClass(std::string_view &MangledName) { |
1653 | const char F = MangledName.front(); |
1654 | MangledName.remove_prefix(n: 1); |
1655 | switch (F) { |
1656 | case '9': |
1657 | return FuncClass(FC_ExternC | FC_NoParameterList); |
1658 | case 'A': |
1659 | return FC_Private; |
1660 | case 'B': |
1661 | return FuncClass(FC_Private | FC_Far); |
1662 | case 'C': |
1663 | return FuncClass(FC_Private | FC_Static); |
1664 | case 'D': |
1665 | return FuncClass(FC_Private | FC_Static | FC_Far); |
1666 | case 'E': |
1667 | return FuncClass(FC_Private | FC_Virtual); |
1668 | case 'F': |
1669 | return FuncClass(FC_Private | FC_Virtual | FC_Far); |
1670 | case 'G': |
1671 | return FuncClass(FC_Private | FC_StaticThisAdjust); |
1672 | case 'H': |
1673 | return FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far); |
1674 | case 'I': |
1675 | return FuncClass(FC_Protected); |
1676 | case 'J': |
1677 | return FuncClass(FC_Protected | FC_Far); |
1678 | case 'K': |
1679 | return FuncClass(FC_Protected | FC_Static); |
1680 | case 'L': |
1681 | return FuncClass(FC_Protected | FC_Static | FC_Far); |
1682 | case 'M': |
1683 | return FuncClass(FC_Protected | FC_Virtual); |
1684 | case 'N': |
1685 | return FuncClass(FC_Protected | FC_Virtual | FC_Far); |
1686 | case 'O': |
1687 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust); |
1688 | case 'P': |
1689 | return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far); |
1690 | case 'Q': |
1691 | return FuncClass(FC_Public); |
1692 | case 'R': |
1693 | return FuncClass(FC_Public | FC_Far); |
1694 | case 'S': |
1695 | return FuncClass(FC_Public | FC_Static); |
1696 | case 'T': |
1697 | return FuncClass(FC_Public | FC_Static | FC_Far); |
1698 | case 'U': |
1699 | return FuncClass(FC_Public | FC_Virtual); |
1700 | case 'V': |
1701 | return FuncClass(FC_Public | FC_Virtual | FC_Far); |
1702 | case 'W': |
1703 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust); |
1704 | case 'X': |
1705 | return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far); |
1706 | case 'Y': |
1707 | return FuncClass(FC_Global); |
1708 | case 'Z': |
1709 | return FuncClass(FC_Global | FC_Far); |
1710 | case '$': { |
1711 | FuncClass VFlag = FC_VirtualThisAdjust; |
1712 | if (consumeFront(S&: MangledName, C: 'R')) |
1713 | VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx); |
1714 | if (MangledName.empty()) |
1715 | break; |
1716 | const char F = MangledName.front(); |
1717 | MangledName.remove_prefix(n: 1); |
1718 | switch (F) { |
1719 | case '0': |
1720 | return FuncClass(FC_Private | FC_Virtual | VFlag); |
1721 | case '1': |
1722 | return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far); |
1723 | case '2': |
1724 | return FuncClass(FC_Protected | FC_Virtual | VFlag); |
1725 | case '3': |
1726 | return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far); |
1727 | case '4': |
1728 | return FuncClass(FC_Public | FC_Virtual | VFlag); |
1729 | case '5': |
1730 | return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far); |
1731 | } |
1732 | } |
1733 | } |
1734 | |
1735 | Error = true; |
1736 | return FC_Public; |
1737 | } |
1738 | |
1739 | CallingConv |
1740 | Demangler::demangleCallingConvention(std::string_view &MangledName) { |
1741 | if (MangledName.empty()) { |
1742 | Error = true; |
1743 | return CallingConv::None; |
1744 | } |
1745 | |
1746 | const char F = MangledName.front(); |
1747 | MangledName.remove_prefix(n: 1); |
1748 | switch (F) { |
1749 | case 'A': |
1750 | case 'B': |
1751 | return CallingConv::Cdecl; |
1752 | case 'C': |
1753 | case 'D': |
1754 | return CallingConv::Pascal; |
1755 | case 'E': |
1756 | case 'F': |
1757 | return CallingConv::Thiscall; |
1758 | case 'G': |
1759 | case 'H': |
1760 | return CallingConv::Stdcall; |
1761 | case 'I': |
1762 | case 'J': |
1763 | return CallingConv::Fastcall; |
1764 | case 'M': |
1765 | case 'N': |
1766 | return CallingConv::Clrcall; |
1767 | case 'O': |
1768 | case 'P': |
1769 | return CallingConv::Eabi; |
1770 | case 'Q': |
1771 | return CallingConv::Vectorcall; |
1772 | case 'S': |
1773 | return CallingConv::Swift; |
1774 | case 'W': |
1775 | return CallingConv::SwiftAsync; |
1776 | } |
1777 | |
1778 | return CallingConv::None; |
1779 | } |
1780 | |
1781 | StorageClass |
1782 | Demangler::demangleVariableStorageClass(std::string_view &MangledName) { |
1783 | assert(MangledName.front() >= '0' && MangledName.front() <= '4'); |
1784 | |
1785 | const char F = MangledName.front(); |
1786 | MangledName.remove_prefix(n: 1); |
1787 | switch (F) { |
1788 | case '0': |
1789 | return StorageClass::PrivateStatic; |
1790 | case '1': |
1791 | return StorageClass::ProtectedStatic; |
1792 | case '2': |
1793 | return StorageClass::PublicStatic; |
1794 | case '3': |
1795 | return StorageClass::Global; |
1796 | case '4': |
1797 | return StorageClass::FunctionLocalStatic; |
1798 | } |
1799 | DEMANGLE_UNREACHABLE; |
1800 | } |
1801 | |
1802 | std::pair<Qualifiers, bool> |
1803 | Demangler::demangleQualifiers(std::string_view &MangledName) { |
1804 | if (MangledName.empty()) { |
1805 | Error = true; |
1806 | return std::make_pair(x: Q_None, y: false); |
1807 | } |
1808 | |
1809 | const char F = MangledName.front(); |
1810 | MangledName.remove_prefix(n: 1); |
1811 | switch (F) { |
1812 | // Member qualifiers |
1813 | case 'Q': |
1814 | return std::make_pair(x: Q_None, y: true); |
1815 | case 'R': |
1816 | return std::make_pair(x: Q_Const, y: true); |
1817 | case 'S': |
1818 | return std::make_pair(x: Q_Volatile, y: true); |
1819 | case 'T': |
1820 | return std::make_pair(x: Qualifiers(Q_Const | Q_Volatile), y: true); |
1821 | // Non-Member qualifiers |
1822 | case 'A': |
1823 | return std::make_pair(x: Q_None, y: false); |
1824 | case 'B': |
1825 | return std::make_pair(x: Q_Const, y: false); |
1826 | case 'C': |
1827 | return std::make_pair(x: Q_Volatile, y: false); |
1828 | case 'D': |
1829 | return std::make_pair(x: Qualifiers(Q_Const | Q_Volatile), y: false); |
1830 | } |
1831 | Error = true; |
1832 | return std::make_pair(x: Q_None, y: false); |
1833 | } |
1834 | |
1835 | // <variable-type> ::= <type> <cvr-qualifiers> |
1836 | // ::= <type> <pointee-cvr-qualifiers> # pointers, references |
1837 | TypeNode *Demangler::demangleType(std::string_view &MangledName, |
1838 | QualifierMangleMode QMM) { |
1839 | Qualifiers Quals = Q_None; |
1840 | bool IsMember = false; |
1841 | if (QMM == QualifierMangleMode::Mangle) { |
1842 | std::tie(args&: Quals, args&: IsMember) = demangleQualifiers(MangledName); |
1843 | } else if (QMM == QualifierMangleMode::Result) { |
1844 | if (consumeFront(S&: MangledName, C: '?')) |
1845 | std::tie(args&: Quals, args&: IsMember) = demangleQualifiers(MangledName); |
1846 | } |
1847 | |
1848 | if (MangledName.empty()) { |
1849 | Error = true; |
1850 | return nullptr; |
1851 | } |
1852 | |
1853 | TypeNode *Ty = nullptr; |
1854 | if (isTagType(S: MangledName)) |
1855 | Ty = demangleClassType(MangledName); |
1856 | else if (isPointerType(S: MangledName)) { |
1857 | if (isMemberPointer(MangledName, Error)) |
1858 | Ty = demangleMemberPointerType(MangledName); |
1859 | else if (!Error) |
1860 | Ty = demanglePointerType(MangledName); |
1861 | else |
1862 | return nullptr; |
1863 | } else if (isArrayType(S: MangledName)) |
1864 | Ty = demangleArrayType(MangledName); |
1865 | else if (isFunctionType(S: MangledName)) { |
1866 | if (consumeFront(S&: MangledName, C: "$$A8@@" )) |
1867 | Ty = demangleFunctionType(MangledName, HasThisQuals: true); |
1868 | else { |
1869 | assert(llvm::itanium_demangle::starts_with(MangledName, "$$A6" )); |
1870 | consumeFront(S&: MangledName, C: "$$A6" ); |
1871 | Ty = demangleFunctionType(MangledName, HasThisQuals: false); |
1872 | } |
1873 | } else if (isCustomType(S: MangledName)) { |
1874 | Ty = demangleCustomType(MangledName); |
1875 | } else { |
1876 | Ty = demanglePrimitiveType(MangledName); |
1877 | } |
1878 | |
1879 | if (!Ty || Error) |
1880 | return Ty; |
1881 | Ty->Quals = Qualifiers(Ty->Quals | Quals); |
1882 | return Ty; |
1883 | } |
1884 | |
1885 | bool Demangler::demangleThrowSpecification(std::string_view &MangledName) { |
1886 | if (consumeFront(S&: MangledName, C: "_E" )) |
1887 | return true; |
1888 | if (consumeFront(S&: MangledName, C: 'Z')) |
1889 | return false; |
1890 | |
1891 | Error = true; |
1892 | return false; |
1893 | } |
1894 | |
1895 | FunctionSignatureNode * |
1896 | Demangler::demangleFunctionType(std::string_view &MangledName, |
1897 | bool HasThisQuals) { |
1898 | FunctionSignatureNode *FTy = Arena.alloc<FunctionSignatureNode>(); |
1899 | |
1900 | if (HasThisQuals) { |
1901 | FTy->Quals = demanglePointerExtQualifiers(MangledName); |
1902 | FTy->RefQualifier = demangleFunctionRefQualifier(MangledName); |
1903 | FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first); |
1904 | } |
1905 | |
1906 | // Fields that appear on both member and non-member functions. |
1907 | FTy->CallConvention = demangleCallingConvention(MangledName); |
1908 | |
1909 | // <return-type> ::= <type> |
1910 | // ::= @ # structors (they have no declared return type) |
1911 | bool IsStructor = consumeFront(S&: MangledName, C: '@'); |
1912 | if (!IsStructor) |
1913 | FTy->ReturnType = demangleType(MangledName, QMM: QualifierMangleMode::Result); |
1914 | |
1915 | FTy->Params = demangleFunctionParameterList(MangledName, IsVariadic&: FTy->IsVariadic); |
1916 | |
1917 | FTy->IsNoexcept = demangleThrowSpecification(MangledName); |
1918 | |
1919 | return FTy; |
1920 | } |
1921 | |
1922 | FunctionSymbolNode * |
1923 | Demangler::demangleFunctionEncoding(std::string_view &MangledName) { |
1924 | FuncClass = FC_None; |
1925 | if (consumeFront(S&: MangledName, C: "$$J0" )) |
1926 | ExtraFlags = FC_ExternC; |
1927 | |
1928 | if (MangledName.empty()) { |
1929 | Error = true; |
1930 | return nullptr; |
1931 | } |
1932 | |
1933 | FuncClass FC = demangleFunctionClass(MangledName); |
1934 | FC = FuncClass(ExtraFlags | FC); |
1935 | |
1936 | FunctionSignatureNode *FSN = nullptr; |
1937 | ThunkSignatureNode *TTN = nullptr; |
1938 | if (FC & FC_StaticThisAdjust) { |
1939 | TTN = Arena.alloc<ThunkSignatureNode>(); |
1940 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); |
1941 | } else if (FC & FC_VirtualThisAdjust) { |
1942 | TTN = Arena.alloc<ThunkSignatureNode>(); |
1943 | if (FC & FC_VirtualThisAdjustEx) { |
1944 | TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName); |
1945 | TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName); |
1946 | } |
1947 | TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName); |
1948 | TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName); |
1949 | } |
1950 | |
1951 | if (FC & FC_NoParameterList) { |
1952 | // This is an extern "C" function whose full signature hasn't been mangled. |
1953 | // This happens when we need to mangle a local symbol inside of an extern |
1954 | // "C" function. |
1955 | FSN = Arena.alloc<FunctionSignatureNode>(); |
1956 | } else { |
1957 | bool HasThisQuals = !(FC & (FC_Global | FC_Static)); |
1958 | FSN = demangleFunctionType(MangledName, HasThisQuals); |
1959 | } |
1960 | |
1961 | if (Error) |
1962 | return nullptr; |
1963 | |
1964 | if (TTN) { |
1965 | *static_cast<FunctionSignatureNode *>(TTN) = *FSN; |
1966 | FSN = TTN; |
1967 | } |
1968 | FSN->FunctionClass = FC; |
1969 | |
1970 | FunctionSymbolNode *Symbol = Arena.alloc<FunctionSymbolNode>(); |
1971 | Symbol->Signature = FSN; |
1972 | return Symbol; |
1973 | } |
1974 | |
1975 | CustomTypeNode *Demangler::demangleCustomType(std::string_view &MangledName) { |
1976 | assert(llvm::itanium_demangle::starts_with(MangledName, '?')); |
1977 | MangledName.remove_prefix(n: 1); |
1978 | |
1979 | CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>(); |
1980 | CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true); |
1981 | if (!consumeFront(S&: MangledName, C: '@')) |
1982 | Error = true; |
1983 | if (Error) |
1984 | return nullptr; |
1985 | return CTN; |
1986 | } |
1987 | |
1988 | // Reads a primitive type. |
1989 | PrimitiveTypeNode * |
1990 | Demangler::demanglePrimitiveType(std::string_view &MangledName) { |
1991 | if (consumeFront(S&: MangledName, C: "$$T" )) |
1992 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Nullptr); |
1993 | |
1994 | const char F = MangledName.front(); |
1995 | MangledName.remove_prefix(n: 1); |
1996 | switch (F) { |
1997 | case 'X': |
1998 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Void); |
1999 | case 'D': |
2000 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Char); |
2001 | case 'C': |
2002 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Schar); |
2003 | case 'E': |
2004 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Uchar); |
2005 | case 'F': |
2006 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Short); |
2007 | case 'G': |
2008 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Ushort); |
2009 | case 'H': |
2010 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Int); |
2011 | case 'I': |
2012 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Uint); |
2013 | case 'J': |
2014 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Long); |
2015 | case 'K': |
2016 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Ulong); |
2017 | case 'M': |
2018 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Float); |
2019 | case 'N': |
2020 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Double); |
2021 | case 'O': |
2022 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Ldouble); |
2023 | case '_': { |
2024 | if (MangledName.empty()) { |
2025 | Error = true; |
2026 | return nullptr; |
2027 | } |
2028 | const char F = MangledName.front(); |
2029 | MangledName.remove_prefix(n: 1); |
2030 | switch (F) { |
2031 | case 'N': |
2032 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Bool); |
2033 | case 'J': |
2034 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Int64); |
2035 | case 'K': |
2036 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Uint64); |
2037 | case 'W': |
2038 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Wchar); |
2039 | case 'Q': |
2040 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Char8); |
2041 | case 'S': |
2042 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Char16); |
2043 | case 'U': |
2044 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Char32); |
2045 | case 'P': |
2046 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::Auto); |
2047 | case 'T': |
2048 | return Arena.alloc<PrimitiveTypeNode>(ConstructorArgs: PrimitiveKind::DecltypeAuto); |
2049 | } |
2050 | break; |
2051 | } |
2052 | } |
2053 | Error = true; |
2054 | return nullptr; |
2055 | } |
2056 | |
2057 | TagTypeNode *Demangler::demangleClassType(std::string_view &MangledName) { |
2058 | TagTypeNode *TT = nullptr; |
2059 | |
2060 | const char F = MangledName.front(); |
2061 | MangledName.remove_prefix(n: 1); |
2062 | switch (F) { |
2063 | case 'T': |
2064 | TT = Arena.alloc<TagTypeNode>(ConstructorArgs: TagKind::Union); |
2065 | break; |
2066 | case 'U': |
2067 | TT = Arena.alloc<TagTypeNode>(ConstructorArgs: TagKind::Struct); |
2068 | break; |
2069 | case 'V': |
2070 | TT = Arena.alloc<TagTypeNode>(ConstructorArgs: TagKind::Class); |
2071 | break; |
2072 | case 'W': |
2073 | if (!consumeFront(S&: MangledName, C: '4')) { |
2074 | Error = true; |
2075 | return nullptr; |
2076 | } |
2077 | TT = Arena.alloc<TagTypeNode>(ConstructorArgs: TagKind::Enum); |
2078 | break; |
2079 | default: |
2080 | assert(false); |
2081 | } |
2082 | |
2083 | TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName); |
2084 | return TT; |
2085 | } |
2086 | |
2087 | // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type> |
2088 | // # the E is required for 64-bit non-static pointers |
2089 | PointerTypeNode *Demangler::demanglePointerType(std::string_view &MangledName) { |
2090 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); |
2091 | |
2092 | std::tie(args&: Pointer->Quals, args&: Pointer->Affinity) = |
2093 | demanglePointerCVQualifiers(MangledName); |
2094 | |
2095 | if (consumeFront(S&: MangledName, C: "6" )) { |
2096 | Pointer->Pointee = demangleFunctionType(MangledName, HasThisQuals: false); |
2097 | return Pointer; |
2098 | } |
2099 | |
2100 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); |
2101 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); |
2102 | |
2103 | Pointer->PointerAuthQualifier = createPointerAuthQualifier(MangledName); |
2104 | |
2105 | Pointer->Pointee = demangleType(MangledName, QMM: QualifierMangleMode::Mangle); |
2106 | return Pointer; |
2107 | } |
2108 | |
2109 | PointerTypeNode * |
2110 | Demangler::demangleMemberPointerType(std::string_view &MangledName) { |
2111 | PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); |
2112 | |
2113 | std::tie(args&: Pointer->Quals, args&: Pointer->Affinity) = |
2114 | demanglePointerCVQualifiers(MangledName); |
2115 | assert(Pointer->Affinity == PointerAffinity::Pointer); |
2116 | |
2117 | Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName); |
2118 | Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals); |
2119 | |
2120 | // isMemberPointer() only returns true if there is at least one character |
2121 | // after the qualifiers. |
2122 | if (consumeFront(S&: MangledName, C: "8" )) { |
2123 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); |
2124 | Pointer->Pointee = demangleFunctionType(MangledName, HasThisQuals: true); |
2125 | } else { |
2126 | Qualifiers PointeeQuals = Q_None; |
2127 | bool IsMember = false; |
2128 | std::tie(args&: PointeeQuals, args&: IsMember) = demangleQualifiers(MangledName); |
2129 | assert(IsMember || Error); |
2130 | Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); |
2131 | |
2132 | Pointer->Pointee = demangleType(MangledName, QMM: QualifierMangleMode::Drop); |
2133 | if (Pointer->Pointee) |
2134 | Pointer->Pointee->Quals = PointeeQuals; |
2135 | } |
2136 | |
2137 | return Pointer; |
2138 | } |
2139 | |
2140 | Qualifiers |
2141 | Demangler::demanglePointerExtQualifiers(std::string_view &MangledName) { |
2142 | Qualifiers Quals = Q_None; |
2143 | if (consumeFront(S&: MangledName, C: 'E')) |
2144 | Quals = Qualifiers(Quals | Q_Pointer64); |
2145 | if (consumeFront(S&: MangledName, C: 'I')) |
2146 | Quals = Qualifiers(Quals | Q_Restrict); |
2147 | if (consumeFront(S&: MangledName, C: 'F')) |
2148 | Quals = Qualifiers(Quals | Q_Unaligned); |
2149 | |
2150 | return Quals; |
2151 | } |
2152 | |
2153 | std::optional<PointerAuthQualifierNode::ArgArray> |
2154 | Demangler::demanglePointerAuthQualifier(std::string_view &MangledName) { |
2155 | if (!consumeFront(S&: MangledName, C: "__ptrauth" )) |
2156 | return std::nullopt; |
2157 | |
2158 | constexpr unsigned NumArgs = PointerAuthQualifierNode::NumArgs; |
2159 | PointerAuthQualifierNode::ArgArray Array; |
2160 | |
2161 | for (unsigned I = 0; I < NumArgs; ++I) { |
2162 | bool IsNegative = false; |
2163 | uint64_t Value = 0; |
2164 | std::tie(args&: Value, args&: IsNegative) = demangleNumber(MangledName); |
2165 | if (IsNegative) |
2166 | return std::nullopt; |
2167 | |
2168 | Array[I] = Value; |
2169 | } |
2170 | |
2171 | return Array; |
2172 | } |
2173 | |
2174 | PointerAuthQualifierNode * |
2175 | Demangler::createPointerAuthQualifier(std::string_view &MangledName) { |
2176 | constexpr unsigned NumArgs = PointerAuthQualifierNode::NumArgs; |
2177 | std::optional<PointerAuthQualifierNode::ArgArray> Vals = |
2178 | demanglePointerAuthQualifier(MangledName); |
2179 | |
2180 | if (!Vals) |
2181 | return nullptr; |
2182 | |
2183 | PointerAuthQualifierNode *PtrAuthQual = |
2184 | Arena.alloc<PointerAuthQualifierNode>(); |
2185 | NodeArrayNode *Array = Arena.alloc<NodeArrayNode>(); |
2186 | PtrAuthQual->Components = Array; |
2187 | Array->Count = NumArgs; |
2188 | Array->Nodes = Arena.allocArray<Node *>(Count: NumArgs); |
2189 | |
2190 | for (unsigned I = 0; I < NumArgs; ++I) |
2191 | Array->Nodes[I] = Arena.alloc<IntegerLiteralNode>(ConstructorArgs&: (*Vals)[I], ConstructorArgs: false); |
2192 | |
2193 | return PtrAuthQual; |
2194 | } |
2195 | |
2196 | ArrayTypeNode *Demangler::demangleArrayType(std::string_view &MangledName) { |
2197 | assert(MangledName.front() == 'Y'); |
2198 | MangledName.remove_prefix(n: 1); |
2199 | |
2200 | uint64_t Rank = 0; |
2201 | bool IsNegative = false; |
2202 | std::tie(args&: Rank, args&: IsNegative) = demangleNumber(MangledName); |
2203 | if (IsNegative || Rank == 0) { |
2204 | Error = true; |
2205 | return nullptr; |
2206 | } |
2207 | |
2208 | ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>(); |
2209 | NodeList *Head = Arena.alloc<NodeList>(); |
2210 | NodeList *Tail = Head; |
2211 | |
2212 | for (uint64_t I = 0; I < Rank; ++I) { |
2213 | uint64_t D = 0; |
2214 | std::tie(args&: D, args&: IsNegative) = demangleNumber(MangledName); |
2215 | if (Error || IsNegative) { |
2216 | Error = true; |
2217 | return nullptr; |
2218 | } |
2219 | Tail->N = Arena.alloc<IntegerLiteralNode>(ConstructorArgs&: D, ConstructorArgs&: IsNegative); |
2220 | if (I + 1 < Rank) { |
2221 | Tail->Next = Arena.alloc<NodeList>(); |
2222 | Tail = Tail->Next; |
2223 | } |
2224 | } |
2225 | ATy->Dimensions = nodeListToNodeArray(Arena, Head, Count: Rank); |
2226 | |
2227 | if (consumeFront(S&: MangledName, C: "$$C" )) { |
2228 | bool IsMember = false; |
2229 | std::tie(args&: ATy->Quals, args&: IsMember) = demangleQualifiers(MangledName); |
2230 | if (IsMember) { |
2231 | Error = true; |
2232 | return nullptr; |
2233 | } |
2234 | } |
2235 | |
2236 | ATy->ElementType = demangleType(MangledName, QMM: QualifierMangleMode::Drop); |
2237 | return ATy; |
2238 | } |
2239 | |
2240 | // Reads a function's parameters. |
2241 | NodeArrayNode * |
2242 | Demangler::demangleFunctionParameterList(std::string_view &MangledName, |
2243 | bool &IsVariadic) { |
2244 | // Empty parameter list. |
2245 | if (consumeFront(S&: MangledName, C: 'X')) |
2246 | return nullptr; |
2247 | |
2248 | NodeList *Head = Arena.alloc<NodeList>(); |
2249 | NodeList **Current = &Head; |
2250 | size_t Count = 0; |
2251 | while (!Error && !llvm::itanium_demangle::starts_with(self: MangledName, C: '@') && |
2252 | !llvm::itanium_demangle::starts_with(self: MangledName, C: 'Z')) { |
2253 | ++Count; |
2254 | |
2255 | if (startsWithDigit(S: MangledName)) { |
2256 | size_t N = MangledName[0] - '0'; |
2257 | if (N >= Backrefs.FunctionParamCount) { |
2258 | Error = true; |
2259 | return nullptr; |
2260 | } |
2261 | MangledName.remove_prefix(n: 1); |
2262 | |
2263 | *Current = Arena.alloc<NodeList>(); |
2264 | (*Current)->N = Backrefs.FunctionParams[N]; |
2265 | Current = &(*Current)->Next; |
2266 | continue; |
2267 | } |
2268 | |
2269 | size_t OldSize = MangledName.size(); |
2270 | |
2271 | *Current = Arena.alloc<NodeList>(); |
2272 | TypeNode *TN = demangleType(MangledName, QMM: QualifierMangleMode::Drop); |
2273 | if (!TN || Error) |
2274 | return nullptr; |
2275 | |
2276 | (*Current)->N = TN; |
2277 | |
2278 | size_t CharsConsumed = OldSize - MangledName.size(); |
2279 | assert(CharsConsumed != 0); |
2280 | |
2281 | // Single-letter types are ignored for backreferences because memorizing |
2282 | // them doesn't save anything. |
2283 | if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1) |
2284 | Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN; |
2285 | |
2286 | Current = &(*Current)->Next; |
2287 | } |
2288 | |
2289 | if (Error) |
2290 | return nullptr; |
2291 | |
2292 | NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count); |
2293 | // A non-empty parameter list is terminated by either 'Z' (variadic) parameter |
2294 | // list or '@' (non variadic). Careful not to consume "@Z", as in that case |
2295 | // the following Z could be a throw specifier. |
2296 | if (consumeFront(S&: MangledName, C: '@')) |
2297 | return NA; |
2298 | |
2299 | if (consumeFront(S&: MangledName, C: 'Z')) { |
2300 | IsVariadic = true; |
2301 | return NA; |
2302 | } |
2303 | |
2304 | DEMANGLE_UNREACHABLE; |
2305 | } |
2306 | |
2307 | NodeArrayNode * |
2308 | Demangler::demangleTemplateParameterList(std::string_view &MangledName) { |
2309 | NodeList *Head = nullptr; |
2310 | NodeList **Current = &Head; |
2311 | size_t Count = 0; |
2312 | |
2313 | while (!llvm::itanium_demangle::starts_with(self: MangledName, C: '@')) { |
2314 | if (consumeFront(S&: MangledName, C: "$S" ) || consumeFront(S&: MangledName, C: "$$V" ) || |
2315 | consumeFront(S&: MangledName, C: "$$$V" ) || consumeFront(S&: MangledName, C: "$$Z" )) { |
2316 | // parameter pack separator |
2317 | continue; |
2318 | } |
2319 | |
2320 | ++Count; |
2321 | |
2322 | // Template parameter lists don't participate in back-referencing. |
2323 | *Current = Arena.alloc<NodeList>(); |
2324 | |
2325 | NodeList &TP = **Current; |
2326 | |
2327 | // <auto-nttp> ::= $ M <type> <nttp> |
2328 | const bool IsAutoNTTP = consumeFront(S&: MangledName, C: "$M" ); |
2329 | if (IsAutoNTTP) { |
2330 | // The deduced type of the auto NTTP parameter isn't printed so |
2331 | // we want to ignore the AST created from demangling the type. |
2332 | // |
2333 | // TODO: Avoid the extra allocations to the bump allocator in this case. |
2334 | (void)demangleType(MangledName, QMM: QualifierMangleMode::Drop); |
2335 | if (Error) |
2336 | return nullptr; |
2337 | } |
2338 | |
2339 | TemplateParameterReferenceNode *TPRN = nullptr; |
2340 | if (consumeFront(S&: MangledName, C: "$$Y" )) { |
2341 | // Template alias |
2342 | TP.N = demangleFullyQualifiedTypeName(MangledName); |
2343 | } else if (consumeFront(S&: MangledName, C: "$$B" )) { |
2344 | // Array |
2345 | TP.N = demangleType(MangledName, QMM: QualifierMangleMode::Drop); |
2346 | } else if (consumeFront(S&: MangledName, C: "$$C" )) { |
2347 | // Type has qualifiers. |
2348 | TP.N = demangleType(MangledName, QMM: QualifierMangleMode::Mangle); |
2349 | } else if (startsWith(S: MangledName, PrefixA: "$1" , PrefixB: "1" , A: !IsAutoNTTP) || |
2350 | startsWith(S: MangledName, PrefixA: "$H" , PrefixB: "H" , A: !IsAutoNTTP) || |
2351 | startsWith(S: MangledName, PrefixA: "$I" , PrefixB: "I" , A: !IsAutoNTTP) || |
2352 | startsWith(S: MangledName, PrefixA: "$J" , PrefixB: "J" , A: !IsAutoNTTP)) { |
2353 | // Pointer to member |
2354 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); |
2355 | TPRN->IsMemberPointer = true; |
2356 | |
2357 | if (!IsAutoNTTP) |
2358 | MangledName.remove_prefix(n: 1); // Remove leading '$' |
2359 | |
2360 | // 1 - single inheritance <name> |
2361 | // H - multiple inheritance <name> <number> |
2362 | // I - virtual inheritance <name> <number> <number> |
2363 | // J - unspecified inheritance <name> <number> <number> <number> |
2364 | char InheritanceSpecifier = MangledName.front(); |
2365 | MangledName.remove_prefix(n: 1); |
2366 | SymbolNode *S = nullptr; |
2367 | if (llvm::itanium_demangle::starts_with(self: MangledName, C: '?')) { |
2368 | S = parse(MangledName); |
2369 | if (Error || !S->Name) { |
2370 | Error = true; |
2371 | return nullptr; |
2372 | } |
2373 | memorizeIdentifier(Identifier: S->Name->getUnqualifiedIdentifier()); |
2374 | } |
2375 | |
2376 | switch (InheritanceSpecifier) { |
2377 | case 'J': |
2378 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2379 | demangleSigned(MangledName); |
2380 | DEMANGLE_FALLTHROUGH; |
2381 | case 'I': |
2382 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2383 | demangleSigned(MangledName); |
2384 | DEMANGLE_FALLTHROUGH; |
2385 | case 'H': |
2386 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2387 | demangleSigned(MangledName); |
2388 | DEMANGLE_FALLTHROUGH; |
2389 | case '1': |
2390 | break; |
2391 | default: |
2392 | DEMANGLE_UNREACHABLE; |
2393 | } |
2394 | TPRN->Affinity = PointerAffinity::Pointer; |
2395 | TPRN->Symbol = S; |
2396 | } else if (llvm::itanium_demangle::starts_with(haystack: MangledName, needle: "$E?" )) { |
2397 | consumeFront(S&: MangledName, C: "$E" ); |
2398 | // Reference to symbol |
2399 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); |
2400 | TPRN->Symbol = parse(MangledName); |
2401 | TPRN->Affinity = PointerAffinity::Reference; |
2402 | } else if (startsWith(S: MangledName, PrefixA: "$F" , PrefixB: "F" , A: !IsAutoNTTP) || |
2403 | startsWith(S: MangledName, PrefixA: "$G" , PrefixB: "G" , A: !IsAutoNTTP)) { |
2404 | TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); |
2405 | |
2406 | // Data member pointer. |
2407 | if (!IsAutoNTTP) |
2408 | MangledName.remove_prefix(n: 1); // Remove leading '$' |
2409 | char InheritanceSpecifier = MangledName.front(); |
2410 | MangledName.remove_prefix(n: 1); |
2411 | |
2412 | switch (InheritanceSpecifier) { |
2413 | case 'G': |
2414 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2415 | demangleSigned(MangledName); |
2416 | DEMANGLE_FALLTHROUGH; |
2417 | case 'F': |
2418 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2419 | demangleSigned(MangledName); |
2420 | TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] = |
2421 | demangleSigned(MangledName); |
2422 | break; |
2423 | default: |
2424 | DEMANGLE_UNREACHABLE; |
2425 | } |
2426 | TPRN->IsMemberPointer = true; |
2427 | |
2428 | } else if (consumeFront(S&: MangledName, PrefixA: "$0" , PrefixB: "0" , A: !IsAutoNTTP)) { |
2429 | // Integral non-type template parameter |
2430 | bool IsNegative = false; |
2431 | uint64_t Value = 0; |
2432 | std::tie(args&: Value, args&: IsNegative) = demangleNumber(MangledName); |
2433 | |
2434 | TP.N = Arena.alloc<IntegerLiteralNode>(ConstructorArgs&: Value, ConstructorArgs&: IsNegative); |
2435 | } else { |
2436 | TP.N = demangleType(MangledName, QMM: QualifierMangleMode::Drop); |
2437 | } |
2438 | if (Error) |
2439 | return nullptr; |
2440 | |
2441 | Current = &TP.Next; |
2442 | } |
2443 | |
2444 | // The loop above returns nullptr on Error. |
2445 | assert(!Error); |
2446 | |
2447 | // Template parameter lists cannot be variadic, so it can only be terminated |
2448 | // by @ (as opposed to 'Z' in the function parameter case). |
2449 | assert(llvm::itanium_demangle::starts_with( |
2450 | MangledName, '@')); // The above loop exits only on '@'. |
2451 | consumeFront(S&: MangledName, C: '@'); |
2452 | return nodeListToNodeArray(Arena, Head, Count); |
2453 | } |
2454 | |
2455 | void Demangler::dumpBackReferences() { |
2456 | std::printf(format: "%d function parameter backreferences\n" , |
2457 | (int)Backrefs.FunctionParamCount); |
2458 | |
2459 | // Create an output stream so we can render each type. |
2460 | OutputBuffer OB; |
2461 | for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) { |
2462 | OB.setCurrentPosition(0); |
2463 | |
2464 | TypeNode *T = Backrefs.FunctionParams[I]; |
2465 | T->output(OB, Flags: OF_Default); |
2466 | |
2467 | std::string_view B = OB; |
2468 | std::printf(format: " [%d] - %.*s\n" , (int)I, (int)B.size(), B.data()); |
2469 | } |
2470 | std::free(ptr: OB.getBuffer()); |
2471 | |
2472 | if (Backrefs.FunctionParamCount > 0) |
2473 | std::printf(format: "\n" ); |
2474 | std::printf(format: "%d name backreferences\n" , (int)Backrefs.NamesCount); |
2475 | for (size_t I = 0; I < Backrefs.NamesCount; ++I) { |
2476 | std::printf(format: " [%d] - %.*s\n" , (int)I, (int)Backrefs.Names[I]->Name.size(), |
2477 | Backrefs.Names[I]->Name.data()); |
2478 | } |
2479 | if (Backrefs.NamesCount > 0) |
2480 | std::printf(format: "\n" ); |
2481 | } |
2482 | |
2483 | std::optional<size_t> |
2484 | llvm::getArm64ECInsertionPointInMangledName(std::string_view MangledName) { |
2485 | std::string_view ProcessedName{MangledName}; |
2486 | |
2487 | // We only support this for MSVC-style C++ symbols. |
2488 | if (!consumeFront(S&: ProcessedName, C: '?')) |
2489 | return std::nullopt; |
2490 | |
2491 | // The insertion point is just after the name of the symbol, so parse that to |
2492 | // remove it from the processed name. |
2493 | Demangler D; |
2494 | D.demangleFullyQualifiedSymbolName(MangledName&: ProcessedName); |
2495 | if (D.Error) |
2496 | return std::nullopt; |
2497 | |
2498 | return MangledName.length() - ProcessedName.length(); |
2499 | } |
2500 | |
2501 | char *llvm::microsoftDemangle(std::string_view MangledName, size_t *NMangled, |
2502 | int *Status, MSDemangleFlags Flags) { |
2503 | Demangler D; |
2504 | |
2505 | std::string_view Name{MangledName}; |
2506 | SymbolNode *AST = D.parse(MangledName&: Name); |
2507 | if (!D.Error && NMangled) |
2508 | *NMangled = MangledName.size() - Name.size(); |
2509 | |
2510 | if (Flags & MSDF_DumpBackrefs) |
2511 | D.dumpBackReferences(); |
2512 | |
2513 | OutputFlags OF = OF_Default; |
2514 | if (Flags & MSDF_NoCallingConvention) |
2515 | OF = OutputFlags(OF | OF_NoCallingConvention); |
2516 | if (Flags & MSDF_NoAccessSpecifier) |
2517 | OF = OutputFlags(OF | OF_NoAccessSpecifier); |
2518 | if (Flags & MSDF_NoReturnType) |
2519 | OF = OutputFlags(OF | OF_NoReturnType); |
2520 | if (Flags & MSDF_NoMemberType) |
2521 | OF = OutputFlags(OF | OF_NoMemberType); |
2522 | if (Flags & MSDF_NoVariableType) |
2523 | OF = OutputFlags(OF | OF_NoVariableType); |
2524 | |
2525 | int InternalStatus = demangle_success; |
2526 | char *Buf; |
2527 | if (D.Error) |
2528 | InternalStatus = demangle_invalid_mangled_name; |
2529 | else { |
2530 | OutputBuffer OB; |
2531 | AST->output(OB, Flags: OF); |
2532 | OB += '\0'; |
2533 | Buf = OB.getBuffer(); |
2534 | } |
2535 | |
2536 | if (Status) |
2537 | *Status = InternalStatus; |
2538 | return InternalStatus == demangle_success ? Buf : nullptr; |
2539 | } |
2540 | |