[lld] 1aa29df - [lld-macho] Support subtractor relocations that reference sections
Jez Ng via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 20 13:59:08 PDT 2021
Author: Jez Ng
Date: 2021-04-20T16:58:57-04:00
New Revision: 1aa29dffceff63c7f2bdecc03ec9c0922a100082
URL: https://github.com/llvm/llvm-project/commit/1aa29dffceff63c7f2bdecc03ec9c0922a100082
DIFF: https://github.com/llvm/llvm-project/commit/1aa29dffceff63c7f2bdecc03ec9c0922a100082.diff
LOG: [lld-macho] Support subtractor relocations that reference sections
The minuend (but not the subtrahend) can reference a section.
Note that we do not yet properly validate that the subtrahend isn't
referencing a section; I've filed PR50034 to track that.
I've also extended the reloc-subtractor.s test to reorder symbols, to
make sure that the addends are being associated with the minuend (and not
the subtrahend) relocation.
Fixes PR49999.
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D100804
Added:
Modified:
lld/MachO/Arch/ARM64.cpp
lld/MachO/Arch/ARM64Common.cpp
lld/MachO/Arch/ARM64_32.cpp
lld/MachO/Arch/X86_64.cpp
lld/MachO/InputFiles.cpp
lld/MachO/InputSection.cpp
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 708b12b92859c..90f7e174f61e9 100644
--- a/lld/MachO/Arch/ARM64.cpp
+++ b/lld/MachO/Arch/ARM64.cpp
@@ -49,7 +49,7 @@ const RelocAttrs &ARM64::getRelocAttrs(uint8_t type) const {
#define B(x) RelocAttrBits::x
{"UNSIGNED",
B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4) | B(BYTE8)},
- {"SUBTRACTOR", B(SUBTRAHEND) | B(BYTE4) | B(BYTE8)},
+ {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)},
{"BRANCH26", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)},
{"PAGE21", B(PCREL) | B(EXTERN) | B(BYTE4)},
{"PAGEOFF12", B(ABSOLUTE) | B(EXTERN) | B(BYTE4)},
diff --git a/lld/MachO/Arch/ARM64Common.cpp b/lld/MachO/Arch/ARM64Common.cpp
index 88e7286d14503..67e7292fd6fdb 100644
--- a/lld/MachO/Arch/ARM64Common.cpp
+++ b/lld/MachO/Arch/ARM64Common.cpp
@@ -47,7 +47,6 @@ int64_t ARM64Common::getEmbeddedAddend(MemoryBufferRef mb, uint64_t offset,
void ARM64Common::relocateOne(uint8_t *loc, const Reloc &r, uint64_t value,
uint64_t pc) const {
uint32_t base = ((r.length == 2) ? read32le(loc) : 0);
- value += r.addend;
switch (r.type) {
case ARM64_RELOC_BRANCH26:
value = encodeBranch26(r, base, value - pc);
diff --git a/lld/MachO/Arch/ARM64_32.cpp b/lld/MachO/Arch/ARM64_32.cpp
index 80bd933f0728a..f7b1439b8930a 100644
--- a/lld/MachO/Arch/ARM64_32.cpp
+++ b/lld/MachO/Arch/ARM64_32.cpp
@@ -44,7 +44,7 @@ const RelocAttrs &ARM64_32::getRelocAttrs(uint8_t type) const {
static const std::array<RelocAttrs, 11> relocAttrsArray{{
#define B(x) RelocAttrBits::x
{"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4)},
- {"SUBTRACTOR", B(SUBTRAHEND) | B(BYTE4)},
+ {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4)},
{"BRANCH26", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)},
{"PAGE21", B(PCREL) | B(EXTERN) | B(BYTE4)},
{"PAGEOFF12", B(ABSOLUTE) | B(EXTERN) | B(BYTE4)},
diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp
index 0feb7bb635101..7e2155801fc2f 100644
--- a/lld/MachO/Arch/X86_64.cpp
+++ b/lld/MachO/Arch/X86_64.cpp
@@ -51,7 +51,7 @@ const RelocAttrs &X86_64::getRelocAttrs(uint8_t type) const {
{"BRANCH", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)},
{"GOT_LOAD", B(PCREL) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)},
{"GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)},
- {"SUBTRACTOR", B(SUBTRAHEND) | B(BYTE4) | B(BYTE8)},
+ {"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)},
{"SIGNED_1", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)},
{"SIGNED_2", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)},
{"SIGNED_4", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)},
@@ -94,7 +94,6 @@ int64_t X86_64::getEmbeddedAddend(MemoryBufferRef mb, uint64_t offset,
void X86_64::relocateOne(uint8_t *loc, const Reloc &r, uint64_t value,
uint64_t relocVA) const {
- value += r.addend;
if (r.pcrel) {
uint64_t pc = relocVA + 4 + pcrelOffset(r.type);
value -= pc;
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index e2eb3379dfe01..c6bae08e86fb2 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -280,6 +280,8 @@ void ObjFile::parseRelocations(ArrayRef<Section> sectionHeaders,
if (relInfo.r_address & R_SCATTERED)
fatal("TODO: Scattered relocations not supported");
+ bool isSubtrahend =
+ target->hasAttr(relInfo.r_type, RelocAttrBits::SUBTRAHEND);
int64_t embeddedAddend = target->getEmbeddedAddend(mb, sec.offset, relInfo);
assert(!(embeddedAddend && pairedAddend));
int64_t totalAddend = pairedAddend + embeddedAddend;
@@ -290,9 +292,9 @@ void ObjFile::parseRelocations(ArrayRef<Section> sectionHeaders,
r.offset = relInfo.r_address;
if (relInfo.r_extern) {
r.referent = symbols[relInfo.r_symbolnum];
- r.addend = totalAddend;
+ r.addend = isSubtrahend ? 0 : totalAddend;
} else {
- SubsectionMap &referentSubsecMap = subsections[relInfo.r_symbolnum - 1];
+ assert(!isSubtrahend);
const Section &referentSec = sectionHeaders[relInfo.r_symbolnum - 1];
uint64_t referentOffset;
if (relInfo.r_pcrel) {
@@ -309,6 +311,7 @@ void ObjFile::parseRelocations(ArrayRef<Section> sectionHeaders,
// The addend for a non-pcrel relocation is its absolute address.
referentOffset = totalAddend - referentSec.addr;
}
+ SubsectionMap &referentSubsecMap = subsections[relInfo.r_symbolnum - 1];
r.referent = findContainingSubsection(referentSubsecMap, &referentOffset);
r.addend = referentOffset;
}
@@ -316,15 +319,26 @@ void ObjFile::parseRelocations(ArrayRef<Section> sectionHeaders,
InputSection *subsec = findContainingSubsection(subsecMap, &r.offset);
subsec->relocs.push_back(r);
- if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) {
- relInfo = relInfos[++i];
+ if (isSubtrahend) {
+ relocation_info minuendInfo = 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);
+ // attached to the same address.
+ assert(target->hasAttr(minuendInfo.r_type, RelocAttrBits::UNSIGNED) &&
+ relInfo.r_address == minuendInfo.r_address);
Reloc p;
- p.type = relInfo.r_type;
- p.referent = symbols[relInfo.r_symbolnum];
+ p.type = minuendInfo.r_type;
+ if (minuendInfo.r_extern) {
+ p.referent = symbols[minuendInfo.r_symbolnum];
+ p.addend = totalAddend;
+ } else {
+ uint64_t referentOffset =
+ totalAddend - sectionHeaders[minuendInfo.r_symbolnum - 1].addr;
+ SubsectionMap &referentSubsecMap =
+ subsections[minuendInfo.r_symbolnum - 1];
+ p.referent =
+ findContainingSubsection(referentSubsecMap, &referentOffset);
+ p.addend = referentOffset;
+ }
subsec->relocs.push_back(p);
}
}
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 70a3a852878c4..8d9113b2d5bfd 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -62,8 +62,13 @@ void InputSection::writeTo(uint8_t *buf) {
uint64_t referentVA = 0;
if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) {
const Symbol *fromSym = r.referent.get<Symbol *>();
- const Symbol *toSym = relocs[++i].referent.get<Symbol *>();
- referentVA = toSym->getVA() - fromSym->getVA();
+ const Reloc &minuend = relocs[++i];
+ uint64_t minuendVA;
+ if (const Symbol *toSym = minuend.referent.dyn_cast<Symbol *>())
+ minuendVA = toSym->getVA();
+ else
+ minuendVA = minuend.referent.get<InputSection *>()->getVA();
+ referentVA = minuendVA - fromSym->getVA() + minuend.addend;
} else if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) {
if (target->hasAttr(r.type, RelocAttrBits::LOAD) &&
!referentSym->isInGot())
@@ -81,7 +86,7 @@ void InputSection::writeTo(uint8_t *buf) {
} else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) {
referentVA = referentIsec->getVA();
}
- target->relocateOne(loc, r, referentVA, getVA() + r.offset);
+ target->relocateOne(loc, r, referentVA + r.addend, getVA() + r.offset);
}
}
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 52b69fa50853e..6ba7ed0eaba9d 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -527,7 +527,6 @@ void Writer::scanRelocations() {
// 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<Symbol *>()));
continue;
}
if (auto *sym = r.referent.dyn_cast<Symbol *>()) {
diff --git a/lld/test/MachO/reloc-subtractor.s b/lld/test/MachO/reloc-subtractor.s
index d426adc60bf2a..550f27d352b57 100644
--- a/lld/test/MachO/reloc-subtractor.s
+++ b/lld/test/MachO/reloc-subtractor.s
@@ -1,37 +1,47 @@
# REQUIRES: x86, aarch64
-# RUN: rm -rf %t; mkdir %t
-# 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: rm -rf %t; split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/x86_64.o
+# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/test.s -o %t/arm64.o
+# RUN: %lld -lSystem %t/x86_64.o -o %t/x86_64 -order_file %t/order-file
# RUN: llvm-objdump --syms --full-contents --rebase %t/x86_64 | FileCheck %s
-# RUN: %lld -arch arm64 -lSystem %t/arm64.o -o %t/arm64
+# RUN: %lld -arch arm64 -lSystem %t/arm64.o -o %t/arm64 -order_file %t/order-file
# RUN: llvm-objdump --syms --full-contents --rebase %t/arm64 | FileCheck %s
# CHECK-LABEL: SYMBOL TABLE:
-# CHECK: {{0*}}[[#%x, SUB1ADDR:]] l {{.*}} __DATA,__data _sub1
-# CHECK: {{0*}}[[#%x, SUB2ADDR:]] l {{.*}} __DATA,__data _sub2
-# CHECK: {{0*}}[[#%x, SUB3ADDR:]] l {{.*}} __DATA,__data _sub3
-# CHECK: {{0*}}[[#%x, SUB4ADDR:]] l {{.*}} __DATA,__data _sub4
-# CHECK-LABEL: Contents of section __DATA,__data:
+# CHECK: {{0*}}[[#%x, SUB1ADDR:]] l {{.*}} __DATA,bar _sub1
+# CHECK: {{0*}}[[#%x, SUB2ADDR:]] l {{.*}} __DATA,bar _sub2
+# CHECK: {{0*}}[[#%x, SUB3ADDR:]] l {{.*}} __DATA,bar _sub3
+# CHECK: {{0*}}[[#%x, SUB4ADDR:]] l {{.*}} __DATA,bar _sub4
+# CHECK: {{0*}}[[#%x, SUB5ADDR:]] l {{.*}} __DATA,bar _sub5
+# CHECK-LABEL: Contents of section __DATA,bar:
# CHECK: [[#SUB1ADDR]] 10000000
# CHECK-NEXT: [[#SUB2ADDR]] f2ffffff
# CHECK-NEXT: [[#SUB3ADDR]] 14000000 00000000
# CHECK-NEXT: [[#SUB4ADDR]] f6ffffff ffffffff
+# CHECK-NEXT: [[#SUB5ADDR]] f1ffffff ffffffff
# CHECK: Rebase table:
# CHECK-NEXT: segment section address type
# CHECK-EMPTY:
+#--- test.s
+
.globl _main, _subtrahend_1, _subtrahend_2, _minuend1, _minuend2
-.data
-_subtrahend_1:
+.section __DATA,foo
+ .space 16
+L_.minuend:
.space 16
+
+.section __DATA,bar
_minuend_1:
.space 16
_minuend_2:
.space 16
+_subtrahend_1:
+ .space 16
_subtrahend_2:
.space 16
+
_sub1:
.long _minuend_1 - _subtrahend_1
.space 12
@@ -43,8 +53,22 @@ _sub3:
.space 8
_sub4:
.quad _minuend_2 - _subtrahend_2 + 6
+ .space 8
+_sub5:
+ .quad L_.minuend - _subtrahend_1 + 1
+ .space 8
.text
.p2align 2
_main:
ret
+
+.subsections_via_symbols
+
+#--- order-file
+## Reorder the symbols to make sure that the addends are being associated with
+## the minuend (and not the subtrahend) relocation.
+_subtrahend_1
+_minuend_1
+_minuend_2
+_subtrahend_2
More information about the llvm-commits
mailing list