[llvm] r231955 - [dsymutil] Correctly clone address attributes.

Frederic Riss friss at apple.com
Wed Mar 11 11:45:52 PDT 2015


Author: friss
Date: Wed Mar 11 13:45:52 2015
New Revision: 231955

URL: http://llvm.org/viewvc/llvm-project?rev=231955&view=rev
Log:
[dsymutil] Correctly clone address attributes.

DW_AT_low_pc on functions is taken care of by the relocation processing, but
DW_AT_high_pc and DW_AT_low_pc on other lexical scopes need special handling.

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=231955&r1=231954&r2=231955&view=diff
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test (original)
+++ llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test Wed Mar 11 13:45:52 2015
@@ -25,6 +25,7 @@ CHECK:      DW_AT_type [DW_FORM_ref4]
 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_high_pc [DW_FORM_addr]    (0x0000000100000ec4)
 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")
@@ -75,6 +76,7 @@ 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_high_pc [DW_FORM_addr]    (0x0000000100000f19)
 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")
@@ -85,6 +87,7 @@ 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_high_pc [DW_FORM_addr]    (0x0000000100000f37)
 CHECK:      DW_AT_frame_base [DW_FORM_block1]	(<0x01> 56 )
 CHECK:    NULL
 
@@ -107,6 +110,7 @@ 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_high_pc [DW_FORM_addr]    (0x0000000100000f84)
 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")
@@ -117,6 +121,7 @@ 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_high_pc [DW_FORM_addr]    (0x0000000100000fa9)
 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=231955&r1=231954&r2=231955&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 Wed Mar 11 13:45:52 2015
@@ -19,6 +19,7 @@ CHECK:      DW_AT_type [DW_FORM_ref4]
 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_high_pc [DW_FORM_addr]     (0x0000000100000f4b)
 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")
@@ -63,12 +64,15 @@ 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_high_pc [DW_FORM_addr]    (0x0000000100000f89)
 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")
 CHECK:        DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
 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)
+CHECK:        DW_AT_high_pc [DW_FORM_addr]  (0x0000000100000f72)
 CHECK:        DW_AT_call_line [DW_FORM_data1]	(20)
 CHECK:      NULL
 CHECK:    DW_TAG_subprogram [11]
@@ -93,11 +97,14 @@ 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_high_pc [DW_FORM_addr]    (0x0000000100000fb4)
 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")
 CHECK:        DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
 CHECK:      DW_TAG_lexical_block [14] *
+CHECK:        DW_AT_low_pc [DW_FORM_addr]   (0x0000000100000f94)
+CHECK         DW_AT_high_pc [DW_FORM_addr]  (0x0000000100000fa7)
 CHECK:        DW_TAG_inlined_subroutine [15]
 CHECK:          DW_AT_abstract_origin [DW_FORM_ref4]        (cu + 0x009a => {0x000001d4} "inc")
 

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=231955&r1=231954&r2=231955&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Wed Mar 11 13:45:52 2015
@@ -54,7 +54,7 @@ class CompileUnit {
 public:
   /// \brief Information gathered about a DIE in the object file.
   struct DIEInfo {
-    uint64_t Address;   ///< Linked address of the described entity.
+    int64_t AddrAdjust; ///< Address offset to apply to the described entity.
     DIE *Clone;         ///< Cloned version of that DIE.
     uint32_t ParentIdx; ///< The index of this DIE's parent.
     bool Keep;          ///< Is the DIE part of the linked output?
@@ -529,17 +529,29 @@ private:
   ///
   /// \param OutOffset is the offset the cloned DIE in the output
   /// compile unit.
+  /// \param PCOffset (while cloning a function scope) is the offset
+  /// applied to the entry point of the function to get the linked address.
   ///
   /// \returns the root of the cloned tree.
   DIE *cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &U,
-                uint32_t OutOffset);
+                int64_t PCOffset, uint32_t OutOffset);
 
   typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec;
 
+  /// \brief Information gathered and exchanged between the various
+  /// clone*Attributes helpers about the attributes of a particular DIE.
+  struct AttributesInfo {
+    uint64_t OrigHighPc; ///< Value of AT_high_pc in the input DIE
+    int64_t PCOffset;    ///< Offset to apply to PC addresses inside a function.
+
+    AttributesInfo() : OrigHighPc(0), PCOffset(0) {}
+  };
+
   /// \brief Helper for cloneDIE.
   unsigned cloneAttribute(DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE,
                           CompileUnit &U, const DWARFFormValue &Val,
-                          const AttributeSpec AttrSpec, unsigned AttrSize);
+                          const AttributeSpec AttrSpec, unsigned AttrSize,
+                          AttributesInfo &AttrInfo);
 
   /// \brief Helper for cloneDIE.
   unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
@@ -557,6 +569,11 @@ private:
                                const DWARFFormValue &Val, unsigned AttrSize);
 
   /// \brief Helper for cloneDIE.
+  unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
+                                 const DWARFFormValue &Val,
+                                 const CompileUnit &Unit, AttributesInfo &Info);
+
+  /// \brief Helper for cloneDIE.
   unsigned cloneScalarAttribute(DIE &Die,
                                 const DWARFDebugInfoEntryMinimal &InputDIE,
                                 const DWARFUnit &U, AttributeSpec AttrSpec,
@@ -831,8 +848,9 @@ bool DwarfLinker::hasValidRelocation(uin
                             ValidReloc.Mapping->getValue().ObjectAddress,
                             ValidReloc.Mapping->getValue().BinaryAddress);
 
-  Info.Address =
-      ValidReloc.Mapping->getValue().BinaryAddress + ValidReloc.Addend;
+  Info.AddrAdjust = int64_t(ValidReloc.Mapping->getValue().BinaryAddress) +
+                    ValidReloc.Addend -
+                    ValidReloc.Mapping->getValue().ObjectAddress;
   Info.InDebugMap = true;
   return true;
 }
@@ -1189,6 +1207,30 @@ unsigned DwarfLinker::cloneBlockAttribut
   return AttrSize;
 }
 
+/// \brief Clone an address attribute and add it to \p Die.
+/// \returns the size of the new attribute.
+unsigned DwarfLinker::cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
+                                            const DWARFFormValue &Val,
+                                            const CompileUnit &Unit,
+                                            AttributesInfo &Info) {
+  int64_t Addr = *Val.getAsAddress(&Unit.getOrigUnit());
+  if (AttrSpec.Attr == dwarf::DW_AT_low_pc) {
+    if (Die.getTag() == dwarf::DW_TAG_inlined_subroutine ||
+        Die.getTag() == dwarf::DW_TAG_lexical_block)
+      Addr += Info.PCOffset;
+  } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc) {
+    // If we have a high_pc recorded for the input DIE, use
+    // it. Otherwise (when no relocations where applied) just use the
+    // one we just decoded.
+    Addr = (Info.OrigHighPc ? Info.OrigHighPc : Addr) + Info.PCOffset;
+  }
+
+  Die.addValue(static_cast<dwarf::Attribute>(AttrSpec.Attr),
+               static_cast<dwarf::Form>(AttrSpec.Form),
+               new (DIEAlloc) DIEInteger(Addr));
+  return Unit.getOrigUnit().getAddressByteSize();
+}
+
 /// \brief Clone a scalar attribute  and add it to \p Die.
 /// \returns the size of the new attribute.
 unsigned DwarfLinker::cloneScalarAttribute(
@@ -1199,8 +1241,6 @@ unsigned DwarfLinker::cloneScalarAttribu
     Value = *Val.getAsSectionOffset();
   else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
     Value = *Val.getAsSignedConstant();
-  else if (AttrSpec.Form == dwarf::DW_FORM_addr)
-    Value = *Val.getAsAddress(&U);
   else if (auto OptionalValue = Val.getAsUnsignedConstant())
     Value = *OptionalValue;
   else {
@@ -1221,7 +1261,7 @@ unsigned DwarfLinker::cloneAttribute(DIE
                                      CompileUnit &Unit,
                                      const DWARFFormValue &Val,
                                      const AttributeSpec AttrSpec,
-                                     unsigned AttrSize) {
+                                     unsigned AttrSize, AttributesInfo &Info) {
   const DWARFUnit &U = Unit.getOrigUnit();
 
   switch (AttrSpec.Form) {
@@ -1242,6 +1282,7 @@ unsigned DwarfLinker::cloneAttribute(DIE
   case dwarf::DW_FORM_exprloc:
     return cloneBlockAttribute(Die, AttrSpec, Val, AttrSize);
   case dwarf::DW_FORM_addr:
+    return cloneAddressAttribute(Die, AttrSpec, Val, Unit, Info);
   case dwarf::DW_FORM_data1:
   case dwarf::DW_FORM_data2:
   case dwarf::DW_FORM_data4:
@@ -1312,7 +1353,8 @@ bool DwarfLinker::applyValidRelocs(Mutab
 ///
 /// \returns the cloned DIE object or null if nothing was selected.
 DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE,
-                           CompileUnit &Unit, uint32_t OutOffset) {
+                           CompileUnit &Unit, int64_t PCOffset,
+                           uint32_t OutOffset) {
   DWARFUnit &U = Unit.getOrigUnit();
   unsigned Idx = U.getDIEIndex(&InputDIE);
   CompileUnit::DIEInfo &Info = Unit.getInfo(Idx);
@@ -1333,6 +1375,7 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
   // Extract and clone every attribute.
   DataExtractor Data = U.getDebugInfoExtractor();
   uint32_t NextOffset = U.getDIEAtIndex(Idx + 1)->getOffset();
+  AttributesInfo AttrInfo;
 
   // 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
@@ -1340,7 +1383,17 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
   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());
+  if (applyValidRelocs(DIECopy, Offset, Data.isLittleEndian())) {
+    // If we applied relocations, we store the value of high_pc that was
+    // potentially stored in the input DIE. If high_pc is an address
+    // (Dwarf version == 2), then it might have been relocated to a
+    // totally unrelated value (because the end address in the object
+    // file might be start address of another function which got moved
+    // independantly by the linker). The computation of the actual
+    // high_pc value is done in cloneAddressAttribute().
+    AttrInfo.OrigHighPc =
+        InputDIE.getAttributeValueAsAddress(&U, dwarf::DW_AT_high_pc, 0);
+  }
 
   // Reset the Offset to 0 as we will be working on the local copy of
   // the data.
@@ -1349,13 +1402,19 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
   const auto *Abbrev = InputDIE.getAbbreviationDeclarationPtr();
   Offset += getULEB128Size(Abbrev->getCode());
 
+  // We are entering a subprogram. Get and propagate the PCOffset.
+  if (Die->getTag() == dwarf::DW_TAG_subprogram)
+    PCOffset = Info.AddrAdjust;
+  AttrInfo.PCOffset = PCOffset;
+
   for (const auto &AttrSpec : Abbrev->attributes()) {
     DWARFFormValue Val(AttrSpec.Form);
     uint32_t AttrSize = Offset;
     Val.extractValue(Data, &Offset, &U);
     AttrSize = Offset - AttrSize;
 
-    OutOffset += cloneAttribute(*Die, InputDIE, Unit, Val, AttrSpec, AttrSize);
+    OutOffset +=
+        cloneAttribute(*Die, InputDIE, Unit, Val, AttrSpec, AttrSize, AttrInfo);
   }
 
   DIEAbbrev &NewAbbrev = Die->getAbbrev();
@@ -1379,7 +1438,7 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
   // Recursively clone children.
   for (auto *Child = InputDIE.getFirstChild(); Child && !Child->isNULL();
        Child = Child->getSibling()) {
-    if (DIE *Clone = cloneDIE(*Child, Unit, OutOffset)) {
+    if (DIE *Clone = cloneDIE(*Child, Unit, PCOffset, OutOffset)) {
       Die->addChild(std::unique_ptr<DIE>(Clone));
       OutOffset = Clone->getOffset() + Clone->getSize();
     }
@@ -1460,8 +1519,8 @@ bool DwarfLinker::link(const DebugMap &M
       for (auto &CurrentUnit : Units) {
         const auto *InputDIE = CurrentUnit.getOrigUnit().getCompileUnitDIE();
         CurrentUnit.setStartOffset(OutputDebugInfoSize);
-        DIE *OutputDIE =
-            cloneDIE(*InputDIE, CurrentUnit, 11 /* Unit Header size */);
+        DIE *OutputDIE = cloneDIE(*InputDIE, CurrentUnit, 0 /* PCOffset */,
+                                  11 /* Unit Header size */);
         CurrentUnit.setOutputUnitDIE(OutputDIE);
         OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset();
       }





More information about the llvm-commits mailing list