diff options
author | Zachary Turner <zturner@google.com> | 2018-08-21 21:23:49 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2018-08-21 21:23:49 +0000 |
commit | df4cd7cbf97c23f363ca07dc4038ecc48c1e6623 (patch) | |
tree | 350b2a3bac606c85da2ffce3d9129860f5afcc9f /llvm/lib/Demangle | |
parent | 4ca11217fcd6c8892cfb688f5f4fe9588d55dee0 (diff) | |
download | bcm5719-llvm-df4cd7cbf97c23f363ca07dc4038ecc48c1e6623.tar.gz bcm5719-llvm-df4cd7cbf97c23f363ca07dc4038ecc48c1e6623.zip |
[MS Demangler] Fix a few more edge cases.
I found these by running llvm-undname over a couple hundred
megabytes of object files generated as part of building chromium.
The issues fixed in this patch are:
1) decltype-auto return types.
2) Indirect vtables (e.g. const A::`vftable'{for `B'})
3) Pointers, references, and rvalue-references to member pointers.
I have exactly one remaining symbol out of a few hundred MB of object
files that produces a name we can't demangle, and it's related to
back-referencing.
llvm-svn: 340341
Diffstat (limited to 'llvm/lib/Demangle')
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangle.cpp | 87 |
1 files changed, 69 insertions, 18 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 69e0a73e651..6145539a819 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -193,6 +193,7 @@ enum class PrimTy : uint8_t { Double, Ldouble, Nullptr, + Custom, Vftable, Vbtable, LocalStaticGuard @@ -271,8 +272,17 @@ enum class OperatorTy : uint8_t { LocalVftableCtorClosure, // ?_T # local vftable constructor closure ArrayNew, // ?_U operator new[] ArrayDelete, // ?_V operator delete[] + ManVectorCtorIter, // ?__A managed vector ctor iterator + ManVectorDtorIter, // ?__B managed vector dtor iterator + EHVectorCopyCtorIter, // ?__C EH vector copy ctor iterator + EHVectorVbaseCopyCtorIter, // ?__D EH vector vbase copy ctor iterator DynamicInitializer, // ?__E dynamic initializer for `T' DynamicAtexitDestructor, // ?__F dynamic atexit destructor for `T' + VectorCopyCtorIter, // ?__G vector copy constructor iterator + VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator + ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor + // iterator + LocalStaticThreadGuard, // ?__J local static thread guard LiteralOperator, // ?__K operator ""_name CoAwait, // ?__L co_await Spaceship, // operator<=> @@ -362,8 +372,19 @@ OperatorMapEntry OperatorMap[] = { {"_T", "`local vftable ctor closure'", OperatorTy::LocalVftableCtorClosure}, {"_U", "operator new[]", OperatorTy::ArrayNew}, {"_V", "operator delete[]", OperatorTy::ArrayDelete}, + {"__A", "managed vector ctor iterator", OperatorTy::ManVectorCtorIter}, + {"__B", "managed vector dtor iterator", OperatorTy::ManVectorDtorIter}, + {"__C", "EH vector copy ctor iterator", OperatorTy::EHVectorCopyCtorIter}, + {"__D", "EH vector vbase copy ctor iterator", + OperatorTy::EHVectorVbaseCopyCtorIter}, {"__E", "dynamic initializer", OperatorTy::DynamicInitializer}, {"__F", "dynamic atexit destructor", OperatorTy::DynamicAtexitDestructor}, + {"__G", "vector copy ctor iterator", OperatorTy::VectorCopyCtorIter}, + {"__H", "vector vbase copy constructor iterator", + OperatorTy::VectorVbaseCopyCtorIter}, + {"__I", "managed vector vbase copy constructor iterator", + OperatorTy::ManVectorVbaseCopyCtorIter}, + {"__J", "local static thread guard", OperatorTy::LocalStaticThreadGuard}, {"__K", "operator \"\"", OperatorTy::LiteralOperator}, {"__L", "co_await", OperatorTy::CoAwait}, }; @@ -467,6 +488,7 @@ struct Type { PrimTy Prim = PrimTy::Unknown; Qualifiers Quals = Q_None; + StringView Custom; StorageClass Storage = StorageClass::None; // storage class }; @@ -498,6 +520,19 @@ struct OperatorInfo : public Name { : OperatorInfo(OperatorMap[(int)OpType]) {} const OperatorMapEntry *Info = nullptr; + bool IsIndirectTable = false; +}; + +struct IndirectTable : public OperatorInfo { + explicit IndirectTable(const OperatorMapEntry &Info) : OperatorInfo(Info) { + this->IsOperator = true; + this->IsIndirectTable = true; + } + explicit IndirectTable(OperatorTy OpType) + : IndirectTable(OperatorMap[(int)OpType]) {} + + const Name *TableLocation = nullptr; + const Name *TableTarget = nullptr; }; struct StringLiteral : public OperatorInfo { @@ -889,6 +924,14 @@ static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty) { const VirtualMemberPtrThunk *Thunk = nullptr; bool PrintLastScopeSeparator = true; if (Operator) { + if (Operator->IsIndirectTable) { + const IndirectTable *Table = static_cast<const IndirectTable *>(Operator); + outputName(OS, Table->TableLocation, nullptr); + OS << "{for `"; + outputName(OS, Table->TableTarget, nullptr); + OS << "'}"; + return; + } if (Operator->Info->Operator == OperatorTy::Vcall) { Thunk = static_cast<const VirtualMemberPtrThunk *>(Operator); OS << "[thunk]: "; @@ -1116,6 +1159,9 @@ void Type::outputPre(OutputStream &OS) { case PrimTy::Nullptr: OS << "std::nullptr_t"; break; + case PrimTy::Custom: + OS << Custom; + break; case PrimTy::Vbtable: case PrimTy::Vftable: break; @@ -1479,11 +1525,16 @@ Symbol *Demangler::parseOperator(StringView &MangledName) { S->Category = SymbolCategory::UnnamedVariable; switch (MangledName.popFront()) { case '6': - case '7': + case '7': { std::tie(S->SymbolQuals, IsMember) = demangleQualifiers(MangledName); - if (!MangledName.consumeFront('@')) - Error = true; + if (!MangledName.consumeFront('@')) { + IndirectTable *Table = Arena.alloc<IndirectTable>(OTy); + Table->TableTarget = demangleFullyQualifiedTypeName(MangledName); + Table->TableLocation = S->SymbolName; + S->SymbolName = Table; + } break; + } default: Error = true; break; @@ -1754,8 +1805,9 @@ Demangler::demangleOperatorName(StringView &MangledName, bool FullyQualified) { case OperatorTy::LocalVftable: // Foo@@6B@ case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@ case OperatorTy::Vbtable: { // Foo@@7B@ - OperatorInfo *Oper = Arena.alloc<OperatorInfo>(*Entry); - N = (FullyQualified) ? demangleNameScopeChain(MangledName, Oper) : Oper; + N = Arena.alloc<OperatorInfo>(*Entry); + if (FullyQualified) + N = demangleNameScopeChain(MangledName, N); break; } @@ -2515,25 +2567,18 @@ Type *Demangler::demangleType(StringView &MangledName, QualifierMangleMode QMM) { Qualifiers Quals = Q_None; bool IsMember = false; - bool IsMemberKnown = false; if (QMM == QualifierMangleMode::Mangle) { std::tie(Quals, IsMember) = demangleQualifiers(MangledName); - IsMemberKnown = true; } else if (QMM == QualifierMangleMode::Result) { - if (MangledName.consumeFront('?')) { + if (MangledName.consumeFront('?')) std::tie(Quals, IsMember) = demangleQualifiers(MangledName); - IsMemberKnown = true; - } } Type *Ty = nullptr; if (isTagType(MangledName)) Ty = demangleClassType(MangledName); else if (isPointerType(MangledName)) { - if (!IsMemberKnown) - IsMember = isMemberPointer(MangledName); - - if (IsMember) + if (isMemberPointer(MangledName)) Ty = demangleMemberPointerType(MangledName); else Ty = demanglePointerType(MangledName); @@ -2648,6 +2693,15 @@ Type *Demangler::demangleBasicType(StringView &MangledName) { Ty->Prim = PrimTy::Nullptr; return Ty; } + if (MangledName.consumeFront("?")) { + Ty->Prim = PrimTy::Custom; + Ty->Custom = demangleSimpleString(MangledName, false); + if (!MangledName.consumeFront('@')) { + Error = true; + return nullptr; + } + return Ty; + } switch (MangledName.popFront()) { case 'X': @@ -2955,10 +3009,7 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || MangledName.consumeFront("$$$V")) { TP.IsEmptyParameterPack = true; - break; - } - - if (MangledName.consumeFront("$$Y")) { + } else if (MangledName.consumeFront("$$Y")) { // Template alias TP.IsTemplateTemplate = true; TP.IsAliasTemplate = true; |