[lld] r273759 - [lld][MachO] Add support for x86-64 negDelta64 references and fix negDelta32.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 24 17:29:54 PDT 2016


Author: lhames
Date: Fri Jun 24 19:29:54 2016
New Revision: 273759

URL: http://llvm.org/viewvc/llvm-project?rev=273759&view=rev
Log:
[lld][MachO] Add support for x86-64 negDelta64 references and fix negDelta32.

These references are used to implement MachO/x64-64 subtractor relocations
where the minuend is being fixed up, rather than the subtrahend. The 64-bit
version was not previously supported, the 32-bit version was partially
implemented but contained bugs not caught by existing test cases. This
patch fixes both functionality and test coverage.


Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=273759&r1=273758&r2=273759&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Fri Jun 24 19:29:54 2016
@@ -203,6 +203,7 @@ private:
     delta32,               /// ex: .long _foo - .
     delta64Anon,           /// ex: .quad L1 - .
     delta32Anon,           /// ex: .long L1 - .
+    negDelta64,            /// ex: .quad . - _foo
     negDelta32,            /// ex: .long . - _foo
 
     // Kinds introduced by Passes:
@@ -224,8 +225,6 @@ private:
   };
 
   Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
-  Reference::KindValue kindFromRelocPair(const normalized::Relocation &reloc1,
-                                         const normalized::Relocation &reloc2);
 
   void applyFixupFinal(const Reference &ref, uint8_t *location,
                        uint64_t fixupAddress, uint64_t targetAddress,
@@ -254,6 +253,7 @@ const Registry::KindStrings ArchHandler_
   LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(pointer64Anon),
   LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(delta64),
   LLD_KIND_STRING_ENTRY(delta32Anon), LLD_KIND_STRING_ENTRY(delta64Anon),
+  LLD_KIND_STRING_ENTRY(negDelta64),
   LLD_KIND_STRING_ENTRY(negDelta32),
   LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot),
   LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
@@ -438,27 +438,6 @@ ArchHandler_x86_64::getReferenceInfo(con
   }
 }
 
-Reference::KindValue
-ArchHandler_x86_64::kindFromRelocPair(const normalized::Relocation &reloc1,
-                                      const normalized::Relocation &reloc2) {
-  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
-        X86_64_RELOC_UNSIGNED    | rExtern | rLength8):
-    return delta64;
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
-        X86_64_RELOC_UNSIGNED    | rExtern | rLength4):
-    return delta32;
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
-        X86_64_RELOC_UNSIGNED              | rLength8):
-    return delta64Anon;
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
-        X86_64_RELOC_UNSIGNED              | rLength4):
-    return delta32Anon;
-  default:
-    llvm_unreachable("bad reloc pairs");
-  }
-}
-
 llvm::Error
 ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
                                    const normalized::Relocation &reloc2,
@@ -471,35 +450,61 @@ ArchHandler_x86_64::getPairReferenceInfo
                                    Reference::KindValue *kind,
                                    const lld::Atom **target,
                                    Reference::Addend *addend) {
-  *kind = kindFromRelocPair(reloc1, reloc2);
-  if (*kind == invalid)
-    return llvm::make_error<GenericError>("unknown pair");
   const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
   uint64_t targetAddress;
   const lld::Atom *fromTarget;
   if (auto ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
     return ec;
-  if (fromTarget != inAtom)
-    return llvm::make_error<GenericError>("pointer diff not in base atom");
-  switch (*kind) {
-  case delta64:
+
+  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
+        X86_64_RELOC_UNSIGNED    | rExtern | rLength8): {
     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
       return ec;
-    *addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
+    uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent;
+    if (inAtom == fromTarget) {
+      *kind = delta64;
+      *addend = encodedAddend + offsetInAtom;
+    } else if (inAtom == *target) {
+      *kind = negDelta64;
+      *addend = encodedAddend - offsetInAtom;
+      *target = fromTarget;
+    } else
+      return llvm::make_error<GenericError>("Invalid pointer diff");
     return llvm::Error();
-  case delta32:
+  }
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
+        X86_64_RELOC_UNSIGNED    | rExtern | rLength4): {
     if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
       return ec;
-    *addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
+    uint32_t encodedAddend = (int32_t)*(const little32_t *)fixupContent;
+    if (inAtom == fromTarget) {
+      *kind = delta32;
+      *addend = encodedAddend + offsetInAtom;
+    } else if (inAtom == *target) {
+      *kind = negDelta32;
+      *addend = encodedAddend - offsetInAtom;
+      *target = fromTarget;
+    } else
+      return llvm::make_error<GenericError>("Invalid pointer diff");
     return llvm::Error();
-  case delta64Anon:
+  }
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
+        X86_64_RELOC_UNSIGNED              | rLength8):
+    if (fromTarget != inAtom)
+      return llvm::make_error<GenericError>("pointer diff not in base atom");
+    *kind = delta64Anon;
     targetAddress = offsetInAtom + (int64_t)*(const little64_t *)fixupContent;
     return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
-  case delta32Anon:
+  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
+        X86_64_RELOC_UNSIGNED              | rLength4):
+    if (fromTarget != inAtom)
+      return llvm::make_error<GenericError>("pointer diff not in base atom");
+    *kind = delta32Anon;
     targetAddress = offsetInAtom + (int32_t)*(const little32_t *)fixupContent;
     return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
   default:
-    llvm_unreachable("bad reloc pair kind");
+    return llvm::make_error<GenericError>("unknown pair");
   }
 }
 
@@ -583,6 +588,9 @@ void ArchHandler_x86_64::applyFixupFinal
     loc[-2] = 0x8D;
     *loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
     return;
+  case negDelta64:
+    *loc64 = fixupAddress - targetAddress + ref.addend();
+    return;
   case negDelta32:
     *loc32 = fixupAddress - targetAddress + ref.addend();
     return;
@@ -687,8 +695,11 @@ void ArchHandler_x86_64::applyFixupReloc
     // Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
     *loc64 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
     return;
+  case negDelta64:
+    *loc64 = ref.addend() + fixupAddress - inAtomAddress;
+    return;
   case negDelta32:
-    *loc32 = fixupAddress - targetAddress + ref.addend();
+    *loc32 = ref.addend() + fixupAddress - inAtomAddress;
     return;
   case ripRel32GotLoadNowLea:
     llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
@@ -808,7 +819,18 @@ void ArchHandler_x86_64::appendSectionRe
     return;
   case unwindFDEToFunction:
   case unwindInfoToEhFrame:
+    return;
   case negDelta32:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                X86_64_RELOC_UNSIGNED   | rExtern | rLength4 );
+    return;
+  case negDelta64:
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+                X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
+    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
+                X86_64_RELOC_UNSIGNED   | rExtern | rLength8 );
     return;
   case ripRel32GotLoadNowLea:
     llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");

Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=273759&r1=273758&r2=273759&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Fri Jun 24 19:29:54 2016
@@ -247,6 +247,8 @@ private:
     offAndAtom.atom   = atom;
      _sectionAtoms[inSection].push_back(offAndAtom);
     addAtom(*atom);
+//     llvm::dbgs() << "In " << inSection->sectionName << ": Added "
+//                  << atom << " (" << atom->name() << ")\n";
   }
 
   typedef llvm::DenseMap<const normalized::Section *,

Modified: lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml?rev=273759&r1=273758&r2=273759&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml (original)
+++ lld/trunk/test/mach-o/parse-data-relocs-x86_64.yaml Fri Jun 24 19:29:54 2016
@@ -76,6 +76,13 @@ sections:
 # Note the addend here is -16 because that is the offset from here back
 # to _d.
                        0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+#  .quad   . - _foo
+# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
+# The subtractor references _d which is the first nonlocal label in this
+# section.  The unsigned references _foo.
+# Note the addend here is -16 because that is the offset from here back
+# to _d.
+                       0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 #  .quad   L1
 # This is a X86_64_RELOC_UNSIGNED without extern set.
 # In this case, we encode the section number for L1 in the relocation, and
@@ -95,121 +102,146 @@ sections:
 # section.  The unsigned references _foo.
 # Note the addend here is -40 because that is the offset from here back
 # to _d.
-                       0xD8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                       0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 #  .quad   _foo + 4 - .
 # This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
 # The subtractor references _d which is the first nonlocal label in this
 # section.  The unsigned references _foo.
-# Note the addend here is -44.  It would have been -48 because that
+# Note the addend here is -52.  It would have been -56 because that
 # would take us from the address of this relocation back to _d.  But as
-# we also add 4 for the offset, we get -44.
-                       0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+# we also add 4 for the offset, we get -52.
+                       0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 #  .quad   L1 - .
 # This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
 # The subtractor references _d which is the first nonlocal label in this
 # section.  The unsigned does not have extern set, so the relocation
 # number is the section number for L1.
-# Note the addend here is -54. Of that, -56 would be the offset from
+# Note the addend here is -62. Of that, -64 would be the offset from
 # this location from _d.  The remaining 2 is the absolute address
 # of L1.
-                       0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                       0xC2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 #  .long   _foo - .
 # This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
 # The subtractor references _d which is the first nonlocal label in this
 # section.  The unsigned references _foo.
-# Note the addend here is -64 because that is the offset from here back
+# Note the addend here is -72 because that is the offset from here back
+# to _d.
+                       0xB8, 0xFF, 0xFF, 0xFF,
+#  .long   . - _foo
+# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
+# The subtractor references _d which is the first nonlocal label in this
+# section.  The unsigned references _foo.
+# Note the addend here is -76 because that is the offset from here back
 # to _d.
-                       0xC0, 0xFF, 0xFF, 0xFF,
+                       0xB4, 0xFF, 0xFF, 0xFF,
 #  .long   _foo + 4 - .
 # This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
 # The subtractor references _d which is the first nonlocal label in this
 # section.  The unsigned references _foo.
-# Note the addend here is -64.  It would have been -68 because that
+# Note the addend here is -76.  It would have been -80 because that
 # would take us from the address of this relocation back to _d.  But as
-# we also add 4 for the offset, we get -64.
-                       0xC0, 0xFF, 0xFF, 0xFF,
+# we also add 4 for the offset, we get -76.
+                       0xB4, 0xFF, 0xFF, 0xFF,
 #  .long   L1 - .
 # This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
 # The subtractor references _d which is the first nonlocal label in this
 # section.  The unsigned does not have extern set, so the relocation
 # number is the section number for L1.
-# Note the addend here is -70. Of that, -72 would be the offset from
+# Note the addend here is -82. Of that, -84 would be the offset from
 # this location from _d.  The remaining 2 is the absolute address
 # of L1.
-                       0xBA, 0xFF, 0xFF, 0xFF ]
+                       0xAE, 0xFF, 0xFF, 0xFF ]
     relocations:
-      - offset:          0x00000048
+      - offset:          0x00000054
         type:            X86_64_RELOC_SUBTRACTOR
         length:          2
         pc-rel:          false
         extern:          true
         symbol:          2
-      - offset:          0x00000048
+      - offset:          0x00000054
         type:            X86_64_RELOC_UNSIGNED
         length:          2
         pc-rel:          false
         extern:          false
         symbol:          2
-      - offset:          0x00000044
+      - offset:          0x00000050
         type:            X86_64_RELOC_SUBTRACTOR
         length:          2
         pc-rel:          false
         extern:          true
         symbol:          2
-      - offset:          0x00000044
+      - offset:          0x00000050
         type:            X86_64_RELOC_UNSIGNED
         length:          2
         pc-rel:          false
         extern:          true
         symbol:          0
-      - offset:          0x00000040
+      - offset:          0x0000004C
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+      - offset:          0x0000004C
+        type:            X86_64_RELOC_UNSIGNED
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          2
+      - offset:          0x00000048
         type:            X86_64_RELOC_SUBTRACTOR
         length:          2
         pc-rel:          false
         extern:          true
         symbol:          2
-      - offset:          0x00000040
+      - offset:          0x00000048
         type:            X86_64_RELOC_UNSIGNED
         length:          2
         pc-rel:          false
         extern:          true
         symbol:          0
-      - offset:          0x00000038
+      - offset:          0x00000040
         type:            X86_64_RELOC_SUBTRACTOR
         length:          3
         pc-rel:          false
         extern:          true
         symbol:          2
-      - offset:          0x00000038
+      - offset:          0x00000040
         type:            X86_64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          false
         symbol:          2
-      - offset:          0x00000030
+      - offset:          0x00000038
         type:            X86_64_RELOC_SUBTRACTOR
         length:          3
         pc-rel:          false
         extern:          true
         symbol:          2
-      - offset:          0x00000030
+      - offset:          0x00000038
         type:            X86_64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
         symbol:          0
-      - offset:          0x00000028
+      - offset:          0x00000030
         type:            X86_64_RELOC_SUBTRACTOR
         length:          3
         pc-rel:          false
         extern:          true
         symbol:          2
-      - offset:          0x00000028
+      - offset:          0x00000030
         type:            X86_64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
         symbol:          0
+      - offset:          0x00000028
+        type:            X86_64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          2
       - offset:          0x00000020
         type:            X86_64_RELOC_UNSIGNED
         length:          3
@@ -217,10 +249,16 @@ sections:
         extern:          false
         symbol:          2
       - offset:          0x00000018
+        type:            X86_64_RELOC_SUBTRACTOR
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          0
+      - offset:          0x00000018
         type:            X86_64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
-        extern:          false
+        extern:          true
         symbol:          2
       - offset:          0x00000010
         type:            X86_64_RELOC_SUBTRACTOR
@@ -266,12 +304,13 @@ page-size:       0x00000000
 # CHECK:defined-atoms:   
 # CHECK:  - name:            _d
 # CHECK:    type:            data
-# CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00, 
-# CHECK:                       00, 00, 00, 00, F0, FF, FF, FF, FF, FF, FF, FF, 
-# CHECK:                       {{..}}, {{..}}, 00, 00, 00, 00, 00, 00, {{..}}, {{..}}, 00, 00,
-# CHECK:                       00, 00, 00, 00, D8, FF, FF, FF, FF, FF, FF, FF, 
-# CHECK:                       D4, FF, FF, FF, FF, FF, FF, FF, {{..}}, {{..}}, {{..}}, {{..}},
-# CHECK:                       {{..}}, {{..}}, {{..}}, {{..}}, C0, FF, FF, FF, C0, FF, FF, FF,
+# CHECK:    content:         [ 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
+# CHECK:                       00, 00, 00, 00, F0, FF, FF, FF, FF, FF, FF, FF,
+# CHECK:                       18, 00, 00, 00, 00, 00, 00, 00, {{..}}, {{..}}, 00, 00,
+# CHECK:                       00, 00, 00, 00, {{..}}, {{..}}, 00, 00, 00, 00, 00, 00,
+# CHECK:                       D0, FF, FF, FF, FF, FF, FF, FF, CC, FF, FF, FF,
+# CHECK:                       FF, FF, FF, FF, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}},
+# CHECK:                       B8, FF, FF, FF, B4, FF, FF, FF, B4, FF, FF, FF,
 # CHECK:                       {{..}}, {{..}}, {{..}}, {{..}} ]
 # CHECK:    dead-strip:      never
 # CHECK:    references:      
@@ -285,32 +324,38 @@ page-size:       0x00000000
 # CHECK:      - kind:            delta64
 # CHECK:        offset:          16
 # CHECK:        target:          _foo
-# CHECK:      - kind:            pointer64Anon
+# CHECK:      - kind:            negDelta64
 # CHECK:        offset:          24
-# CHECK:        target:          L003
+# CHECK:        target:          _foo
 # CHECK:      - kind:            pointer64Anon
 # CHECK:        offset:          32
 # CHECK:        target:          L003
+# CHECK:      - kind:            pointer64Anon
+# CHECK:        offset:          40
+# CHECK:        target:          L003
 # CHECK:        addend:          2
 # CHECK:      - kind:            delta64
-# CHECK:        offset:          40
+# CHECK:        offset:          48
 # CHECK:        target:          _foo
 # CHECK:      - kind:            delta64
-# CHECK:        offset:          48
+# CHECK:        offset:          56
 # CHECK:        target:          _foo
 # CHECK:        addend:          4
 # CHECK:      - kind:            delta64Anon
-# CHECK:        offset:          56
+# CHECK:        offset:          64
 # CHECK:        target:          L003
 # CHECK:      - kind:            delta32
-# CHECK:        offset:          64
+# CHECK:        offset:          72
+# CHECK:        target:          _foo
+# CHECK:      - kind:            negDelta32
+# CHECK:        offset:          76
 # CHECK:        target:          _foo
 # CHECK:      - kind:            delta32
-# CHECK:        offset:          68
+# CHECK:        offset:          80
 # CHECK:        target:          _foo
 # CHECK:        addend:          4
 # CHECK:      - kind:            delta32Anon
-# CHECK:        offset:          72
+# CHECK:        offset:          84
 # CHECK:        target:          L003
 # CHECK:  - name:            _foo
 # CHECK:    content:         [ C3 ]




More information about the llvm-commits mailing list