diff options
Diffstat (limited to 'lld/ELF/Arch/AArch64.cpp')
| -rw-r--r-- | lld/ELF/Arch/AArch64.cpp | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 5cf07029fa1d..df41a12f7454 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -37,10 +37,11 @@ public: RelType getDynRel(RelType type) const override; void writeGotPlt(uint8_t *buf, const Symbol &s) const override; void writePltHeader(uint8_t *buf) const override; - void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, - int32_t index, unsigned relOff) const override; + void writePlt(uint8_t *buf, const Symbol &sym, + uint64_t pltEntryAddr) const override; bool needsThunk(RelExpr expr, RelType type, const InputFile *file, - uint64_t branchAddr, const Symbol &s) const override; + uint64_t branchAddr, const Symbol &s, + int64_t a) const override; uint32_t getThunkSectionSpacing() const override; bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; bool usesOnlyLowPageBits(RelType type) const override; @@ -63,8 +64,9 @@ AArch64::AArch64() { symbolicRel = R_AARCH64_ABS64; tlsDescRel = R_AARCH64_TLSDESC; tlsGotRel = R_AARCH64_TLS_TPREL64; - pltEntrySize = 16; pltHeaderSize = 32; + pltEntrySize = 16; + ipltEntrySize = 16; defaultMaxPageSize = 65536; // Align to the 2 MiB page size (known as a superpage or huge page). @@ -212,9 +214,8 @@ void AArch64::writePltHeader(uint8_t *buf) const { relocateOne(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16); } -void AArch64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, - uint64_t pltEntryAddr, int32_t index, - unsigned relOff) const { +void AArch64::writePlt(uint8_t *buf, const Symbol &sym, + uint64_t pltEntryAddr) const { const uint8_t inst[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n])) 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))] @@ -223,6 +224,7 @@ void AArch64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, }; memcpy(buf, inst, sizeof(inst)); + uint64_t gotPltEntryAddr = sym.getGotPltVA(); relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21, getAArch64Page(gotPltEntryAddr) - getAArch64Page(pltEntryAddr)); relocateOne(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr); @@ -230,13 +232,18 @@ void AArch64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, } bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file, - uint64_t branchAddr, const Symbol &s) const { + uint64_t branchAddr, const Symbol &s, + int64_t a) const { + // If s is an undefined weak symbol and does not have a PLT entry then it + // will be resolved as a branch to the next instruction. + if (s.isUndefWeak() && !s.isInPlt()) + return false; // ELF for the ARM 64-bit architecture, section Call and Jump relocations // only permits range extension thunks for R_AARCH64_CALL26 and // R_AARCH64_JUMP26 relocation types. if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26) return false; - uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA() : s.getVA(); + uint64_t dst = expr == R_PLT_PC ? s.getPltVA() : s.getVA(a); return !inBranchRange(type, branchAddr, dst); } @@ -567,8 +574,8 @@ class AArch64BtiPac final : public AArch64 { public: AArch64BtiPac(); void writePltHeader(uint8_t *buf) const override; - void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, - int32_t index, unsigned relOff) const override; + void writePlt(uint8_t *buf, const Symbol &sym, + uint64_t pltEntryAddr) const override; private: bool btiHeader; // bti instruction needed in PLT Header @@ -589,8 +596,10 @@ AArch64BtiPac::AArch64BtiPac() { btiEntry = btiHeader && !config->shared; pacEntry = (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC); - if (btiEntry || pacEntry) + if (btiEntry || pacEntry) { pltEntrySize = 24; + ipltEntrySize = 24; + } } void AArch64BtiPac::writePltHeader(uint8_t *buf) const { @@ -627,9 +636,8 @@ void AArch64BtiPac::writePltHeader(uint8_t *buf) const { memcpy(buf + sizeof(pltData), nopData, sizeof(nopData)); } -void AArch64BtiPac::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, - uint64_t pltEntryAddr, int32_t index, - unsigned relOff) const { +void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym, + uint64_t pltEntryAddr) const { // The PLT entry is of the form: // [btiData] addrInst (pacBr | stdBr) [nopData] const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c @@ -654,6 +662,7 @@ void AArch64BtiPac::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, pltEntryAddr += sizeof(btiData); } + uint64_t gotPltEntryAddr = sym.getGotPltVA(); memcpy(buf, addrInst, sizeof(addrInst)); relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21, getAArch64Page(gotPltEntryAddr) - |
