[lld] [LLD] Add support for two special openbsd-sections (PR #97122)

John Ericson via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 28 15:58:19 PDT 2024


https://github.com/Ericson2314 created https://github.com/llvm/llvm-project/pull/97122


> (rebaser's note) adapted from:
> https://github.com/openbsd/src/commit/bd249b5664da50f0178adea78250a7a0d8ea6566
> 
> 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


> (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@


Note that I think it would seem better if all this OpenBSD stuff was conditioned on `config->osabi == ELFOSABI_FREEBSD`, but the `-m` flag for `ld.llld` is quite underpowered compared to `--target`.

>From a70d51eae28eaad4b4ef8c55dd0c4672a5c0e979 Mon Sep 17 00:00:00 2001
From: deraadt <deraadt at openbsd.org>
Date: Fri, 7 Oct 2022 15:04:51 +0000
Subject: [PATCH 1/2] [LLD] Add support for `.openbsd.mutable`

(rebaser's note) adapted from:
https://github.com/openbsd/src/commit/bd249b5664da50f0178adea78250a7a0d8ea6566

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
---
 lld/ELF/LinkerScript.cpp | 3 ++-
 lld/ELF/ScriptParser.cpp | 1 +
 lld/ELF/Writer.cpp       | 6 ++++++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 1ec796a3bdd99..e1f38eccb1518 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -107,7 +107,8 @@ static StringRef getOutputSectionName(const InputSectionBase *s) {
   for (StringRef v :
        {".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", ".ldata",
         ".lrodata", ".lbss", ".gcc_except_table", ".init_array", ".fini_array",
-        ".tbss", ".tdata", ".ARM.exidx", ".ARM.extab", ".ctors", ".dtors"})
+        ".tbss", ".tdata", ".ARM.exidx", ".ARM.extab", ".ctors", ".dtors",
+        ".openbsd.randomdata", ".openbsd.mutable"})
     if (isSectionPrefix(v, s->name))
       return v;
 
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index db46263115242..b8d18f516f461 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1628,6 +1628,7 @@ 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_WXNEEDED", PT_OPENBSD_WXNEEDED)
                      .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 640cb2a445f7d..99e13ee89b6dd 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2245,6 +2245,12 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
     addHdr(PT_GNU_EH_FRAME, part.ehFrameHdr->getParent()->getPhdrFlags())
         ->add(part.ehFrameHdr->getParent());
 
+  // PT_OPENBSD_MUTABLE is an OpenBSD-specific feature. That 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 is an OpenBSD-specific feature. That makes
   // the dynamic linker fill the segment with random data.
   if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo))

>From 05716a80240edda6091e48ff6d425b8bb2ef4c1b Mon Sep 17 00:00:00 2001
From: kettenis <kettenis at openbsd.org>
Date: Sun, 3 Dec 2023 21:15:11 +0000
Subject: [PATCH 2/2] [LLD] 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@
---
 lld/ELF/ScriptParser.cpp | 1 +
 lld/ELF/Writer.cpp       | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index b8d18f516f461..41bd9a95053f7 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1630,6 +1630,7 @@ unsigned ScriptParser::readPhdrType() {
                      .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 99e13ee89b6dd..917ed48bf0ec4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2256,6 +2256,11 @@ SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
   if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo))
     addHdr(PT_OPENBSD_RANDOMIZE, cmd->getPhdrFlags())->add(cmd);
 
+  // PT_OPENBSD_SYSCALLS is an OpenBSD-specific feature. That 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
     // pages for the stack non-executable. If you really want an executable



More information about the llvm-commits mailing list