[llvm] r338031 - dwarfgen: Add support for generating the debug_str_offsets section, take 3
Pavel Labath via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 26 07:36:07 PDT 2018
Author: labath
Date: Thu Jul 26 07:36:07 2018
New Revision: 338031
URL: http://llvm.org/viewvc/llvm-project?rev=338031&view=rev
Log:
dwarfgen: Add support for generating the debug_str_offsets section, take 3
Previous version of this patch failed on darwin targets because of
different handling of cross-debug-section relocations. This fixes the
tests to emit the DW_AT_str_offsets_base attribute correctly in both
cases. Since doing this is a non-trivial amount of code, and I'm going
to need it in more than one test, I've added a helper function to the
dwarfgen DIE class to do it.
Original commit message follows:
The motivation for this is D49493, where we'd like to test details of
debug_str_offsets behavior which is difficult to trigger from a
traditional test.
This adds the plubming necessary for dwarfgen to generate this section.
The more interesting changes are:
- I've moved emitStringOffsetsTableHeader function from DwarfFile to
DwarfStringPool, so I can generate the section header more easily from
the unit test.
- added a new addAttribute overload taking an MCExpr*. This is used to
generate the DW_AT_str_offsets_base, which links a compile unit to the
offset table.
I've also added a basic test for reading and writing DW_form_strx forms.
Reviewers: dblaikie, JDevlieghere, probinson
Subscribers: llvm-commits, aprantl
Differential Revision: https://reviews.llvm.org/D49670
Modified:
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h
llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Thu Jul 26 07:36:07 2018
@@ -1506,8 +1506,9 @@ void DwarfDebug::emitAbbreviations() {
void DwarfDebug::emitStringOffsetsTableHeader() {
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
- Holder.emitStringOffsetsTableHeader(
- Asm->getObjFileLowering().getDwarfStrOffSection());
+ Holder.getStringPool().emitStringOffsetsTableHeader(
+ *Asm, Asm->getObjFileLowering().getDwarfStrOffSection(),
+ Holder.getStringOffsetsStartSym());
}
template <typename AccelTableT>
@@ -2292,8 +2293,9 @@ void DwarfDebug::emitDebugLineDWO() {
void DwarfDebug::emitStringOffsetsTableHeaderDWO() {
assert(useSplitDwarf() && "No split dwarf?");
- InfoHolder.emitStringOffsetsTableHeader(
- Asm->getObjFileLowering().getDwarfStrOffDWOSection());
+ InfoHolder.getStringPool().emitStringOffsetsTableHeader(
+ *Asm, Asm->getObjFileLowering().getDwarfStrOffDWOSection(),
+ InfoHolder.getStringOffsetsStartSym());
}
// Emit the .debug_str.dwo section for separated dwarf. This contains the
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp Thu Jul 26 07:36:07 2018
@@ -28,26 +28,6 @@ void DwarfFile::addUnit(std::unique_ptr<
CUs.push_back(std::move(U));
}
-void DwarfFile::emitStringOffsetsTableHeader(MCSection *Section) {
- if (StrPool.empty())
- return;
- Asm->OutStreamer->SwitchSection(Section);
- unsigned EntrySize = 4;
- // FIXME: DWARF64
- // We are emitting the header for a contribution to the string offsets
- // table. The header consists of an entry with the contribution's
- // size (not including the size of the length field), the DWARF version and
- // 2 bytes of padding.
- Asm->emitInt32(StrPool.size() * EntrySize + 4);
- Asm->emitInt16(Asm->getDwarfVersion());
- Asm->emitInt16(0);
- // Define the symbol that marks the start of the contribution. It is
- // referenced by most unit headers via DW_AT_str_offsets_base.
- // Split units do not use the attribute.
- if (StringOffsetsStartSym)
- Asm->OutStreamer->EmitLabel(StringOffsetsStartSym);
-}
-
// Emit the various dwarf units to the unit section USection with
// the abbreviations going into ASection.
void DwarfFile::emitUnits(bool UseOffsets) {
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.h Thu Jul 26 07:36:07 2018
@@ -91,9 +91,6 @@ public:
/// Add a unit to the list of CUs.
void addUnit(std::unique_ptr<DwarfCompileUnit> U);
- /// Emit the string table offsets header.
- void emitStringOffsetsTableHeader(MCSection *Section);
-
/// Emit all of the units to the section listed with the given
/// abbreviation section.
void emitUnits(bool UseOffsets);
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp Thu Jul 26 07:36:07 2018
@@ -39,6 +39,28 @@ DwarfStringPool::EntryRef DwarfStringPoo
return EntryRef(*I.first);
}
+void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
+ MCSection *Section,
+ MCSymbol *StartSym) {
+ if (empty())
+ return;
+ Asm.OutStreamer->SwitchSection(Section);
+ unsigned EntrySize = 4;
+ // FIXME: DWARF64
+ // We are emitting the header for a contribution to the string offsets
+ // table. The header consists of an entry with the contribution's
+ // size (not including the size of the length field), the DWARF version and
+ // 2 bytes of padding.
+ Asm.emitInt32(size() * EntrySize + 4);
+ Asm.emitInt16(Asm.getDwarfVersion());
+ Asm.emitInt16(0);
+ // Define the symbol that marks the start of the contribution. It is
+ // referenced by most unit headers via DW_AT_str_offsets_base.
+ // Split units do not use the attribute.
+ if (StartSym)
+ Asm.OutStreamer->EmitLabel(StartSym);
+}
+
void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
MCSection *OffsetSection, bool UseRelativeOffsets) {
if (Pool.empty())
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfStringPool.h Thu Jul 26 07:36:07 2018
@@ -19,6 +19,7 @@ namespace llvm {
class AsmPrinter;
class MCSection;
+class MCSymbol;
// Collection of strings for this unit and assorted symbols.
// A String->Symbol mapping of strings used by indirect
@@ -36,6 +37,9 @@ public:
DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, StringRef Prefix);
+ void emitStringOffsetsTableHeader(AsmPrinter &Asm, MCSection *OffsetSection,
+ MCSymbol *StartSym);
+
void emit(AsmPrinter &Asm, MCSection *StrSection,
MCSection *OffsetSection = nullptr,
bool UseRelativeOffsets = false);
Modified: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp Thu Jul 26 07:36:07 2018
@@ -67,12 +67,21 @@ void TestAllForms() {
const uint32_t Dwarf32Values[] = {1, 2, 3, 4, 5, 6, 7, 8};
const char *StringValue = "Hello";
const char *StrpValue = "World";
+ const char *StrxValue = "Indexed";
+ const char *Strx1Value = "Indexed1";
+ const char *Strx2Value = "Indexed2";
+ const char *Strx3Value = "Indexed3";
+ const char *Strx4Value = "Indexed4";
auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded());
dwarfgen::Generator *DG = ExpectedDG.get().get();
dwarfgen::CompileUnit &CU = DG->addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
+
+ if (Version >= 5)
+ CUDie.addStrOffsetsBaseAttribute();
+
uint16_t Attr = DW_AT_lo_user;
//----------------------------------------------------------------------
@@ -122,6 +131,19 @@ void TestAllForms() {
const auto Attr_DW_FORM_string = static_cast<dwarf::Attribute>(Attr++);
CUDie.addAttribute(Attr_DW_FORM_string, DW_FORM_string, StringValue);
+ const auto Attr_DW_FORM_strx = static_cast<dwarf::Attribute>(Attr++);
+ const auto Attr_DW_FORM_strx1 = static_cast<dwarf::Attribute>(Attr++);
+ const auto Attr_DW_FORM_strx2 = static_cast<dwarf::Attribute>(Attr++);
+ const auto Attr_DW_FORM_strx3 = static_cast<dwarf::Attribute>(Attr++);
+ const auto Attr_DW_FORM_strx4 = static_cast<dwarf::Attribute>(Attr++);
+ if (Version >= 5) {
+ CUDie.addAttribute(Attr_DW_FORM_strx, DW_FORM_strx, StrxValue);
+ CUDie.addAttribute(Attr_DW_FORM_strx1, DW_FORM_strx1, Strx1Value);
+ CUDie.addAttribute(Attr_DW_FORM_strx2, DW_FORM_strx2, Strx2Value);
+ CUDie.addAttribute(Attr_DW_FORM_strx3, DW_FORM_strx3, Strx3Value);
+ CUDie.addAttribute(Attr_DW_FORM_strx4, DW_FORM_strx4, Strx4Value);
+ }
+
const auto Attr_DW_FORM_strp = static_cast<dwarf::Attribute>(Attr++);
CUDie.addAttribute(Attr_DW_FORM_strp, DW_FORM_strp, StrpValue);
@@ -281,11 +303,33 @@ void TestAllForms() {
//----------------------------------------------------------------------
auto ExtractedStringValue = toString(DieDG.find(Attr_DW_FORM_string));
EXPECT_TRUE((bool)ExtractedStringValue);
- EXPECT_TRUE(strcmp(StringValue, *ExtractedStringValue) == 0);
+ EXPECT_STREQ(StringValue, *ExtractedStringValue);
+
+ if (Version >= 5) {
+ auto ExtractedStrxValue = toString(DieDG.find(Attr_DW_FORM_strx));
+ EXPECT_TRUE((bool)ExtractedStrxValue);
+ EXPECT_STREQ(StrxValue, *ExtractedStrxValue);
+
+ auto ExtractedStrx1Value = toString(DieDG.find(Attr_DW_FORM_strx1));
+ EXPECT_TRUE((bool)ExtractedStrx1Value);
+ EXPECT_STREQ(Strx1Value, *ExtractedStrx1Value);
+
+ auto ExtractedStrx2Value = toString(DieDG.find(Attr_DW_FORM_strx2));
+ EXPECT_TRUE((bool)ExtractedStrx2Value);
+ EXPECT_STREQ(Strx2Value, *ExtractedStrx2Value);
+
+ auto ExtractedStrx3Value = toString(DieDG.find(Attr_DW_FORM_strx3));
+ EXPECT_TRUE((bool)ExtractedStrx3Value);
+ EXPECT_STREQ(Strx3Value, *ExtractedStrx3Value);
+
+ auto ExtractedStrx4Value = toString(DieDG.find(Attr_DW_FORM_strx4));
+ EXPECT_TRUE((bool)ExtractedStrx4Value);
+ EXPECT_STREQ(Strx4Value, *ExtractedStrx4Value);
+ }
auto ExtractedStrpValue = toString(DieDG.find(Attr_DW_FORM_strp));
EXPECT_TRUE((bool)ExtractedStrpValue);
- EXPECT_TRUE(strcmp(StrpValue, *ExtractedStrpValue) == 0);
+ EXPECT_STREQ(StrpValue, *ExtractedStrpValue);
//----------------------------------------------------------------------
// Test reference forms
Modified: llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.cpp Thu Jul 26 07:36:07 2018
@@ -54,17 +54,36 @@ void dwarfgen::DIE::addAttribute(uint16_
DIEInteger(U));
}
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const MCExpr &Expr) {
+ auto &DG = CU->getGenerator();
+ Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+ DIEExpr(&Expr));
+}
+
void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
StringRef String) {
auto &DG = CU->getGenerator();
- if (Form == DW_FORM_string) {
+ switch (Form) {
+ case DW_FORM_string:
Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
new (DG.getAllocator())
DIEInlineString(String, DG.getAllocator()));
- } else {
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
Die->addValue(
DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
+ break;
+
+ default:
+ llvm_unreachable("Unhandled form!");
}
}
@@ -97,6 +116,24 @@ void dwarfgen::DIE::addAttribute(uint16_
DIEInteger(1));
}
+void dwarfgen::DIE::addStrOffsetsBaseAttribute() {
+ auto &DG = CU->getGenerator();
+ auto &MC = *DG.getMCContext();
+ AsmPrinter *Asm = DG.getAsmPrinter();
+
+ const MCSymbol *SectionStart =
+ Asm->getObjFileLowering().getDwarfStrOffSection()->getBeginSymbol();
+
+ const MCExpr *Expr =
+ MCSymbolRefExpr::create(DG.getStringOffsetsStartSym(), MC);
+
+ if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ Expr = MCBinaryExpr::createSub(
+ Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);
+
+ addAttribute(dwarf::DW_AT_str_offsets_base, DW_FORM_sec_offset, *Expr);
+}
+
dwarfgen::DIE dwarfgen::DIE::addChild(dwarf::Tag Tag) {
auto &DG = CU->getGenerator();
return dwarfgen::DIE(CU,
@@ -429,6 +466,7 @@ llvm::Error dwarfgen::Generator::init(Tr
Asm->setDwarfVersion(Version);
StringPool = llvm::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
+ StringOffsetsStartSym = Asm->createTempSymbol("str_offsets_base");
return Error::success();
}
@@ -450,7 +488,12 @@ StringRef dwarfgen::Generator::generate(
CU->setLength(CUOffset - 4);
}
Abbreviations.Emit(Asm.get(), TLOF->getDwarfAbbrevSection());
- StringPool->emit(*Asm, TLOF->getDwarfStrSection());
+
+ StringPool->emitStringOffsetsTableHeader(*Asm, TLOF->getDwarfStrOffSection(),
+ StringOffsetsStartSym);
+ StringPool->emit(*Asm, TLOF->getDwarfStrSection(),
+ TLOF->getDwarfStrOffSection());
+
MS->SwitchSection(TLOF->getDwarfInfoSection());
for (auto &CU : CompileUnits) {
uint16_t Version = CU->getVersion();
Modified: llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h?rev=338031&r1=338030&r2=338031&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DwarfGenerator.h Thu Jul 26 07:36:07 2018
@@ -89,6 +89,14 @@ public:
/// \param U the unsigned integer to encode.
void addAttribute(uint16_t Attr, dwarf::Form Form, uint64_t U);
+ /// Add an attribute value to be encoded as a DIEExpr
+ ///
+ /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
+ /// represents a user defined DWARF attribute.
+ /// \param Form the dwarf::Form to use when encoding the attribute.
+ /// \param Expr the MC expression used to compute the value.
+ void addAttribute(uint16_t Attr, dwarf::Form Form, const MCExpr &Expr);
+
/// Add an attribute value to be encoded as a DIEString or DIEInlinedString.
///
/// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
@@ -123,6 +131,9 @@ public:
/// \param S the size in bytes of the data pointed to by P .
void addAttribute(uint16_t Attr, dwarf::Form Form, const void *P, size_t S);
+ /// Add a DW_AT_str_offsets_base attribute to this DIE.
+ void addStrOffsetsBaseAttribute();
+
/// Add a new child to this DIE object.
///
/// \param Tag the dwarf::Tag to assing to the llvm::DIE object.
@@ -242,6 +253,8 @@ class Generator {
std::vector<std::unique_ptr<LineTable>> LineTables;
DIEAbbrevSet Abbreviations;
+ MCSymbol *StringOffsetsStartSym;
+
SmallString<4096> FileBytes;
/// The stream we use to generate the DWARF into as an ELF file.
std::unique_ptr<raw_svector_ostream> Stream;
@@ -293,6 +306,7 @@ public:
MCContext *getMCContext() const { return MC.get(); }
DIEAbbrevSet &getAbbrevSet() { return Abbreviations; }
DwarfStringPool &getStringPool() { return *StringPool; }
+ MCSymbol *getStringOffsetsStartSym() const { return StringOffsetsStartSym; }
/// Save the generated DWARF file to disk.
///
More information about the llvm-commits
mailing list