diff --git a/lld/ELF/AArch64ErrataFix.cpp b/lld/ELF/AArch64ErrataFix.cpp index a2ab58f96b2b..6e1169c6d90f 100644 --- a/lld/ELF/AArch64ErrataFix.cpp +++ b/lld/ELF/AArch64ErrataFix.cpp @@ -539,9 +539,9 @@ static void implementPatch(Ctx &ctx, uint64_t adrpAddr, uint64_t patcheeOffset, // Case 1: R_AARCH64_JUMP26 branch relocation. We have already patched this // instance of the erratum on a previous patch and altered the relocation. We // have nothing more to do. - // Case 2: A TLS Relaxation R_RELAX_TLS_IE_TO_LE. In this case the ADRP that - // we read will be transformed into a MOVZ later so we actually don't match - // the sequence and have nothing more to do. + // Case 2: A TLS IE to LE optimization. In this case the ADRP that we read + // will be transformed into a MOVZ later so we actually don't match the + // sequence and have nothing more to do. // Case 3: A load/store register (unsigned immediate) class relocation. There // are two of these R_AARCH_LD64_ABS_LO12_NC and R_AARCH_LD64_GOT_LO12_NC and // they are both absolute. We need to add the same relocation to the patch, @@ -551,8 +551,12 @@ static void implementPatch(Ctx &ctx, uint64_t adrpAddr, uint64_t patcheeOffset, auto relIt = llvm::find_if(isec->relocs(), [=](const Relocation &r) { return r.offset == patcheeOffset; }); + // Detect and skip Case 1 and Case 2 above. if (relIt != isec->relocs().end() && - (relIt->type == R_AARCH64_JUMP26 || relIt->expr == R_RELAX_TLS_IE_TO_LE)) + (relIt->type == R_AARCH64_JUMP26 || + ((relIt->type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 || + relIt->type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) && + relIt->expr == R_TPREL))) return; Log(ctx) << "detected cortex-a53-843419 erratum sequence starting at " << diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 3c0d4ca64555..f85a3f48f218 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -8,6 +8,7 @@ #include "InputFiles.h" #include "OutputSections.h" +#include "RelocScan.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" @@ -78,6 +79,14 @@ public: void writePltHeader(uint8_t *buf) const override; void writePlt(uint8_t *buf, const Symbol &sym, uint64_t pltEntryAddr) const override; + template + void scanSectionImpl(InputSectionBase &sec, Relocs rels); + void scanSection(InputSectionBase &sec) override { + if (ctx.arg.ekind == ELF64BEKind) + elf::scanSection1(*this, sec); + else + elf::scanSection1(*this, sec); + } bool needsThunk(RelExpr expr, RelType type, const InputFile *file, uint64_t branchAddr, const Symbol &s, int64_t a) const override; @@ -86,7 +95,6 @@ public: bool usesOnlyLowPageBits(RelType type) const override; void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; - RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; void relocateAlloc(InputSection &sec, uint8_t *buf) const override; void applyBranchToBranchOpt() const override; @@ -137,106 +145,17 @@ AArch64::AArch64(Ctx &ctx) : TargetInfo(ctx) { needsThunks = true; } +// Only needed to support relocations used by relocateNonAlloc and +// preprocessRelocs. RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { - case R_AARCH64_ABS16: case R_AARCH64_ABS32: case R_AARCH64_ABS64: - case R_AARCH64_FUNCINIT64: - case R_AARCH64_ADD_ABS_LO12_NC: - case R_AARCH64_LDST128_ABS_LO12_NC: - case R_AARCH64_LDST16_ABS_LO12_NC: - case R_AARCH64_LDST32_ABS_LO12_NC: - case R_AARCH64_LDST64_ABS_LO12_NC: - case R_AARCH64_LDST8_ABS_LO12_NC: - case R_AARCH64_MOVW_SABS_G0: - case R_AARCH64_MOVW_SABS_G1: - case R_AARCH64_MOVW_SABS_G2: - case R_AARCH64_MOVW_UABS_G0: - case R_AARCH64_MOVW_UABS_G0_NC: - case R_AARCH64_MOVW_UABS_G1: - case R_AARCH64_MOVW_UABS_G1_NC: - case R_AARCH64_MOVW_UABS_G2: - case R_AARCH64_MOVW_UABS_G2_NC: - case R_AARCH64_MOVW_UABS_G3: return R_ABS; - case R_AARCH64_PATCHINST: - if (!isAbsolute(s)) - Err(ctx) << getErrorLoc(ctx, loc) - << "R_AARCH64_PATCHINST relocation against non-absolute symbol " - << &s; - return R_ABS; - case R_AARCH64_AUTH_ABS64: - return RE_AARCH64_AUTH; - case R_AARCH64_TLSDESC_ADR_PAGE21: - return RE_AARCH64_TLSDESC_PAGE; - case R_AARCH64_AUTH_TLSDESC_ADR_PAGE21: - return RE_AARCH64_AUTH_TLSDESC_PAGE; - case R_AARCH64_TLSDESC_LD64_LO12: - case R_AARCH64_TLSDESC_ADD_LO12: - return R_TLSDESC; - case R_AARCH64_AUTH_TLSDESC_LD64_LO12: - case R_AARCH64_AUTH_TLSDESC_ADD_LO12: - return RE_AARCH64_AUTH_TLSDESC; - case R_AARCH64_TLSDESC_CALL: - return R_TLSDESC_CALL; - case R_AARCH64_TLSLE_ADD_TPREL_HI12: - case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: - case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: - case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC: - case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: - case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: - case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: - case R_AARCH64_TLSLE_MOVW_TPREL_G0: - case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: - case R_AARCH64_TLSLE_MOVW_TPREL_G1: - case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: - case R_AARCH64_TLSLE_MOVW_TPREL_G2: - return R_TPREL; - case R_AARCH64_CALL26: - case R_AARCH64_CONDBR19: - case R_AARCH64_JUMP26: - case R_AARCH64_TSTBR14: - return R_PLT_PC; - case R_AARCH64_PLT32: - const_cast(s).thunkAccessed = true; - return R_PLT_PC; - case R_AARCH64_PREL16: case R_AARCH64_PREL32: case R_AARCH64_PREL64: - case R_AARCH64_ADR_PREL_LO21: - case R_AARCH64_LD_PREL_LO19: - case R_AARCH64_MOVW_PREL_G0: - case R_AARCH64_MOVW_PREL_G0_NC: - case R_AARCH64_MOVW_PREL_G1: - case R_AARCH64_MOVW_PREL_G1_NC: - case R_AARCH64_MOVW_PREL_G2: - case R_AARCH64_MOVW_PREL_G2_NC: - case R_AARCH64_MOVW_PREL_G3: return R_PC; - case R_AARCH64_ADR_PREL_PG_HI21: - case R_AARCH64_ADR_PREL_PG_HI21_NC: - return RE_AARCH64_PAGE_PC; - case R_AARCH64_LD64_GOT_LO12_NC: - case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: - return R_GOT; - case R_AARCH64_AUTH_LD64_GOT_LO12_NC: - case R_AARCH64_AUTH_GOT_ADD_LO12_NC: - return RE_AARCH64_AUTH_GOT; - case R_AARCH64_AUTH_GOT_LD_PREL19: - case R_AARCH64_AUTH_GOT_ADR_PREL_LO21: - return RE_AARCH64_AUTH_GOT_PC; - case R_AARCH64_LD64_GOTPAGE_LO15: - return RE_AARCH64_GOT_PAGE; - case R_AARCH64_ADR_GOT_PAGE: - case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: - return RE_AARCH64_GOT_PAGE_PC; - case R_AARCH64_AUTH_ADR_GOT_PAGE: - return RE_AARCH64_AUTH_GOT_PAGE_PC; - case R_AARCH64_GOTPCREL32: - case R_AARCH64_GOT_LD_PREL19: - return R_GOT_PC; case R_AARCH64_NONE: return R_NONE; default: @@ -246,21 +165,14 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, } } -RelExpr AArch64::adjustTlsExpr(RelType type, RelExpr expr) const { - if (expr == R_RELAX_TLS_GD_TO_IE) { - if (type == R_AARCH64_TLSDESC_ADR_PAGE21) - return RE_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC; - return R_RELAX_TLS_GD_TO_IE_ABS; - } - return expr; -} - bool AArch64::usesOnlyLowPageBits(RelType type) const { switch (type) { default: return false; case R_AARCH64_ADD_ABS_LO12_NC: case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_AUTH_LD64_GOT_LO12_NC: + case R_AARCH64_AUTH_GOT_ADD_LO12_NC: case R_AARCH64_LDST128_ABS_LO12_NC: case R_AARCH64_LDST16_ABS_LO12_NC: case R_AARCH64_LDST32_ABS_LO12_NC: @@ -273,6 +185,199 @@ bool AArch64::usesOnlyLowPageBits(RelType type) const { } } +template +void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs rels) { + RelocScan rs(ctx, &sec); + sec.relocations.reserve(rels.size()); + + for (auto it = rels.begin(); it != rels.end(); ++it) { + const RelTy &rel = *it; + uint32_t symIdx = rel.getSymbol(false); + Symbol &sym = sec.getFile()->getSymbol(symIdx); + uint64_t offset = rel.r_offset; + RelType type = rel.getType(false); + if (sym.isUndefined() && symIdx != 0 && + rs.maybeReportUndefined(cast(sym), offset)) + continue; + int64_t addend = rs.getAddend(rel, type); + RelExpr expr; + // Relocation types that only need a RelExpr set `expr` and break out of + // the switch to reach rs.process(). Types that need special handling + // (fast-path helpers, TLS) call a handler and use `continue`. + switch (type) { + case R_AARCH64_NONE: + continue; + + // Absolute relocations: + case R_AARCH64_ABS16: + case R_AARCH64_ABS32: + case R_AARCH64_ABS64: + case R_AARCH64_FUNCINIT64: + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_MOVW_SABS_G0: + case R_AARCH64_MOVW_SABS_G1: + case R_AARCH64_MOVW_SABS_G2: + case R_AARCH64_MOVW_UABS_G0: + case R_AARCH64_MOVW_UABS_G0_NC: + case R_AARCH64_MOVW_UABS_G1: + case R_AARCH64_MOVW_UABS_G1_NC: + case R_AARCH64_MOVW_UABS_G2: + case R_AARCH64_MOVW_UABS_G2_NC: + case R_AARCH64_MOVW_UABS_G3: + expr = R_ABS; + break; + + case R_AARCH64_AUTH_ABS64: + expr = RE_AARCH64_AUTH; + break; + + case R_AARCH64_PATCHINST: + if (!isAbsolute(sym)) + Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset) + << "R_AARCH64_PATCHINST relocation against non-absolute " + "symbol " + << &sym; + expr = R_ABS; + break; + + // PC-relative relocations: + case R_AARCH64_PREL16: + case R_AARCH64_PREL32: + case R_AARCH64_PREL64: + case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_MOVW_PREL_G0: + case R_AARCH64_MOVW_PREL_G0_NC: + case R_AARCH64_MOVW_PREL_G1: + case R_AARCH64_MOVW_PREL_G1_NC: + case R_AARCH64_MOVW_PREL_G2: + case R_AARCH64_MOVW_PREL_G2_NC: + case R_AARCH64_MOVW_PREL_G3: + rs.processR_PC(type, offset, addend, sym); + continue; + + // Page-PC relocations: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_ADR_PREL_PG_HI21_NC: + expr = RE_AARCH64_PAGE_PC; + break; + + // PLT-generating relocations: + case R_AARCH64_PLT32: + sym.thunkAccessed = true; + [[fallthrough]]; + case R_AARCH64_CALL26: + case R_AARCH64_CONDBR19: + case R_AARCH64_JUMP26: + case R_AARCH64_TSTBR14: + rs.processR_PLT_PC(type, offset, addend, sym); + continue; + + // GOT relocations: + case R_AARCH64_ADR_GOT_PAGE: + expr = RE_AARCH64_GOT_PAGE_PC; + break; + case R_AARCH64_LD64_GOT_LO12_NC: + expr = R_GOT; + break; + case R_AARCH64_LD64_GOTPAGE_LO15: + expr = RE_AARCH64_GOT_PAGE; + break; + case R_AARCH64_GOTPCREL32: + case R_AARCH64_GOT_LD_PREL19: + expr = R_GOT_PC; + break; + + // AUTH GOT relocations. Set NEEDS_GOT_AUTH to detect incompatibility with + // NEEDS_GOT_NONAUTH. rs.process does not set the flag. + case R_AARCH64_AUTH_LD64_GOT_LO12_NC: + case R_AARCH64_AUTH_GOT_ADD_LO12_NC: + sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH); + rs.processAux(R_GOT, type, offset, sym, addend); + continue; + case R_AARCH64_AUTH_GOT_LD_PREL19: + case R_AARCH64_AUTH_GOT_ADR_PREL_LO21: + sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH); + rs.processAux(R_GOT_PC, type, offset, sym, addend); + continue; + case R_AARCH64_AUTH_ADR_GOT_PAGE: + sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH); + rs.processAux(RE_AARCH64_GOT_PAGE_PC, type, offset, sym, addend); + continue; + + // TLS LE relocations: + case R_AARCH64_TLSLE_ADD_TPREL_HI12: + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: + case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC: + case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: + case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: + case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G0: + case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G1: + case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC: + case R_AARCH64_TLSLE_MOVW_TPREL_G2: + if (rs.checkTlsLe(offset, sym, type)) + continue; + expr = R_TPREL; + break; + + // TLS IE relocations: + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + rs.handleTlsIe(RE_AARCH64_GOT_PAGE_PC, type, offset, addend, sym); + continue; + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + rs.handleTlsIe(R_GOT, type, offset, addend, sym); + continue; + + // TLSDESC relocations: + case R_AARCH64_TLSDESC_ADR_PAGE21: + rs.handleTlsDesc(RE_AARCH64_TLSDESC_PAGE, RE_AARCH64_GOT_PAGE_PC, type, + offset, addend, sym); + continue; + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_TLSDESC_ADD_LO12: + rs.handleTlsDesc(R_TLSDESC, R_GOT, type, offset, addend, sym); + continue; + case R_AARCH64_TLSDESC_CALL: + sym.setFlags(NEEDS_TLSDESC_NONAUTH); + if (!ctx.arg.shared) + sec.addReloc({R_TPREL, type, offset, addend, &sym}); + continue; + + // AUTH TLSDESC relocations. Do not optimize to LE/IE because PAUTHELF64 + // only supports the descriptor based TLS (TLSDESC). + // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#general-restrictions + case R_AARCH64_AUTH_TLSDESC_ADR_PAGE21: + sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_AUTH); + sec.addReloc({RE_AARCH64_TLSDESC_PAGE, type, offset, addend, &sym}); + continue; + case R_AARCH64_AUTH_TLSDESC_LD64_LO12: + case R_AARCH64_AUTH_TLSDESC_ADD_LO12: + sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_AUTH); + sec.addReloc({R_TLSDESC, type, offset, addend, &sym}); + continue; + + default: + Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset) + << "unknown relocation (" << type.v << ") against symbol " + << &sym; + continue; + } + rs.process(expr, type, offset, sym, addend); + } + + if (ctx.arg.branchToBranch) + llvm::stable_sort(sec.relocs(), + [](auto &l, auto &r) { return l.offset < r.offset; }); +} + RelType AArch64::getDynRel(RelType type) const { if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64 || type == R_AARCH64_FUNCINIT64) @@ -807,8 +912,7 @@ bool AArch64Relaxer::tryRelaxAdrpAdd(const Relocation &adrpRel, // to // NOP // ADR xn, sym - if (!ctx.arg.relax || adrpRel.type != R_AARCH64_ADR_PREL_PG_HI21 || - addRel.type != R_AARCH64_ADD_ABS_LO12_NC) + if (!ctx.arg.relax || addRel.type != R_AARCH64_ADD_ABS_LO12_NC) return false; // Check if the relocations apply to consecutive instructions. if (adrpRel.offset + 4 != addRel.offset) @@ -945,34 +1049,44 @@ void AArch64::relocateAlloc(InputSection &sec, uint8_t *buf) const { continue; } - switch (rel.expr) { - case RE_AARCH64_GOT_PAGE_PC: + switch (rel.type) { + case R_AARCH64_ADR_GOT_PAGE: if (i + 1 < size && relaxer.tryRelaxAdrpLdr(rel, relocs[i + 1], secAddr, buf)) { ++i; continue; } break; - case RE_AARCH64_PAGE_PC: + case R_AARCH64_ADR_PREL_PG_HI21: if (i + 1 < size && relaxer.tryRelaxAdrpAdd(rel, relocs[i + 1], secAddr, buf)) { ++i; continue; } break; - case RE_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: - case R_RELAX_TLS_GD_TO_IE_ABS: - relaxTlsGdToIe(loc, rel, val); + + case R_AARCH64_TLSDESC_ADR_PAGE21: + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_TLSDESC_ADD_LO12: + case R_AARCH64_TLSDESC_CALL: + if (rel.expr == R_TPREL) + relaxTlsGdToLe(loc, rel, val); + else if (rel.expr == RE_AARCH64_GOT_PAGE_PC || rel.expr == R_GOT) + relaxTlsGdToIe(loc, rel, val); + else + relocate(loc, rel, val); continue; - case R_RELAX_TLS_GD_TO_LE: - relaxTlsGdToLe(loc, rel, val); - continue; - case R_RELAX_TLS_IE_TO_LE: - relaxTlsIeToLe(loc, rel, val); + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + if (rel.expr == R_TPREL) + relaxTlsIeToLe(loc, rel, val); + else + relocate(loc, rel, val); continue; default: break; } + relocate(loc, rel, val); } } diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index c71bb6c2c201..e5fc0bafec61 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -820,7 +820,6 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, case RE_ARM_SBREL: return r.sym->getVA(ctx, a) - getARMStaticBase(*r.sym); case R_GOT: - case RE_AARCH64_AUTH_GOT: case R_RELAX_TLS_GD_TO_IE_ABS: return r.sym->getGotVA(ctx) + a; case RE_LOONGARCH_GOT: @@ -847,13 +846,10 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, case R_RELAX_TLS_GD_TO_IE_GOT_OFF: return r.sym->getGotOffset(ctx) + a; case RE_AARCH64_GOT_PAGE_PC: - case RE_AARCH64_AUTH_GOT_PAGE_PC: - case RE_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: return getAArch64Page(r.sym->getGotVA(ctx) + a) - getAArch64Page(p); case RE_AARCH64_GOT_PAGE: return r.sym->getGotVA(ctx) + a - getAArch64Page(ctx.in.got->getVA()); case R_GOT_PC: - case RE_AARCH64_AUTH_GOT_PC: case R_RELAX_TLS_GD_TO_IE: return r.sym->getGotVA(ctx) + a - p; case R_GOTPLT_GOTREL: @@ -1012,14 +1008,12 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r, case R_SIZE: return r.sym->getSize() + a; case R_TLSDESC: - case RE_AARCH64_AUTH_TLSDESC: return ctx.in.got->getTlsDescAddr(*r.sym) + a; case R_TLSDESC_PC: return ctx.in.got->getTlsDescAddr(*r.sym) + a - p; case R_TLSDESC_GOTPLT: return ctx.in.got->getTlsDescAddr(*r.sym) + a - ctx.in.gotPlt->getVA(); case RE_AARCH64_TLSDESC_PAGE: - case RE_AARCH64_AUTH_TLSDESC_PAGE: return getAArch64Page(ctx.in.got->getTlsDescAddr(*r.sym) + a) - getAArch64Page(p); case RE_LOONGARCH_TLSDESC_PAGE_PC: diff --git a/lld/ELF/RelocScan.h b/lld/ELF/RelocScan.h index 1ce4d8417dc3..a06d20a8bd38 100644 --- a/lld/ELF/RelocScan.h +++ b/lld/ELF/RelocScan.h @@ -112,8 +112,9 @@ public: } else { sym.setFlags(NEEDS_TLSIE); // R_GOT (absolute GOT address) needs a RELATIVE dynamic relocation in - // PIC. This is used by R_386_TLS_IE. - if (ieExpr == R_GOT && ctx.arg.isPic) + // PIC when the relocation uses the full address (not just low page bits). + if (ieExpr == R_GOT && ctx.arg.isPic && + !ctx.target->usesOnlyLowPageBits(type)) sec->getPartition(ctx).relaDyn->addRelativeReloc( ctx.target->relativeRel, *sec, offset, sym, addend, type, ieExpr); else @@ -159,7 +160,9 @@ public: void handleTlsDesc(RelExpr sharedExpr, RelExpr ieExpr, RelType type, uint64_t offset, int64_t addend, Symbol &sym) { if (ctx.arg.shared) { - sym.setFlags(NEEDS_TLSDESC); + // NEEDS_TLSDESC_NONAUTH is a no-op for non-AArch64 targets and detects + // incompatibility with NEEDS_TLSDESC_AUTH. + sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_NONAUTH); sec->addReloc({sharedExpr, type, offset, addend, &sym}); } else if (sym.isPreemptible) { // Optimize to Initial Exec. diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index e19fb24f469d..f0015580fc7b 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -134,10 +134,8 @@ static bool needsPlt(RelExpr expr) { } bool lld::elf::needsGot(RelExpr expr) { - return oneof( expr); } @@ -843,13 +841,11 @@ bool RelocScan::isStaticLinkTimeConstant(RelExpr e, RelType type, // These expressions always compute a constant if (oneof(e)) + RE_RISCV_ADD, RE_AARCH64_GOT_PAGE, RE_LOONGARCH_PLT_PAGE_PC, + RE_LOONGARCH_GOT, RE_LOONGARCH_GOT_PAGE_PC>(e)) return true; // These never do, except if the entire file is position dependent or if @@ -960,11 +956,7 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset, } else if (!sym.isTls() || ctx.arg.emachine != EM_LOONGARCH) { // Many LoongArch TLS relocs reuse the RE_LOONGARCH_GOT type, in which // case the NEEDS_GOT flag shouldn't get set. - if (expr == RE_AARCH64_AUTH_GOT || expr == RE_AARCH64_AUTH_GOT_PAGE_PC || - expr == RE_AARCH64_AUTH_GOT_PC) - sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH); - else - sym.setFlags(NEEDS_GOT | NEEDS_GOT_NONAUTH); + sym.setFlags(NEEDS_GOT | NEEDS_GOT_NONAUTH); } } else if (needsPlt(expr)) { sym.setFlags(NEEDS_PLT); @@ -1131,27 +1123,6 @@ void RelocScan::processAux(RelExpr expr, RelType type, uint64_t offset, printLocation(diag, *sec, sym, offset); } -static unsigned handleAArch64PAuthTlsRelocation(InputSectionBase *sec, - RelExpr expr, RelType type, - uint64_t offset, Symbol &sym, - int64_t addend) { - // Do not optimize signed TLSDESC to LE/IE (as described in pauthabielf64). - // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#general-restrictions - // > PAUTHELF64 only supports the descriptor based TLS (TLSDESC). - if (oneof(expr)) { - sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_AUTH); - sec->addReloc({expr, type, offset, addend, &sym}); - return 1; - } - - // TLSDESC_CALL hint relocation should not be emitted by compiler with signed - // TLSDESC enabled. - if (expr == R_TLSDESC_CALL) - sym.setFlags(NEEDS_TLSDESC_NONAUTH); - - return 0; -} - // Notes about General Dynamic and Local Dynamic TLS models below. They may // require the generation of a pair of GOT entries that have associated dynamic // relocations. The pair of GOT entries created are of the form GOT[e0] Module @@ -1162,27 +1133,18 @@ static unsigned handleAArch64PAuthTlsRelocation(InputSectionBase *sec, unsigned RelocScan::handleTlsRelocation(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend) { - bool isAArch64 = ctx.arg.emachine == EM_AARCH64; - - if (isAArch64) - if (unsigned processed = handleAArch64PAuthTlsRelocation( - sec, expr, type, offset, sym, addend)) - return processed; - if (expr == R_TPREL || expr == R_TPREL_NEG) return checkTlsLe(offset, sym, type) ? 1 : 0; bool isRISCV = ctx.arg.emachine == EM_RISCV; - if (oneof(expr) && + if (oneof(expr) && ctx.arg.shared) { // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12_I,CALL} reference a label. Do not // set NEEDS_TLSDESC on the label. if (expr != R_TLSDESC_CALL) { - if (isAArch64) - sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_NONAUTH); - else if (!isRISCV || type == R_RISCV_TLSDESC_HI20) + if (!isRISCV || type == R_RISCV_TLSDESC_HI20) sym.setFlags(NEEDS_TLSDESC); sec->addReloc({expr, type, offset, addend, &sym}); } @@ -1256,9 +1218,9 @@ unsigned RelocScan::handleTlsRelocation(RelExpr expr, RelType type, return 1; } - if (oneof(expr)) { + if (oneof(expr)) { if (!execOptimize) { sym.setFlags(NEEDS_TLSGD); sec->addReloc({expr, type, offset, addend, &sym}); @@ -1282,8 +1244,8 @@ unsigned RelocScan::handleTlsRelocation(RelExpr expr, RelType type, return ctx.target->getTlsGdRelaxSkip(type); } - if (oneof(expr)) { + if (oneof(expr)) { // Initial-Exec relocs can be optimized to Local-Exec if the symbol is // locally defined. if (execOptimize && isLocalInExecutable) { diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h index 7966c050a166..d7233e3e7b27 100644 --- a/lld/ELF/Relocations.h +++ b/lld/ELF/Relocations.h @@ -94,15 +94,9 @@ enum RelExpr { // of a relocation type, there are some relocations whose semantics are // unique to a target. Such relocation are marked with RE_. RE_AARCH64_GOT_PAGE_PC, - RE_AARCH64_AUTH_GOT_PAGE_PC, RE_AARCH64_GOT_PAGE, - RE_AARCH64_AUTH_GOT, - RE_AARCH64_AUTH_GOT_PC, RE_AARCH64_PAGE_PC, - RE_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC, RE_AARCH64_TLSDESC_PAGE, - RE_AARCH64_AUTH_TLSDESC_PAGE, - RE_AARCH64_AUTH_TLSDESC, RE_AARCH64_AUTH, RE_ARM_PCA, RE_ARM_SBREL,