mirror of
https://github.com/rui314/mold.git
synced 2026-11-07 09:16:04 -10:00
Start the ARM64 PLT header with bti c regardless of BTI
PLT entries jump to the PLT header with an indirect branch, so the header needs a landing pad if BTI is enabled. Like the x86-64 PLT header, which starts with endbr64 whether or not IBT is enabled, we now always write `bti c` to it. The header runs only when a symbol is resolved lazily, so the extra instruction doesn't matter. PLT entries are on the hot path and still get one only if BTI is enabled.
This commit is contained in:
1 parent
7f6d60fb80
commit
7866fb4799
2 files changed
+15
-12
No files matched your search
+11
-11
@@ -210,8 +210,13 @@ impl<const LE: bool> Target for Arm64Target<LE> {
|
||||
32 + idx as u64 * Self::plt_entry_size(ctx)
|
||||
}
|
||||
|
||||
// PLT entries jump to the header with an indirect branch, so the header
|
||||
// starts with a BTI landing pad. We write it even if BTI is disabled, in
|
||||
// which case `bti c` is a no-op, because the header is executed only when
|
||||
// a symbol is resolved lazily.
|
||||
fn write_plt_header(ctx: &Context<Self>, buf: &mut [u8]) {
|
||||
const INSN: [u32; 8] = [
|
||||
0xd503_245f, // bti c
|
||||
0xa9bf_7bf0, // stp x16, x30, [sp,#-16]!
|
||||
0x9000_0010, // adrp x16, .got.plt[2]
|
||||
0xf940_0211, // ldr x17, [x16, .got.plt[2]]
|
||||
@@ -219,20 +224,15 @@ impl<const LE: bool> Target for Arm64Target<LE> {
|
||||
0xd61f_0220, // br x17
|
||||
0xd420_7d00, // brk
|
||||
0xd420_7d00, // brk
|
||||
0xd420_7d00, // brk
|
||||
];
|
||||
// PLT entries jump to the header with an indirect branch. A landing
|
||||
// pad, if any, replaces one of the trailing brks.
|
||||
let off = write_landing_pad(buf, note_property::is_bti(ctx));
|
||||
let buf = &mut buf[off..32];
|
||||
for (loc, &v) in buf.chunks_exact_mut(4).zip(&INSN) {
|
||||
write_ul32(loc, v);
|
||||
for (i, &v) in INSN.iter().enumerate() {
|
||||
write_ul32(&mut buf[i * 4..], v);
|
||||
}
|
||||
let gotplt = ctx.gotplt.shdr.sh_addr.get() + 16;
|
||||
let plt = ctx.plt.hdr.shdr.sh_addr.get() + off as u64;
|
||||
write_adrp(&mut buf[4..], page(gotplt).wrapping_sub(page(plt + 4)));
|
||||
or_insn(&mut buf[8..], (bits(gotplt, 11, 3) << 10) as u32);
|
||||
or_insn(&mut buf[12..], ((gotplt & 0xfff) << 10) as u32);
|
||||
let plt = ctx.plt.hdr.shdr.sh_addr.get();
|
||||
write_adrp(&mut buf[8..], page(gotplt).wrapping_sub(page(plt + 8)));
|
||||
or_insn(&mut buf[12..], (bits(gotplt, 11, 3) << 10) as u32);
|
||||
or_insn(&mut buf[16..], ((gotplt & 0xfff) << 10) as u32);
|
||||
}
|
||||
|
||||
// A PLT entry is 16 bytes long by default and 24 bytes long if BTI is
|
||||
|
||||
@@ -14,7 +14,10 @@ EOF
|
||||
|
||||
./mold -shared -o $t/c.so $t/a.o $t/b.o
|
||||
readelf -n $t/c.so | not grep 'AArch64 feature'
|
||||
$OBJDUMP -d -j .plt $t/c.so | grep -A1 '<_PROCEDURE_LINKAGE_TABLE_>:' | not grep -w bti
|
||||
readelf --dynamic $t/c.so | not grep AARCH64_BTI_PLT
|
||||
|
||||
# The PLT header starts with `bti c` even if BTI is disabled.
|
||||
$OBJDUMP -d -j .plt $t/c.so | grep -A1 '<_PROCEDURE_LINKAGE_TABLE_>:' | grep -w bti
|
||||
|
||||
./mold -shared -o $t/c.so $t/a.o $t/b.o -z force-bti 2> $t/log
|
||||
readelf -n $t/c.so | grep 'AArch64 feature: BTI'
|
||||
|
||||
Reference in new issue
Block a user