From b6162622c054fa74a7f2588df00059475f112212 Mon Sep 17 00:00:00 2001 From: Daniel Kiss Date: Tue, 18 Feb 2020 09:53:39 +0100 Subject: [PATCH] [LLD][ELF][AArch64] Change the semantics of -z pac-plt. Summary: Generate PAC protected plt only when "-z pac-plt" is passed to the linker. GNU toolchain generates when it is explicitly requested[1]. When pac-plt is requested then set the GNU_PROPERTY_AARCH64_FEATURE_1_PAC note even when not all function compiled with PAC but issue a warning. Harmonizing the warning style for BTI/PAC/IBT. Generate BTI protected PLT if case of "-z force-bti". [1] https://www.sourceware.org/ml/binutils/2019-03/msg00021.html Reviewers: peter.smith, espindola, MaskRay, grimar Reviewed By: peter.smith, MaskRay Subscribers: tatyana-krasnukha, emaste, arichardson, kristof.beyls, MaskRay, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D74537 --- lld/ELF/Arch/AArch64.cpp | 4 ++- lld/ELF/Driver.cpp | 12 ++++--- lld/ELF/SyntheticSections.cpp | 2 +- lld/test/ELF/aarch64-feature-bti.s | 2 +- lld/test/ELF/aarch64-feature-btipac.s | 65 ++++++++++++++++++++++++++--------- lld/test/ELF/aarch64-feature-pac.s | 33 +++++++++--------- 6 files changed, 76 insertions(+), 42 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 7231707..3245163 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -601,8 +601,10 @@ AArch64BtiPac::AArch64BtiPac() { // the function in an executable being taken by a shared library. // FIXME: There is a potential optimization to omit the BTI if we detect // that the address of the PLT entry isn't taken. + // 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. btiEntry = btiHeader && !config->shared; - pacEntry = (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC); + pacEntry = config->zPacPlt; if (btiEntry || pacEntry) { pltEntrySize = 24; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 021895a..06512e2 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1736,7 +1736,8 @@ template static uint32_t getAndFeatures() { for (InputFile *f : objectFiles) { uint32_t features = cast>(f)->andFeatures; if (config->zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) { - warn(toString(f) + ": -z force-bti: file does not have BTI property"); + warn(toString(f) + ": -z force-bti: file does not have " + "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property"); features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI; } else if (config->zForceIbt && !(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) { @@ -1744,13 +1745,14 @@ template static uint32_t getAndFeatures() { "GNU_PROPERTY_X86_FEATURE_1_IBT property"); features |= GNU_PROPERTY_X86_FEATURE_1_IBT; } + if (config->zPacPlt && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) { + warn(toString(f) + ": -z pac-plt: file does not have " + "GNU_PROPERTY_AARCH64_FEATURE_1_PAC property"); + features |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC; + } ret &= features; } - // Force enable pointer authentication Plt, we don't warn in this case as - // this does not require support in the object for correctness. - if (config->zPacPlt) - ret |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC; // Force enable Shadow Stack. if (config->zShstk) ret |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 3a0251c..8fede22 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1401,7 +1401,7 @@ template void DynamicSection::finalizeContents() { if (config->emachine == EM_AARCH64) { if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) addInt(DT_AARCH64_BTI_PLT, 0); - if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) + if (config->zPacPlt) addInt(DT_AARCH64_PAC_PLT, 0); } diff --git a/lld/test/ELF/aarch64-feature-bti.s b/lld/test/ELF/aarch64-feature-bti.s index cbaf17b..e1a7f51 100644 --- a/lld/test/ELF/aarch64-feature-bti.s +++ b/lld/test/ELF/aarch64-feature-bti.s @@ -174,7 +174,7 @@ # RUN: ld.lld %t.o %t2.o -z force-bti %t.so -o %tforcebti.exe 2>&1 | FileCheck --check-prefix=FORCE-WARN %s -# FORCE-WARN: aarch64-feature-bti.s.tmp2.o: -z force-bti: file does not have BTI property +# FORCE-WARN: aarch64-feature-bti.s.tmp2.o: -z force-bti: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property # RUN: llvm-readelf -n %tforcebti.exe | FileCheck --check-prefix=BTIPROP %s diff --git a/lld/test/ELF/aarch64-feature-btipac.s b/lld/test/ELF/aarch64-feature-btipac.s index 17f8487..f41412c 100644 --- a/lld/test/ELF/aarch64-feature-btipac.s +++ b/lld/test/ELF/aarch64-feature-btipac.s @@ -25,32 +25,30 @@ # BTIPACSO-NEXT: 10360: bti c # BTIPACSO-NEXT: stp x16, x30, [sp, #-16]! # BTIPACSO-NEXT: adrp x16, #131072 -# BTIPACSO-NEXT: ldr x17, [x16, #1160] -# BTIPACSO-NEXT: add x16, x16, #1160 +# BTIPACSO-NEXT: ldr x17, [x16, #1136] +# BTIPACSO-NEXT: add x16, x16, #1136 # BTIPACSO-NEXT: br x17 # BTIPACSO-NEXT: nop # BTIPACSO-NEXT: nop # BTIPACSO: 0000000000010380 func3@plt: # BTIPACSO-NEXT: 10380: adrp x16, #131072 -# BTIPACSO-NEXT: ldr x17, [x16, #1168] -# BTIPACSO-NEXT: add x16, x16, #1168 -# BTIPACSO-NEXT: autia1716 +# BTIPACSO-NEXT: ldr x17, [x16, #1144] +# BTIPACSO-NEXT: add x16, x16, #1144 # BTIPACSO-NEXT: br x17 -# BTIPACSO-NEXT: nop # BTIPACPROP: Properties: aarch64 feature: BTI, PAC # BTIPACDYN: 0x0000000070000001 (AARCH64_BTI_PLT) -# BTIPACDYN: 0x0000000070000003 (AARCH64_PAC_PLT) +# BTIPACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) ## Make an executable with both BTI and PAC properties. Expect: ## PLT[0] bti c as first instruction -## PLT[n] bti n as first instruction, autia1716 before br x17 +## PLT[n] bti n as first instruction # RUN: ld.lld %t.o %t3btipac.o %t.so -o %t.exe # RUN: llvm-readelf -n %t.exe | FileCheck --check-prefix=BTIPACPROP %s # RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix BTIPACEX %s -# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYN %s +# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYNEX %s # BTIPACEX: Disassembly of section .text: # BTIPACEX: 0000000000210370 func1: @@ -64,19 +62,21 @@ # BTIPACEX-NEXT: 210380: bti c # BTIPACEX-NEXT: stp x16, x30, [sp, #-16]! # BTIPACEX-NEXT: adrp x16, #131072 -# BTIPACEX-NEXT: ldr x17, [x16, #1208] -# BTIPACEX-NEXT: add x16, x16, #1208 +# BTIPACEX-NEXT: ldr x17, [x16, #1192] +# BTIPACEX-NEXT: add x16, x16, #1192 # BTIPACEX-NEXT: br x17 # BTIPACEX-NEXT: nop # BTIPACEX-NEXT: nop # BTIPACEX: 00000000002103a0 func2@plt: # BTIPACEX-NEXT: 2103a0: bti c # BTIPACEX-NEXT: adrp x16, #131072 -# BTIPACEX-NEXT: ldr x17, [x16, #1216] -# BTIPACEX-NEXT: add x16, x16, #1216 -# BTIPACEX-NEXT: autia1716 +# BTIPACEX-NEXT: ldr x17, [x16, #1200] +# BTIPACEX-NEXT: add x16, x16, #1200 # BTIPACEX-NEXT: br x17 +# BTIPACDYNEX: 0x0000000070000001 (AARCH64_BTI_PLT) +# BTIPACDYNEX-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) + ## Check that combinations of BTI+PAC with 0 properties results in standard PLT # RUN: ld.lld %t.o %t3.o %t.so -o %t.exe @@ -112,14 +112,17 @@ ## Check that combination of -z pac-plt and -z force-bti warns for the file that ## doesn't contain the BTI property, but generates PAC and BTI PLT sequences. ## The -z pac-plt doesn't warn as it is not required for correctness. +## Expect: +## PLT[0] bti c as first instruction +## PLT[n] bti n as first instruction, autia1716 before br x17 # RUN: ld.lld %t.o %t3.o %t.so -z pac-plt -z force-bti -o %t.exe 2>&1 | FileCheck --check-prefix=FORCE-WARN %s -# FORCE-WARN: aarch64-feature-btipac.s.tmp3.o: -z force-bti: file does not have BTI property +# FORCE-WARN: aarch64-feature-btipac.s.tmp3.o: -z force-bti: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property # RUN: llvm-readelf -n %t.exe | FileCheck --check-prefix=BTIPACPROP %s -# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix BTIPACEX %s -# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYN %s +# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix BTIPACEX2 %s +# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYN2 %s .section ".note.gnu.property", "a" .long 4 .long 0x10 @@ -140,3 +143,31 @@ func1: .globl func3 .type func3,%function ret + +# BTIPACEX2: Disassembly of section .text: +# BTIPACEX2: 0000000000210370 func1: +# BTIPACEX2-NEXT: 210370: bl #48 +# BTIPACEX2-NEXT: ret +# BTIPACEX2-NEXT: ret +# BTIPACEX2: 000000000021037c func3: +# BTIPACEX2-NEXT: 21037c: ret +# BTIPACEX2: Disassembly of section .plt: +# BTIPACEX2: 0000000000210380 .plt: +# BTIPACEX2-NEXT: 210380: bti c +# BTIPACEX2-NEXT: stp x16, x30, [sp, #-16]! +# BTIPACEX2-NEXT: adrp x16, #131072 +# BTIPACEX2-NEXT: ldr x17, [x16, #1208] +# BTIPACEX2-NEXT: add x16, x16, #1208 +# BTIPACEX2-NEXT: br x17 +# BTIPACEX2-NEXT: nop +# BTIPACEX2-NEXT: nop +# BTIPACEX2: 00000000002103a0 func2@plt: +# BTIPACEX2-NEXT: 2103a0: bti c +# BTIPACEX2-NEXT: adrp x16, #131072 +# BTIPACEX2-NEXT: ldr x17, [x16, #1216] +# BTIPACEX2-NEXT: add x16, x16, #1216 +# BTIPACEX2-NEXT: autia1716 +# BTIPACEX2-NEXT: br x17 + +# BTIPACDYN2: 0x0000000070000001 (AARCH64_BTI_PLT) +# BTIPACDYN2-NEXT: 0x0000000070000003 (AARCH64_PAC_PLT) \ No newline at end of file diff --git a/lld/test/ELF/aarch64-feature-pac.s b/lld/test/ELF/aarch64-feature-pac.s index 41c6cb6..9dd6129 100644 --- a/lld/test/ELF/aarch64-feature-pac.s +++ b/lld/test/ELF/aarch64-feature-pac.s @@ -32,6 +32,10 @@ # NOPAC-NEXT: add x16, x16, #968 # NOPAC-NEXT: br x17 +# SOGOTPLT: Hex dump of section '.got.plt': +# SOGOTPLT-NEXT: 0x000303b0 00000000 00000000 00000000 00000000 +# SOGOTPLT-NEXT: 0x000303c0 00000000 00000000 d0020100 00000000 + # NOPACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) # NOPACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) @@ -41,9 +45,7 @@ # RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT2 %s # RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix PACDYN %s -## PAC has no effect on PLT[0], for PLT[N] autia1716 is used to authenticate -## the address in x17 (context in x16) before branching to it. The dynamic -## loader is responsible for calling pacia1716 on the entry. +## PAC has no effect on PLT[0], for PLT[N]. # PACSO: 0000000000010348 func2: # PACSO-NEXT: 10348: bl #56 # PACSO-NEXT: ret @@ -53,32 +55,26 @@ # PACSO: 0000000000010360 .plt: # PACSO-NEXT: 10360: stp x16, x30, [sp, #-16]! # PACSO-NEXT: adrp x16, #131072 -# PACSO-NEXT: ldr x17, [x16, #1144] -# PACSO-NEXT: add x16, x16, #1144 +# PACSO-NEXT: ldr x17, [x16, #1120] +# PACSO-NEXT: add x16, x16, #1120 # PACSO-NEXT: br x17 # PACSO-NEXT: nop # PACSO-NEXT: nop # PACSO-NEXT: nop # PACSO: 0000000000010380 func3@plt: # PACSO-NEXT: 10380: adrp x16, #131072 -# PACSO-NEXT: ldr x17, [x16, #1152] -# PACSO-NEXT: add x16, x16, #1152 -# PACSO-NEXT: autia1716 +# PACSO-NEXT: ldr x17, [x16, #1128] +# PACSO-NEXT: add x16, x16, #1128 # PACSO-NEXT: br x17 -# PACSO-NEXT: nop - -# SOGOTPLT: Hex dump of section '.got.plt': -# SOGOTPLT-NEXT: 0x000303b0 00000000 00000000 00000000 00000000 -# SOGOTPLT-NEXT: 0x000303c0 00000000 00000000 d0020100 00000000 # SOGOTPLT2: Hex dump of section '.got.plt': -# SOGOTPLT2-NEXT: 0x00030468 00000000 00000000 00000000 00000000 -# SOGOTPLT2-NEXT: 0x00030478 00000000 00000000 60030100 00000000 +# SOGOTPLT2-NEXT: 0x00030450 00000000 00000000 00000000 00000000 +# SOGOTPLT2-NEXT: 0x00030460 00000000 00000000 60030100 00000000 # PACPROP: Properties: aarch64 feature: PAC # PACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) -# PACDYN: 0x0000000070000003 (AARCH64_PAC_PLT) +# PACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT) ## Turn on PAC entries with the -z pac-plt command line option. There are no ## warnings in this case as the choice to use PAC in PLT entries is orthogonal @@ -87,7 +83,7 @@ # RUN: ld.lld %t.o %t2.o -z pac-plt %t.so -o %tpacplt.exe # RUN: llvm-readelf -n %tpacplt.exe | FileCheck --check-prefix=PACPROP %s -# RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN %s +# RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN2 %s # RUN: llvm-objdump -d -mattr=+v8.3a --no-show-raw-insn %tpacplt.exe | FileCheck --check-prefix PACPLT %s # PACPLT: Disassembly of section .text: @@ -114,6 +110,9 @@ # PACPLT-NEXT: br x17 # PACPLT-NEXT: nop +# PACDYN2-NOT: 0x0000000070000001 (AARCH64_BTI_PLT) +# PACDYN2: 0x0000000070000003 (AARCH64_PAC_PLT) + .section ".note.gnu.property", "a" .long 4 .long 0x10 -- 2.7.4