From cc6c7c482dc05baaea052aee638e86ae81540406 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Mon, 28 Oct 2024 21:23:54 +0300 Subject: [PATCH 1/3] [PAC][lld] Use braa instr in PAC PLT sequence with valid PAuth core info Assume PAC instructions being supported with PAuth core info different from (0,0). Given that, `autia1716; br x17` can be replaced with `braa x17, x16; nop`. --- lld/ELF/Arch/AArch64.cpp | 19 +++++++++++++++---- lld/test/ELF/aarch64-feature-pauth.s | 10 ++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index c4334a6b1a101..321bdb638ccab 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -999,7 +999,9 @@ class AArch64BtiPac final : public AArch64 { private: bool btiHeader; // bti instruction needed in PLT Header and Entry - bool pacEntry; // autia1716 instruction needed in PLT Entry + bool pacEntry; // Authenticated branch needed in PLT Entry + bool pacUseHint = + true; // Use hint space instructions for authenticated branch in PLT entry }; } // namespace @@ -1016,6 +1018,10 @@ AArch64BtiPac::AArch64BtiPac(Ctx &ctx) : AArch64(ctx) { // from properties in the objects, so we use the command line flag. pacEntry = ctx.arg.zPacPlt; + if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo, + [](uint8_t c) { return c != 0; })) + pacUseHint = false; + if (btiHeader || pacEntry) { pltEntrySize = 24; ipltEntrySize = 24; @@ -1066,9 +1072,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 @@ -1097,7 +1107,8 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym, relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr); if (pacEntry) - memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr)); + memcpy(buf + sizeof(addrInst), (pacUseHint ? pacHintBr : pacBr), + sizeof(pacUseHint ? 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 From 13875e750ef9e7784aedf1cda12a73ad33fb3544 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Fri, 1 Nov 2024 14:20:44 +0300 Subject: [PATCH 2/3] Address review comments --- lld/ELF/Arch/AArch64.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 321bdb638ccab..e76d53f2adaae 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -999,9 +999,11 @@ class AArch64BtiPac final : public AArch64 { private: bool btiHeader; // bti instruction needed in PLT Header and Entry - bool pacEntry; // Authenticated branch needed in PLT Entry - bool pacUseHint = - true; // Use hint space instructions for authenticated branch 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 @@ -1016,13 +1018,18 @@ 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; - if (llvm::any_of(ctx.aarch64PauthAbiCoreInfo, - [](uint8_t c) { return c != 0; })) - pacUseHint = false; + 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; } @@ -1106,9 +1113,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), (pacUseHint ? pacHintBr : pacBr), - sizeof(pacUseHint ? pacHintBr : 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) From 3d1670d893e0ae98ee96ad4a73272d86d3fb3c5d Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Sun, 10 Nov 2024 19:52:31 +0300 Subject: [PATCH 3/3] Add a comment --- lld/ELF/Arch/AArch64.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index e76d53f2adaae..c64a0dbe8bd62 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -1018,6 +1018,9 @@ 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. + // 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,