diff --git a/lld/MachO/Arch/ARM64.cpp b/lld/MachO/Arch/ARM64.cpp index 7419046c8e0ba0..0d1e2f447adca6 100644 --- a/lld/MachO/Arch/ARM64.cpp +++ b/lld/MachO/Arch/ARM64.cpp @@ -79,7 +79,8 @@ const RelocAttrs &ARM64::getRelocAttrs(uint8_t type) const { uint64_t ARM64::getEmbeddedAddend(MemoryBufferRef mb, const section_64 &sec, const relocation_info rel) const { - if (rel.r_type != ARM64_RELOC_UNSIGNED) { + if (rel.r_type != ARM64_RELOC_UNSIGNED && + rel.r_type != ARM64_RELOC_SUBTRACTOR) { // All other reloc types should use the ADDEND relocation to store their // addends. // TODO(gkm): extract embedded addend just so we can assert that it is 0 @@ -159,6 +160,7 @@ void ARM64::relocateOne(uint8_t *loc, const Reloc &r, uint64_t value, case ARM64_RELOC_BRANCH26: value = encodeBranch26(base, value - pc); break; + case ARM64_RELOC_SUBTRACTOR: case ARM64_RELOC_UNSIGNED: break; case ARM64_RELOC_POINTER_TO_GOT: diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp index f986818d14f7b4..32ef5b46730a99 100644 --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -276,16 +276,6 @@ void ObjFile::parseRelocations(const section_64 &sec, if (relInfo.r_address & R_SCATTERED) fatal("TODO: Scattered relocations not supported"); - Reloc p; - if (target->hasAttr(relInfo.r_type, RelocAttrBits::SUBTRAHEND)) { - 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); - } uint64_t embeddedAddend = target->getEmbeddedAddend(mb, sec, relInfo); assert(!(embeddedAddend && pairedAddend)); uint64_t totalAddend = pairedAddend + embeddedAddend; @@ -320,9 +310,19 @@ void ObjFile::parseRelocations(const section_64 &sec, } InputSection *subsec = findContainingSubsection(subsecMap, &r.offset); - if (p.type != GENERIC_RELOC_INVALID) - subsec->relocs.push_back(p); subsec->relocs.push_back(r); + + if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) { + 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 p; + p.type = relInfo.r_type; + p.referent = symbols[relInfo.r_symbolnum]; + subsec->relocs.push_back(p); + } } } diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp index a54d83618bb0c0..03d2fc54a5962e 100644 --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -58,15 +58,12 @@ void InputSection::writeTo(uint8_t *buf) { memcpy(buf, data.data(), data.size()); for (size_t i = 0; i < relocs.size(); i++) { - const Symbol *fromSym = - target->hasAttr(relocs[i].type, RelocAttrBits::SUBTRAHEND) - ? relocs[i++].referent.get() - : nullptr; const Reloc &r = relocs[i]; uint8_t *loc = buf + r.offset; uint64_t referentVA = 0; - if (fromSym) { - const Symbol *toSym = r.referent.get(); + if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) { + const Symbol *fromSym = r.referent.get(); + const Symbol *toSym = relocs[++i].referent.get(); referentVA = toSym->getVA() - fromSym->getVA(); } else if (auto *referentSym = r.referent.dyn_cast()) { if (target->hasAttr(r.type, RelocAttrBits::LOAD) && diff --git a/lld/test/MachO/reloc-subtractor.s b/lld/test/MachO/reloc-subtractor.s index dead12f06766d4..d426adc60bf2a6 100644 --- a/lld/test/MachO/reloc-subtractor.s +++ b/lld/test/MachO/reloc-subtractor.s @@ -21,7 +21,7 @@ # CHECK-NEXT: segment section address type # CHECK-EMPTY: -.globl _main, _subtrahend_1, _subtrahend_2, _minued1, _minued2 +.globl _main, _subtrahend_1, _subtrahend_2, _minuend1, _minuend2 .data _subtrahend_1: