[llvm] r232267 - [dsymutil] Add support for debug_loc section.

Frederic Riss friss at apple.com
Sat Mar 14 08:49:08 PDT 2015


Author: friss
Date: Sat Mar 14 10:49:07 2015
New Revision: 232267

URL: http://llvm.org/viewvc/llvm-project?rev=232267&view=rev
Log:
[dsymutil] Add support for debug_loc section.

There is no need to look into the location expressions to transfer them,
the only modification to apply is to patch their base address to reflect
the linked function address.

Modified:
    llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
    llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test
    llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
    llvm/trunk/tools/dsymutil/DwarfLinker.cpp

Modified: llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test?rev=232267&r1=232266&r2=232267&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test Sat Mar 14 10:49:07 2015
@@ -129,6 +129,9 @@ CHECK:      DW_AT_frame_base [DW_FORM_bl
 
 CHECK:    NULL
 
+CHECK: .debug_loc contents
+CHECK-NOT: Location
+
 CHECK:.debug_aranges contents:
 CHECK-NEXT:Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
 CHECK-NEXT:[0x0000000100000ea0 - 0x0000000100000ec4)

Modified: llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test?rev=232267&r1=232266&r2=232267&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test Sat Mar 14 10:49:07 2015
@@ -66,7 +66,8 @@ CHECK:      DW_AT_frame_base [DW_FORM_ex
 CHECK:      DW_AT_name [DW_FORM_strp]	( .debug_str[0x0000005c] = "foo")
 CHECK:      DW_AT_prototyped [DW_FORM_flag_present]	(true)
 CHECK:      DW_AT_type [DW_FORM_ref4]	(cu + 0x002a => {0x000000a1})
-CHECK:      DW_TAG_formal_parameter [11]  
+CHECK:      DW_TAG_formal_parameter [11]
+CHECK:        DW_AT_location [DW_FORM_sec_offset]   (0x00000000)
 CHECK:        DW_AT_name [DW_FORM_strp]	( .debug_str[0x00000060] = "arg")
 CHECK:        DW_AT_type [DW_FORM_ref4]	(cu + 0x002a => {0x000000a1})
 CHECK:      DW_TAG_inlined_subroutine [12]  
@@ -95,7 +96,8 @@ CHECK:      DW_AT_low_pc [DW_FORM_addr]
 CHECK:      DW_AT_high_pc [DW_FORM_data4]	(0x00000024)
 CHECK:      DW_AT_frame_base [DW_FORM_exprloc]	(<0x1> 56 )
 CHECK:      DW_AT_name [DW_FORM_strp]	( .debug_str[0x00000071] = "bar")
-CHECK:      DW_TAG_formal_parameter [16]  
+CHECK:      DW_TAG_formal_parameter [16]
+CHECK:        DW_AT_location [DW_FORM_sec_offset]   (0x00000025)
 CHECK:        DW_AT_name [DW_FORM_strp]	( .debug_str[0x00000060] = "arg")
 CHECK:      DW_TAG_inlined_subroutine [17]  
 CHECK:        DW_AT_abstract_origin [DW_FORM_ref4]	(cu + 0x0044 => {0x0000015f} "inc")
@@ -106,6 +108,20 @@ CHECK:           [0x0000000100000f9f - 0
 CHECK:      NULL
 CHECK:    NULL
 
+
+CHECK: .debug_loc contents:
+CHECK-NEXT: 0x00000000: Beginning address offset: 0x0000000000000000
+CHECK-NEXT:                Ending address offset: 0x000000000000000c
+CHECK-NEXT:                 Location description: 55 93 04
+CHECK-NEXT: {{^$}}
+CHECK-NEXT: 0x00000025: Beginning address offset: 0x0000000000000000
+CHECK-NEXT:                Ending address offset: 0x000000000000000f
+CHECK-NEXT:                 Location description: 55 93 04 
+CHECK-NEXT: {{^$}}
+CHECK-NEXT:             Beginning address offset: 0x0000000000000019
+CHECK-NEXT:                Ending address offset: 0x000000000000001d
+CHECK-NEXT:                 Location description: 55 93 04 
+
 CHECK: .debug_aranges contents:
 CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
 CHECK-NEXT: [0x0000000100000f40 - 0x0000000100000f4b)

Modified: llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test?rev=232267&r1=232266&r2=232267&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test Sat Mar 14 10:49:07 2015
@@ -71,6 +71,7 @@ CHECK:      DW_AT_frame_base [DW_FORM_bl
 CHECK:      DW_TAG_formal_parameter [9]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000086] = "arg")
 CHECK:        DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
+CHECK:        DW_AT_location [DW_FORM_data4]        (0x00000000)
 CHECK:      DW_TAG_inlined_subroutine [10]
 CHECK:        DW_AT_abstract_origin [DW_FORM_ref4]  (cu + 0x00a7 => {0x00000128} "inc")
 CHECK:        DW_AT_low_pc [DW_FORM_addr]   (0x0000000100000f63)
@@ -105,6 +106,7 @@ CHECK:      DW_AT_frame_base [DW_FORM_bl
 CHECK:      DW_TAG_formal_parameter [9]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000086] = "arg")
 CHECK:        DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
+CHECK:        DW_AT_location [DW_FORM_data4]        (0x00000025)
 CHECK:      DW_TAG_lexical_block [14] *
 CHECK:        DW_AT_low_pc [DW_FORM_addr]   (0x0000000100000f94)
 CHECK         DW_AT_high_pc [DW_FORM_addr]  (0x0000000100000fa7)
@@ -120,6 +122,19 @@ CHECK:      DW_AT_name [DW_FORM_strp]
 CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
 CHECK:    NULL
 
+CHECK:.debug_loc contents:
+CHECK-NEXT: 0x00000000: Beginning address offset: 0x0000000000000000
+CHECK-NEXT:                Ending address offset: 0x000000000000000e
+CHECK-NEXT:                 Location description: 55 93 04 
+CHECK-NEXT: {{^$}}
+CHECK-NEXT: 0x00000025: Beginning address offset: 0x0000000000000000
+CHECK-NEXT:                Ending address offset: 0x000000000000000f
+CHECK-NEXT:                 Location description: 55 93 04 
+CHECK-NEXT: {{^$}}
+CHECK-NEXT:             Beginning address offset: 0x0000000000000019
+CHECK-NEXT:                Ending address offset: 0x000000000000001d
+CHECK-NEXT:                 Location description: 55 93 04 
+
 CHECK: .debug_aranges contents:
 CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00
 CHECK-NEXT: [0x0000000100000f40 - 0x0000000100000f4b)

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=232267&r1=232266&r2=232267&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Sat Mar 14 10:49:07 2015
@@ -110,6 +110,11 @@ public:
     return RangeAttributes;
   }
 
+  const std::vector<std::pair<DIEInteger *, int64_t>> &
+  getLocationAttributes() const {
+    return LocationAttributes;
+  }
+
   /// \brief Compute the end offset for this unit. Must be
   /// called after the CU's DIEs have been cloned.
   /// \returns the next unit offset (which is also the current
@@ -133,6 +138,10 @@ public:
   /// patch up later.
   void noteRangeAttribute(const DIE &Die, DIEInteger *Attr);
 
+  /// \brief Keep track of a location attribute pointing to a location
+  /// list in the debug_loc section.
+  void noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset);
+
 private:
   DWARFUnit &OrigUnit;
   unsigned ID;
@@ -166,6 +175,12 @@ private:
   std::vector<DIEInteger *> RangeAttributes;
   DIEInteger *UnitRangeAttribute;
   /// @}
+
+  /// \brief Location attributes that need to be transfered from th
+  /// original debug_loc section to the liked one. They are stored
+  /// along with the PC offset that is to be applied to their
+  /// function's address.
+  std::vector<std::pair<DIEInteger *, int64_t>> LocationAttributes;
 };
 
 uint64_t CompileUnit::computeNextUnitOffset() {
@@ -210,6 +225,10 @@ void CompileUnit::noteRangeAttribute(con
     UnitRangeAttribute = Attr;
 }
 
+void CompileUnit::noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset) {
+  LocationAttributes.emplace_back(Attr, PcOffset);
+}
+
 /// \brief A string table that doesn't need relocations.
 ///
 /// We are doing a final link, no need for a string table that
@@ -319,6 +338,7 @@ class DwarfStreamer {
   std::unique_ptr<raw_fd_ostream> OutFile;
 
   uint32_t RangesSectionSize;
+  uint32_t LocSectionSize;
 
 public:
   /// \brief Actually create the streamer and the ouptut file.
@@ -367,6 +387,11 @@ public:
   void emitUnitRangesEntries(CompileUnit &Unit, bool DoRangesSection);
 
   uint32_t getRangesSectionSize() const { return RangesSectionSize; }
+
+  /// \brief Emit the debug_loc contribution for \p Unit by copying
+  /// the entries from \p Dwarf and offseting them. Update the
+  /// location attributes to point to the new entries.
+  void emitLocationsForUnit(const CompileUnit &Unit, DWARFContext &Dwarf);
 };
 
 bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
@@ -433,6 +458,7 @@ bool DwarfStreamer::init(Triple TheTripl
     return error("no asm printer for target " + TripleName, Context);
 
   RangesSectionSize = 0;
+  LocSectionSize = 0;
 
   return true;
 }
@@ -617,6 +643,57 @@ void DwarfStreamer::emitUnitRangesEntrie
   RangesSectionSize += 2 * AddressSize;
 }
 
+/// \brief Emit location lists for \p Unit and update attribtues to
+/// point to the new entries.
+void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
+                                         DWARFContext &Dwarf) {
+  const std::vector<std::pair<DIEInteger *, int64_t>> &Attributes =
+      Unit.getLocationAttributes();
+
+  if (Attributes.empty())
+    return;
+
+  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLocSection());
+
+  unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
+  const DWARFSection &InputSec = Dwarf.getLocSection();
+  DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
+  DWARFUnit &OrigUnit = Unit.getOrigUnit();
+  const auto *OrigUnitDie = OrigUnit.getCompileUnitDIE(false);
+  int64_t UnitPcOffset = 0;
+  uint64_t OrigLowPc = OrigUnitDie->getAttributeValueAsAddress(
+      &OrigUnit, dwarf::DW_AT_low_pc, -1ULL);
+  if (OrigLowPc != -1ULL)
+    UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
+
+  for (const auto &Attr : Attributes) {
+    uint32_t Offset = Attr.first->getValue();
+    Attr.first->setValue(LocSectionSize);
+    // This is the quantity to add to the old location address to get
+    // the correct address for the new one.
+    int64_t LocPcOffset = Attr.second + UnitPcOffset;
+    while (Data.isValidOffset(Offset)) {
+      uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
+      uint64_t High = Data.getUnsigned(&Offset, AddressSize);
+      LocSectionSize += 2 * AddressSize;
+      if (Low == 0 && High == 0) {
+        Asm->OutStreamer.EmitIntValue(0, AddressSize);
+        Asm->OutStreamer.EmitIntValue(0, AddressSize);
+        break;
+      }
+      Asm->OutStreamer.EmitIntValue(Low + LocPcOffset, AddressSize);
+      Asm->OutStreamer.EmitIntValue(High + LocPcOffset, AddressSize);
+      uint64_t Length = Data.getU16(&Offset);
+      Asm->OutStreamer.EmitIntValue(Length, 2);
+      // Just copy the bytes over.
+      Asm->OutStreamer.EmitBytes(
+          StringRef(InputSec.Data.substr(Offset, Length)));
+      Offset += Length;
+      LocSectionSize += Length + 2;
+    }
+  }
+}
+
 /// \brief The core of the Dwarf linking logic.
 ///
 /// The link of the dwarf information from the object files will be
@@ -791,7 +868,8 @@ private:
   unsigned cloneScalarAttribute(DIE &Die,
                                 const DWARFDebugInfoEntryMinimal &InputDIE,
                                 CompileUnit &U, AttributeSpec AttrSpec,
-                                const DWARFFormValue &Val, unsigned AttrSize);
+                                const DWARFFormValue &Val, unsigned AttrSize,
+                                const AttributesInfo &Info);
 
   /// \brief Helper for cloneDIE.
   bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
@@ -1486,7 +1564,8 @@ unsigned DwarfLinker::cloneAddressAttrib
 /// \returns the size of the new attribute.
 unsigned DwarfLinker::cloneScalarAttribute(
     DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit,
-    AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize) {
+    AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize,
+    const AttributesInfo &Info) {
   uint64_t Value;
   if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
       Die.getTag() == dwarf::DW_TAG_compile_unit) {
@@ -1508,6 +1587,13 @@ unsigned DwarfLinker::cloneScalarAttribu
   DIEInteger *Attr = new (DIEAlloc) DIEInteger(Value);
   if (AttrSpec.Attr == dwarf::DW_AT_ranges)
     Unit.noteRangeAttribute(Die, Attr);
+  // A more generic way to check for location attributes would be
+  // nice, but it's very unlikely that any other attribute needs a
+  // location list.
+  else if (AttrSpec.Attr == dwarf::DW_AT_location ||
+           AttrSpec.Attr == dwarf::DW_AT_frame_base)
+    Unit.noteLocationAttribute(Attr, Info.PCOffset);
+
   Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form),
                Attr);
   return AttrSize;
@@ -1552,7 +1638,8 @@ unsigned DwarfLinker::cloneAttribute(DIE
   case dwarf::DW_FORM_sec_offset:
   case dwarf::DW_FORM_flag:
   case dwarf::DW_FORM_flag_present:
-    return cloneScalarAttribute(Die, InputDIE, Unit, AttrSpec, Val, AttrSize);
+    return cloneScalarAttribute(Die, InputDIE, Unit, AttrSpec, Val, AttrSize,
+                                Info);
   default:
     reportWarning("Unsupported attribute form in cloneAttribute. Dropping.", &U,
                   &InputDIE);
@@ -1843,6 +1930,7 @@ bool DwarfLinker::link(const DebugMap &M
         if (!OutputDIE || Options.NoOutput)
           continue;
         patchRangesForUnit(CurrentUnit, DwarfContext);
+        Streamer->emitLocationsForUnit(CurrentUnit, DwarfContext);
       }
 
     // Emit all the compile unit's debug information.





More information about the llvm-commits mailing list