summaryrefslogtreecommitdiffstats
path: root/llvm/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests')
-rw-r--r--llvm/unittests/DebugInfo/CMakeLists.txt1
-rw-r--r--llvm/unittests/DebugInfo/GSYM/CMakeLists.txt15
-rw-r--r--llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp390
3 files changed, 406 insertions, 0 deletions
diff --git a/llvm/unittests/DebugInfo/CMakeLists.txt b/llvm/unittests/DebugInfo/CMakeLists.txt
index 579fdb202cf..0a0a1141d92 100644
--- a/llvm/unittests/DebugInfo/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(CodeView)
add_subdirectory(DWARF)
+add_subdirectory(GSYM)
add_subdirectory(MSF)
add_subdirectory(PDB)
diff --git a/llvm/unittests/DebugInfo/GSYM/CMakeLists.txt b/llvm/unittests/DebugInfo/GSYM/CMakeLists.txt
new file mode 100644
index 00000000000..5fdf95c983a
--- /dev/null
+++ b/llvm/unittests/DebugInfo/GSYM/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ AsmPrinter
+ DebugInfoGSYM
+ MC
+ Object
+ ObjectYAML
+ Support
+ )
+
+add_llvm_unittest(DebugInfoGSYMTests
+ GSYMTest.cpp
+ )
+
+target_link_libraries(DebugInfoGSYMTests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
new file mode 100644
index 00000000000..499edefe6da
--- /dev/null
+++ b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
@@ -0,0 +1,390 @@
+//===- llvm/unittest/DebugInfo/GSYMTest.cpp -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/DebugInfo/GSYM/FileEntry.h"
+#include "llvm/DebugInfo/GSYM/FunctionInfo.h"
+#include "llvm/DebugInfo/GSYM/InlineInfo.h"
+#include "llvm/DebugInfo/GSYM/Range.h"
+#include "llvm/DebugInfo/GSYM/StringTable.h"
+#include "llvm/Testing/Support/Error.h"
+
+#include "gtest/gtest.h"
+#include <sstream>
+#include <string>
+
+using namespace llvm;
+using namespace gsym;
+
+TEST(GSYMTest, TestFileEntry) {
+ // Make sure default constructed GSYM FileEntry has zeroes in the
+ // directory and basename string table indexes.
+ FileEntry empty1;
+ FileEntry empty2;
+ EXPECT_EQ(empty1.Dir, 0u);
+ EXPECT_EQ(empty1.Base, 0u);
+ // Verify equality operator works
+ FileEntry a1(10,30);
+ FileEntry a2(10,30);
+ FileEntry b(10,40);
+ EXPECT_EQ(empty1, empty2);
+ EXPECT_EQ(a1, a2);
+ EXPECT_NE(a1, b);
+ EXPECT_NE(a1, empty1);
+ // Test we can use llvm::gsym::FileEntry in llvm::DenseMap.
+ DenseMap<FileEntry, uint32_t> EntryToIndex;
+ constexpr uint32_t Index1 = 1;
+ constexpr uint32_t Index2 = 1;
+ auto R = EntryToIndex.insert(std::make_pair(a1, Index1));
+ EXPECT_TRUE(R.second);
+ EXPECT_EQ(R.first->second, Index1);
+ R = EntryToIndex.insert(std::make_pair(a1, Index1));
+ EXPECT_FALSE(R.second);
+ EXPECT_EQ(R.first->second, Index1);
+ R = EntryToIndex.insert(std::make_pair(b, Index2));
+ EXPECT_TRUE(R.second);
+ EXPECT_EQ(R.first->second, Index2);
+ R = EntryToIndex.insert(std::make_pair(a1, Index2));
+ EXPECT_FALSE(R.second);
+ EXPECT_EQ(R.first->second, Index2);
+}
+
+
+TEST(GSYMTest, TestFunctionInfo) {
+ // Test GSYM FunctionInfo structs and functionality.
+ FunctionInfo invalid;
+ EXPECT_FALSE(invalid.isValid());
+ EXPECT_FALSE(invalid.hasRichInfo());
+ const uint64_t StartAddr = 0x1000;
+ const uint64_t EndAddr = 0x1100;
+ const uint64_t Size = EndAddr - StartAddr;
+ const uint32_t NameOffset = 30;
+ FunctionInfo FI(StartAddr, Size, NameOffset);
+ EXPECT_TRUE(FI.isValid());
+ EXPECT_FALSE(FI.hasRichInfo());
+ EXPECT_EQ(FI.startAddress(), StartAddr);
+ EXPECT_EQ(FI.endAddress(), EndAddr);
+ EXPECT_EQ(FI.size(), Size);
+ const uint32_t FileIdx = 1;
+ const uint32_t Line = 12;
+ FI.Lines.push_back(LineEntry(StartAddr,FileIdx,Line));
+ EXPECT_TRUE(FI.hasRichInfo());
+ FI.clear();
+ EXPECT_FALSE(FI.isValid());
+ EXPECT_FALSE(FI.hasRichInfo());
+
+ FunctionInfo A1(0x1000, 0x100, NameOffset);
+ FunctionInfo A2(0x1000, 0x100, NameOffset);
+ FunctionInfo B;
+ // Check == operator
+ EXPECT_EQ(A1, A2);
+ // Make sure things are not equal if they only differ by start address.
+ B = A2;
+ B.setStartAddress(0x2000);
+ EXPECT_NE(B, A2);
+ // Make sure things are not equal if they only differ by size.
+ B = A2;
+ B.setSize(0x101);
+ EXPECT_NE(B, A2);
+ // Make sure things are not equal if they only differ by name.
+ B = A2;
+ B.Name = 60;
+ EXPECT_NE(B, A2);
+ // Check < operator.
+ // Check less than where address differs.
+ B = A2;
+ B.setStartAddress(A2.startAddress() + 0x1000);
+ EXPECT_LT(A1, B);
+
+ // We use the < operator to take a variety of different FunctionInfo
+ // structs from a variety of sources: symtab, debug info, runtime info
+ // and we sort them and want the sorting to allow us to quickly get the
+ // best version of a function info.
+ FunctionInfo FISymtab(StartAddr, Size, NameOffset);
+ FunctionInfo FIWithLines(StartAddr, Size, NameOffset);
+ FIWithLines.Lines.push_back(LineEntry(StartAddr,FileIdx,Line));
+ // Test that a FunctionInfo with just a name and size is less than one
+ // that has name, size and any number of line table entries
+ EXPECT_LT(FISymtab, FIWithLines);
+
+ FunctionInfo FIWithLinesAndInline = FIWithLines;
+ FIWithLinesAndInline.Inline.Ranges.insert(AddressRange(StartAddr, StartAddr + 0x10));
+ // Test that a FunctionInfo with name, size, and line entries is less than
+ // the same one with valid inline info
+ EXPECT_LT(FIWithLines, FIWithLinesAndInline);
+
+ // Test if we have an entry with lines and one with more lines for the same
+ // range, the ones with more lines is greater than the one with less.
+ FunctionInfo FIWithMoreLines = FIWithLines;
+ FIWithMoreLines.Lines.push_back(LineEntry(StartAddr,FileIdx,Line+5));
+ EXPECT_LT(FIWithLines, FIWithMoreLines);
+
+ // Test that if we have the same number of lines we compare the line entries
+ // in the FunctionInfo.Lines vector.
+ FunctionInfo FIWithLinesWithHigherAddress = FIWithLines;
+ FIWithLinesWithHigherAddress.Lines[0].Addr += 0x10;
+ EXPECT_LT(FIWithLines, FIWithLinesWithHigherAddress);
+}
+
+TEST(GSYMTest, TestInlineInfo) {
+ // Test InlineInfo structs.
+ InlineInfo II;
+ EXPECT_FALSE(II.isValid());
+ II.Ranges.insert(AddressRange(0x1000,0x2000));
+ // Make sure InlineInfo in valid with just an address range since
+ // top level InlineInfo objects have ranges with no name, call file
+ // or call line
+ EXPECT_TRUE(II.isValid());
+ // Make sure InlineInfo isn't after being cleared.
+ II.clear();
+ EXPECT_FALSE(II.isValid());
+
+ // Create an InlineInfo that contains the following data. The
+ // indentation of the address range indicates the parent child
+ // relationships of the InlineInfo objects:
+ //
+ // Variable Range and values
+ // =========== ====================================================
+ // Root [0x100-0x200) (no name, file, or line)
+ // Inline1 [0x150-0x160) Name = 1, File = 1, Line = 11
+ // Inline1Sub1 [0x152-0x155) Name = 2, File = 2, Line = 22
+ // Inline1Sub2 [0x157-0x158) Name = 3, File = 3, Line = 33
+ InlineInfo Root;
+ Root.Ranges.insert(AddressRange(0x100,0x200));
+ InlineInfo Inline1;
+ Inline1.Ranges.insert(AddressRange(0x150,0x160));
+ Inline1.Name = 1;
+ Inline1.CallFile = 1;
+ Inline1.CallLine = 11;
+ InlineInfo Inline1Sub1;
+ Inline1Sub1.Ranges.insert(AddressRange(0x152, 0x155));
+ Inline1Sub1.Name = 2;
+ Inline1Sub1.CallFile = 2;
+ Inline1Sub1.CallLine = 22;
+ InlineInfo Inline1Sub2;
+ Inline1Sub2.Ranges.insert(AddressRange(0x157,0x158));
+ Inline1Sub2.Name = 3;
+ Inline1Sub2.CallFile = 3;
+ Inline1Sub2.CallLine = 33;
+ Inline1.Children.push_back(Inline1Sub1);
+ Inline1.Children.push_back(Inline1Sub2);
+ Root.Children.push_back(Inline1);
+
+ // Make sure an address that is out of range won't match
+ EXPECT_FALSE(Root.getInlineStack(0x50));
+
+ // Verify that we get no inline stacks for addresses out of [0x100-0x200)
+ EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].startAddress()-1));
+ EXPECT_FALSE(Root.getInlineStack(Root.Ranges[0].endAddress()));
+
+ // Verify we get no inline stack entries for addresses that are in
+ // [0x100-0x200) but not in [0x150-0x160)
+ EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].startAddress()-1));
+ EXPECT_FALSE(Root.getInlineStack(Inline1.Ranges[0].endAddress()));
+
+
+ // Verify we get one inline stack entry for addresses that are in
+ // [[0x150-0x160)) but not in [0x152-0x155) or [0x157-0x158)
+ auto InlineInfos = Root.getInlineStack(Inline1.Ranges[0].startAddress());
+ ASSERT_TRUE(InlineInfos);
+ ASSERT_EQ(InlineInfos->size(), 1u);
+ ASSERT_EQ(*InlineInfos->at(0), Inline1);
+ InlineInfos = Root.getInlineStack(Inline1.Ranges[0].endAddress()-1);
+ EXPECT_TRUE(InlineInfos);
+ ASSERT_EQ(InlineInfos->size(), 1u);
+ ASSERT_EQ(*InlineInfos->at(0), Inline1);
+
+ // Verify we get two inline stack entries for addresses that are in
+ // [0x152-0x155)
+ InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].startAddress());
+ EXPECT_TRUE(InlineInfos);
+ ASSERT_EQ(InlineInfos->size(), 2u);
+ ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);
+ ASSERT_EQ(*InlineInfos->at(1), Inline1);
+ InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].endAddress()-1);
+ EXPECT_TRUE(InlineInfos);
+ ASSERT_EQ(InlineInfos->size(), 2u);
+ ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);
+ ASSERT_EQ(*InlineInfos->at(1), Inline1);
+
+ // Verify we get two inline stack entries for addresses that are in
+ // [0x157-0x158)
+ InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].startAddress());
+ EXPECT_TRUE(InlineInfos);
+ ASSERT_EQ(InlineInfos->size(), 2u);
+ ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);
+ ASSERT_EQ(*InlineInfos->at(1), Inline1);
+ InlineInfos = Root.getInlineStack(Inline1Sub2.Ranges[0].endAddress()-1);
+ EXPECT_TRUE(InlineInfos);
+ ASSERT_EQ(InlineInfos->size(), 2u);
+ ASSERT_EQ(*InlineInfos->at(0), Inline1Sub2);
+ ASSERT_EQ(*InlineInfos->at(1), Inline1);
+}
+
+TEST(GSYMTest, TestLineEntry) {
+ // test llvm::gsym::LineEntry structs.
+ const uint64_t ValidAddr = 0x1000;
+ const uint64_t InvalidFileIdx = 0;
+ const uint32_t ValidFileIdx = 1;
+ const uint32_t ValidLine = 5;
+
+ LineEntry Invalid;
+ EXPECT_FALSE(Invalid.isValid());
+ // Make sure that an entry is invalid if it has a bad file index.
+ LineEntry BadFile(ValidAddr, InvalidFileIdx, ValidLine);
+ EXPECT_FALSE(BadFile.isValid());
+ // Test operators
+ LineEntry E1(ValidAddr, ValidFileIdx, ValidLine);
+ LineEntry E2(ValidAddr, ValidFileIdx, ValidLine);
+ LineEntry DifferentAddr(ValidAddr+1, ValidFileIdx, ValidLine);
+ LineEntry DifferentFile(ValidAddr, ValidFileIdx+1, ValidLine);
+ LineEntry DifferentLine(ValidAddr, ValidFileIdx, ValidLine+1);
+ EXPECT_TRUE(E1.isValid());
+ EXPECT_EQ(E1, E2);
+ EXPECT_NE(E1, DifferentAddr);
+ EXPECT_NE(E1, DifferentFile);
+ EXPECT_NE(E1, DifferentLine);
+ EXPECT_LT(E1, DifferentAddr);
+}
+
+TEST(GSYMTest, TestRanges) {
+ // test llvm::gsym::AddressRange.
+ const uint64_t StartAddr = 0x1000;
+ const uint64_t EndAddr = 0x2000;
+ // Verify constructor and API to ensure it takes start and end address.
+ const AddressRange Range(StartAddr, EndAddr);
+ EXPECT_EQ(Range.startAddress(), StartAddr);
+ EXPECT_EQ(Range.endAddress(), EndAddr);
+ EXPECT_EQ(Range.size(), EndAddr-StartAddr);
+
+ // Verify llvm::gsym::AddressRange::contains().
+ EXPECT_FALSE(Range.contains(0));
+ EXPECT_FALSE(Range.contains(StartAddr-1));
+ EXPECT_TRUE(Range.contains(StartAddr));
+ EXPECT_TRUE(Range.contains(EndAddr-1));
+ EXPECT_FALSE(Range.contains(EndAddr));
+ EXPECT_FALSE(Range.contains(UINT64_MAX));
+
+ const AddressRange RangeSame(StartAddr, EndAddr);
+ const AddressRange RangeDifferentStart(StartAddr+1, EndAddr);
+ const AddressRange RangeDifferentEnd(StartAddr, EndAddr+1);
+ const AddressRange RangeDifferentStartEnd(StartAddr+1, EndAddr+1);
+ // Test == and != with values that are the same
+ EXPECT_EQ(Range, RangeSame);
+ EXPECT_FALSE(Range != RangeSame);
+ // Test == and != with values that are the different
+ EXPECT_NE(Range, RangeDifferentStart);
+ EXPECT_NE(Range, RangeDifferentEnd);
+ EXPECT_NE(Range, RangeDifferentStartEnd);
+ EXPECT_FALSE(Range == RangeDifferentStart);
+ EXPECT_FALSE(Range == RangeDifferentEnd);
+ EXPECT_FALSE(Range == RangeDifferentStartEnd);
+
+ // Test "bool operator<(const AddressRange &, const AddressRange &)".
+ EXPECT_FALSE(Range < RangeSame);
+ EXPECT_FALSE(RangeSame < Range);
+ EXPECT_LT(Range, RangeDifferentStart);
+ EXPECT_LT(Range, RangeDifferentEnd);
+ EXPECT_LT(Range, RangeDifferentStartEnd);
+ // Test "bool operator<(const AddressRange &, uint64_t)"
+ EXPECT_LT(Range, StartAddr + 1);
+ // Test "bool operator<(uint64_t, const AddressRange &)"
+ EXPECT_LT(StartAddr - 1, Range);
+
+ // Verify llvm::gsym::AddressRange::isContiguousWith() and
+ // llvm::gsym::AddressRange::intersects().
+ const AddressRange EndsBeforeRangeStart(0, StartAddr-1);
+ const AddressRange EndsAtRangeStart(0, StartAddr);
+ const AddressRange OverlapsRangeStart(StartAddr-1, StartAddr+1);
+ const AddressRange InsideRange(StartAddr+1, EndAddr-1);
+ const AddressRange OverlapsRangeEnd(EndAddr-1, EndAddr+1);
+ const AddressRange StartsAtRangeEnd(EndAddr, EndAddr+0x100);
+ const AddressRange StartsAfterRangeEnd(EndAddr+1, EndAddr+0x100);
+
+ EXPECT_FALSE(Range.isContiguousWith(EndsBeforeRangeStart));
+ EXPECT_TRUE(Range.isContiguousWith(EndsAtRangeStart));
+ EXPECT_TRUE(Range.isContiguousWith(OverlapsRangeStart));
+ EXPECT_TRUE(Range.isContiguousWith(InsideRange));
+ EXPECT_TRUE(Range.isContiguousWith(OverlapsRangeEnd));
+ EXPECT_TRUE(Range.isContiguousWith(StartsAtRangeEnd));
+ EXPECT_FALSE(Range.isContiguousWith(StartsAfterRangeEnd));
+
+ EXPECT_FALSE(Range.intersects(EndsBeforeRangeStart));
+ EXPECT_FALSE(Range.intersects(EndsAtRangeStart));
+ EXPECT_TRUE(Range.intersects(OverlapsRangeStart));
+ EXPECT_TRUE(Range.intersects(InsideRange));
+ EXPECT_TRUE(Range.intersects(OverlapsRangeEnd));
+ EXPECT_FALSE(Range.intersects(StartsAtRangeEnd));
+ EXPECT_FALSE(Range.intersects(StartsAfterRangeEnd));
+
+ // Test the functions that maintain GSYM address ranges:
+ // "bool AddressRange::contains(uint64_t Addr) const;"
+ // "void AddressRanges::insert(const AddressRange &R);"
+ AddressRanges Ranges;
+ Ranges.insert(AddressRange(0x1000, 0x2000));
+ Ranges.insert(AddressRange(0x2000, 0x3000));
+ Ranges.insert(AddressRange(0x4000, 0x5000));
+
+ EXPECT_FALSE(Ranges.contains(0));
+ EXPECT_FALSE(Ranges.contains(0x1000-1));
+ EXPECT_TRUE(Ranges.contains(0x1000));
+ EXPECT_TRUE(Ranges.contains(0x2000));
+ EXPECT_TRUE(Ranges.contains(0x4000));
+ EXPECT_TRUE(Ranges.contains(0x2000-1));
+ EXPECT_TRUE(Ranges.contains(0x3000-1));
+ EXPECT_FALSE(Ranges.contains(0x3000+1));
+ EXPECT_TRUE(Ranges.contains(0x5000-1));
+ EXPECT_FALSE(Ranges.contains(0x5000+1));
+ EXPECT_FALSE(Ranges.contains(UINT64_MAX));
+
+ // Verify that intersecting ranges get combined
+ Ranges.clear();
+ Ranges.insert(AddressRange(0x1100, 0x1F00));
+ // Verify a wholy contained range that is added doesn't do anything.
+ Ranges.insert(AddressRange(0x1500, 0x1F00));
+ EXPECT_EQ(Ranges.size(), 1u);
+ EXPECT_EQ(Ranges[0], AddressRange(0x1100, 0x1F00));
+
+ // Verify a range that starts before and intersects gets combined.
+ Ranges.insert(AddressRange(0x1000, Ranges[0].startAddress()+1));
+ EXPECT_EQ(Ranges.size(), 1u);
+ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x1F00));
+
+ // Verify a range that starts inside and extends ranges gets combined.
+ Ranges.insert(AddressRange(Ranges[0].endAddress()-1, 0x2000));
+ EXPECT_EQ(Ranges.size(), 1u);
+ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000));
+
+ // Verify that adjacent ranges don't get combined
+ Ranges.insert(AddressRange(0x2000, 0x3000));
+ EXPECT_EQ(Ranges.size(), 2u);
+ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000));
+ EXPECT_EQ(Ranges[1], AddressRange(0x2000, 0x3000));
+ // Verify if we add an address range that intersects two ranges
+ // that they get combined
+ Ranges.insert(AddressRange(Ranges[0].endAddress()-1,
+ Ranges[1].startAddress()+1));
+ EXPECT_EQ(Ranges.size(), 1u);
+ EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x3000));
+
+
+}
+
+TEST(GSYMTest, TestStringTable) {
+ StringTable StrTab(StringRef("\0Hello\0World\0", 13));
+ // Test extracting strings from a string table.
+ EXPECT_EQ(StrTab.getString(0), "");
+ EXPECT_EQ(StrTab.getString(1), "Hello");
+ EXPECT_EQ(StrTab.getString(7), "World");
+ EXPECT_EQ(StrTab.getString(8), "orld");
+ // Test pointing to last NULL terminator gets empty string.
+ EXPECT_EQ(StrTab.getString(12), "");
+ // Test pointing to past end gets empty string.
+ EXPECT_EQ(StrTab.getString(13), "");
+}
OpenPOWER on IntegriCloud