[lld] r222198 - [mach-o] enhance arm64 reloc parser to support local pointer relocations

Nick Kledzik kledzik at apple.com
Mon Nov 17 16:30:17 PST 2014


Author: kledzik
Date: Mon Nov 17 18:30:17 2014
New Revision: 222198

URL: http://llvm.org/viewvc/llvm-project?rev=222198&view=rev
Log:
[mach-o] enhance arm64 reloc parser to support local pointer relocations

The arm64 assembler almost always uses r_extern=1 relocations in which the
r_symbolnum field is the index of the symbol the relocation references.  But
sometimes it will set r_extern=0 in which case the linker needs to read the
content of the reloction to determine the target.

Add test case that the r_extern=0 relocation round trips.

Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
    lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=222198&r1=222197&r2=222198&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Mon Nov 17 18:30:17 2014
@@ -191,7 +191,7 @@ private:
 
   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
                              uint64_t fixupAddress, uint64_t targetAddress,
-                             uint64_t inAtomAddress);
+                             uint64_t inAtomAddress, bool targetUnnamed);
 
   // Utility functions for inspecting/updating instructions.
   static uint32_t setDisplacementInBranch26(uint32_t instr, int32_t disp);
@@ -399,6 +399,11 @@ std::error_code ArchHandler_arm64::getRe
       return ec;
     *addend = *(const little64_t *)fixupContent;
     return std::error_code();
+  case ARM64_RELOC_UNSIGNED                              | rLength8:
+     // ex: .quad Lfoo + N
+     *kind = pointer64;
+     return atomFromAddress(reloc.symbol, *(little64_t *)fixupContent,
+                            target, addend);
   case ARM64_RELOC_POINTER_TO_GOT              | rExtern | rLength8:
     // ex: .quad _foo at GOT
     *kind = pointer64ToGOT;
@@ -482,6 +487,7 @@ void ArchHandler_arm64::generateAtomCont
   for (const Reference *ref : atom) {
     uint32_t offset = ref->offsetInAtom();
     const Atom *target = ref->target();
+    bool targetUnnamed = target->name().empty();
     uint64_t targetAddress = 0;
     if (isa<DefinedAtom>(target))
       targetAddress = findAddress(*target);
@@ -489,7 +495,7 @@ void ArchHandler_arm64::generateAtomCont
     uint64_t fixupAddress = atomAddress + offset;
     if (relocatable) {
       applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
-                            targetAddress, atomAddress);
+                            targetAddress, atomAddress, targetUnnamed);
     } else {
       applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
                       targetAddress, atomAddress);
@@ -588,7 +594,8 @@ void ArchHandler_arm64::applyFixupReloca
                                               uint8_t *loc,
                                               uint64_t fixupAddress,
                                               uint64_t targetAddress,
-                                              uint64_t inAtomAddress) {
+                                              uint64_t inAtomAddress,
+                                              bool targetUnnamed) {
   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
   assert(ref.kindArch() == Reference::KindArch::AArch64);
@@ -613,7 +620,10 @@ void ArchHandler_arm64::applyFixupReloca
     *loc32 = setImm12(*loc32, 0);
     return;
   case pointer64:
-    *loc64 = ref.addend();
+    if (targetUnnamed)
+      *loc64 = targetAddress + ref.addend();
+    else
+      *loc64 = ref.addend();
     return;
   case delta64:
     *loc64 = ref.addend() + inAtomAddress - fixupAddress;
@@ -707,7 +717,11 @@ void ArchHandler_arm64::appendSectionRel
                   ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4);
     return;
   case pointer64:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+    if (ref.target()->name().empty())
+      appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+                  ARM64_RELOC_UNSIGNED           | rLength8);
+    else
+      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
                   ARM64_RELOC_UNSIGNED | rExtern | rLength8);
     return;
   case delta64:

Modified: lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml?rev=222198&r1=222197&r2=222198&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml (original)
+++ lld/trunk/test/mach-o/parse-data-relocs-arm64.yaml Mon Nov 17 18:30:17 2014
@@ -1,5 +1,5 @@
-# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s \
-# RUN:  && lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
 #
 # Test parsing and writing of arm64 data relocations.
 #
@@ -14,127 +14,126 @@
 --- !mach-o
 arch:            arm64
 file-type:       MH_OBJECT
-flags:           [  ]
-has-UUID:        false
-OS:              unknown
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
 sections:
-  - segment:         __TEXT
-    section:         __text
-    type:            S_REGULAR
-    attributes:      [ S_ATTR_PURE_INSTRUCTIONS ]
-    address:         0x0000000000000000
   - segment:         __DATA
     section:         __data
     type:            S_REGULAR
     attributes:      [  ]
-    alignment:       3
     address:         0x0000000000000000
     content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                        0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-                       0xD0, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0xFF,
-                       0xC8, 0xFF, 0xFF, 0xFF ]
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0xC0, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xFF, 0xFF,
+                       0xB0, 0xFF, 0xFF, 0xFF ]
     relocations:
-      - offset:          0x00000038
+      - offset:          0x00000050
         type:            ARM64_RELOC_POINTER_TO_GOT
         length:          2
         pc-rel:          true
         extern:          true
-        symbol:          3
-      - offset:          0x00000034
+        symbol:          1
+      - offset:          0x0000004C
         type:            ARM64_RELOC_SUBTRACTOR
         length:          2
         pc-rel:          false
         extern:          true
-        symbol:          2
-      - offset:          0x00000034
+        symbol:          1
+      - offset:          0x0000004C
         type:            ARM64_RELOC_UNSIGNED
         length:          2
         pc-rel:          false
         extern:          true
-        symbol:          3
-      - offset:          0x00000030
+        symbol:          1
+      - offset:          0x00000048
         type:            ARM64_RELOC_SUBTRACTOR
         length:          2
         pc-rel:          false
         extern:          true
-        symbol:          2
-      - offset:          0x00000030
+        symbol:          1
+      - offset:          0x00000048
         type:            ARM64_RELOC_UNSIGNED
         length:          2
         pc-rel:          false
         extern:          true
-        symbol:          3
-      - offset:          0x00000028
+        symbol:          1
+      - offset:          0x00000040
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          true
+        symbol:          1
+      - offset:          0x00000038
+        type:            ARM64_RELOC_UNSIGNED
+        length:          3
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x00000030
         type:            ARM64_RELOC_SUBTRACTOR
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          2
-      - offset:          0x00000028
+        symbol:          1
+      - offset:          0x00000030
         type:            ARM64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          3
-      - offset:          0x00000020
+        symbol:          1
+      - offset:          0x00000028
         type:            ARM64_RELOC_SUBTRACTOR
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          2
-      - offset:          0x00000020
+        symbol:          1
+      - offset:          0x00000028
         type:            ARM64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          3
-      - offset:          0x00000018
+        symbol:          1
+      - offset:          0x00000020
         type:            ARM64_RELOC_SUBTRACTOR
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          2
-      - offset:          0x00000018
+        symbol:          1
+      - offset:          0x00000020
         type:            ARM64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          3
-      - offset:          0x00000010
+        symbol:          1
+      - offset:          0x00000018
         type:            ARM64_RELOC_POINTER_TO_GOT
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          3
-      - offset:          0x00000008
+        symbol:          1
+      - offset:          0x00000010
         type:            ARM64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          3
-      - offset:          0x00000000
+        symbol:          1
+      - offset:          0x00000008
         type:            ARM64_RELOC_UNSIGNED
         length:          3
         pc-rel:          false
         extern:          true
-        symbol:          3
+        symbol:          1
 local-symbols:
-  - name:            ltmp0
-    type:            N_SECT
-    sect:            1
-    value:           0x0000000000000000
-  - name:            ltmp1
-    type:            N_SECT
-    sect:            2
-    value:           0x0000000000000000
   - name:            _v1
     type:            N_SECT
-    sect:            2
-    value:           0x0000000000000000
+    sect:            1
+    value:           0x0000000000000008
 undefined-symbols:
   - name:            _foo
     type:            N_UNDF
@@ -143,13 +142,18 @@ undefined-symbols:
 ...
 
 # CHECK: defined-atoms:
+# CHECK:   - ref-name:        L000
+# CHECK:     type:            data
+# CHECK:     content:         [ 00, 00, 00, 00, 00, 00, 00, 00 ]
 # CHECK:   - name:            _v1
 # CHECK:     type:            data
 # CHECK:     content:         [ 00, 00, 00, 00, 00, 00, 00, 00, 08, 00, 00, 00,
 # CHECK:                        00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
 # CHECK:                        00, 00, 00, 00, 00, 00, 00, 00, E0, FF, FF, FF,
 # CHECK:                        FF, FF, FF, FF, DC, FF, FF, FF, FF, FF, FF, FF,
-# CHECK:                        D0, FF, FF, FF, CE, FF, FF, FF, C8, FF, FF, FF ]
+# CHECK:                        00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
+# CHECK:                        00, 00, 00, 00, C0, FF, FF, FF, BE, FF, FF, FF,
+# CHECK:                        B0, FF, FF, FF ]
 # CHECK:     references:
 # CHECK:       - kind:            pointer64
 # CHECK:         offset:          0
@@ -175,17 +179,44 @@ undefined-symbols:
 # CHECK:         offset:          40
 # CHECK:         target:          _foo
 # CHECK:         addend:          4
-# CHECK:       - kind:            delta32
+# CHECK:       - kind:            pointer64
 # CHECK:         offset:          48
+# CHECK:         target:          L000
+# CHECK-NOT:     addend:
+# CHECK:       - kind:            pointer64
+# CHECK:         offset:          56
+# CHECK:         target:          _foo
+# CHECK:         addend:          4
+# CHECK:       - kind:            delta32
+# CHECK:         offset:          64
 # CHECK:         target:          _foo
 # CHECK-NOT:     addend:
 # CHECK:       - kind:            delta32
-# CHECK:         offset:          52
+# CHECK:         offset:          68
 # CHECK:         target:          _foo
 # CHECK:         addend:          2
 # CHECK:       - kind:            delta32ToGOT
-# CHECK:         offset:          56
+# CHECK:         offset:          72
 # CHECK:         target:          _foo
 # CHECK-NOT:     addend:
 # CHECK: undefined-atoms:
 # CHECK:   - name:            _foo
+
+
+
+#  .data
+#Lanon:
+#  .quad     0
+#_v1:
+# .quad   _foo
+# .quad   _foo + 8
+#  .quad   _foo at GOT
+#  .quad   _foo + 24 - .
+#  .quad   _foo - .
+#  .quad   _foo + 4 - .
+#  .quad   Lanon
+#  .quad   Lanon + 4
+#  .long   _foo - .
+#  .long   _foo +2 - .
+# .long   _foo at GOT - .
+





More information about the llvm-commits mailing list