diff options
| author | Zachary Turner <zturner@google.com> | 2018-09-21 22:36:04 +0000 |
|---|---|---|
| committer | Zachary Turner <zturner@google.com> | 2018-09-21 22:36:04 +0000 |
| commit | 355ffb0032182e74f64349dc7e4b941147bac2a2 (patch) | |
| tree | 94e7412254a486f98b5faf0ee6e0c8ae58ead533 /llvm/lib/DebugInfo/PDB | |
| parent | 10febb0779ec74ed9090bcc11667567910a807d5 (diff) | |
| download | bcm5719-llvm-355ffb0032182e74f64349dc7e4b941147bac2a2.tar.gz bcm5719-llvm-355ffb0032182e74f64349dc7e4b941147bac2a2.zip | |
[PDB] Add native reading support for UDT / class types.
This allows the native reader to find records of class/struct/
union type and dump them. This behavior is tested by using the
diadump subcommand against golden output produced by actual DIA
SDK on the same PDB file, and again using pretty -native to
confirm that we actually dump the classes. We don't find class
members or anything like that yet, for now it's just the class
itself.
llvm-svn: 342779
Diffstat (limited to 'llvm/lib/DebugInfo/PDB')
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp | 29 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp | 117 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp | 221 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp | 80 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp | 32 |
8 files changed, 377 insertions, 131 deletions
diff --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt index 8bf16c505cb..db39ba3b0ee 100644 --- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -55,6 +55,7 @@ add_pdb_impl_folder(Native Native/NativeTypeBuiltin.cpp Native/NativeTypeEnum.cpp Native/NativeTypePointer.cpp + Native/NativeTypeUDT.cpp Native/NamedStreamMap.cpp Native/NativeSession.cpp Native/PDBFile.cpp diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp index 97348a55d61..f16b776dc65 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" @@ -22,21 +23,24 @@ using namespace llvm::pdb; NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, LazyRandomTypeCollection &Types, - TypeLeafKind Kind) + std::vector<codeview::TypeLeafKind> Kinds) : Matches(), Index(0), Session(PDBSession) { Optional<TypeIndex> TI = Types.getFirst(); while (TI) { CVType CVT = Types.getType(*TI); TypeLeafKind K = CVT.kind(); - if (K == Kind) - Matches.push_back(*TI); - else if (K == TypeLeafKind::LF_MODIFIER) { - ModifierRecord MR; - if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, MR)) { - consumeError(std::move(EC)); - } else if (!MR.ModifiedType.isSimple()) { - CVType UnmodifiedCVT = Types.getType(MR.ModifiedType); - if (UnmodifiedCVT.kind() == Kind) + if (llvm::is_contained(Kinds, K)) { + // Don't add forward refs, we'll find those later while enumerating. + if (!isUdtForwardRef(CVT)) + Matches.push_back(*TI); + } else if (K == TypeLeafKind::LF_MODIFIER) { + TypeIndex ModifiedTI = getModifiedType(CVT); + if (!ModifiedTI.isSimple()) { + CVType UnmodifiedCVT = Types.getType(ModifiedTI); + // LF_MODIFIERs point to forward refs, but don't worry about that + // here. We're pushing the TypeIndex of the LF_MODIFIER itself, + // so we'll worry about resolving forward refs later. + if (llvm::is_contained(Kinds, UnmodifiedCVT.kind())) Matches.push_back(*TI); } } @@ -44,11 +48,6 @@ NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, } } -NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, - const std::vector<TypeIndex> &Matches, - TypeLeafKind Kind) - : Matches(Matches), Index(0), Session(PDBSession) {} - uint32_t NativeEnumTypes::getChildCount() const { return static_cast<uint32_t>(Matches.size()); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index 97d20d4d3bb..ca173808358 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -45,6 +45,10 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const { return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM); case PDB_SymType::PointerType: return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER); + case PDB_SymType::UDT: + return Session.getSymbolCache().createTypeEnumerator( + {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION, + codeview::LF_INTERFACE}); default: break; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 1a8c75db998..62950cb3e52 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -31,68 +31,68 @@ void NativeRawSymbol::dump(raw_ostream &OS, int Indent, std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLines() const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp index 0994be4af42..37176fe083b 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -40,8 +40,7 @@ namespace { class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks { public: NativeEnumEnumEnumerators(NativeSession &Session, - const NativeTypeEnum &ClassParent, - const codeview::EnumRecord &CVEnum); + const NativeTypeEnum &ClassParent); uint32_t getChildCount() const override; std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; @@ -56,7 +55,6 @@ private: NativeSession &Session; const NativeTypeEnum &ClassParent; - const codeview::EnumRecord &CVEnum; std::vector<EnumeratorRecord> Enumerators; Optional<TypeIndex> ContinuationIndex; uint32_t Index = 0; @@ -64,13 +62,12 @@ private: } // namespace NativeEnumEnumEnumerators::NativeEnumEnumEnumerators( - NativeSession &Session, const NativeTypeEnum &ClassParent, - const codeview::EnumRecord &CVEnum) - : Session(Session), ClassParent(ClassParent), CVEnum(CVEnum) { + NativeSession &Session, const NativeTypeEnum &ClassParent) + : Session(Session), ClassParent(ClassParent) { TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); LazyRandomTypeCollection &Types = Tpi.typeCollection(); - ContinuationIndex = CVEnum.FieldList; + ContinuationIndex = ClassParent.getEnumRecord().FieldList; while (ContinuationIndex) { CVType FieldList = Types.getType(*ContinuationIndex); assert(FieldList.kind() == LF_FIELDLIST); @@ -100,10 +97,10 @@ NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const { if (Index >= getChildCount()) return nullptr; - SymIndexId Id = - Session.getSymbolCache() - .getOrCreateFieldListMember<NativeSymbolEnumerator>( - CVEnum.FieldList, Index, ClassParent, Enumerators[Index]); + SymIndexId Id = Session.getSymbolCache() + .getOrCreateFieldListMember<NativeSymbolEnumerator>( + ClassParent.getEnumRecord().FieldList, Index, + ClassParent, Enumerators[Index]); return Session.getSymbolCache().getSymbolById(Id); } @@ -122,11 +119,10 @@ NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, Record(std::move(Record)) {} NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, - codeview::TypeIndex ModifierTI, - codeview::ModifierRecord Modifier, - codeview::EnumRecord EnumRecord) - : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(ModifierTI), - Record(std::move(EnumRecord)), Modifiers(std::move(Modifier)) {} + NativeTypeEnum &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::Enum, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} NativeTypeEnum::~NativeTypeEnum() {} @@ -173,22 +169,20 @@ NativeTypeEnum::findChildren(PDB_SymType Type) const { const NativeTypeEnum *ClassParent = nullptr; if (!Modifiers) ClassParent = this; - else { - NativeRawSymbol &NRS = - Session.getSymbolCache().getNativeSymbolById(getUnmodifiedTypeId()); - assert(NRS.getSymTag() == PDB_SymType::Enum); - ClassParent = static_cast<NativeTypeEnum *>(&NRS); - } - return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent, - Record); + else + ClassParent = UnmodifiedType; + return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent); } PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; } PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { - Session.getSymbolCache().findSymbolByTypeIndex(Record.getUnderlyingType()); + if (UnmodifiedType) + return UnmodifiedType->getBuiltinType(); + + Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType()); - codeview::TypeIndex Underlying = Record.getUnderlyingType(); + codeview::TypeIndex Underlying = Record->getUnderlyingType(); // This indicates a corrupt record. if (!Underlying.isSimple() || @@ -255,67 +249,101 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { } SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const { - if (!Modifiers) - return 0; - - return Session.getSymbolCache().findSymbolByTypeIndex( - Modifiers->ModifiedType); + return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0; } bool NativeTypeEnum::hasConstructor() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasConstructorOrDestructor); } bool NativeTypeEnum::hasAssignmentOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasOverloadedAssignmentOperator); } bool NativeTypeEnum::hasNestedTypes() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return bool(Record->getOptions() & codeview::ClassOptions::ContainsNestedClass); } bool NativeTypeEnum::isIntrinsic() const { - return bool(Record.getOptions() & codeview::ClassOptions::Intrinsic); + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic); } bool NativeTypeEnum::hasCastOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasConversionOperator); } uint64_t NativeTypeEnum::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + const auto Id = Session.getSymbolCache().findSymbolByTypeIndex( - Record.getUnderlyingType()); + Record->getUnderlyingType()); const auto UnderlyingType = Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id); return UnderlyingType ? UnderlyingType->getLength() : 0; } -std::string NativeTypeEnum::getName() const { return Record.getName(); } +std::string NativeTypeEnum::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Record->getName(); +} bool NativeTypeEnum::isNested() const { - return bool(Record.getOptions() & codeview::ClassOptions::Nested); + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return bool(Record->getOptions() & codeview::ClassOptions::Nested); } bool NativeTypeEnum::hasOverloadedOperator() const { - return bool(Record.getOptions() & + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return bool(Record->getOptions() & codeview::ClassOptions::HasOverloadedOperator); } bool NativeTypeEnum::isPacked() const { - return bool(Record.getOptions() & codeview::ClassOptions::Packed); + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return bool(Record->getOptions() & codeview::ClassOptions::Packed); } bool NativeTypeEnum::isScoped() const { - return bool(Record.getOptions() & codeview::ClassOptions::Scoped); + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return bool(Record->getOptions() & codeview::ClassOptions::Scoped); } SymIndexId NativeTypeEnum::getTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getTypeId(); + return Session.getSymbolCache().findSymbolByTypeIndex( - Record.getUnderlyingType()); + Record->getUnderlyingType()); } bool NativeTypeEnum::isRefUdt() const { return false; } @@ -346,6 +374,9 @@ bool NativeTypeEnum::isUnalignedType() const { } const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const { + if (UnmodifiedType) + return UnmodifiedType->getUnderlyingBuiltinType(); + return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>( getTypeId()); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp new file mode 100644 index 00000000000..3abf91dcc6a --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp @@ -0,0 +1,221 @@ +//===- NativeTypeUDT.cpp - info about class/struct type ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" + +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +#include <cassert> + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::ClassRecord CR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Class(std::move(CR)), Tag(Class.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::UnionRecord UR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Union(std::move(UR)), Tag(Union.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + NativeTypeUDT &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} + +NativeTypeUDT::~NativeTypeUDT() {} + +void NativeTypeUDT::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + if (Modifiers.hasValue()) + dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent, + Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields, + RecurseIdFields); + if (getUdtKind() != PDB_UdtType::Union) + dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(), + Indent); + dumpSymbolField(OS, "length", getLength(), Indent); + dumpSymbolField(OS, "udtKind", getUdtKind(), Indent); + dumpSymbolField(OS, "constructor", hasConstructor(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent); + dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent); + dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent); + dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent); + dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent); + dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent); + dumpSymbolField(OS, "nested", isNested(), Indent); + dumpSymbolField(OS, "packed", isPacked(), Indent); + dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent); + dumpSymbolField(OS, "scoped", isScoped(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +std::string NativeTypeUDT::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Tag->getName(); +} + +SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; } + +SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getSymIndexId(); + + return 0; +} + +SymIndexId NativeTypeUDT::getVirtualTableShapeId() const { + if (UnmodifiedType) + return UnmodifiedType->getVirtualTableShapeId(); + + if (Class) + return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape); + + return 0; +} + +uint64_t NativeTypeUDT::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + + if (Class) + return Class->getSize(); + + return Union->getSize(); +} + +PDB_UdtType NativeTypeUDT::getUdtKind() const { + if (UnmodifiedType) + return UnmodifiedType->getUdtKind(); + + switch (Tag->Kind) { + case TypeRecordKind::Class: + return PDB_UdtType::Class; + case TypeRecordKind::Union: + return PDB_UdtType::Union; + case TypeRecordKind::Struct: + return PDB_UdtType::Struct; + case TypeRecordKind::Interface: + return PDB_UdtType::Interface; + default: + llvm_unreachable("Unexected udt kind"); + } +} + +bool NativeTypeUDT::hasConstructor() const { + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return (Tag->Options & ClassOptions::HasConstructorOrDestructor) != + ClassOptions::None; +} + +bool NativeTypeUDT::isConstType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Const) != + ModifierOptions::None; +} + +bool NativeTypeUDT::hasAssignmentOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasCastOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return (Tag->Options & ClassOptions::HasConversionOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasNestedTypes() const { + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return (Tag->Options & ClassOptions::ContainsNestedClass) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasOverloadedOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::isInterfaceUdt() const { return false; } + +bool NativeTypeUDT::isIntrinsic() const { + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None; +} + +bool NativeTypeUDT::isNested() const { + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return (Tag->Options & ClassOptions::Nested) != ClassOptions::None; +} + +bool NativeTypeUDT::isPacked() const { + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return (Tag->Options & ClassOptions::Packed) != ClassOptions::None; +} + +bool NativeTypeUDT::isRefUdt() const { return false; } + +bool NativeTypeUDT::isScoped() const { + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None; +} + +bool NativeTypeUDT::isValueUdt() const { return false; } + +bool NativeTypeUDT::isUnalignedType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Unaligned) != + ModifierOptions::None; +} + +bool NativeTypeUDT::isVolatileType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Volatile) != + ModifierOptions::None; +} diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp index d714177509d..4fd7adf1632 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -1,6 +1,7 @@ #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" @@ -9,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" @@ -50,10 +52,18 @@ SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) if (Dbi) Compilands.resize(Dbi->modules().getModuleCount()); + + auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); + Tpi.buildHashMap(); +} + +std::unique_ptr<IPDBEnumSymbols> +SymbolCache::createTypeEnumerator(TypeLeafKind Kind) { + return createTypeEnumerator(std::vector<TypeLeafKind>{Kind}); } std::unique_ptr<IPDBEnumSymbols> -SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { +SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) { auto Tpi = Session.getPDBFile().getPDBTpiStream(); if (!Tpi) { consumeError(Tpi.takeError()); @@ -61,7 +71,7 @@ SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) { } auto &Types = Tpi->typeCollection(); return std::unique_ptr<IPDBEnumSymbols>( - new NativeEnumTypes(Session, Types, Kind)); + new NativeEnumTypes(Session, Types, std::move(Kinds))); } SymIndexId SymbolCache::createSimpleType(TypeIndex Index, @@ -98,38 +108,24 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, if (Record.ModifiedType.isSimple()) return createSimpleType(Record.ModifiedType, Record.Modifiers); - auto Tpi = Session.getPDBFile().getPDBTpiStream(); - if (!Tpi) { - consumeError(Tpi.takeError()); - return 0; - } - codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); - - codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType); - - switch (UnmodifiedType.kind()) { - case LF_ENUM: { - EnumRecord ER; - if (auto EC = - TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) { - consumeError(std::move(EC)); - return 0; - } - return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record), - std::move(ER)); - } - case LF_STRUCTURE: - case LF_UNION: - case LF_CLASS: - // FIXME: Handle these - break; + // Make sure we create and cache a record for the unmodified type. + SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType); + NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId]; + + switch (UnmodifiedNRS.getSymTag()) { + case PDB_SymType::Enum: + return createSymbol<NativeTypeEnum>( + static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record)); + case PDB_SymType::UDT: + return createSymbol<NativeTypeUDT>( + static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record)); default: // No other types can be modified. (LF_POINTER, for example, records // its modifiers a different way. assert(false && "Invalid LF_MODIFIER record"); break; } - return createSymbolPlaceholder(); + return 0; } SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { @@ -150,13 +146,37 @@ SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { } codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); codeview::CVType CVT = Types.getType(Index); - // TODO(amccarth): Make this handle all types. - SymIndexId Id = 0; + if (isUdtForwardRef(CVT)) { + Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index); + + if (!EFD) + consumeError(EFD.takeError()); + else if (*EFD != Index) { + assert(!isUdtForwardRef(Types.getType(*EFD))); + SymIndexId Result = findSymbolByTypeIndex(*EFD); + // Record a mapping from ForwardRef -> SymIndex of complete type so that + // we'll take the fast path next time. + TypeIndexToSymbolId[Index] = Result; + return Result; + } + } + + // At this point if we still have a forward ref udt it means the full decl was + // not in the PDB. We just have to deal with it and use the forward ref. + SymIndexId Id = 0; switch (CVT.kind()) { case codeview::LF_ENUM: Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT)); break; + case codeview::LF_CLASS: + case codeview::LF_STRUCTURE: + case codeview::LF_INTERFACE: + Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT)); + break; + case codeview::LF_UNION: + Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT)); + break; case codeview::LF_POINTER: Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index, std::move(CVT)); diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp index 311c3859acf..96221f7d6ec 100644 --- a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -11,9 +11,8 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" -#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" @@ -161,35 +160,6 @@ void TpiStream::buildHashMap() { bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); } -template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) { - RecordT Record; - if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { - consumeError(std::move(EC)); - return ClassOptions::None; - } - return Record.getOptions(); -} - -static bool isUdtForwardRef(CVType CVT) { - ClassOptions UdtOptions = ClassOptions::None; - switch (CVT.kind()) { - case LF_STRUCTURE: - case LF_CLASS: - case LF_INTERFACE: - UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT)); - break; - case LF_ENUM: - UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT)); - break; - case LF_UNION: - UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT)); - break; - default: - return false; - } - return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; -} - Expected<TypeIndex> TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const { CVType F = Types->getType(ForwardRefTI); |

