From 52574b5f40606b8319952e45d0c407675d9ee0fa Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Thu, 19 Dec 2024 19:41:42 -0500 Subject: [PATCH] [ELF] Add support for PT_OPENBSD_NOBTCFI (#120005) --- lld/ELF/Config.h | 1 + lld/ELF/Driver.cpp | 3 +++ lld/ELF/Writer.cpp | 5 +++++ lld/docs/ld.lld.1 | 5 +++++ lld/test/ELF/openbsd-phdr.s | 10 ++++++++-- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 5b6b332cd597df..48f0db6c214982 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -363,6 +363,7 @@ struct Config { bool zInterpose; bool zKeepTextSectionPrefix; bool zLrodataAfterBss; + bool zNoBtCfi = false; bool zNodefaultlib; bool zNodelete; bool zNodlopen; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 9240f29d98d614..dfb17f9257c8f5 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1897,6 +1897,9 @@ static void setConfigs(Ctx &ctx, opt::InputArgList &args) { ErrAlways(ctx) << "cannot open --why-extract= file " << ctx.arg.whyExtract << ": " << e.message(); } + + if (ctx.arg.osabi == ELFOSABI_OPENBSD) + ctx.arg.zNoBtCfi = hasZOption(args, "nobtcfi"); } static bool isFormatBinary(Ctx &ctx, StringRef s) { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index d5581ca3e1c921..3e92b7653e31af 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2405,6 +2405,11 @@ Writer::createPhdrs(Partition &part) { addHdr(PT_GNU_STACK, perm)->p_memsz = ctx.arg.zStackSize; } + // PT_OPENBSD_NOBTCFI is an OpenBSD-specific header to mark that the + // executable is expected to violate branch-target CFI checks. + if (ctx.arg.zNoBtCfi) + addHdr(PT_OPENBSD_NOBTCFI, PF_X); + // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable // is expected to perform W^X violations, such as calling mprotect(2) or // mmap(2) with PROT_WRITE | PROT_EXEC, which is prohibited by default on diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 2fa6f64b2d2032..b28c6082f68b09 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -952,6 +952,11 @@ Let __start_/__stop_ references retain the associated C identifier name sections Do not allow relocations against read-only segments. This is the default. .Pp +.It Cm nobtcfi +Create a +.Dv PT_OPENBSD_NOBTCFI +segment. +.Pp .It Cm wxneeded Create a .Dv PT_OPENBSD_WXNEEDED diff --git a/lld/test/ELF/openbsd-phdr.s b/lld/test/ELF/openbsd-phdr.s index 275f944511701e..e0269e642f759a 100644 --- a/lld/test/ELF/openbsd-phdr.s +++ b/lld/test/ELF/openbsd-phdr.s @@ -4,8 +4,11 @@ # 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-unknown-openbsd /dev/null -o wxneeded.o -# RUN: ld.lld -z wxneeded wxneeded.o -o wxneeded +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-openbsd /dev/null -o empty.o +# RUN: ld.lld -z nobtcfi empty.o -o nobtcfi +# RUN: llvm-readelf -l nobtcfi | FileCheck %s --check-prefix=NOBTCFI + +# RUN: ld.lld -z wxneeded empty.o -o wxneeded # RUN: llvm-readelf -l wxneeded | FileCheck %s --check-prefix=WXNEEDED # RUN: ld.lld -T lds randomdata.o -o out @@ -14,6 +17,9 @@ # RANDOMDATA: Name Type Address Off Size ES Flg Lk Inf Al # RANDOMDATA: .openbsd.randomdata PROGBITS [[ADDR:[0-9a-f]+]] [[O:[0-9a-f]+]] 000008 00 A 0 0 1 +# NOBTCFI: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# NOBTCFI: OPENBSD_NOBTCFI 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 E 0 + # WXNEEDED: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # WXNEEDED: OPENBSD_WXNEEDED 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 E 0