1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[DebugInfo] GSYM cleanups after D63104/r364427

llvm-svn: 364634
This commit is contained in:
Fangrui Song 2019-06-28 08:58:05 +00:00
parent 0c599cd301
commit 693b277806
9 changed files with 70 additions and 90 deletions

View File

@ -19,8 +19,8 @@
namespace llvm {
namespace gsym {
/// Files in GSYM are contained in FileEntry structs where we split the
/// directory and basename into two different strings in the string
/// Files in GSYM are contained in FileEntry structs where we split the
/// directory and basename into two different strings in the string
/// table. This allows paths to shared commont directory and filename
/// strings and saves space.
struct FileEntry {
@ -48,12 +48,11 @@ struct FileEntry {
template <> struct DenseMapInfo<gsym::FileEntry> {
static inline gsym::FileEntry getEmptyKey() {
const auto key = DenseMapInfo<uint32_t>::getEmptyKey();
uint32_t key = DenseMapInfo<uint32_t>::getEmptyKey();
return gsym::FileEntry(key, key);
}
static inline gsym::FileEntry getTombstoneKey() {
const auto key = DenseMapInfo<uint32_t>::getTombstoneKey();
uint32_t key = DenseMapInfo<uint32_t>::getTombstoneKey();
return gsym::FileEntry(key, key);
}
static unsigned getHashValue(const gsym::FileEntry &Val) {

View File

@ -21,7 +21,7 @@ namespace llvm {
class raw_ostream;
namespace gsym {
/// Function information in GSYM files encodes information for one
/// Function information in GSYM files encodes information for one
/// contiguous address range. The name of the function is encoded as
/// a string table offset and allows multiple functions with the same
/// name to share the name string in the string table. Line tables are
@ -41,7 +41,7 @@ struct FunctionInfo {
bool hasRichInfo() const {
/// Returns whether we have something else than range and name. When
/// converting information from a symbol table and from debug info, we
/// converting information from a symbol table and from debug info, we
/// might end up with multiple FunctionInfo objects for the same range
/// and we need to be able to tell which one is the better object to use.
return !Lines.empty() || Inline.isValid();
@ -50,8 +50,8 @@ struct FunctionInfo {
bool isValid() const {
/// Address and size can be zero and there can be no line entries for a
/// symbol so the only indication this entry is valid is if the name is
/// not zero. This can happen when extracting information from symbol
/// tables that do not encode symbol sizes. In that case only the
/// not zero. This can happen when extracting information from symbol
/// tables that do not encode symbol sizes. In that case only the
/// address and name will be filled in.
return Name != 0;
}
@ -82,7 +82,7 @@ inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
/// followed by inlining being valid and line tables. We might end up with a
/// FunctionInfo from debug info that will have the same range as one from the
/// symbol table, but we want to quickly be able to sort and use the best version
/// when creating the final GSYM file.
/// when creating the final GSYM file.
inline bool operator<(const FunctionInfo &LHS, const FunctionInfo &RHS) {
// First sort by address range
if (LHS.Range != RHS.Range)

View File

@ -23,8 +23,8 @@ namespace gsym {
/// Inline information stores the name of the inline function along with
/// an array of address ranges. It also stores the call file and call line
/// that called this inline function. This allows us to unwind inline call
/// stacks back to the inline or concrete function that called this
/// that called this inline function. This allows us to unwind inline call
/// stacks back to the inline or concrete function that called this
/// function. Inlined functions contained in this function are stored in the
/// "Children" variable. All address ranges must be sorted and all address
/// ranges of all children must be contained in the ranges of this function.
@ -48,13 +48,13 @@ struct InlineInfo {
}
bool isValid() const { return !Ranges.empty(); }
typedef std::vector<const InlineInfo *> InlineArray;
using InlineArray = std::vector<const InlineInfo *>;
/// Lookup an address in the InlineInfo object
///
/// This function is used to symbolicate an inline call stack and can
/// This function is used to symbolicate an inline call stack and can
/// turn one address in the program into one or more inline call stacks
/// and have the stack trace show the original call site from
/// and have the stack trace show the original call site from
/// non-inlined code.
///
/// \param Addr the address to lookup

View File

@ -30,7 +30,7 @@ struct LineEntry {
};
inline raw_ostream &operator<<(raw_ostream &OS, const LineEntry &LE) {
return OS << "addr=" << HEX64(LE.Addr) << ", file=" << format("%3u", LE.File)
return OS << "addr=" << HEX64(LE.Addr) << ", file=" << format("%3u", LE.File)
<< ", line=" << format("%3u", LE.Line);
}

View File

@ -26,7 +26,7 @@ class raw_ostream;
namespace gsym {
/// A class that represents an address range. The range is specified using
/// a start and an end address.
/// a start and an end address.
class AddressRange {
uint64_t Start;
uint64_t End;
@ -43,7 +43,7 @@ public:
uint64_t startAddress() const { return Start; }
/// Access to the end address must use the size() accessor to ensure the
/// correct answer. This allows an AddressRange to be constructed with
/// invalid address ranges where the end address is less that the start
/// invalid address ranges where the end address is less that the start
/// address either because it was not set, or because of incorrect data.
uint64_t endAddress() const { return Start + size(); }
void clear() {
@ -78,12 +78,6 @@ inline bool operator<(const AddressRange &LHS, const AddressRange &RHS) {
return LHS.endAddress() < RHS.endAddress();
return LHS.startAddress() < RHS.startAddress();
}
inline bool operator<(const AddressRange &LHS, uint64_t Addr) {
return LHS.startAddress() < Addr;
}
inline bool operator<(uint64_t Addr, const AddressRange &RHS) {
return Addr < RHS.startAddress();
}
raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R);
@ -96,7 +90,7 @@ raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R);
/// representation for address ranges when writing to disk.
class AddressRanges {
protected:
typedef std::vector<AddressRange> Collection;
using Collection = std::vector<AddressRange>;
Collection Ranges;
public:
void clear() { Ranges.clear(); }

View File

@ -20,7 +20,7 @@
namespace llvm {
namespace gsym {
/// String tables in GSYM files are required to start with an empty
/// String tables in GSYM files are required to start with an empty
/// string at offset zero. Strings must be UTF8 NULL terminated strings.
struct StringTable {
StringRef Data;

View File

@ -44,14 +44,10 @@ void AddressRanges::insert(const AddressRange &Range) {
}
bool AddressRanges::contains(uint64_t Addr) const {
if (Ranges.empty())
return false;
auto Begin = Ranges.begin();
auto Pos = std::upper_bound(Begin, Ranges.end(), Addr);
if (Pos == Begin)
return false;
--Pos;
return Pos->contains(Addr);
auto It = std::partition_point(
Ranges.begin(), Ranges.end(),
[=](const AddressRange &R) { return R.startAddress() <= Addr; });
return It != Ranges.begin() && It[-1].contains(Addr);
}
raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRange &R) {

View File

@ -1,10 +1,5 @@
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
AsmPrinter
DebugInfoGSYM
MC
Object
ObjectYAML
Support
)

View File

@ -16,23 +16,22 @@
#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
// 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);
FileEntry a1(10, 30);
FileEntry a2(10, 30);
FileEntry b(10, 40);
EXPECT_EQ(empty1, empty2);
EXPECT_EQ(a1, a2);
EXPECT_NE(a1, b);
@ -55,7 +54,6 @@ TEST(GSYMTest, TestFileEntry) {
EXPECT_EQ(R.first->second, Index2);
}
TEST(GSYMTest, TestFunctionInfo) {
// Test GSYM FunctionInfo structs and functionality.
FunctionInfo invalid;
@ -73,7 +71,7 @@ TEST(GSYMTest, TestFunctionInfo) {
EXPECT_EQ(FI.size(), Size);
const uint32_t FileIdx = 1;
const uint32_t Line = 12;
FI.Lines.push_back(LineEntry(StartAddr,FileIdx,Line));
FI.Lines.push_back(LineEntry(StartAddr, FileIdx, Line));
EXPECT_TRUE(FI.hasRichInfo());
FI.clear();
EXPECT_FALSE(FI.isValid());
@ -101,20 +99,21 @@ TEST(GSYMTest, TestFunctionInfo) {
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.
// best version of a function info.
FunctionInfo FISymtab(StartAddr, Size, NameOffset);
FunctionInfo FIWithLines(StartAddr, Size, NameOffset);
FIWithLines.Lines.push_back(LineEntry(StartAddr,FileIdx,Line));
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));
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);
@ -122,7 +121,7 @@ TEST(GSYMTest, TestFunctionInfo) {
// 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));
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
@ -136,7 +135,7 @@ TEST(GSYMTest, TestInlineInfo) {
// Test InlineInfo structs.
InlineInfo II;
EXPECT_FALSE(II.isValid());
II.Ranges.insert(AddressRange(0x1000,0x2000));
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
@ -156,9 +155,9 @@ TEST(GSYMTest, TestInlineInfo) {
// 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));
Root.Ranges.insert(AddressRange(0x100, 0x200));
InlineInfo Inline1;
Inline1.Ranges.insert(AddressRange(0x150,0x160));
Inline1.Ranges.insert(AddressRange(0x150, 0x160));
Inline1.Name = 1;
Inline1.CallFile = 1;
Inline1.CallLine = 11;
@ -168,7 +167,7 @@ TEST(GSYMTest, TestInlineInfo) {
Inline1Sub1.CallFile = 2;
Inline1Sub1.CallLine = 22;
InlineInfo Inline1Sub2;
Inline1Sub2.Ranges.insert(AddressRange(0x157,0x158));
Inline1Sub2.Ranges.insert(AddressRange(0x157, 0x158));
Inline1Sub2.Name = 3;
Inline1Sub2.CallFile = 3;
Inline1Sub2.CallLine = 33;
@ -179,23 +178,22 @@ TEST(GSYMTest, TestInlineInfo) {
// 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));
// 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].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);
InlineInfos = Root.getInlineStack(Inline1.Ranges[0].endAddress() - 1);
EXPECT_TRUE(InlineInfos);
ASSERT_EQ(InlineInfos->size(), 1u);
ASSERT_EQ(*InlineInfos->at(0), Inline1);
@ -207,7 +205,7 @@ TEST(GSYMTest, TestInlineInfo) {
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);
InlineInfos = Root.getInlineStack(Inline1Sub1.Ranges[0].endAddress() - 1);
EXPECT_TRUE(InlineInfos);
ASSERT_EQ(InlineInfos->size(), 2u);
ASSERT_EQ(*InlineInfos->at(0), Inline1Sub1);
@ -220,12 +218,12 @@ TEST(GSYMTest, TestInlineInfo) {
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);
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.
@ -242,9 +240,9 @@ TEST(GSYMTest, TestLineEntry) {
// 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);
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);
@ -261,20 +259,20 @@ TEST(GSYMTest, TestRanges) {
const AddressRange Range(StartAddr, EndAddr);
EXPECT_EQ(Range.startAddress(), StartAddr);
EXPECT_EQ(Range.endAddress(), EndAddr);
EXPECT_EQ(Range.size(), EndAddr-StartAddr);
EXPECT_EQ(Range.size(), EndAddr - StartAddr);
// Verify llvm::gsym::AddressRange::contains().
EXPECT_FALSE(Range.contains(0));
EXPECT_FALSE(Range.contains(StartAddr-1));
EXPECT_FALSE(Range.contains(StartAddr - 1));
EXPECT_TRUE(Range.contains(StartAddr));
EXPECT_TRUE(Range.contains(EndAddr-1));
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);
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);
@ -299,13 +297,13 @@ TEST(GSYMTest, TestRanges) {
// Verify llvm::gsym::AddressRange::isContiguousWith() and
// llvm::gsym::AddressRange::intersects().
const AddressRange EndsBeforeRangeStart(0, StartAddr-1);
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);
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));
@ -332,15 +330,15 @@ TEST(GSYMTest, TestRanges) {
Ranges.insert(AddressRange(0x4000, 0x5000));
EXPECT_FALSE(Ranges.contains(0));
EXPECT_FALSE(Ranges.contains(0x1000-1));
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_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
@ -352,12 +350,12 @@ TEST(GSYMTest, TestRanges) {
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));
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));
Ranges.insert(AddressRange(Ranges[0].endAddress() - 1, 0x2000));
EXPECT_EQ(Ranges.size(), 1u);
EXPECT_EQ(Ranges[0], AddressRange(0x1000, 0x2000));
@ -368,12 +366,10 @@ TEST(GSYMTest, TestRanges) {
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));
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) {