[llvm] r231544 - [dsymutil] Apply relocations to DIE data before cloning.

Frederic Riss friss at apple.com
Fri Mar 6 17:25:09 PST 2015


Author: friss
Date: Fri Mar  6 19:25:09 2015
New Revision: 231544

URL: http://llvm.org/viewvc/llvm-project?rev=231544&view=rev
Log:
[dsymutil] Apply relocations to DIE data before cloning.

Doing this gets function's low_pc and global variable's locations right
in the output debug info. It also could get right other attributes
that need to be relocated (in linker terms), but I don't know of any
other than the address attributes.

This doesn't fixup low_pc attributes in compile_unit, lexical_block
or inlined subroutine, nor does it get right high_pc attributes
for function. This will come in a subsequent commit.

Modified:
    llvm/trunk/test/tools/dsymutil/X86/basic-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=231544&r1=231543&r2=231544&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test Fri Mar  6 19:25:09 2015
@@ -3,8 +3,8 @@ RUN: llvm-dsymutil -oso-prepend-path=%p/
 RUN: llvm-dwarfdump %t1.dwarf | FileCheck %s
 RUN: llvm-dsymutil -o %t2 -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64
 RUN: llvm-dwarfdump %t2 | FileCheck %s
-RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 | llvm-dwarfdump - | FileCheck %s
-RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic-archive.macho.x86_64 | llvm-dwarfdump - | FileCheck %s
+RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=BASIC
+RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic-archive.macho.x86_64 | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=ARCHIVE
 
 CHECK: file format Mach-O 64-bit x86-64
 
@@ -24,6 +24,7 @@ CHECK:      DW_AT_prototyped [DW_FORM_fl
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0063 => {0x00000063})
 CHECK:      DW_AT_external [DW_FORM_flag]	(0x01)
 CHECK:      DW_AT_accessibility [DW_FORM_data1]	(DW_ACCESS_public)
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000ea0)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:      DW_TAG_formal_parameter [3]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000056] = "argc")
@@ -64,12 +65,16 @@ CHECK:      DW_AT_name [DW_FORM_strp]
 CHECK:    DW_TAG_variable [7]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000072] = "private_int")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0026 => {0x000000a7})
+BASIC:      DW_AT_location [DW_FORM_block1] (<0x09> 03 08 10 00 00 01 00 00 00 )
+ARCHIVE:    DW_AT_location [DW_FORM_block1] (<0x09> 03 04 10 00 00 01 00 00 00 )
 CHECK:    DW_TAG_variable [7]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000007e] = "baz")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0026 => {0x000000a7})
+CHECK:      DW_AT_location [DW_FORM_block1] (<0x09> 03 00 10 00 00 01 00 00 00 )
 CHECK:    DW_TAG_subprogram [2] *
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000082] = "foo")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0026 => {0x000000a7})
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000ed0)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:      DW_TAG_formal_parameter [3]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000086] = "arg")
@@ -79,6 +84,7 @@ CHECK:      NULL
 CHECK:    DW_TAG_subprogram [8]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000008a] = "inc")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0026 => {0x000000a7})
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000f20)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:    NULL
 
@@ -91,6 +97,8 @@ CHECK:    DW_AT_comp_dir [DW_FORM_strp]
 CHECK:    DW_TAG_variable [9]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000097] = "val")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x003c => {0x00000162})
+BASIC:      DW_AT_location [DW_FORM_block1] (<0x09> 03 04 10 00 00 01 00 00 00 )
+ARCHIVE:    DW_AT_location [DW_FORM_block1] (<0x09> 03 08 10 00 00 01 00 00 00 )
 CHECK:    DW_TAG_volatile_type [10]
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0041 => {0x00000167})
 CHECK:    DW_TAG_base_type [4]
@@ -98,6 +106,7 @@ CHACK:      DW_AT_name [DW_FORM_strp]
 CHECK:    DW_TAG_subprogram [2] *
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000009b] = "bar")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0041 => {0x00000167})
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000f40)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:      DW_TAG_formal_parameter [3]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000086] = "arg")
@@ -107,6 +116,7 @@ CHECK:      NULL
 CHECK:    DW_TAG_subprogram [8]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000008a] = "inc")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0041 => {0x00000167})
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000f90)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 
 CHECK:    NULL

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=231544&r1=231543&r2=231544&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 Fri Mar  6 19:25:09 2015
@@ -18,6 +18,7 @@ CHECK:      DW_AT_prototyped [DW_FORM_fl
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0063 => {0x00000063})
 CHECK:      DW_AT_external [DW_FORM_flag]	(0x01)
 CHECK:      DW_AT_accessibility [DW_FORM_data1]	(DW_ACCESS_public)
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000f40)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:      DW_TAG_formal_parameter [3]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000056] = "argc")
@@ -53,12 +54,15 @@ CHECK:    DW_AT_comp_dir [DW_FORM_strp]
 CHECK:    DW_TAG_variable [7]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000072] = "private_int")
 CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
+CHECK:      DW_AT_location [DW_FORM_block1] (<0x09> 03 08 10 00 00 01 00 00 00 )
 CHECK:    DW_TAG_variable [7]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000007e] = "baz")
 CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
+CHECK:      DW_AT_location [DW_FORM_block1] (<0x09> 03 00 10 00 00 01 00 00 00 )
 CHECK:    DW_TAG_subprogram [8] *
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000082] = "foo")
 CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000f50)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:      DW_TAG_formal_parameter [9]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000086] = "arg")
@@ -82,11 +86,13 @@ CHECK:    DW_AT_comp_dir [DW_FORM_strp]
 CHECK:    DW_TAG_variable [12]
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000097] = "val")
 CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x003c => {0x00000176})
+CHECK:      DW_AT_location [DW_FORM_block1] (<0x09> 03 04 10 00 00 01 00 00 00 )
 CHECK:    DW_TAG_volatile_type [13]
 CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
 CHECK:    DW_TAG_subprogram [8] *
 CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000009b] = "bar")
 CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
+CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000f90)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:      DW_TAG_formal_parameter [9]
 CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000086] = "arg")

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=231544&r1=231543&r2=231544&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Fri Mar  6 19:25:09 2015
@@ -463,7 +463,7 @@ private:
   /// consider. As we walk the DIEs in acsending file offset and as
   /// ValidRelocs is sorted by file offset, keeping this index
   /// uptodate is all we have to do to have a cheap lookup during the
-  /// root DIE selection.
+  /// root DIE selection and during DIE cloning.
   unsigned NextValidReloc;
 
   bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
@@ -562,6 +562,10 @@ private:
                                 const DWARFUnit &U, AttributeSpec AttrSpec,
                                 const DWARFFormValue &Val, unsigned AttrSize);
 
+  /// \brief Helper for cloneDIE.
+  bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
+                        bool isLittleEndian);
+
   /// \brief Assign an abbreviation number to \p Abbrev
   void AssignAbbrev(DIEAbbrev &Abbrev);
 
@@ -1256,6 +1260,50 @@ unsigned DwarfLinker::cloneAttribute(DIE
   return 0;
 }
 
+/// \brief Apply the valid relocations found by findValidRelocs() to
+/// the buffer \p Data, taking into account that Data is at \p BaseOffset
+/// in the debug_info section.
+///
+/// Like for findValidRelocs(), this function must be called with
+/// monotonic \p BaseOffset values.
+///
+/// \returns wether any reloc has been applied.
+bool DwarfLinker::applyValidRelocs(MutableArrayRef<char> Data,
+                                   uint32_t BaseOffset, bool isLittleEndian) {
+  assert(NextValidReloc == 0 ||
+         BaseOffset > ValidRelocs[NextValidReloc - 1].Offset &&
+             "BaseOffset should only be increasing.");
+  if (NextValidReloc >= ValidRelocs.size())
+    return false;
+
+  // Skip relocs that haven't been applied.
+  while (NextValidReloc < ValidRelocs.size() &&
+         ValidRelocs[NextValidReloc].Offset < BaseOffset)
+    ++NextValidReloc;
+
+  bool Applied = false;
+  uint64_t EndOffset = BaseOffset + Data.size();
+  while (NextValidReloc < ValidRelocs.size() &&
+         ValidRelocs[NextValidReloc].Offset >= BaseOffset &&
+         ValidRelocs[NextValidReloc].Offset < EndOffset) {
+    const auto &ValidReloc = ValidRelocs[NextValidReloc++];
+    assert(ValidReloc.Offset - BaseOffset < Data.size());
+    assert(ValidReloc.Offset - BaseOffset + ValidReloc.Size <= Data.size());
+    char Buf[8];
+    uint64_t Value = ValidReloc.Mapping->getValue().BinaryAddress;
+    Value += ValidReloc.Addend;
+    for (unsigned i = 0; i != ValidReloc.Size; ++i) {
+      unsigned Index = isLittleEndian ? i : (ValidReloc.Size - i - 1);
+      Buf[i] = uint8_t(Value >> (Index * 8));
+    }
+    assert(ValidReloc.Size <= sizeof(Buf));
+    memcpy(&Data[ValidReloc.Offset - BaseOffset], Buf, ValidReloc.Size);
+    Applied = true;
+  }
+
+  return Applied;
+}
+
 /// \brief Recursively clone \p InputDIE's subtrees that have been
 /// selected to appear in the linked output.
 ///
@@ -1284,6 +1332,20 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
 
   // Extract and clone every attribute.
   DataExtractor Data = U.getDebugInfoExtractor();
+  uint32_t NextOffset = U.getDIEAtIndex(Idx + 1)->getOffset();
+
+  // We could copy the data only if we need to aply a relocation to
+  // it. After testing, it seems there is no performance downside to
+  // doing the copy unconditionally, and it makes the code simpler.
+  SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
+  Data = DataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
+  // Modify the copy with relocated addresses.
+  applyValidRelocs(DIECopy, Offset, Data.isLittleEndian());
+
+  // Reset the Offset to 0 as we will be working on the local copy of
+  // the data.
+  Offset = 0;
+
   const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr();
   Offset += getULEB128Size(Abbrev->getCode());
 
@@ -1386,6 +1448,11 @@ bool DwarfLinker::link(const DebugMap &M
       lookForDIEsToKeep(*CurrentUnit.getOrigUnit().getCompileUnitDIE(), *Obj,
                         CurrentUnit, 0);
 
+    // The calls to applyValidRelocs inside cloneDIE will walk the
+    // reloc array again (in the same way findValidRelocsInDebugInfo()
+    // did). We need to reset the NextValidReloc index to the beginning.
+    NextValidReloc = 0;
+
     // Construct the output DIE tree by cloning the DIEs we chose to
     // keep above. If there are no valid relocs, then there's nothing
     // to clone/emit.





More information about the llvm-commits mailing list