diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index c4334a6b1a101..c64a0dbe8bd62 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -999,7 +999,11 @@ class AArch64BtiPac final : public AArch64 { private: bool btiHeader; // bti instruction needed in PLT Header and Entry - bool pacEntry; // autia1716 instruction needed in PLT Entry + enum { + PEK_NoAuth, + PEK_AuthHint, // use autia1716 instr for authenticated branch in PLT entry + PEK_Auth, // use braa instr for authenticated branch in PLT entry + } pacEntryKind; }; } // namespace @@ -1014,9 +1018,21 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) { // relocations. // The PAC PLT entries require dynamic loader support and this isn't known // from properties in the objects, so we use the command line flag. - pacEntry = ctx.arg.zPacPlt; + // By default we only use hint-space instructions, but if we detect the + // PAuthABI, which requires v8.3-A, we can use the non-hint space + // instructions. + + if (ctx.arg.zPacPlt) { + if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo, + [](uint8_t c) { return c != 0; })) + pacEntryKind = PEK_Auth; + else + pacEntryKind = PEK_AuthHint; + } else { + pacEntryKind = PEK_NoAuth; + } - if (btiHeader || pacEntry) { + if (btiHeader || (pacEntryKind != PEK_NoAuth)) { pltEntrySize = 24; ipltEntrySize = 24; } @@ -1066,9 +1082,13 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym, 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.got.plt[n]))] 0x10, 0x02, 0x00, 0x91 // add x16, x16, Offset(&(.got.plt[n])) }; + const uint8_t pacHintBr[] = { + 0x9f, 0x21, 0x03, 0xd5, // autia1716 + 0x20, 0x02, 0x1f, 0xd6 // br x17 + }; const uint8_t pacBr[] = { - 0x9f, 0x21, 0x03, 0xd5, // autia1716 - 0x20, 0x02, 0x1f, 0xd6 // br x17 + 0x30, 0x0a, 0x1f, 0xd7, // braa x17, x16 + 0x1f, 0x20, 0x03, 0xd5 // nop }; const uint8_t stdBr[] = { 0x20, 0x02, 0x1f, 0xd6, // br x17 @@ -1096,8 +1116,10 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym, relocateNoSym(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr); relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr); - if (pacEntry) - memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr)); + if (pacEntryKind != PEK_NoAuth) + memcpy(buf + sizeof(addrInst), + pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr, + sizeof(pacEntryKind == PEK_AuthHint ? pacHintBr : pacBr)); else memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr)); if (!hasBti) diff --git a/lld/test/ELF/aarch64-feature-pauth.s b/lld/test/ELF/aarch64-feature-pauth.s index 3150c130d460f..c50f38f4a7c97 100644 --- a/lld/test/ELF/aarch64-feature-pauth.s +++ b/lld/test/ELF/aarch64-feature-pauth.s @@ -56,8 +56,8 @@ # PACPLTTAG: 0x0000000070000003 (AARCH64_PAC_PLT) -# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefix PACPLT -DA=10380 -DB=478 -DC=480 %s -# RUN: llvm-objdump -d pacplt-warn | FileCheck --check-prefix PACPLT -DA=10390 -DB=488 -DC=490 %s +# RUN: llvm-objdump -d pacplt-nowarn | FileCheck --check-prefixes=PACPLT,NOHINT -DA=10380 -DB=478 -DC=480 %s +# RUN: llvm-objdump -d pacplt-warn | FileCheck --check-prefixes=PACPLT,HINT -DA=10390 -DB=488 -DC=490 %s # PACPLT: Disassembly of section .text: # PACPLT: : @@ -77,8 +77,10 @@ # PACPLT-NEXT: adrp x16, 0x30000 # PACPLT-NEXT: ldr x17, [x16, #0x[[C]]] # PACPLT-NEXT: add x16, x16, #0x[[C]] -# PACPLT-NEXT: autia1716 -# PACPLT-NEXT: br x17 +# NOHINT-NEXT: braa x17, x16 +# NOHINT-NEXT: nop +# HINT-NEXT: autia1716 +# HINT-NEXT: br x17 # PACPLT-NEXT: nop #--- abi-tag-short.s