1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[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
This commit is contained in:
Zachary Turner 2018-08-21 21:23:49 +00:00
parent b7d1c521b2
commit 7a7fb4f525
4 changed files with 77 additions and 18 deletions

View File

@ -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;

View File

@ -392,3 +392,6 @@
??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ
; CHECK: __thiscall PR26029::L<class PR26029::H<int *>>::L<class PR26029::H<int *>>(void)
; ??$emplace_back@ABH@?$vector@HV?$allocator@H@std@@@std@@QAE?A?<decltype-auto>@@ABH@Z
<decltype-auto> __thiscall std::vector<int, class std::allocator<int>>::emplace_back<int const &>(int const &)

View File

@ -140,6 +140,9 @@
??_7Base@@6B@
; CHECK: const Base::`vftable'
??_7A@B@@6BC@D@@@
; CHECK: const B::A::`vftable'{for `D::C'}
??_8Middle2@@7B@
; CHECK: const Middle2::`vbtable'

View File

@ -93,3 +93,5 @@
??$ReadField@UV@@$FM@A@@@YAHAAUV@@@Z
; CHECK: int __cdecl ReadField<struct V, {12, 0}>(struct V &)
?Q@@3$$QEAP8Foo@@EAAXXZEA
; CHECK: void (__cdecl Foo::*&&Q)(void)