From 99582cddc79f98bf499a87b4c8683e57438e6a90 Mon Sep 17 00:00:00 2001 From: Nerixyz Date: Wed, 27 Aug 2025 15:58:02 +0200 Subject: [PATCH 1/3] [MsDemangle] Read entire chain of target names in special table --- .../llvm/Demangle/MicrosoftDemangleNodes.h | 2 +- llvm/lib/Demangle/MicrosoftDemangle.cpp | 50 +++++++++++++------ llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 4 +- llvm/test/Demangle/ms-operators.test | 15 ++++++ 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h index 155cfe8dd3a98..711aa70a4a8d3 100644 --- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -708,7 +708,7 @@ struct DEMANGLE_ABI SpecialTableSymbolNode : public SymbolNode { return N->kind() == NodeKind::SpecialTableSymbol; } - QualifiedNameNode *TargetName = nullptr; + NodeArrayNode *TargetNames = nullptr; Qualifiers Quals = Qualifiers::Q_None; }; diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index b22928be3be50..0aefe6e077c24 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -277,6 +277,18 @@ demanglePointerCVQualifiers(std::string_view &MangledName) { DEMANGLE_UNREACHABLE; } +static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, + size_t Count) { + NodeArrayNode *N = Arena.alloc(); + N->Count = Count; + N->Nodes = Arena.allocArray(Count); + for (size_t I = 0; I < Count; ++I) { + N->Nodes[I] = Head->N; + Head = Head->Next; + } + return N; +} + std::string_view Demangler::copyString(std::string_view Borrowed) { char *Stable = Arena.allocUnalignedBuffer(Borrowed.size()); // This is not a micro-optimization, it avoids UB, should Borrowed be an null @@ -323,8 +335,30 @@ Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName, } std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName); - if (!consumeFront(MangledName, '@')) - STSN->TargetName = demangleFullyQualifiedTypeName(MangledName); + + NodeList *TargetCurrent = nullptr; + NodeList *TargetHead = nullptr; + size_t Count = 0; + while (!consumeFront(MangledName, '@')) { + ++Count; + + NodeList *Next = Arena.alloc(); + if (TargetCurrent) + TargetCurrent->Next = Next; + else + TargetHead = Next; + + TargetCurrent = Next; + QualifiedNameNode *QN = demangleFullyQualifiedTypeName(MangledName); + if (Error) + return nullptr; + assert(QN); + TargetCurrent->N = QN; + } + + if (Count > 0) + STSN->TargetNames = nodeListToNodeArray(Arena, TargetHead, Count); + return STSN; } @@ -1605,18 +1639,6 @@ Demangler::demangleNameScopePiece(std::string_view &MangledName) { return demangleSimpleName(MangledName, /*Memorize=*/true); } -static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, - size_t Count) { - NodeArrayNode *N = Arena.alloc(); - N->Count = Count; - N->Nodes = Arena.allocArray(Count); - for (size_t I = 0; I < Count; ++I) { - N->Nodes[I] = Head->N; - Head = Head->Next; - } - return N; -} - QualifiedNameNode * Demangler::demangleNameScopeChain(std::string_view &MangledName, IdentifierNode *UnqualifiedName) { diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp index 61e4961c714bc..17c6aab500049 100644 --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -662,9 +662,9 @@ void VcallThunkIdentifierNode::output(OutputBuffer &OB, void SpecialTableSymbolNode::output(OutputBuffer &OB, OutputFlags Flags) const { outputQualifiers(OB, Quals, false, true); Name->output(OB, Flags); - if (TargetName) { + if (TargetNames) { OB << "{for `"; - TargetName->output(OB, Flags); + TargetNames->output(OB, Flags, "'s `"); OB << "'}"; } } diff --git a/llvm/test/Demangle/ms-operators.test b/llvm/test/Demangle/ms-operators.test index b940488786631..cafa1ae3c0663 100644 --- a/llvm/test/Demangle/ms-operators.test +++ b/llvm/test/Demangle/ms-operators.test @@ -143,9 +143,24 @@ ??_7A@B@@6BC@D@@@ ; CHECK: const B::A::`vftable'{for `D::C'} +??_7A@B@@6BC@D@@E@F@@@ +; CHECK: const B::A::`vftable'{for `D::C's `F::E'} + +??_7A@B@@6BC@D@@E@F@@G@H@@@ +; CHECK: const B::A::`vftable'{for `D::C's `F::E's `H::G'} + ??_8Middle2@@7B@ ; CHECK: const Middle2::`vbtable' +??_7A@@6BB@@@ +; CHECK: const A::`vftable'{for `B'} + +??_7A@@6BB@@C@@@ +; CHECK: const A::`vftable'{for `B's `C'} + +??_7A@@6BB@@C@@D@@@ +; CHECK: const A::`vftable'{for `B's `C's `D'} + ??_9Base@@$B7AA ; CHECK: [thunk]: __cdecl Base::`vcall'{8, {flat}} From 544e9d2f383179b8c6f0972009ce719e7f1cc0c9 Mon Sep 17 00:00:00 2001 From: Nerixyz Date: Wed, 5 Nov 2025 15:23:54 +0100 Subject: [PATCH 2/3] fix: use small vector --- llvm/lib/Demangle/MicrosoftDemangle.cpp | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 0aefe6e077c24..f5013640d162a 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -15,6 +15,7 @@ #include "llvm/Demangle/MicrosoftDemangle.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Demangle/Demangle.h" #include "llvm/Demangle/DemangleConfig.h" #include "llvm/Demangle/MicrosoftDemangleNodes.h" @@ -289,6 +290,16 @@ static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, return N; } +template +static NodeArrayNode *smallVecToNodeArray(ArenaAllocator &Arena, + const SmallVector &Vec) { + NodeArrayNode *Arr = Arena.alloc(); + Arr->Count = Vec.size(); + Arr->Nodes = Arena.allocArray(Vec.size()); + std::memcpy(Arr->Nodes, Vec.data(), Vec.size() * sizeof(Node *)); + return Arr; +} + std::string_view Demangler::copyString(std::string_view Borrowed) { char *Stable = Arena.allocUnalignedBuffer(Borrowed.size()); // This is not a micro-optimization, it avoids UB, should Borrowed be an null @@ -336,28 +347,17 @@ Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName, std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName); - NodeList *TargetCurrent = nullptr; - NodeList *TargetHead = nullptr; - size_t Count = 0; + SmallVector TargetNames; while (!consumeFront(MangledName, '@')) { - ++Count; - - NodeList *Next = Arena.alloc(); - if (TargetCurrent) - TargetCurrent->Next = Next; - else - TargetHead = Next; - - TargetCurrent = Next; QualifiedNameNode *QN = demangleFullyQualifiedTypeName(MangledName); if (Error) return nullptr; assert(QN); - TargetCurrent->N = QN; + TargetNames.push_back(QN); } - if (Count > 0) - STSN->TargetNames = nodeListToNodeArray(Arena, TargetHead, Count); + if (!TargetNames.empty()) + STSN->TargetNames = smallVecToNodeArray(Arena, TargetNames); return STSN; } From 7e181010d715aa64349ecd17c43e5468e65978e5 Mon Sep 17 00:00:00 2001 From: Nerixyz Date: Wed, 5 Nov 2025 16:02:11 +0100 Subject: [PATCH 3/3] fix: use ArrayRef and move nodeListToNodeArray back --- llvm/lib/Demangle/MicrosoftDemangle.cpp | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index f5013640d162a..250d382998982 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -15,6 +15,7 @@ #include "llvm/Demangle/MicrosoftDemangle.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Demangle/Demangle.h" #include "llvm/Demangle/DemangleConfig.h" @@ -278,21 +279,8 @@ demanglePointerCVQualifiers(std::string_view &MangledName) { DEMANGLE_UNREACHABLE; } -static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, - size_t Count) { - NodeArrayNode *N = Arena.alloc(); - N->Count = Count; - N->Nodes = Arena.allocArray(Count); - for (size_t I = 0; I < Count; ++I) { - N->Nodes[I] = Head->N; - Head = Head->Next; - } - return N; -} - -template static NodeArrayNode *smallVecToNodeArray(ArenaAllocator &Arena, - const SmallVector &Vec) { + ArrayRef Vec) { NodeArrayNode *Arr = Arena.alloc(); Arr->Count = Vec.size(); Arr->Nodes = Arena.allocArray(Vec.size()); @@ -1639,6 +1627,18 @@ Demangler::demangleNameScopePiece(std::string_view &MangledName) { return demangleSimpleName(MangledName, /*Memorize=*/true); } +static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, + size_t Count) { + NodeArrayNode *N = Arena.alloc(); + N->Count = Count; + N->Nodes = Arena.allocArray(Count); + for (size_t I = 0; I < Count; ++I) { + N->Nodes[I] = Head->N; + Head = Head->Next; + } + return N; +} + QualifiedNameNode * Demangler::demangleNameScopeChain(std::string_view &MangledName, IdentifierNode *UnqualifiedName) {