[llvm] 121452a - [DebugInfo] Handle fixed-width DW_FORM_addrx variants in DWARFFormValue::getAsSectionedAddress()

Benjamin Maxwell via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 6 09:18:37 PST 2023


Author: Benjamin Maxwell
Date: 2023-02-06T17:15:54Z
New Revision: 121452aa50afe99f56bffc1086016f3ceedd20e6

URL: https://github.com/llvm/llvm-project/commit/121452aa50afe99f56bffc1086016f3ceedd20e6
DIFF: https://github.com/llvm/llvm-project/commit/121452aa50afe99f56bffc1086016f3ceedd20e6.diff

LOG: [DebugInfo] Handle fixed-width DW_FORM_addrx variants in DWARFFormValue::getAsSectionedAddress()

Previously this would incorrectly return the raw offset into the .debug_addr section for the
DW_FORM_addrx1/2/3/4 forms rather than the actual address.

Note that this was handled correctly in the dump() function so this issue only occurs for users
of this API and not in tools such as llvm-dwarfdump. The dump() method has now been updated
to use this method to increase coverage.

This also now adds a few unit tests for indexed addresses to DWARFDebugInfoTest.

Differential Revision: https://reviews.llvm.org/D143073

Added: 
    

Modified: 
    llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
    llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
    llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
    llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
index 5dd9515aafdbb..1c26f1306b5e3 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -420,39 +420,27 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
   case DW_FORM_addrx2:
   case DW_FORM_addrx3:
   case DW_FORM_addrx4:
-  case DW_FORM_GNU_addr_index: {
+  case DW_FORM_GNU_addr_index:
+  case DW_FORM_LLVM_addrx_offset: {
     if (U == nullptr) {
       OS << "<invalid dwarf unit>";
       break;
     }
-    std::optional<object::SectionedAddress> A =
-        U->getAddrOffsetSectionItem(UValue);
-    if (!A || DumpOpts.Verbose)
-      AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);
+    std::optional<object::SectionedAddress> A = getAsSectionedAddress();
+    if (!A || DumpOpts.Verbose) {
+      if (Form == DW_FORM_LLVM_addrx_offset) {
+        uint32_t Index = UValue >> 32;
+        uint32_t Offset = UValue & 0xffffffff;
+        AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);
+      } else
+        AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);
+    }
     if (A)
       dumpSectionedAddress(AddrOS, DumpOpts, *A);
     else
       OS << "<unresolved>";
     break;
   }
-  case DW_FORM_LLVM_addrx_offset: {
-    if (U == nullptr) {
-      OS << "<invalid dwarf unit>";
-      break;
-    }
-    uint32_t Index = UValue >> 32;
-    uint32_t Offset = UValue & 0xffffffff;
-    std::optional<object::SectionedAddress> A =
-        U->getAddrOffsetSectionItem(Index);
-    if (!A || DumpOpts.Verbose)
-      AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);
-    if (A) {
-      A->Address += Offset;
-      dumpSectionedAddress(AddrOS, DumpOpts, *A);
-    } else
-      OS << "<unresolved>";
-    break;
-  }
   case DW_FORM_flag_present:
     OS << "true";
     break;
@@ -677,7 +665,9 @@ DWARFFormValue::getAsSectionedAddress() const {
   if (!isFormClass(FC_Address))
     return std::nullopt;
   bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
-  if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx || AddrOffset) {
+  if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx ||
+      Form == DW_FORM_addrx1 || Form == DW_FORM_addrx2 ||
+      Form == DW_FORM_addrx3 || Form == DW_FORM_addrx4 || AddrOffset) {
 
     uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval;
     if (!U)

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index edda022840067..e1bb6abfd7e30 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -48,6 +48,11 @@ void TestAllForms() {
 
   // Test that we can decode all DW_FORM values correctly.
   const AddrType AddrValue = (AddrType)0x0123456789abcdefULL;
+  const AddrType AddrxValue = (AddrType)0x4231abcd4231abcdULL;
+  const AddrType Addrx1Value = (AddrType)0x0000aaaabbbbccccULL;
+  const AddrType Addrx2Value = (AddrType)0xf00123f00456f000ULL;
+  const AddrType Addrx4Value = (AddrType)0xa1b2c3d4e5f6e5d4ULL;
+
   const uint8_t BlockData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
   const uint32_t BlockSize = sizeof(BlockData);
   const RefAddrType RefAddr = 0x12345678;
@@ -79,8 +84,10 @@ void TestAllForms() {
   dwarfgen::CompileUnit &CU = DG->addCompileUnit();
   dwarfgen::DIE CUDie = CU.getUnitDIE();
 
-  if (Version >= 5)
+  if (Version >= 5) {
     CUDie.addStrOffsetsBaseAttribute();
+    CUDie.addAddrBaseAttribute();
+  }
 
   uint16_t Attr = DW_AT_lo_user;
 
@@ -90,6 +97,20 @@ void TestAllForms() {
   const auto Attr_DW_FORM_addr = static_cast<dwarf::Attribute>(Attr++);
   CUDie.addAttribute(Attr_DW_FORM_addr, DW_FORM_addr, AddrValue);
 
+  const auto Attr_DW_FORM_addrx = static_cast<dwarf::Attribute>(Attr++);
+  const auto Attr_DW_FORM_addrx1 = static_cast<dwarf::Attribute>(Attr++);
+  const auto Attr_DW_FORM_addrx2 = static_cast<dwarf::Attribute>(Attr++);
+  // TODO: Add Attr_DW_FORM_addrx3 test (this form type is currently
+  // unsupported)
+  const auto Attr_DW_FORM_addrx4 = static_cast<dwarf::Attribute>(Attr++);
+
+  if (Version >= 5) {
+    CUDie.addAttribute(Attr_DW_FORM_addrx, DW_FORM_addrx, AddrxValue);
+    CUDie.addAttribute(Attr_DW_FORM_addrx1, DW_FORM_addrx1, Addrx1Value);
+    CUDie.addAttribute(Attr_DW_FORM_addrx2, DW_FORM_addrx2, Addrx2Value);
+    CUDie.addAttribute(Attr_DW_FORM_addrx4, DW_FORM_addrx4, Addrx4Value);
+  }
+
   //----------------------------------------------------------------------
   // Test block forms
   //----------------------------------------------------------------------
@@ -241,6 +262,24 @@ void TestAllForms() {
   //----------------------------------------------------------------------
   EXPECT_EQ(AddrValue, toAddress(DieDG.find(Attr_DW_FORM_addr), 0));
 
+  if (Version >= 5) {
+    auto ExtractedAddrxValue = toAddress(DieDG.find(Attr_DW_FORM_addrx));
+    EXPECT_TRUE(ExtractedAddrxValue.has_value());
+    EXPECT_EQ(AddrxValue, *ExtractedAddrxValue);
+
+    auto ExtractedAddrx1Value = toAddress(DieDG.find(Attr_DW_FORM_addrx1));
+    EXPECT_TRUE(ExtractedAddrx1Value.has_value());
+    EXPECT_EQ(Addrx1Value, *ExtractedAddrx1Value);
+
+    auto ExtractedAddrx2Value = toAddress(DieDG.find(Attr_DW_FORM_addrx2));
+    EXPECT_TRUE(ExtractedAddrx2Value.has_value());
+    EXPECT_EQ(Addrx2Value, *ExtractedAddrx2Value);
+
+    auto ExtractedAddrx4Value = toAddress(DieDG.find(Attr_DW_FORM_addrx4));
+    EXPECT_TRUE(ExtractedAddrx1Value.has_value());
+    EXPECT_EQ(Addrx4Value, *ExtractedAddrx4Value);
+  }
+
   //----------------------------------------------------------------------
   // Test block forms
   //----------------------------------------------------------------------

diff  --git a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
index 590c0b92ec51f..67c6e7c54ff8a 100644
--- a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp
@@ -53,6 +53,16 @@ unsigned dwarfgen::DIE::computeSizeAndOffsets(unsigned Offset) {
 
 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, uint64_t U) {
   auto &DG = CU->getGenerator();
+  switch (Form) {
+  case DW_FORM_addrx:
+  case DW_FORM_addrx1:
+  case DW_FORM_addrx2:
+  case DW_FORM_addrx3:
+  case DW_FORM_addrx4:
+    U = DG.getAddressPool().getIndex(U);
+  default:
+    break;
+  }
   Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
                 DIEInteger(U));
 }
@@ -142,6 +152,24 @@ void dwarfgen::DIE::addStrOffsetsBaseAttribute() {
   addAttribute(dwarf::DW_AT_str_offsets_base, DW_FORM_sec_offset, *Expr);
 }
 
+// This is currently fixed to be the first address entry after the header.
+void dwarfgen::DIE::addAddrBaseAttribute() {
+  auto &DG = CU->getGenerator();
+  auto &MC = *DG.getMCContext();
+  AsmPrinter *Asm = DG.getAsmPrinter();
+
+  const MCSymbol *SectionStart =
+      Asm->getObjFileLowering().getDwarfAddrSection()->getBeginSymbol();
+
+  const MCExpr *Expr = MCSymbolRefExpr::create(DG.getAddrTableStartSym(), MC);
+
+  if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+    Expr = MCBinaryExpr::createSub(
+        Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);
+
+  addAttribute(dwarf::DW_AT_addr_base, DW_FORM_sec_offset, *Expr);
+}
+
 dwarfgen::DIE dwarfgen::DIE::addChild(dwarf::Tag Tag) {
   auto &DG = CU->getGenerator();
   return dwarfgen::DIE(CU,
@@ -495,9 +523,41 @@ llvm::Error dwarfgen::Generator::init(Triple TheTriple, uint16_t V) {
   StringPool = std::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
   StringOffsetsStartSym = Asm->createTempSymbol("str_offsets_base");
 
+  AddrTableStartSym = Asm->createTempSymbol("addr_table_base");
+
   return Error::success();
 }
 
+unsigned dwarfgen::Generator::DummyAddressPool::getIndex(uint64_t Address) {
+  AddressValues.push_back(Address);
+  return static_cast<unsigned>(AddressValues.size() - 1);
+}
+
+void dwarfgen::Generator::DummyAddressPool::emit(AsmPrinter &Asm,
+                                                 MCSection *AddrSection,
+                                                 MCSymbol *StartSym) {
+  const uint8_t AddrSize = Asm.getPointerSize();
+
+  // Switch to .debug_addr section
+  Asm.OutStreamer->switchSection(AddrSection);
+
+  if (Asm.getDwarfVersion() >= 5) {
+    // Emit header
+    Asm.emitDwarfUnitLength(AddrSize * AddressValues.size() + 4,
+                            "Length of contribution");
+    Asm.emitInt16(Asm.getDwarfVersion());
+    Asm.emitInt8(AddrSize);
+    Asm.emitInt8(0);
+  }
+
+  if (StartSym)
+    Asm.OutStreamer->emitLabel(StartSym);
+
+  // Emit addresses
+  for (uint64_t Addr : AddressValues)
+    Asm.OutStreamer->emitIntValue(Addr, AddrSize);
+}
+
 StringRef dwarfgen::Generator::generate() {
   // Offset from the first CU in the debug info section is 0 initially.
   uint64_t SecOffset = 0;
@@ -521,6 +581,8 @@ StringRef dwarfgen::Generator::generate() {
   StringPool->emit(*Asm, TLOF->getDwarfStrSection(),
                    TLOF->getDwarfStrOffSection());
 
+  AddressPool.emit(*Asm, TLOF->getDwarfAddrSection(), AddrTableStartSym);
+
   MS->switchSection(TLOF->getDwarfInfoSection());
   for (auto &CU : CompileUnits) {
     uint16_t Version = CU->getVersion();

diff  --git a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h
index 4d97059b569a2..8565ee52a0801 100644
--- a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h
+++ b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.h
@@ -133,6 +133,9 @@ class DIE {
   /// Add a DW_AT_str_offsets_base attribute to this DIE.
   void addStrOffsetsBaseAttribute();
 
+  /// Add a DW_AT_addr_base attribute to this DIE.
+  void addAddrBaseAttribute();
+
   /// Add a new child to this DIE object.
   ///
   /// \param Tag the dwarf::Tag to assing to the llvm::DIE object.
@@ -258,7 +261,17 @@ class Generator {
   std::vector<std::unique_ptr<LineTable>> LineTables;
   DIEAbbrevSet Abbreviations;
 
+  // Mimics llvm::AddressPool, but allows for constant addresses for testing.
+  struct DummyAddressPool {
+    unsigned getIndex(uint64_t Address);
+
+    void emit(AsmPrinter &Asm, MCSection *AddrSection, MCSymbol *StartSym);
+
+    std::vector<uint64_t> AddressValues;
+  } AddressPool;
+
   MCSymbol *StringOffsetsStartSym;
+  MCSymbol *AddrTableStartSym;
 
   SmallString<4096> FileBytes;
   /// The stream we use to generate the DWARF into as an ELF file.
@@ -312,6 +325,8 @@ class Generator {
   DIEAbbrevSet &getAbbrevSet() { return Abbreviations; }
   DwarfStringPool &getStringPool() { return *StringPool; }
   MCSymbol *getStringOffsetsStartSym() const { return StringOffsetsStartSym; }
+  DummyAddressPool &getAddressPool() { return AddressPool; }
+  MCSymbol *getAddrTableStartSym() const { return AddrTableStartSym; }
 
   /// Save the generated DWARF file to disk.
   ///


        


More information about the llvm-commits mailing list