[lld] [LLD] Add flag to force PLT entries to have a BTI (PR #168365)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 17 05:29:03 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
Author: Gergely Bálint (bgergely0)
<details>
<summary>Changes</summary>
Added the `--force-bti-plt` flag to make sure the PacBtiPlts have a `BTI c` landing pad regardless of indirect calls inside the linked binary.
Post-link optimizations may require adding new thunks. Having this flag would simplify these optimizations by requiring less patching by tools.
Note that always adding a `BTI c` to PLT stubs is the default behaviour for GNU BFD.
---
Full diff: https://github.com/llvm/llvm-project/pull/168365.diff
5 Files Affected:
- (modified) lld/ELF/Arch/AArch64.cpp (+2-2)
- (modified) lld/ELF/Config.h (+1)
- (modified) lld/ELF/Driver.cpp (+1)
- (modified) lld/ELF/Options.td (+2)
- (modified) lld/test/ELF/aarch64-feature-bti.s (+7)
``````````diff
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 2a97df4785ecb..a9702fde05b9b 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -1186,8 +1186,8 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
// address may escape if referenced by a direct relocation. If relative
// vtables are used then if the vtable is in a shared object the offsets will
// be to the PLT entry. The condition is conservative.
- bool hasBti = btiHeader &&
- (sym.hasFlag(NEEDS_COPY) || sym.isInIplt || sym.thunkAccessed);
+ bool hasBti = btiHeader && (sym.hasFlag(NEEDS_COPY) || sym.isInIplt ||
+ sym.thunkAccessed || ctx.arg.forceBtiPlt);
if (hasBti) {
memcpy(buf, btiData, sizeof(btiData));
buf += sizeof(btiData);
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 8ec5a2c04e71c..b1060bf165ac8 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -330,6 +330,7 @@ struct Config {
bool exportDynamic;
bool fixCortexA53Errata843419;
bool fixCortexA8;
+ bool forceBtiPlt = false;
bool formatBinary = false;
bool fortranCommon;
bool gcSections;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 8647752be31fe..14c6b6f8a1dad 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1486,6 +1486,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
ctx.arg.nmagic = args.hasFlag(OPT_nmagic, OPT_no_nmagic, false);
ctx.arg.noinhibitExec = args.hasArg(OPT_noinhibit_exec);
ctx.arg.nostdlib = args.hasArg(OPT_nostdlib);
+ ctx.arg.forceBtiPlt = args.hasArg(OPT_bti_plt);
ctx.arg.oFormatBinary = isOutputFormatBinary(ctx, args);
ctx.arg.omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false);
ctx.arg.optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 75184de496448..2059e0c62d748 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -212,6 +212,8 @@ defm eh_frame_hdr: B<"eh-frame-hdr",
def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">;
+def bti_plt: FF<"force-bti-plt">, HelpText<"Force all PLT entries to have BTI">;
+
def enable_new_dtags: F<"enable-new-dtags">,
HelpText<"Enable new dynamic tags (default)">;
diff --git a/lld/test/ELF/aarch64-feature-bti.s b/lld/test/ELF/aarch64-feature-bti.s
index 8d7c1f2826c17..191e3710054f8 100644
--- a/lld/test/ELF/aarch64-feature-bti.s
+++ b/lld/test/ELF/aarch64-feature-bti.s
@@ -262,6 +262,13 @@
# REPORT-ERR: error: unknown -z bti-report= value: u{{$}}
# REPORT-EMPTY:
+## Force all PLT entries to start with BTI with the force-bti-plt command line option.
+# RUN: ld.lld %t.o %t2.o -z force-bti --force-bti-plt %t.so -o %tforcebtiplt.exe
+# RUN: llvm-objdump --no-print-imm-hex -d --mattr=+bti --no-show-raw-insn %tforcebtiplt.exe | FileCheck --check-prefix=FORCE-BTI %s
+
+# FORCE-BTI: 00000000002103a0 <func2 at plt>:
+# FORCE-BTI-NEXT: 2103a0: bti c
+
.section ".note.gnu.property", "a"
.long 4
.long 0x10
``````````
</details>
https://github.com/llvm/llvm-project/pull/168365
More information about the llvm-commits
mailing list