[lld] 5413901 - [lld-macho] Don't emit rebase opcodes for subtractor minuend relocs

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 27 09:32:03 PST 2021


Author: Jez Ng
Date: 2021-02-27T12:31:34-05:00
New Revision: 541390131ef72a8dad93c936d816279c8b76374e

URL: https://github.com/llvm/llvm-project/commit/541390131ef72a8dad93c936d816279c8b76374e
DIFF: https://github.com/llvm/llvm-project/commit/541390131ef72a8dad93c936d816279c8b76374e.diff

LOG: [lld-macho] Don't emit rebase opcodes for subtractor minuend relocs

Also add a few asserts to verify that we are indeed handling an
UNSIGNED relocation as the minued. I haven't made it an actual
user-facing error since I don't think llvm-mc is capable of generating
SUBTRACTOR relocations without an associated UNSIGNED.

Reviewed By: #lld-macho, smeenai

Differential Revision: https://reviews.llvm.org/D97103

Added: 
    

Modified: 
    lld/MachO/Arch/ARM64.cpp
    lld/MachO/InputFiles.cpp
    lld/MachO/InputSection.cpp
    lld/MachO/Target.h
    lld/MachO/Writer.cpp
    lld/test/MachO/reloc-subtractor.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Arch/ARM64.cpp b/lld/MachO/Arch/ARM64.cpp
index d70574c285d3..8428ef480b03 100644
--- a/lld/MachO/Arch/ARM64.cpp
+++ b/lld/MachO/Arch/ARM64.cpp
@@ -47,7 +47,6 @@ struct ARM64 : TargetInfo {
 
 // Random notes on reloc types:
 // ADDEND always pairs with BRANCH26, PAGE21, or PAGEOFF12
-// SUBTRACTOR always pairs with UNSIGNED (a delta between two sections)
 // POINTER_TO_GOT: ld64 supports a 4-byte pc-relative form as well as an 8-byte
 // absolute version of this relocation. The semantics of the absolute relocation
 // are weird -- it results in the value of the GOT slot being written, instead

diff  --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 249cde3c8385..92030222a589 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -287,6 +287,10 @@ void ObjFile::parseRelocations(const section_64 &sec,
       p.type = relInfo.r_type;
       p.referent = symbols[relInfo.r_symbolnum];
       relInfo = relInfos[++i];
+      // SUBTRACTOR relocations should always be followed by an UNSIGNED one
+      // indicating the minuend symbol.
+      assert(target->hasAttr(relInfo.r_type, RelocAttrBits::UNSIGNED) &&
+             relInfo.r_extern);
     }
     Reloc r;
     r.type = relInfo.r_type;
@@ -317,8 +321,7 @@ void ObjFile::parseRelocations(const section_64 &sec,
     }
 
     InputSection *subsec = findContainingSubsection(subsecMap, &r.offset);
-    if (p.type != GENERIC_RELOC_INVALID &&
-        target->hasAttr(p.type, RelocAttrBits::SUBTRAHEND))
+    if (p.type != GENERIC_RELOC_INVALID)
       subsec->relocs.push_back(p);
     subsec->relocs.push_back(r);
   }

diff  --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 971ca6436fbe..33f79ddb3f6d 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -59,13 +59,13 @@ void InputSection::writeTo(uint8_t *buf) {
 
   for (size_t i = 0; i < relocs.size(); i++) {
     auto *fromSym = target->hasAttr(relocs[i].type, RelocAttrBits::SUBTRAHEND)
-                        ? relocs[i++].referent.dyn_cast<Symbol *>()
+                        ? relocs[i++].referent.get<Symbol *>()
                         : nullptr;
     const Reloc &r = relocs[i];
     uint8_t *loc = buf + r.offset;
     uint64_t referentVA = 0;
     if (fromSym) {
-      auto *toSym = r.referent.dyn_cast<Symbol *>();
+      auto *toSym = r.referent.get<Symbol *>();
       referentVA = toSym->getVA() - fromSym->getVA();
     } else if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) {
       if (target->hasAttr(r.type, RelocAttrBits::LOAD) &&

diff  --git a/lld/MachO/Target.h b/lld/MachO/Target.h
index f07a69eef91a..4ad833fae43a 100644
--- a/lld/MachO/Target.h
+++ b/lld/MachO/Target.h
@@ -52,6 +52,7 @@ enum class RelocAttrBits {
   UNSIGNED = 1 << 14,  // *_UNSIGNED relocs
   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ (1 << 15) - 1),
 };
+// Note: SUBTRACTOR always pairs with UNSIGNED (a delta between two symbols).
 
 class TargetInfo {
 public:

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index a0b3ac4082af..56da22c1a19d 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -449,9 +449,16 @@ void Writer::scanRelocations() {
       continue;
     }
 
-    for (Reloc &r : isec->relocs) {
-      if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND))
+    for (auto it = isec->relocs.begin(); it != isec->relocs.end(); ++it) {
+      Reloc &r = *it;
+      if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) {
+        // Skip over the following UNSIGNED relocation -- it's just there as the
+        // minuend, and doesn't have the usual UNSIGNED semantics. We don't want
+        // to emit rebase opcodes for it.
+        it = std::next(it);
+        assert(isa<Defined>(it->referent.dyn_cast<lld::macho::Symbol *>()));
         continue;
+      }
       if (auto *sym = r.referent.dyn_cast<lld::macho::Symbol *>()) {
         if (auto *undefined = dyn_cast<Undefined>(sym))
           treatUndefinedSymbol(*undefined);

diff  --git a/lld/test/MachO/reloc-subtractor.s b/lld/test/MachO/reloc-subtractor.s
index 14355f377182..e445184e44b1 100644
--- a/lld/test/MachO/reloc-subtractor.s
+++ b/lld/test/MachO/reloc-subtractor.s
@@ -3,9 +3,9 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/x86_64.o
 # RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t/arm64.o
 # RUN: %lld -lSystem %t/x86_64.o -o %t/x86_64
-# RUN: llvm-objdump --syms --full-contents %t/x86_64 | FileCheck %s
+# RUN: llvm-objdump --syms --full-contents --rebase %t/x86_64 | FileCheck %s
 # RUN: %lld -arch arm64 -lSystem %t/arm64.o -o %t/arm64
-# RUN: llvm-objdump --syms --full-contents %t/arm64 | FileCheck %s
+# RUN: llvm-objdump --syms --full-contents --rebase %t/arm64 | FileCheck %s
 
 # CHECK-LABEL: SYMBOL TABLE:
 # CHECK:       {{0*}}[[#%x, SUB1ADDR:]] l {{.*}} __DATA,__data _sub1
@@ -17,6 +17,9 @@
 # CHECK-NEXT:  [[#SUB2ADDR]] f0ffffff
 # CHECK-NEXT:  [[#SUB3ADDR]] 10000000 00000000
 # CHECK-NEXT:  [[#SUB4ADDR]] f0ffffff ffffffff
+# CHECK:       Rebase table:
+# CHECK-NEXT:  segment  section            address     type
+# CHECK-EMPTY:
 
 .globl _main, _subtrahend_1, _subtrahend_2, _minued1, _minued2
 


        


More information about the llvm-commits mailing list