Skip to content

[LLD][ELF][AArch64] Mark .plt and .iplt with PURECODE flag #134798

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2594,6 +2594,11 @@ PltSection::PltSection(Ctx &ctx)
: SyntheticSection(ctx, ".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
16),
headerSize(ctx.target->pltHeaderSize) {
// On AArch64, PLT entries only do loads from the .got.plt section, so the
// .plt section can be marked with the SHF_AARCH64_PURECODE section flag.
if (ctx.arg.emachine == EM_AARCH64)
this->flags |= SHF_AARCH64_PURECODE;

// On PowerPC, this section contains lazy symbol resolvers.
if (ctx.arg.emachine == EM_PPC64) {
name = ".glink";
Expand Down Expand Up @@ -2654,6 +2659,11 @@ void PltSection::addSymbols() {
IpltSection::IpltSection(Ctx &ctx)
: SyntheticSection(ctx, ".iplt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
16) {
// On AArch64, PLT entries only do loads from the .got.plt section, so the
// .iplt section can be marked with the SHF_AARCH64_PURECODE section flag.
if (ctx.arg.emachine == EM_AARCH64)
this->flags |= SHF_AARCH64_PURECODE;

if (ctx.arg.emachine == EM_PPC || ctx.arg.emachine == EM_PPC64) {
name = ".glink";
addralign = 4;
Expand Down
35 changes: 35 additions & 0 deletions lld/test/ELF/aarch64-execute-only-plt.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// REQUIRES: aarch64

// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %S/Inputs/plt-aarch64.s -o %t2.o
// RUN: ld.lld -shared %t2.o -soname=t2.so -o %t2.so
// RUN: ld.lld %t.o %t2.so -o %t
// RUN: llvm-readelf -S -l %t | FileCheck %s

// CHECK-LABEL: Section Headers:
// CHECK: .text PROGBITS 00000000002102a0 0002a0 000010 00 AXy 0 0 4
// CHECK: .plt PROGBITS 00000000002102b0 0002b0 000030 00 AXy 0 0 16
// CHECK: .iplt PROGBITS 00000000002102e0 0002e0 000010 00 AXy 0 0 16

// CHECK-LABEL: Program Headers:
// CHECK: PHDR
// CHECK-NEXT: LOAD
// CHECK-NEXT: LOAD 0x0002a0 0x00000000002102a0 0x00000000002102a0 0x000050 0x000050 E 0x10000

// CHECK-LABEL: Section to Segment mapping:
/// Index should match the index of the LOAD segment above.
// CHECK: 02 .text .plt .iplt

.global bar

.section .text,"axy",@progbits,unique,0
.global _start
_start:
bl foo
bl bar
ret

.globl foo
.type foo STT_GNU_IFUNC
foo:
ret
36 changes: 19 additions & 17 deletions lld/test/ELF/aarch64-gnu-ifunc-plt.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,34 @@
// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout
// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %tout | FileCheck %s --check-prefix=DISASM
// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
// RUN: llvm-readobj --dynamic-table -r %tout | FileCheck %s
// RUN: llvm-readelf -S --dynamic-table -r %tout | FileCheck %s

// RUN: llvm-mc -filetype=obj -triple=aarch64_be %S/Inputs/shared2.s -o %t1.be.o
// RUN: ld.lld %t1.be.o --shared --soname=t.so -o %t.be.so
// RUN: llvm-mc -filetype=obj -triple=aarch64_be %s -o %t.be.o
// RUN: ld.lld --hash-style=sysv %t.be.so %t.be.o -o %t.be
// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t.be | FileCheck %s --check-prefix=DISASM
// RUN: llvm-objdump -s %t.be | FileCheck %s --check-prefix=GOTPLT_BE
// RUN: llvm-readobj --dynamic-table -r %t.be | FileCheck %s
// RUN: llvm-readelf -S --dynamic-table -r %t.be | FileCheck %s

// Check that the PLTRELSZ tag does not include the IRELATIVE relocations
// CHECK: DynamicSection [
// CHECK: 0x0000000000000008 RELASZ 48 (bytes)
// CHECK: 0x0000000000000002 PLTRELSZ 48 (bytes)
// CHECK-LABEL: Section Headers:
/// Name Type Address Off Size ES Flg Lk Inf Al
// CHECK: .iplt PROGBITS 0000000000210330 000330 000020 00 AXy 0 0 16

// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt
// CHECK: Relocations [
// CHECK-NEXT: Section (4) .rela.dyn {
// CHECK-NEXT: 0x230468 R_AARCH64_IRELATIVE - 0x2102D8
// CHECK-NEXT: 0x230470 R_AARCH64_IRELATIVE - 0x2102DC
// CHECK-NEXT: }
// CHECK-NEXT: Section (5) .rela.plt {
// CHECK-NEXT: 0x230458 R_AARCH64_JUMP_SLOT bar2 0x0
// CHECK-NEXT: 0x230460 R_AARCH64_JUMP_SLOT zed2 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
/// Check that the PLTRELSZ tag does not include the IRELATIVE relocations
// CHECK-LABEL: Dynamic section at offset 0x350 contains 15 entries:
// CHECK: 0x0000000000000008 (RELASZ) 48 (bytes)
// CHECK: 0x0000000000000002 (PLTRELSZ) 48 (bytes)

/// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt
// CHECK-LABEL: Relocation section '.rela.dyn' at offset 0x278 contains 2 entries:
// CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
// CHECK-NEXT: 0000000000230468 0000000000000408 R_AARCH64_IRELATIVE 2102d8
// CHECK-NEXT: 0000000000230470 0000000000000408 R_AARCH64_IRELATIVE 2102dc
// CHECK-LABEL: Relocation section '.rela.plt' at offset 0x2a8 contains 2 entries:
// CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
// CHECK-NEXT: 0000000000230458 0000000100000402 R_AARCH64_JUMP_SLOT 0000000000000000 bar2 + 0
// CHECK-NEXT: 0000000000230460 0000000200000402 R_AARCH64_JUMP_SLOT 0000000000000000 zed2 + 0

// Check that .got.plt entries point back to PLT header
// GOTPLT: Contents of section .got.plt:
Expand Down
103 changes: 26 additions & 77 deletions lld/test/ELF/aarch64-plt.s
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,26 @@
// RUN: ld.lld -shared %t2.o -soname=t2.so -o %t2.so
// RUN: ld.lld -shared %t.o %t2.so -o %t.so
// RUN: ld.lld %t.o %t2.so -o %t.exe
// RUN: llvm-readobj -S -r %t.so | FileCheck --check-prefix=CHECKDSO %s
// RUN: llvm-readelf -S -r %t.so | FileCheck --check-prefix=CHECKDSO %s
// RUN: llvm-objdump -s --section=.got.plt %t.so | FileCheck --check-prefix=DUMPDSO %s
// RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t.so | FileCheck --check-prefix=DISASMDSO %s
// RUN: llvm-readobj -S -r %t.exe | FileCheck --check-prefix=CHECKEXE %s
// RUN: llvm-readelf -S -r %t.exe | FileCheck --check-prefix=CHECKEXE %s
// RUN: llvm-objdump -s --section=.got.plt %t.exe | FileCheck --check-prefix=DUMPEXE %s
// RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t.exe | FileCheck --check-prefix=DISASMEXE %s

// CHECKDSO: Name: .plt
// CHECKDSO-NEXT: Type: SHT_PROGBITS
// CHECKDSO-NEXT: Flags [
// CHECKDSO-NEXT: SHF_ALLOC
// CHECKDSO-NEXT: SHF_EXECINSTR
// CHECKDSO-NEXT: ]
// CHECKDSO-NEXT: Address: 0x10340
// CHECKDSO-NEXT: Offset:
// CHECKDSO-NEXT: Size: 80
// CHECKDSO-NEXT: Link:
// CHECKDSO-NEXT: Info:
// CHECKDSO-NEXT: AddressAlignment: 16

// CHECKDSO: Name: .got.plt
// CHECKDSO-NEXT: Type: SHT_PROGBITS
// CHECKDSO-NEXT: Flags [
// CHECKDSO-NEXT: SHF_ALLOC
// CHECKDSO-NEXT: SHF_WRITE
// CHECKDSO-NEXT: ]
// CHECKDSO-NEXT: Address: 0x30450
// CHECKDSO-NEXT: Offset:
// CHECKDSO-NEXT: Size: 48
// CHECKDSO-NEXT: Link:
// CHECKDSO-NEXT: Info:
// CHECKDSO-NEXT: AddressAlignment: 8

// CHECKDSO: Relocations [
// CHECKDSO-NEXT: Section ({{.*}}) .rela.plt {

// &(.got.plt[3]) = 0x30450 + 3 * 8 = 0x30468
// CHECKDSO-NEXT: 0x30468 R_AARCH64_JUMP_SLOT foo

// &(.got.plt[4]) = 0x30450 + 4 * 8 = 0x30470
// CHECKDSO-NEXT: 0x30470 R_AARCH64_JUMP_SLOT bar

// &(.got.plt[5]) = 0x30000 + 5 * 8 = 0x30470
// CHECKDSO-NEXT: 0x30478 R_AARCH64_JUMP_SLOT weak
// CHECKDSO-NEXT: }
// CHECKDSO-NEXT: ]
// CHECKDSO-LABEL: Section Headers:
/// Name Type Address Off Size ES Flg Lk Inf Al
// CHECKDSO: .plt PROGBITS 0000000000010340 000340 000050 00 AXy 0 0 16
// CHECKDSO: .got.plt PROGBITS 0000000000030450 000450 000030 00 WA 0 0 8

// CHECKDSO-LABEL: Relocation section '.rela.plt' at offset 0x2e8 contains 3 entries:
// CHECKDSO-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
/// &(.got.plt[3]) = 0x30450 + 3 * 8 = 0x30468
// CHECKDSO-NEXT: 0000000000030468 0000000400000402 R_AARCH64_JUMP_SLOT 000000000001033c foo + 0
/// &(.got.plt[4]) = 0x30450 + 4 * 8 = 0x30470
// CHECKDSO-NEXT: 0000000000030470 0000000100000402 R_AARCH64_JUMP_SLOT 0000000000000000 bar + 0
/// &(.got.plt[5]) = 0x30000 + 5 * 8 = 0x30478
// CHECKDSO-NEXT: 0000000000030478 0000000200000402 R_AARCH64_JUMP_SLOT 0000000000000000 weak + 0

// DUMPDSO: Contents of section .got.plt:
// .got.plt[0..2] = 0 (reserved)
Expand Down Expand Up @@ -106,42 +80,17 @@
// DISASMDSO-NEXT: 10388: add x16, x16, #0x478
// DISASMDSO-NEXT: 1038c: br x17

// CHECKEXE: Name: .plt
// CHECKEXE-NEXT: Type: SHT_PROGBITS
// CHECKEXE-NEXT: Flags [
// CHECKEXE-NEXT: SHF_ALLOC
// CHECKEXE-NEXT: SHF_EXECINSTR
// CHECKEXE-NEXT: ]
// CHECKEXE-NEXT: Address: 0x2102E0
// CHECKEXE-NEXT: Offset:
// CHECKEXE-NEXT: Size: 64
// CHECKEXE-NEXT: Link:
// CHECKEXE-NEXT: Info:
// CHECKEXE-NEXT: AddressAlignment: 16

// CHECKEXE: Name: .got.plt
// CHECKEXE-NEXT: Type: SHT_PROGBITS
// CHECKEXE-NEXT: Flags [
// CHECKEXE-NEXT: SHF_ALLOC
// CHECKEXE-NEXT: SHF_WRITE
// CHECKEXE-NEXT: ]
// CHECKEXE-NEXT: Address: 0x2303F0
// CHECKEXE-NEXT: Offset:
// CHECKEXE-NEXT: Size: 40
// CHECKEXE-NEXT: Link:
// CHECKEXE-NEXT: Info:
// CHECKEXE-NEXT: AddressAlignment: 8

// CHECKEXE: Relocations [
// CHECKEXE-NEXT: Section ({{.*}}) .rela.plt {

// &(.got.plt[3]) = 0x2303f0 + 3 * 8 = 0x230408
// CHECKEXE-NEXT: 0x230408 R_AARCH64_JUMP_SLOT bar 0x0

// &(.got.plt[4]) = 0x2303f0 + 4 * 8 = 0x230410
// CHECKEXE-NEXT: 0x230410 R_AARCH64_JUMP_SLOT weak 0x0
// CHECKEXE-NEXT: }
// CHECKEXE-NEXT: ]
// CHECKEXE-LABEL: Section Headers:
/// Name Type Address Off Size ES Flg Lk Inf Al
// CHECKEXE: .plt PROGBITS 00000000002102e0 0002e0 000040 00 AXy 0 0 16
// CHECKEXE: .got.plt PROGBITS 00000000002303f0 0003f0 000028 00 WA 0 0 8

// CHECKEXE-LABEL: Relocation section '.rela.plt' at offset 0x298 contains 2 entries:
// CHECKEXE-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
/// &(.got.plt[3]) = 0x2303f0 + 3 * 8 = 0x230408
// CHECKEXE-NEXT: 0000000000230408 0000000100000402 R_AARCH64_JUMP_SLOT 0000000000000000 bar + 0
/// &(.got.plt[4]) = 0x2303f0 + 4 * 8 = 0x230410
// CHECKEXE-NEXT: 0000000000230410 0000000200000402 R_AARCH64_JUMP_SLOT 0000000000000000 weak + 0

// DUMPEXE: Contents of section .got.plt:
// .got.plt[0..2] = 0 (reserved)
Expand Down