summaryrefslogtreecommitdiff
path: root/unittests/DebugInfo
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
commit08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch)
tree80108f0f128657f8623f8f66ad9735b4d88e7b47 /unittests/DebugInfo
parent7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff)
Notes
Diffstat (limited to 'unittests/DebugInfo')
-rw-r--r--unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp52
-rw-r--r--unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp87
-rw-r--r--unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp29
-rw-r--r--unittests/DebugInfo/PDB/PDBApiTest.cpp4
4 files changed, 151 insertions, 21 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));
+}
diff --git a/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp b/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
index da7f43e721aa..621796b684d6 100644
--- a/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
+++ b/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
@@ -23,43 +23,52 @@ namespace {
TEST(DWARFFormValue, FixedFormSizes) {
Optional<uint8_t> RefSize;
Optional<uint8_t> AddrSize;
+
// Test 32 bit DWARF version 2 with 4 byte addresses.
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32);
- AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32);
+ DWARFFormParams Params_2_4_32 = {2, 4, DWARF32};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_4_32);
+ AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_TRUE(AddrSize.hasValue());
EXPECT_EQ(*RefSize, *AddrSize);
// Test 32 bit DWARF version 2 with 8 byte addresses.
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32);
- AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32);
+ DWARFFormParams Params_2_8_32 = {2, 8, DWARF32};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_8_32);
+ AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_8_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_TRUE(AddrSize.hasValue());
EXPECT_EQ(*RefSize, *AddrSize);
// DW_FORM_ref_addr is 4 bytes in DWARF 32 in DWARF version 3 and beyond.
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 4, DWARF32);
+ DWARFFormParams Params_3_4_32 = {3, 4, DWARF32};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_3_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 4);
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 4, DWARF32);
+ DWARFFormParams Params_4_4_32 = {4, 4, DWARF32};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_4_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 4);
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 4, DWARF32);
+ DWARFFormParams Params_5_4_32 = {5, 4, DWARF32};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_5_4_32);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 4);
// DW_FORM_ref_addr is 8 bytes in DWARF 64 in DWARF version 3 and beyond.
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 8, DWARF64);
+ DWARFFormParams Params_3_8_64 = {3, 8, DWARF64};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_3_8_64);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 8);
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 8, DWARF64);
+ DWARFFormParams Params_4_8_64 = {4, 8, DWARF64};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_4_8_64);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 8);
- RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 8, DWARF64);
+ DWARFFormParams Params_5_8_64 = {5, 8, DWARF64};
+ RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_5_8_64);
EXPECT_TRUE(RefSize.hasValue());
EXPECT_EQ(*RefSize, 8);
}
diff --git a/unittests/DebugInfo/PDB/PDBApiTest.cpp b/unittests/DebugInfo/PDB/PDBApiTest.cpp
index 6afe83cd90dd..257a8879e439 100644
--- a/unittests/DebugInfo/PDB/PDBApiTest.cpp
+++ b/unittests/DebugInfo/PDB/PDBApiTest.cpp
@@ -63,9 +63,7 @@ namespace {
class MockSession : public IPDBSession {
uint64_t getLoadAddress() const override { return 0; }
void setLoadAddress(uint64_t Address) override {}
- std::unique_ptr<PDBSymbolExe> getGlobalScope() const override {
- return nullptr;
- }
+ std::unique_ptr<PDBSymbolExe> getGlobalScope() override { return nullptr; }
std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override {
return nullptr;
}