[lld] d7fd8b1 - [LLD] Extend special OpenBSD support, but scope under ELFOSABI (#97122)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 12 11:34:20 PDT 2024


Author: John Ericson
Date: 2024-07-12T14:34:17-04:00
New Revision: d7fd8b19e560fbb613159625acd8046d0df75115

URL: https://github.com/llvm/llvm-project/commit/d7fd8b19e560fbb613159625acd8046d0df75115
DIFF: https://github.com/llvm/llvm-project/commit/d7fd8b19e560fbb613159625acd8046d0df75115.diff

LOG: [LLD] Extend special OpenBSD support, but scope under ELFOSABI (#97122)

- Add support for `.openbsd.mutable`

  (rebaser's note) adapted from:

https://github.com/openbsd/src/commit/bd249b5664da50f0178adea78250a7a0d8ea6566
  New auto-coalescing sections removed

  In the linkers, collect objects in section "openbsd.mutable" and place
  them into a page-aligned region in the bss, with the right markers for
kernel/ld.so to identify the region and skip making it immutable. While
here, fix readelf/objdump versions to show all of this. ok miod kettenis

- Add support for `.openbsd.syscalls`

  (rebaser's note) adapted from:

https://github.com/openbsd/src/commit/42a61acefa8b3288ff2163fb55e934a3fee39974

  Collect .openbsd.syscalls sections into a new PT_OPENBSD_SYSCALLS
  segment. This will be used soon to pin system calls to designated call
  sites.

  ok deraadt@

- Scope OpenBSD special section handling under that ELFOSABI

  As a preexisting comment in `ELF/Writer.cpp` says:

  > section names shouldn't be significant in ELF in spirit.

  so scoping OSABI-specific magic name hacks to just the OSABI in
  question limits the degree to which we deviate from that "spirit" for
  all other OSABIs.

  OpenBSD in particular is very fast moving, having added a number of
  special sections, etc. in recent years. It is unclear how possible /
  reasonable it is for upstream to implement all these features in any
  event, but scoping like this at least mitigates the fallout for other
  OSABIs systems which wish to be more slow-moving.

Co-authored-by: deraadt <deraadt at openbsd.org>

Added: 
    lld/test/ELF/relro-openbsd.s

Modified: 
    lld/ELF/ScriptParser.cpp
    lld/ELF/Writer.cpp
    lld/test/ELF/openbsd-phdr.s
    lld/test/ELF/relro.s

Removed: 
    


################################################################################
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<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 
diff erently.
+    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 at GOTPCREL(%rip)
+
+.section .data,"aw"
+.quad 0
+
+.zero 4
+.section .foo,"aw"
+.section .bss,"", at 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,"", at nobits
 
-.section .openbsd.randomdata, "aw"
+.section .data.rel.ro, "aw"
 .quad 0


        


More information about the llvm-commits mailing list