diff options
Diffstat (limited to 'unittests/DebugInfo/CodeView')
| -rw-r--r-- | unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp | 52 | ||||
| -rw-r--r-- | unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp | 87 |
2 files changed, 131 insertions, 8 deletions
diff --git a/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp index 4fa172a37ef2..92134513b75b 100644 --- a/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp +++ b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp @@ -351,3 +351,55 @@ TEST_F(RandomAccessVisitorTest, InnerChunk) { for (auto &I : enumerate(IndicesToVisit)) EXPECT_TRUE(ValidateVisitedRecord(I.index(), I.value())); } + +TEST_F(RandomAccessVisitorTest, CrossChunkName) { + TypeTableBuilder Builder(GlobalState->Allocator); + + // TypeIndex 0 + ClassRecord Class(TypeRecordKind::Class); + Class.Name = "FooClass"; + Class.Options = ClassOptions::None; + Class.MemberCount = 0; + Class.Size = 4U; + Class.DerivationList = TypeIndex::fromArrayIndex(0); + Class.FieldList = TypeIndex::fromArrayIndex(0); + Class.VTableShape = TypeIndex::fromArrayIndex(0); + TypeIndex IndexZero = Builder.writeKnownType(Class); + + // TypeIndex 1 refers to type index 0. + ModifierRecord Modifier(TypeRecordKind::Modifier); + Modifier.ModifiedType = TypeIndex::fromArrayIndex(0); + Modifier.Modifiers = ModifierOptions::Const; + TypeIndex IndexOne = Builder.writeKnownType(Modifier); + + // set up a type stream that refers to the above two serialized records. + std::vector<CVType> TypeArray; + TypeArray.push_back( + CVType(static_cast<TypeLeafKind>(Class.Kind), Builder.records()[0])); + TypeArray.push_back( + CVType(static_cast<TypeLeafKind>(Modifier.Kind), Builder.records()[1])); + BinaryItemStream<CVType> ItemStream(llvm::support::little); + ItemStream.setItems(TypeArray); + VarStreamArray<CVType> TypeStream(ItemStream); + + // Figure out the byte offset of the second item. + auto ItemOneIter = TypeStream.begin(); + ++ItemOneIter; + + // Set up a partial offsets buffer that contains the first and second items + // in separate chunks. + std::vector<TypeIndexOffset> TIO; + TIO.push_back({IndexZero, ulittle32_t(0u)}); + TIO.push_back({IndexOne, ulittle32_t(ItemOneIter.offset())}); + ArrayRef<uint8_t> Buffer(reinterpret_cast<const uint8_t *>(TIO.data()), + TIO.size() * sizeof(TypeIndexOffset)); + + BinaryStreamReader Reader(Buffer, llvm::support::little); + FixedStreamArray<TypeIndexOffset> PartialOffsets; + ASSERT_THAT_ERROR(Reader.readArray(PartialOffsets, 2), Succeeded()); + + LazyRandomTypeCollection Types(TypeStream, 2, PartialOffsets); + + StringRef Name = Types.getTypeName(IndexOne); + EXPECT_EQ("const FooClass", Name); +}
\ No newline at end of file diff --git a/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp index 99c84906be9c..fa9e96123184 100644 --- a/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp +++ b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/Support/Allocator.h" #include "gmock/gmock.h" @@ -26,6 +27,7 @@ public: Refs.clear(); TTB = make_unique<TypeTableBuilder>(Storage); FLRB = make_unique<FieldListRecordBuilder>(*TTB); + Symbols.clear(); } void TearDown() override { @@ -37,7 +39,19 @@ protected: template <typename... Indices> bool checkTypeReferences(uint32_t RecordIndex, Indices &&... TIs) const { EXPECT_EQ(sizeof...(Indices), countRefs(RecordIndex)); - return checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(TIs)...); + + // Choose between type or symbol records. The checking code doesn't care + // which we have. + std::vector<ArrayRef<uint8_t>> CVRecords; + if (Symbols.empty()) { + CVRecords = TTB->records(); + } else { + for (const CVSymbol &S : Symbols) + CVRecords.push_back(S.data()); + } + + return checkTypeReferencesImpl(RecordIndex, CVRecords, + std::forward<Indices>(TIs)...); } template <typename... T> void writeFieldList(T &&... MemberRecords) { @@ -54,6 +68,13 @@ protected: discoverAllTypeIndices(); } + template <typename... T> void writeSymbolRecords(T &&... Records) { + writeSymbolRecordsImpl(std::forward<T>(Records)...); + ASSERT_EQ(sizeof...(T), Symbols.size()); + discoverTypeIndicesInSymbols(); + } + + std::unique_ptr<TypeTableBuilder> TTB; private: @@ -83,18 +104,20 @@ private: } template <typename... Indices> - bool checkTypeReferencesImpl(uint32_t RecordIndex) const { + bool checkTypeReferencesImpl(uint32_t RecordIndex, + ArrayRef<ArrayRef<uint8_t>> CVRecords) const { return true; } template <typename... Indices> - bool checkTypeReferencesImpl(uint32_t RecordIndex, TypeIndex TI, - Indices &&... Rest) const { - ArrayRef<uint8_t> Record = TTB->records()[RecordIndex]; + bool checkTypeReferencesImpl(uint32_t RecordIndex, + ArrayRef<ArrayRef<uint8_t>> CVRecords, + TypeIndex TI, Indices &&... Rest) const { + ArrayRef<uint8_t> Record = CVRecords[RecordIndex]; bool Success = checkOneTypeReference(RecordIndex, Record, TI); EXPECT_TRUE(Success); - return Success & - checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(Rest)...); + return Success & checkTypeReferencesImpl(RecordIndex, CVRecords, + std::forward<Indices>(Rest)...); } void discoverAllTypeIndices() { @@ -105,6 +128,12 @@ private: } } + void discoverTypeIndicesInSymbols() { + Refs.resize(Symbols.size()); + for (uint32_t I = 0; I < Symbols.size(); ++I) + discoverTypeIndices(Symbols[I], Refs[I]); + } + // Helper function to write out a field list record with the given list // of member records. void writeFieldListImpl() {} @@ -124,8 +153,19 @@ private: writeTypeRecordsImpl(std::forward<Rest>(Records)...); } + // Helper function to write out a list of symbol records. + void writeSymbolRecordsImpl() {} + + template <typename RecType, typename... Rest> + void writeSymbolRecordsImpl(RecType &&Record, Rest &&... Records) { + Symbols.push_back(SymbolSerializer::writeOneSymbol(Record, Storage, + CodeViewContainer::Pdb)); + writeSymbolRecordsImpl(std::forward<Rest>(Records)...); + } + std::vector<SmallVector<TiReference, 4>> Refs; std::unique_ptr<FieldListRecordBuilder> FLRB; + std::vector<CVSymbol> Symbols; BumpPtrAllocator Storage; }; @@ -492,4 +532,35 @@ TEST_F(TypeIndexIteratorTest, ManyMembers) { OneMethod.T1, OneMethod.T2, OneMethod.T3, OneMethod.T4, NestedType.Type, StaticDataMember.Type, VirtualBaseClass.BaseType, VirtualBaseClass.VBPtrType, VFPtr.Type, Continuation.ContinuationIndex); -}
\ No newline at end of file +} + +TEST_F(TypeIndexIteratorTest, ProcSym) { + ProcSym GS(SymbolRecordKind::GlobalProcSym); + GS.FunctionType = TypeIndex(0x40); + ProcSym LS(SymbolRecordKind::ProcSym); + LS.FunctionType = TypeIndex(0x41); + writeSymbolRecords(GS, LS); + checkTypeReferences(0, GS.FunctionType); + checkTypeReferences(1, LS.FunctionType); +} + +TEST_F(TypeIndexIteratorTest, DataSym) { + DataSym DS(SymbolRecordKind::GlobalData); + DS.Type = TypeIndex(0x40); + writeSymbolRecords(DS); + checkTypeReferences(0, DS.Type); +} + +TEST_F(TypeIndexIteratorTest, CallerSym) { + CallerSym Callees(SymbolRecordKind::CalleeSym); + Callees.Indices.push_back(TypeIndex(1)); + Callees.Indices.push_back(TypeIndex(2)); + Callees.Indices.push_back(TypeIndex(3)); + CallerSym Callers(SymbolRecordKind::CallerSym); + Callers.Indices.push_back(TypeIndex(4)); + Callers.Indices.push_back(TypeIndex(5)); + Callers.Indices.push_back(TypeIndex(6)); + writeSymbolRecords(Callees, Callers); + checkTypeReferences(0, TypeIndex(1), TypeIndex(2), TypeIndex(3)); + checkTypeReferences(1, TypeIndex(4), TypeIndex(5), TypeIndex(6)); +} |
