Skip to content

[LLD] Extend special OpenBSD support, but scope under ELFOSABI #97122

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 1 commit into from
Jul 12, 2024
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
2 changes: 2 additions & 0 deletions lld/ELF/ScriptParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1628,7 +1628,9 @@ unsigned ScriptParser::readPhdrType() {
.Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME)
.Case("PT_GNU_STACK", PT_GNU_STACK)
.Case("PT_GNU_RELRO", PT_GNU_RELRO)
.Case("PT_OPENBSD_MUTABLE", PT_OPENBSD_MUTABLE)
.Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE)
.Case("PT_OPENBSD_SYSCALLS", PT_OPENBSD_SYSCALLS)
.Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED)
.Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
.Default(-1);
Expand Down
34 changes: 26 additions & 8 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,10 +601,16 @@ static bool isRelroSection(const OutputSection *sec) {
// ELF in spirit. But in reality many linker features depend on
// magic section names.
StringRef s = sec->name;
return s == ".data.rel.ro" || s == ".bss.rel.ro" || s == ".ctors" ||
s == ".dtors" || s == ".jcr" || s == ".eh_frame" ||
s == ".fini_array" || s == ".init_array" ||
s == ".openbsd.randomdata" || s == ".preinit_array";

bool abiAgnostic = s == ".data.rel.ro" || s == ".bss.rel.ro" ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be fine to keep this unchanged. We can add the osabi check if the .openbsd.* list ever gets longer.

Copy link
Member Author

@Ericson2314 Ericson2314 Jul 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MaskRay I would sort of like to change it for consistency.

I ended up duplicating the test I had to change so we have a Linux and OpenBSD version, and this makes me feel better about coverage, etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(And checked locally that both the new tests worked, and the old test failed.)

s == ".ctors" || s == ".dtors" || s == ".jcr" ||
s == ".eh_frame" || s == ".fini_array" ||
s == ".init_array" || s == ".preinit_array";

bool abiSpecific =
config->osabi == ELFOSABI_OPENBSD && s == ".openbsd.randomdata";

return abiAgnostic || abiSpecific;
}

// We compute a rank for each section. The rank indicates where the
Expand Down Expand Up @@ -2273,10 +2279,22 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
addHdr(PT_GNU_EH_FRAME, part.ehFrameHdr->getParent()->getPhdrFlags())
->add(part.ehFrameHdr->getParent());

// PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes
// the dynamic linker fill the segment with random data.
if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo))
addHdr(PT_OPENBSD_RANDOMIZE, cmd->getPhdrFlags())->add(cmd);
if (config->osabi == ELFOSABI_OPENBSD) {
// PT_OPENBSD_MUTABLE makes the dynamic linker fill the segment with
// zero data, like bss, but it can be treated differently.
if (OutputSection *cmd = findSection(".openbsd.mutable", partNo))
addHdr(PT_OPENBSD_MUTABLE, cmd->getPhdrFlags())->add(cmd);

// PT_OPENBSD_RANDOMIZE makes the dynamic linker fill the segment
// with random data.
if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo))
addHdr(PT_OPENBSD_RANDOMIZE, cmd->getPhdrFlags())->add(cmd);

// PT_OPENBSD_SYSCALLS makes the kernel and dynamic linker register
// system call sites.
if (OutputSection *cmd = findSection(".openbsd.syscalls", partNo))
addHdr(PT_OPENBSD_SYSCALLS, cmd->getPhdrFlags())->add(cmd);
}

if (config->zGnustack != GnuStackKind::None) {
// PT_GNU_STACK is a special section to tell the loader to make the
Expand Down
8 changes: 6 additions & 2 deletions lld/test/ELF/openbsd-phdr.s
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=x86_64 randomdata.s -o randomdata.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-openbsd randomdata.s -o randomdata.o
# RUN: ld.lld randomdata.o -o randomdata
# RUN: llvm-readelf -S -l randomdata | FileCheck %s --check-prefix=RANDOMDATA

# RUN: llvm-mc -filetype=obj -triple=x86_64 /dev/null -o wxneeded.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-openbsd /dev/null -o wxneeded.o
# RUN: ld.lld -z wxneeded wxneeded.o -o wxneeded
# RUN: llvm-readelf -l wxneeded | FileCheck %s --check-prefix=WXNEEDED

Expand All @@ -20,6 +20,8 @@
# RANDOMDATA: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# RANDOMDATA: OPENBSD_RANDOMIZE 0x[[O]] 0x[[ADDR]] 0x[[ADDR]] 0x000008 0x000008 R 0x1
# CHECK-NEXT: OPENBSD_BOOTDATA 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 R 0
# CHECK-NEXT: OPENBSD_MUTABLE 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 R 0
# CHECK-NEXT: OPENBSD_SYSCALLS 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 R 0
# CHECK-NEXT: OPENBSD_WXNEEDED 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 R 0

#--- randomdata.s
Expand All @@ -31,6 +33,8 @@ PHDRS {
text PT_LOAD FILEHDR PHDRS;
rand PT_OPENBSD_RANDOMIZE;
boot PT_OPENBSD_BOOTDATA;
mutable PT_OPENBSD_MUTABLE;
syscalls PT_OPENBSD_SYSCALLS;
wxneeded PT_OPENBSD_WXNEEDED;
}
SECTIONS {
Expand Down
46 changes: 46 additions & 0 deletions lld/test/ELF/relro-openbsd.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// REQUIRES: x86

// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-openbsd %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-openbsd %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so

// RUN: ld.lld %t.o %t2.so -z now -z norelro -z relro -o %t
// RUN: llvm-readelf -l %t | FileCheck --check-prefix=CHECK --check-prefix=FULLRELRO %s

// RUN: ld.lld %t.o %t2.so -z norelro -z relro -o %t
// RUN: llvm-readelf -l %t | FileCheck --check-prefix=CHECK --check-prefix=PARTRELRO %s

// RUN: ld.lld %t.o %t2.so -z norelro -o %t
// RUN: llvm-readelf -l %t | FileCheck --check-prefix=NORELRO %s

// CHECK: Program Headers:
// CHECK-NEXT: Type
// CHECK-NEXT: PHDR
// CHECK-NEXT: LOAD
// CHECK-NEXT: LOAD
// CHECK-NEXT: LOAD
// CHECK-NEXT: LOAD
// CHECK-NEXT: DYNAMIC
// CHECK-NEXT: GNU_RELRO
// CHECK: Section to Segment mapping:

// FULLRELRO: 03 .openbsd.randomdata .dynamic .got .got.plt .relro_padding {{$}}
// PARTRELRO: 03 .openbsd.randomdata .dynamic .got .relro_padding {{$}}


// NORELRO-NOT: GNU_RELRO

.global _start
_start:
.long bar
jmp *bar2@GOTPCREL(%rip)

.section .data,"aw"
.quad 0

.zero 4
.section .foo,"aw"
.section .bss,"",@nobits

.section .openbsd.randomdata, "aw"
.quad 0
6 changes: 3 additions & 3 deletions lld/test/ELF/relro.s
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
// CHECK-NEXT: GNU_RELRO
// CHECK: Section to Segment mapping:

// FULLRELRO: 03 .openbsd.randomdata .dynamic .got .got.plt .relro_padding {{$}}
// PARTRELRO: 03 .openbsd.randomdata .dynamic .got .relro_padding {{$}}
// FULLRELRO: 03 .data.rel.ro .dynamic .got .got.plt .relro_padding {{$}}
// PARTRELRO: 03 .data.rel.ro .dynamic .got .relro_padding {{$}}


// NORELRO-NOT: GNU_RELRO
Expand All @@ -42,5 +42,5 @@ _start:
.section .foo,"aw"
.section .bss,"",@nobits

.section .openbsd.randomdata, "aw"
.section .data.rel.ro, "aw"
.quad 0
Loading