diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index db46263115242..41bd9a95053f7 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -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); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index bce3cd2de7ed2..8940a1c5d5113 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -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" || + 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 @@ -2273,10 +2279,22 @@ SmallVector Writer::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 diff --git a/lld/test/ELF/openbsd-phdr.s b/lld/test/ELF/openbsd-phdr.s index 5ba0e031b2c26..275f944511701 100644 --- a/lld/test/ELF/openbsd-phdr.s +++ b/lld/test/ELF/openbsd-phdr.s @@ -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 @@ -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 @@ -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 { diff --git a/lld/test/ELF/relro-openbsd.s b/lld/test/ELF/relro-openbsd.s new file mode 100644 index 0000000000000..142b6a5e1a5c1 --- /dev/null +++ b/lld/test/ELF/relro-openbsd.s @@ -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 diff --git a/lld/test/ELF/relro.s b/lld/test/ELF/relro.s index 0ab9665443d1f..139f008c51ac9 100644 --- a/lld/test/ELF/relro.s +++ b/lld/test/ELF/relro.s @@ -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 @@ -42,5 +42,5 @@ _start: .section .foo,"aw" .section .bss,"",@nobits -.section .openbsd.randomdata, "aw" +.section .data.rel.ro, "aw" .quad 0