[llvm] Don't warn about missing DWO files when converting mach-o files. (PR #152598)
Greg Clayton via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 7 17:00:27 PDT 2025
https://github.com/clayborg updated https://github.com/llvm/llvm-project/pull/152598
>From 600ef12f9205ef461107f6d01e189856c8524b13 Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Thu, 7 Aug 2025 14:39:00 -0700
Subject: [PATCH] Don't warn about missing DWO files when converting mach-o
files.
Apple uses the DW_AT_GNU_dwo_id for non split DWARF cases. Any compile units with this attribute would cause many warnings to be emitted:
"warning: Unable to retrieve DWO .debug_info section for"
This patch fixes the DWARFTransformer to not look for skeleton compile unit in mach-o based binaries and adds a unit test.
---
.../llvm/DebugInfo/GSYM/DwarfTransformer.h | 12 +-
llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp | 19 +-
llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp | 9 +-
llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp | 401 +++++++++++-------
4 files changed, 263 insertions(+), 178 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h b/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h
index 77ce052201f7a..509ecc246cffb 100644
--- a/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h
+++ b/llvm/include/llvm/DebugInfo/GSYM/DwarfTransformer.h
@@ -43,8 +43,14 @@ class DwarfTransformer {
///
/// \param LDCS Flag to indicate whether we should load the call site
/// information from DWARF `DW_TAG_call_site` entries
- DwarfTransformer(DWARFContext &D, GsymCreator &G, bool LDCS = false)
- : DICtx(D), Gsym(G), LoadDwarfCallSites(LDCS) {}
+ ///
+ /// \param MachO Flag to indicate if the object file is mach-o (Apple's
+ /// executable format). Apple has some compile unit attributes that look like
+ /// split DWARF, but they aren't and they can cause warnins to be emitted
+ /// about missing DWO files.
+ DwarfTransformer(DWARFContext &D, GsymCreator &G, bool LDCS = false,
+ bool MachO = false)
+ : DICtx(D), Gsym(G), LoadDwarfCallSites(LDCS), IsMachO(MachO) {}
/// Extract the DWARF from the supplied object file and convert it into the
/// Gsym format in the GsymCreator object that is passed in. Returns an
@@ -63,7 +69,6 @@ class DwarfTransformer {
LLVM_ABI llvm::Error verify(StringRef GsymPath, OutputAggregator &OS);
private:
-
/// Parse the DWARF in the object file and convert it into the GsymCreator.
Error parse();
@@ -97,6 +102,7 @@ class DwarfTransformer {
DWARFContext &DICtx;
GsymCreator &Gsym;
bool LoadDwarfCallSites;
+ bool IsMachO;
friend class DwarfTransformerTest;
};
diff --git a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
index 7a0256f10ea60..77b04656308c0 100644
--- a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
+++ b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
@@ -82,7 +82,6 @@ struct llvm::gsym::CUInfo {
}
};
-
static DWARFDie GetParentDeclContextDIE(DWARFDie &Die) {
if (DWARFDie SpecDie =
Die.getAttributeValueAsReferencedDie(dwarf::DW_AT_specification)) {
@@ -170,7 +169,7 @@ getQualifiedNameIndex(DWARFDie &Die, uint64_t Language, GsymCreator &Gsym) {
// templates
if (ParentName.front() == '<' && ParentName.back() == '>')
Name = "{" + ParentName.substr(1, ParentName.size() - 2).str() + "}" +
- "::" + Name;
+ "::" + Name;
else
Name = ParentName.str() + "::" + Name;
}
@@ -432,7 +431,7 @@ static void convertFunctionLineTable(OutputAggregator &Out, CUInfo &CUI,
// Skip multiple line entries for the same file and line.
auto LastLE = FI.OptLineTable->last();
if (LastLE && LastLE->File == FileIdx && LastLE->Line == Row.Line)
- continue;
+ continue;
// Only push a row if it isn't an end sequence. End sequence markers are
// included for the last address in a function or the last contiguous
// address in a sequence.
@@ -629,6 +628,10 @@ Error DwarfTransformer::convert(uint32_t NumThreads, OutputAggregator &Out) {
size_t NumBefore = Gsym.getNumFunctionInfos();
auto getDie = [&](DWARFUnit &DwarfUnit) -> DWARFDie {
DWARFDie ReturnDie = DwarfUnit.getUnitDIE(false);
+ // Apple uses DW_AT_GNU_dwo_id for things other than split DWARF.
+ if (IsMachO)
+ return ReturnDie;
+
if (DwarfUnit.getDWOId()) {
DWARFUnit *DWOCU = DwarfUnit.getNonSkeletonUnitDIE(false).getDwarfUnit();
if (!DWOCU->isDWOUnit())
@@ -718,8 +721,8 @@ llvm::Error DwarfTransformer::verify(StringRef GsymPath,
for (uint32_t I = 0; I < NumAddrs; ++I) {
auto FuncAddr = Gsym->getAddress(I);
if (!FuncAddr)
- return createStringError(std::errc::invalid_argument,
- "failed to extract address[%i]", I);
+ return createStringError(std::errc::invalid_argument,
+ "failed to extract address[%i]", I);
auto FI = Gsym->getFunctionInfo(*FuncAddr);
if (!FI)
@@ -734,8 +737,7 @@ llvm::Error DwarfTransformer::verify(StringRef GsymPath,
if (!LR)
return LR.takeError();
- auto DwarfInlineInfos =
- DICtx.getInliningInfoForAddress(SectAddr, DLIS);
+ auto DwarfInlineInfos = DICtx.getInliningInfoForAddress(SectAddr, DLIS);
uint32_t NumDwarfInlineInfos = DwarfInlineInfos.getNumberOfFrames();
if (NumDwarfInlineInfos == 0) {
DwarfInlineInfos.addFrame(
@@ -773,8 +775,7 @@ llvm::Error DwarfTransformer::verify(StringRef GsymPath,
continue;
}
- for (size_t Idx = 0, count = LR->Locations.size(); Idx < count;
- ++Idx) {
+ for (size_t Idx = 0, count = LR->Locations.size(); Idx < count; ++Idx) {
const auto &gii = LR->Locations[Idx];
if (Idx < NumDwarfInlineInfos) {
const auto &dii = DwarfInlineInfos.getFrame(Idx);
diff --git a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
index de83a0dc8ebe2..28b7ff80b0dbd 100644
--- a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
+++ b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
@@ -374,19 +374,20 @@ static llvm::Error handleObjectFile(ObjectFile &Obj, const std::string &OutFile,
// Make sure there is DWARF to convert first.
std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(
Obj,
- /*RelocAction=*/DWARFContext::ProcessDebugRelocations::Process,
- nullptr,
+ /*RelocAction=*/DWARFContext::ProcessDebugRelocations::Process, nullptr,
/*DWPName=*/"",
/*RecoverableErrorHandler=*/WithColor::defaultErrorHandler,
/*WarningHandler=*/WithColor::defaultWarningHandler,
- /*ThreadSafe*/true);
+ /*ThreadSafe*/ true);
if (!DICtx)
return createStringError(std::errc::invalid_argument,
"unable to create DWARF context");
// Make a DWARF transformer object and populate the ranges of the code
// so we don't end up adding invalid functions to GSYM data.
- DwarfTransformer DT(*DICtx, Gsym, LoadDwarfCallSites);
+ bool IsMachO = dyn_cast<object::MachOObjectFile>(&Obj) != nullptr;
+
+ DwarfTransformer DT(*DICtx, Gsym, LoadDwarfCallSites, IsMachO);
if (!TextRanges.empty())
Gsym.SetValidTextRanges(TextRanges);
diff --git a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
index 33f53de2e77bc..8493221dc8aa5 100644
--- a/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
+++ b/llvm/unittests/DebugInfo/GSYM/GSYMTest.cpp
@@ -24,8 +24,8 @@
#include "llvm/Support/DataExtractor.h"
#include "llvm/Testing/Support/Error.h"
-#include "gtest/gtest.h"
#include "gmock/gmock.h"
+#include "gtest/gtest.h"
#include <string>
using namespace llvm;
@@ -99,7 +99,7 @@ TEST(GSYMTest, TestFunctionInfo) {
const uint32_t FileIdx = 1;
const uint32_t Line = 12;
FI.OptLineTable = LineTable();
- FI.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line));
+ FI.OptLineTable->push(LineEntry(StartAddr, FileIdx, Line));
EXPECT_TRUE(FI.hasRichInfo());
FI.clear();
EXPECT_FALSE(FI.isValid());
@@ -135,7 +135,7 @@ TEST(GSYMTest, TestFunctionInfo) {
FunctionInfo FISymtab(StartAddr, Size, NameOffset);
FunctionInfo FIWithLines(StartAddr, Size, NameOffset);
FIWithLines.OptLineTable = LineTable();
- FIWithLines.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line));
+ FIWithLines.OptLineTable->push(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);
@@ -166,7 +166,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.OptLineTable->push(LineEntry(StartAddr,FileIdx,Line+5));
+ FIWithMoreLines.OptLineTable->push(LineEntry(StartAddr, FileIdx, Line + 5));
EXPECT_LT(FIWithLines, FIWithMoreLines);
// Test that if we have the same number of lines we compare the line entries
@@ -198,24 +198,27 @@ TEST(GSYMTest, TestFunctionInfoDecodeErrors) {
FileWriter FW(OutStrm, ByteOrder);
const uint64_t BaseAddr = 0x100;
TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000000: missing FunctionInfo Size");
+ "0x00000000: missing FunctionInfo Size");
FW.writeU32(0x100); // Function size.
TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000004: missing FunctionInfo Name");
+ "0x00000004: missing FunctionInfo Name");
// Write out an invalid Name string table offset of zero.
FW.writeU32(0);
- TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
+ TestFunctionInfoDecodeError(
+ ByteOrder, OutStrm.str(), BaseAddr,
"0x00000004: invalid FunctionInfo Name value 0x00000000");
// Modify the Name to be 0x00000001, which is a valid value.
FW.fixup32(0x00000001, 4);
- TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
+ TestFunctionInfoDecodeError(
+ ByteOrder, OutStrm.str(), BaseAddr,
"0x00000008: missing FunctionInfo InfoType value");
auto FixupOffset = FW.tell();
FW.writeU32(1); // InfoType::LineTableInfo.
- TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
+ TestFunctionInfoDecodeError(
+ ByteOrder, OutStrm.str(), BaseAddr,
"0x0000000c: missing FunctionInfo InfoType length");
FW.fixup32(7, FixupOffset); // Write an invalid InfoType enumeration value
- FW.writeU32(0); // LineTableInfo InfoType data length.
+ FW.writeU32(0); // LineTableInfo InfoType data length.
TestFunctionInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
"0x00000008: unsupported InfoType 7");
}
@@ -278,25 +281,24 @@ static void TestFunctionInfoEncodeDecode(llvm::endianness ByteOrder,
}
static void AddLines(uint64_t FuncAddr, uint32_t FileIdx, FunctionInfo &FI) {
- FI.OptLineTable = LineTable();
- LineEntry Line0(FuncAddr + 0x000, FileIdx, 10);
- LineEntry Line1(FuncAddr + 0x010, FileIdx, 11);
- LineEntry Line2(FuncAddr + 0x100, FileIdx, 1000);
- FI.OptLineTable->push(Line0);
- FI.OptLineTable->push(Line1);
- FI.OptLineTable->push(Line2);
+ FI.OptLineTable = LineTable();
+ LineEntry Line0(FuncAddr + 0x000, FileIdx, 10);
+ LineEntry Line1(FuncAddr + 0x010, FileIdx, 11);
+ LineEntry Line2(FuncAddr + 0x100, FileIdx, 1000);
+ FI.OptLineTable->push(Line0);
+ FI.OptLineTable->push(Line1);
+ FI.OptLineTable->push(Line2);
}
-
static void AddInline(uint64_t FuncAddr, uint64_t FuncSize, FunctionInfo &FI) {
- FI.Inline = InlineInfo();
- FI.Inline->Ranges.insert(AddressRange(FuncAddr, FuncAddr + FuncSize));
- InlineInfo Inline1;
- Inline1.Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x30));
- Inline1.Name = 1;
- Inline1.CallFile = 1;
- Inline1.CallLine = 11;
- FI.Inline->Children.push_back(Inline1);
+ FI.Inline = InlineInfo();
+ FI.Inline->Ranges.insert(AddressRange(FuncAddr, FuncAddr + FuncSize));
+ InlineInfo Inline1;
+ Inline1.Ranges.insert(AddressRange(FuncAddr + 0x10, FuncAddr + 0x30));
+ Inline1.Name = 1;
+ Inline1.CallFile = 1;
+ Inline1.CallLine = 11;
+ FI.Inline->Children.push_back(Inline1);
}
TEST(GSYMTest, TestFunctionInfoEncoding) {
@@ -514,21 +516,25 @@ TEST(GSYMTest, TestInlineInfoDecodeErrors) {
raw_svector_ostream OutStrm(Str);
FileWriter FW(OutStrm, ByteOrder);
const uint64_t BaseAddr = 0x100;
- TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
+ TestInlineInfoDecodeError(
+ ByteOrder, OutStrm.str(), BaseAddr,
"0x00000000: missing InlineInfo address ranges data");
AddressRanges Ranges;
- Ranges.insert({BaseAddr, BaseAddr+0x100});
+ Ranges.insert({BaseAddr, BaseAddr + 0x100});
encodeRanges(Ranges, FW, BaseAddr);
- TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
+ TestInlineInfoDecodeError(
+ ByteOrder, OutStrm.str(), BaseAddr,
"0x00000004: missing InlineInfo uint8_t indicating children");
FW.writeU8(0);
TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000005: missing InlineInfo uint32_t for name");
+ "0x00000005: missing InlineInfo uint32_t for name");
FW.writeU32(0);
- TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
+ TestInlineInfoDecodeError(
+ ByteOrder, OutStrm.str(), BaseAddr,
"0x00000009: missing ULEB128 for InlineInfo call file");
FW.writeU8(0);
- TestInlineInfoDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
+ TestInlineInfoDecodeError(
+ ByteOrder, OutStrm.str(), BaseAddr,
"0x0000000a: missing ULEB128 for InlineInfo call line");
}
@@ -708,20 +714,20 @@ TEST(GSYMTest, TestLineTable) {
const uint64_t StartAddr = 0x1000;
const uint32_t FileIdx = 1;
LineTable LT;
- LineEntry Line0(StartAddr+0x000, FileIdx, 10);
- LineEntry Line1(StartAddr+0x010, FileIdx, 11);
- LineEntry Line2(StartAddr+0x100, FileIdx, 1000);
+ LineEntry Line0(StartAddr + 0x000, FileIdx, 10);
+ LineEntry Line1(StartAddr + 0x010, FileIdx, 11);
+ LineEntry Line2(StartAddr + 0x100, FileIdx, 1000);
ASSERT_TRUE(LT.empty());
ASSERT_EQ(LT.size(), (size_t)0);
LT.push(Line0);
ASSERT_EQ(LT.size(), (size_t)1);
LT.push(Line1);
LT.push(Line2);
- LT.push(LineEntry(StartAddr+0x120, FileIdx, 900));
- LT.push(LineEntry(StartAddr+0x120, FileIdx, 2000));
- LT.push(LineEntry(StartAddr+0x121, FileIdx, 2001));
- LT.push(LineEntry(StartAddr+0x122, FileIdx, 2002));
- LT.push(LineEntry(StartAddr+0x123, FileIdx, 2003));
+ LT.push(LineEntry(StartAddr + 0x120, FileIdx, 900));
+ LT.push(LineEntry(StartAddr + 0x120, FileIdx, 2000));
+ LT.push(LineEntry(StartAddr + 0x121, FileIdx, 2001));
+ LT.push(LineEntry(StartAddr + 0x122, FileIdx, 2002));
+ LT.push(LineEntry(StartAddr + 0x123, FileIdx, 2003));
ASSERT_FALSE(LT.empty());
ASSERT_EQ(LT.size(), (size_t)8);
// Test operator[].
@@ -783,30 +789,30 @@ TEST(GSYMTest, TestLineTableDecodeErrors) {
FileWriter FW(OutStrm, ByteOrder);
const uint64_t BaseAddr = 0x100;
TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000000: missing LineTable MinDelta");
+ "0x00000000: missing LineTable MinDelta");
FW.writeU8(1); // MinDelta (ULEB)
TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000001: missing LineTable MaxDelta");
+ "0x00000001: missing LineTable MaxDelta");
FW.writeU8(10); // MaxDelta (ULEB)
TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000002: missing LineTable FirstLine");
+ "0x00000002: missing LineTable FirstLine");
FW.writeU8(20); // FirstLine (ULEB)
TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000003: EOF found before EndSequence");
+ "0x00000003: EOF found before EndSequence");
// Test a SetFile with the argument missing from the stream
FW.writeU8(1); // SetFile opcode (uint8_t)
TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000004: EOF found before SetFile value");
+ "0x00000004: EOF found before SetFile value");
FW.writeU8(5); // SetFile value as index (ULEB)
// Test a AdvancePC with the argument missing from the stream
FW.writeU8(2); // AdvancePC opcode (uint8_t)
TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000006: EOF found before AdvancePC value");
+ "0x00000006: EOF found before AdvancePC value");
FW.writeU8(20); // AdvancePC value as offset (ULEB)
// Test a AdvancePC with the argument missing from the stream
FW.writeU8(3); // AdvanceLine opcode (uint8_t)
TestLineTableDecodeError(ByteOrder, OutStrm.str(), BaseAddr,
- "0x00000008: EOF found before AdvanceLine value");
+ "0x00000008: EOF found before AdvanceLine value");
FW.writeU8(20); // AdvanceLine value as offset (LLEB)
}
@@ -823,16 +829,17 @@ TEST(GSYMTest, TestLineTableEncodeErrors) {
// Try to encode a line table where a line entry has an address that is less
// than BaseAddr and verify we get an appropriate error.
- LineEntry Line0(BaseAddr+0x000, FileIdx, 10);
- LineEntry Line1(BaseAddr+0x010, FileIdx, 11);
+ LineEntry Line0(BaseAddr + 0x000, FileIdx, 10);
+ LineEntry Line1(BaseAddr + 0x010, FileIdx, 11);
LT.push(Line0);
LT.push(Line1);
checkError("LineEntry has address 0x1000 which is less than the function "
- "start address 0x1010", LT.encode(FW, BaseAddr+0x10));
+ "start address 0x1010",
+ LT.encode(FW, BaseAddr + 0x10));
LT.clear();
- // Try to encode a line table where a line entries has an address that is less
- // than BaseAddr and verify we get an appropriate error.
+ // Try to encode a line table where a line entries has an address that is
+ // less than BaseAddr and verify we get an appropriate error.
LT.push(Line1);
LT.push(Line0);
checkError("LineEntry in LineTable not in ascending order",
@@ -870,9 +877,9 @@ static void InitHeader(Header &H) {
H.UUIDSize = 16;
H.BaseAddress = 0x1000;
H.NumAddresses = 1;
- H.StrtabOffset= 0x2000;
+ H.StrtabOffset = 0x2000;
H.StrtabSize = 0x1000;
- for (size_t i=0; i<GSYM_MAX_UUID_SIZE; ++i) {
+ for (size_t i = 0; i < GSYM_MAX_UUID_SIZE; ++i) {
if (i < H.UUIDSize)
H.UUID[i] = i;
else
@@ -952,10 +959,10 @@ static void TestGsymCreatorEncodeError(llvm::endianness ByteOrder,
}
TEST(GSYMTest, TestGsymCreatorEncodeErrors) {
- const uint8_t ValidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16};
- const uint8_t InvalidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21};
+ const uint8_t ValidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16};
+ const uint8_t InvalidUUID[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
// Verify we get an error when trying to encode an GsymCreator with no
// function infos. We shouldn't be saving a GSYM file in this case since
// there is nothing inside of it.
@@ -988,7 +995,7 @@ TEST(GSYMTest, TestGsymCreatorEncodeErrors) {
// table.
GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
FI.OptLineTable = LineTable(); // Invalid line table.
- return false; // Stop iterating
+ return false; // Stop iterating
});
TestGsymCreatorEncodeError(llvm::endianness::little, GC,
"attempted to encode invalid LineTable object");
@@ -997,7 +1004,7 @@ TEST(GSYMTest, TestGsymCreatorEncodeErrors) {
GC.forEachFunctionInfo([](FunctionInfo &FI) -> bool {
FI.OptLineTable = std::nullopt;
FI.Inline = InlineInfo(); // Invalid InlineInfo.
- return false; // Stop iterating
+ return false; // Stop iterating
});
TestGsymCreatorEncodeError(llvm::endianness::little, GC,
"attempted to encode invalid InlineInfo object");
@@ -1043,8 +1050,8 @@ TEST(GSYMTest, TestGsymCreator1ByteAddrOffsets) {
constexpr uint8_t AddrOffSize = 1;
const uint32_t Func1Name = GC.insertString("foo");
const uint32_t Func2Name = GC.insertString("bar");
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x00, 0x10, Func1Name));
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20, 0x10, Func2Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x00, 0x10, Func1Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x20, 0x10, Func2Name));
OutputAggregator Null(nullptr);
Error Err = GC.finalize(Null);
ASSERT_FALSE(Err);
@@ -1066,8 +1073,8 @@ TEST(GSYMTest, TestGsymCreator2ByteAddrOffsets) {
constexpr uint8_t AddrOffSize = 2;
const uint32_t Func1Name = GC.insertString("foo");
const uint32_t Func2Name = GC.insertString("bar");
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x200, 0x100, Func2Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x000, 0x100, Func1Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x200, 0x100, Func2Name));
OutputAggregator Null(nullptr);
Error Err = GC.finalize(Null);
ASSERT_FALSE(Err);
@@ -1089,8 +1096,8 @@ TEST(GSYMTest, TestGsymCreator4ByteAddrOffsets) {
constexpr uint8_t AddrOffSize = 4;
const uint32_t Func1Name = GC.insertString("foo");
const uint32_t Func2Name = GC.insertString("bar");
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x20000, 0x100, Func2Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x000, 0x100, Func1Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x20000, 0x100, Func2Name));
OutputAggregator Null(nullptr);
Error Err = GC.finalize(Null);
ASSERT_FALSE(Err);
@@ -1112,8 +1119,8 @@ TEST(GSYMTest, TestGsymCreator8ByteAddrOffsets) {
constexpr uint8_t AddrOffSize = 8;
const uint32_t Func1Name = GC.insertString("foo");
const uint32_t Func2Name = GC.insertString("bar");
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x000, 0x100, Func1Name));
- GC.addFunctionInfo(FunctionInfo(BaseAddr+0x100000000, 0x100, Func2Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x000, 0x100, Func1Name));
+ GC.addFunctionInfo(FunctionInfo(BaseAddr + 0x100000000, 0x100, Func2Name));
OutputAggregator Null(nullptr);
Error Err = GC.finalize(Null);
ASSERT_FALSE(Err);
@@ -1147,7 +1154,7 @@ TEST(GSYMTest, TestGsymReader) {
GC.setUUID(UUID);
constexpr uint64_t BaseAddr = 0x1000;
constexpr uint64_t Func1Addr = BaseAddr;
- constexpr uint64_t Func2Addr = BaseAddr+0x20;
+ constexpr uint64_t Func2Addr = BaseAddr + 0x20;
constexpr uint64_t FuncSize = 0x10;
const uint32_t Func1Name = GC.insertString("foo");
const uint32_t Func2Name = GC.insertString("bar");
@@ -1164,20 +1171,20 @@ TEST(GSYMTest, TestGsymReader) {
ASSERT_FALSE((bool)Err);
if (auto ExpectedGR = GsymReader::copyBuffer(OutStrm.str())) {
const GsymReader &GR = ExpectedGR.get();
- VerifyFunctionInfoError(GR, Func1Addr-1, "address 0xfff is not in GSYM");
+ VerifyFunctionInfoError(GR, Func1Addr - 1, "address 0xfff is not in GSYM");
FunctionInfo Func1(Func1Addr, FuncSize, Func1Name);
VerifyFunctionInfo(GR, Func1Addr, Func1);
- VerifyFunctionInfo(GR, Func1Addr+1, Func1);
- VerifyFunctionInfo(GR, Func1Addr+FuncSize-1, Func1);
- VerifyFunctionInfoError(GR, Func1Addr+FuncSize,
+ VerifyFunctionInfo(GR, Func1Addr + 1, Func1);
+ VerifyFunctionInfo(GR, Func1Addr + FuncSize - 1, Func1);
+ VerifyFunctionInfoError(GR, Func1Addr + FuncSize,
"address 0x1010 is not in GSYM");
- VerifyFunctionInfoError(GR, Func2Addr-1, "address 0x101f is not in GSYM");
+ VerifyFunctionInfoError(GR, Func2Addr - 1, "address 0x101f is not in GSYM");
FunctionInfo Func2(Func2Addr, FuncSize, Func2Name);
VerifyFunctionInfo(GR, Func2Addr, Func2);
- VerifyFunctionInfo(GR, Func2Addr+1, Func2);
- VerifyFunctionInfo(GR, Func2Addr+FuncSize-1, Func2);
- VerifyFunctionInfoError(GR, Func2Addr+FuncSize,
+ VerifyFunctionInfo(GR, Func2Addr + 1, Func2);
+ VerifyFunctionInfo(GR, Func2Addr + FuncSize - 1, Func2);
+ VerifyFunctionInfoError(GR, Func2Addr + FuncSize,
"address 0x1030 is not in GSYM");
}
}
@@ -1234,53 +1241,57 @@ TEST(GSYMTest, TestGsymLookups) {
// Verify inline info is correct when doing lookups.
auto LR = GR->lookup(0x1000);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5}));
+ EXPECT_THAT(LR->Locations, testing::ElementsAre(
+ SourceLocation{"main", "/tmp", "main.c", 5}));
LR = GR->lookup(0x100F);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 5, 15}));
+ EXPECT_THAT(LR->Locations, testing::ElementsAre(SourceLocation{
+ "main", "/tmp", "main.c", 5, 15}));
LR = GR->lookup(0x1010);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 10},
- SourceLocation{"main", "/tmp", "main.c", 6, 16}));
+ EXPECT_THAT(
+ LR->Locations,
+ testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 10},
+ SourceLocation{"main", "/tmp", "main.c", 6, 16}));
LR = GR->lookup(0x1012);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline2", "/tmp", "foo.h", 20},
- SourceLocation{"inline1", "/tmp", "foo.h", 33, 2},
- SourceLocation{"main", "/tmp", "main.c", 6, 18}));
+ EXPECT_THAT(
+ LR->Locations,
+ testing::ElementsAre(SourceLocation{"inline2", "/tmp", "foo.h", 20},
+ SourceLocation{"inline1", "/tmp", "foo.h", 33, 2},
+ SourceLocation{"main", "/tmp", "main.c", 6, 18}));
LR = GR->lookup(0x1014);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 11, 4},
- SourceLocation{"main", "/tmp", "main.c", 6, 20}));
+ EXPECT_THAT(
+ LR->Locations,
+ testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 11, 4},
+ SourceLocation{"main", "/tmp", "main.c", 6, 20}));
LR = GR->lookup(0x1016);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline3", "/tmp", "foo.h", 30},
- SourceLocation{"inline1", "/tmp", "foo.h", 35, 6},
- SourceLocation{"main", "/tmp", "main.c", 6, 22}));
+ EXPECT_THAT(
+ LR->Locations,
+ testing::ElementsAre(SourceLocation{"inline3", "/tmp", "foo.h", 30},
+ SourceLocation{"inline1", "/tmp", "foo.h", 35, 6},
+ SourceLocation{"main", "/tmp", "main.c", 6, 22}));
LR = GR->lookup(0x1018);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 12, 8},
- SourceLocation{"main", "/tmp", "main.c", 6, 24}));
+ EXPECT_THAT(
+ LR->Locations,
+ testing::ElementsAre(SourceLocation{"inline1", "/tmp", "foo.h", 12, 8},
+ SourceLocation{"main", "/tmp", "main.c", 6, 24}));
LR = GR->lookup(0x1020);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 8, 32}));
+ EXPECT_THAT(LR->Locations, testing::ElementsAre(SourceLocation{
+ "main", "/tmp", "main.c", 8, 32}));
}
-
TEST(GSYMTest, TestDWARFFunctionWithAddresses) {
// Create a single compile unit with a single function and make sure it gets
// converted to DWARF correctly. The function's address range is in where
@@ -1851,43 +1862,46 @@ TEST(GSYMTest, TestDWARFInlineInfo) {
StringRef MethodName = GR->getString(ExpFI->Name);
EXPECT_EQ(MethodName, "main");
- // Verify inline info is correct when doing lookups.
+ // Verify inline info is correct when doing lookups.
auto LR = GR->lookup(0x1000);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10}));
- LR = GR->lookup(0x1100-1);
+ EXPECT_THAT(LR->Locations, testing::ElementsAre(
+ SourceLocation{"main", "/tmp", "main.c", 10}));
+ LR = GR->lookup(0x1100 - 1);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 10, 255}));
+ EXPECT_THAT(LR->Locations, testing::ElementsAre(SourceLocation{
+ "main", "/tmp", "main.c", 10, 255}));
LR = GR->lookup(0x1100);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20},
- SourceLocation{"main", "/tmp", "main.c", 10, 256}));
- LR = GR->lookup(0x1180-1);
+ EXPECT_THAT(
+ LR->Locations,
+ testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20},
+ SourceLocation{"main", "/tmp", "main.c", 10, 256}));
+ LR = GR->lookup(0x1180 - 1);
ASSERT_THAT_EXPECTED(LR, Succeeded());
EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 20, 127},
- SourceLocation{"main", "/tmp", "main.c", 10, 383}));
+ testing::ElementsAre(
+ SourceLocation{"inline1", "/tmp", "inline.h", 20, 127},
+ SourceLocation{"main", "/tmp", "main.c", 10, 383}));
LR = GR->lookup(0x1180);
ASSERT_THAT_EXPECTED(LR, Succeeded());
EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 128},
- SourceLocation{"main", "/tmp", "main.c", 10, 384}));
- LR = GR->lookup(0x1200-1);
+ testing::ElementsAre(
+ SourceLocation{"inline1", "/tmp", "inline.h", 21, 128},
+ SourceLocation{"main", "/tmp", "main.c", 10, 384}));
+ LR = GR->lookup(0x1200 - 1);
ASSERT_THAT_EXPECTED(LR, Succeeded());
EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"inline1", "/tmp", "inline.h", 21, 255},
- SourceLocation{"main", "/tmp", "main.c", 10, 511}));
+ testing::ElementsAre(
+ SourceLocation{"inline1", "/tmp", "inline.h", 21, 255},
+ SourceLocation{"main", "/tmp", "main.c", 10, 511}));
LR = GR->lookup(0x1200);
ASSERT_THAT_EXPECTED(LR, Succeeded());
- EXPECT_THAT(LR->Locations,
- testing::ElementsAre(SourceLocation{"main", "/tmp", "main.c", 11, 512}));
+ EXPECT_THAT(LR->Locations, testing::ElementsAre(SourceLocation{
+ "main", "/tmp", "main.c", 11, 512}));
}
-
TEST(GSYMTest, TestDWARFNoLines) {
// Check that if a DW_TAG_subprogram doesn't have line table entries that
// we fall back and use the DW_AT_decl_file and DW_AT_decl_line to at least
@@ -2150,7 +2164,6 @@ TEST(GSYMTest, TestDWARFNoLines) {
EXPECT_EQ(ExpFI->OptLineTable->first()->Line, 40u);
}
-
TEST(GSYMTest, TestDWARFDeadStripAddr4) {
// Check that various techniques that compilers use for dead code stripping
// work for 4 byte addresses. Make sure we keep the good functions and
@@ -2459,7 +2472,8 @@ TEST(GSYMTest, TestGsymCreatorMultipleSymbolsWithNoSize) {
ArrayRef<uint8_t>(UUID));
}
-// Helper function to quickly create a FunctionInfo in a GsymCreator for testing.
+// Helper function to quickly create a FunctionInfo in a GsymCreator for
+// testing.
static void AddFunctionInfo(GsymCreator &GC, const char *FuncName,
uint64_t FuncAddr, const char *SourcePath,
const char *HeaderPath) {
@@ -2467,18 +2481,21 @@ static void AddFunctionInfo(GsymCreator &GC, const char *FuncName,
FI.OptLineTable = LineTable();
const uint32_t SourceFileIdx = GC.insertFile(SourcePath);
const uint32_t HeaderFileIdx = GC.insertFile(HeaderPath);
- FI.OptLineTable->push(LineEntry(FuncAddr+0x00, SourceFileIdx, 5));
- FI.OptLineTable->push(LineEntry(FuncAddr+0x10, HeaderFileIdx, 10));
- FI.OptLineTable->push(LineEntry(FuncAddr+0x12, HeaderFileIdx, 20));
- FI.OptLineTable->push(LineEntry(FuncAddr+0x14, HeaderFileIdx, 11));
- FI.OptLineTable->push(LineEntry(FuncAddr+0x16, HeaderFileIdx, 30));
- FI.OptLineTable->push(LineEntry(FuncAddr+0x18, HeaderFileIdx, 12));
- FI.OptLineTable->push(LineEntry(FuncAddr+0x20, SourceFileIdx, 8));
+ FI.OptLineTable->push(LineEntry(FuncAddr + 0x00, SourceFileIdx, 5));
+ FI.OptLineTable->push(LineEntry(FuncAddr + 0x10, HeaderFileIdx, 10));
+ FI.OptLineTable->push(LineEntry(FuncAddr + 0x12, HeaderFileIdx, 20));
+ FI.OptLineTable->push(LineEntry(FuncAddr + 0x14, HeaderFileIdx, 11));
+ FI.OptLineTable->push(LineEntry(FuncAddr + 0x16, HeaderFileIdx, 30));
+ FI.OptLineTable->push(LineEntry(FuncAddr + 0x18, HeaderFileIdx, 12));
+ FI.OptLineTable->push(LineEntry(FuncAddr + 0x20, SourceFileIdx, 8));
FI.Inline = InlineInfo();
- std::string InlineName1(FuncName); InlineName1.append("1");
- std::string InlineName2(FuncName); InlineName2.append("2");
- std::string InlineName3(FuncName); InlineName3.append("3");
+ std::string InlineName1(FuncName);
+ InlineName1.append("1");
+ std::string InlineName2(FuncName);
+ InlineName2.append("2");
+ std::string InlineName3(FuncName);
+ InlineName3.append("3");
FI.Inline->Name = GC.insertString(InlineName1);
FI.Inline->CallFile = SourceFileIdx;
@@ -2530,7 +2547,7 @@ TEST(GSYMTest, TestGsymSegmenting) {
AddFunctionInfo(GC, "baz", 0x4000, "/tmp/baz.c", "/tmp/baz.h");
Expected<GsymReader> GR = FinalizeEncodeAndDecode(GC);
ASSERT_THAT_EXPECTED(GR, Succeeded());
- //GR->dump(outs());
+ // GR->dump(outs());
// Create segmented GSYM files where each file contains 1 function. We will
// then test doing lookups on the "GR", or the full GSYM file and then test
@@ -2552,7 +2569,8 @@ TEST(GSYMTest, TestGsymSegmenting) {
GC.createSegment(57, FuncIdx);
ASSERT_FALSE((bool)GCError);
checkError("a segment size of 57 is to small to fit any function infos, "
- "specify a larger value", GCError.takeError());
+ "specify a larger value",
+ GCError.takeError());
// Make sure that the function index didn't get incremented when we didn't
// encode any values into the segmented GsymCreator.
ASSERT_EQ(FuncIdx, (size_t)0);
@@ -2627,7 +2645,6 @@ TEST(GSYMTest, TestGsymSegmenting) {
ASSERT_THAT_EXPECTED(GR2000->lookup(0x1000), Failed());
ASSERT_THAT_EXPECTED(GR2000->lookup(0x3000), Failed());
ASSERT_THAT_EXPECTED(GR2000->lookup(0x4000), Failed());
-
}
// Verify that all lookups match the range [0x3000-0x3030) when doing lookups
@@ -2646,7 +2663,7 @@ TEST(GSYMTest, TestGsymSegmenting) {
ASSERT_THAT_EXPECTED(GR3000->lookup(0x1000), Failed());
ASSERT_THAT_EXPECTED(GR3000->lookup(0x2000), Failed());
ASSERT_THAT_EXPECTED(GR3000->lookup(0x4000), Failed());
-}
+ }
// Verify that all lookups match the range [0x4000-0x4030) when doing lookups
// in the GsymReader that contains all functions and from the segmented
@@ -2681,7 +2698,7 @@ TEST(GSYMTest, TestGsymSegmentingNoBase) {
AddFunctionInfo(GC, "baz", 0x4000, "/tmp/baz.c", "/tmp/baz.h");
Expected<GsymReader> GR = FinalizeEncodeAndDecode(GC);
ASSERT_THAT_EXPECTED(GR, Succeeded());
- //GR->dump(outs());
+ // GR->dump(outs());
// Create segmented GSYM files where each file contains 1 function. We will
// then test doing lookups on the "GR", or the full GSYM file and then test
@@ -2703,7 +2720,8 @@ TEST(GSYMTest, TestGsymSegmentingNoBase) {
GC.createSegment(57, FuncIdx);
ASSERT_FALSE((bool)GCError);
checkError("a segment size of 57 is to small to fit any function infos, "
- "specify a larger value", GCError.takeError());
+ "specify a larger value",
+ GCError.takeError());
// Make sure that the function index didn't get incremented when we didn't
// encode any values into the segmented GsymCreator.
ASSERT_EQ(FuncIdx, (size_t)0);
@@ -2778,7 +2796,6 @@ TEST(GSYMTest, TestGsymSegmentingNoBase) {
ASSERT_THAT_EXPECTED(GR2000->lookup(0x1000), Failed());
ASSERT_THAT_EXPECTED(GR2000->lookup(0x3000), Failed());
ASSERT_THAT_EXPECTED(GR2000->lookup(0x4000), Failed());
-
}
// Verify that all lookups match the range [0x3000-0x3030) when doing lookups
@@ -2797,7 +2814,7 @@ TEST(GSYMTest, TestGsymSegmentingNoBase) {
ASSERT_THAT_EXPECTED(GR3000->lookup(0x1000), Failed());
ASSERT_THAT_EXPECTED(GR3000->lookup(0x2000), Failed());
ASSERT_THAT_EXPECTED(GR3000->lookup(0x4000), Failed());
-}
+ }
// Verify that all lookups match the range [0x4000-0x4030) when doing lookups
// in the GsymReader that contains all functions and from the segmented
@@ -2819,7 +2836,6 @@ TEST(GSYMTest, TestGsymSegmentingNoBase) {
}
}
-
TEST(GSYMTest, TestDWARFInlineRangeScopes) {
// Test cases where inlined functions address ranges are not contained in the
// parent ranges and that we can successfully remove them and emit error
@@ -3074,16 +3090,19 @@ TEST(GSYMTest, TestDWARFInlineRangeScopes) {
StringRef FuncName = GR->getString(ExpFI->Name);
EXPECT_EQ(FuncName, "foo");
std::vector<std::string> ExpectedLogErrors = {
- "error: inlined function DIE at 0x0000002a has a range [0x0000000000000fff "
- "- 0x0000000000001001) that isn't contained in any parent address ranges, "
- "this inline range will be removed.",
- "error: inlined function DIE at 0x00000058 has a range [0x0000000000001000 "
- "- 0x0000000000001100) that isn't contained in any parent address ranges, "
- "this inline range will be removed."
- };
+ "error: inlined function DIE at 0x0000002a has a range "
+ "[0x0000000000000fff "
+ "- 0x0000000000001001) that isn't contained in any parent address "
+ "ranges, "
+ "this inline range will be removed.",
+ "error: inlined function DIE at 0x00000058 has a range "
+ "[0x0000000000001000 "
+ "- 0x0000000000001100) that isn't contained in any parent address "
+ "ranges, "
+ "this inline range will be removed."};
// Make sure all expected errors are in the error stream for the two invalid
// inlined functions that we removed due to invalid range scoping.
- for (const auto &Error: ExpectedLogErrors) {
+ for (const auto &Error : ExpectedLogErrors) {
EXPECT_TRUE(OS.str().find(Error) != std::string::npos);
}
// The top level inline info is for the function "foo" itself. Verify that
@@ -3096,7 +3115,6 @@ TEST(GSYMTest, TestDWARFInlineRangeScopes) {
EXPECT_EQ(ExpFI->Inline->CallLine, 0u);
EXPECT_EQ(ExpFI->Inline->Children.size(), 1u);
-
// The first inline function "valid1" contains two inline functions in the
// DWARF, but one has an address range which isn't contained in any ranges
// from "foo", so only 1 inline function be parsed.
@@ -3107,7 +3125,6 @@ TEST(GSYMTest, TestDWARFInlineRangeScopes) {
EXPECT_EQ(Inline1.CallLine, 11u);
EXPECT_EQ(Inline1.Children.size(), 1u);
-
// The second inline function "valid2" contains two inline functions in the
// DWARF, but one has an address range which isn't contained in any ranges
// from "valid1", so only 1 inline function be parsed.
@@ -3302,15 +3319,17 @@ TEST(GSYMTest, TestDWARFEmptyInline) {
StringRef FuncName = GR->getString(ExpFI->Name);
EXPECT_EQ(FuncName, "foo");
std::vector<std::string> ExpectedLogErrors = {
- "error: inlined function DIE at 0x0000002a has a range [0x0000000000001100"
- " - 0x0000000000001200) that isn't contained in any parent address ranges,"
- " this inline range will be removed.",
- "warning: DIE contains inline function information that has no valid "
- "ranges, removing inline information:",
+ "error: inlined function DIE at 0x0000002a has a range "
+ "[0x0000000000001100"
+ " - 0x0000000000001200) that isn't contained in any parent address "
+ "ranges,"
+ " this inline range will be removed.",
+ "warning: DIE contains inline function information that has no valid "
+ "ranges, removing inline information:",
};
// Make sure all expected errors are in the error stream for the two invalid
// inlined functions that we removed due to invalid range scoping.
- for (const auto &Error: ExpectedLogErrors) {
+ for (const auto &Error : ExpectedLogErrors) {
EXPECT_TRUE(OS.str().find(Error) != std::string::npos);
}
}
@@ -3344,7 +3363,8 @@ TEST(GSYMTest, TestFinalizeForLineTables) {
// DW_AT_high_pc (0x0000000000002050)
//
// 0x0000003f: NULL
- // 0x00000040: Compile Unit: length = 0x0000003c, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00000080)
+ // 0x00000040: Compile Unit: length = 0x0000003c, format = DWARF32, version =
+ // 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00000080)
//
// 0x0000004b: DW_TAG_compile_unit
// DW_AT_name ("/tmp/main.cpp")
@@ -3550,7 +3570,6 @@ TEST(GSYMTest, TestFinalizeForLineTables) {
EXPECT_EQ(FuncName2, "bar");
}
-
TEST(GSYMTest, TestRangeWarnings) {
// This example has a single compile unit that has a DW_TAG_subprogram that
// has two discontiguous ranges. We will create two FunctionInfo objects for
@@ -4026,7 +4045,6 @@ TEST(GSYMTest, TestEmptyRangeWarnings) {
EXPECT_TRUE(errors.find("error:") == std::string::npos);
}
-
TEST(GSYMTest, TestEmptyLinkageName) {
// This example has a single compile unit that has a DW_TAG_subprogram that
// has a function that has an empty linkage name and a valid normal name.
@@ -4051,7 +4069,6 @@ TEST(GSYMTest, TestEmptyLinkageName) {
//
// 0x0000002e: NULL
-
StringRef yamldata = R"(
debug_str:
- ''
@@ -4899,3 +4916,63 @@ TEST(GSYMTest, TestLookupsOfOverlappingAndUnequalRanges) {
for (const auto &Line : ExpectedDumpLines)
EXPECT_TRUE(DumpStr.find(Line) != std::string::npos);
}
+
+TEST(GSYMTest, TestUnableToLocateDWO) {
+ // Test that llvm-gsymutil will not produce "uanble to locate DWO file" for
+ // Apple binaries. Apple uses DW_AT_GNU_dwo_id for non split DWARF purposes
+ // and this makes llvm-gsymutil create warnings and errors.
+ //
+ // 0x0000000b: DW_TAG_compile_unit
+ // DW_AT_name ("main.cpp")
+ // DW_AT_language (DW_LANG_C)
+ // DW_AT_GNU_dwo_id (0xfffffffe)
+ StringRef yamldata = R"(
+ debug_str:
+ - ''
+ - main.cpp
+ debug_abbrev:
+ - ID: 0
+ Table:
+ - Code: 0x1
+ Tag: DW_TAG_compile_unit
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_strp
+ - Attribute: DW_AT_language
+ Form: DW_FORM_udata
+ - Attribute: DW_AT_GNU_dwo_id
+ Form: DW_FORM_data4
+ debug_info:
+ - Length: 0x11
+ Version: 4
+ AbbrevTableID: 0
+ AbbrOffset: 0x0
+ AddrSize: 8
+ Entries:
+ - AbbrCode: 0x1
+ Values:
+ - Value: 0x1
+ - Value: 0x2
+ - Value: 0xFFFFFFFE
+ )";
+ auto ErrOrSections = DWARFYAML::emitDebugSections(yamldata);
+ ASSERT_THAT_EXPECTED(ErrOrSections, Succeeded());
+ std::unique_ptr<DWARFContext> DwarfContext =
+ DWARFContext::create(*ErrOrSections, 8);
+ ASSERT_TRUE(DwarfContext.get() != nullptr);
+ std::string errors;
+ raw_string_ostream OS(errors);
+ OutputAggregator OSAgg(&OS);
+ GsymCreator GC;
+ // Make a DWARF transformer that is MachO (Apple) to avoid warnings about
+ // not finding DWO files.
+ DwarfTransformer DT(*DwarfContext, GC, /*LDCS=*/false, /*MachO*/ true);
+ const uint32_t ThreadCount = 1;
+ ASSERT_THAT_ERROR(DT.convert(ThreadCount, OSAgg), Succeeded());
+ ASSERT_THAT_ERROR(GC.finalize(OSAgg), Succeeded());
+
+ // Make sure this warning is not in the binary
+ std::string warn("warning: Unable to retrieve DWO .debug_info section for");
+ EXPECT_TRUE(errors.find(warn) == std::string::npos);
+}
More information about the llvm-commits
mailing list