Index: lld/ELF/Writer.cpp --- lld/ELF/Writer.cpp.orig +++ lld/ELF/Writer.cpp @@ -242,6 +242,7 @@ void elf::addReservedSymbols() { }; ElfSym::bss = add("__bss_start", 0); + ElfSym::data = add("__data_start", 0); ElfSym::end1 = add("end", -1); ElfSym::end2 = add("_end", -1); ElfSym::etext1 = add("etext", -1); @@ -798,7 +799,11 @@ static bool isRelroSection(const OutputSection *sec) { // However, if "-z now" is given, the lazy symbol resolution is // disabled, which enables us to put it into RELRO. if (sec == in.gotPlt->getParent()) +#ifndef __OpenBSD__ return config->zNow; +#else + return true; /* kbind(2) means we can always put these in RELRO */ +#endif // .dynamic section contains data for the dynamic linker, and // there's no need to write to it at runtime, so it's better to put @@ -1089,6 +1094,9 @@ template void Writer::setReservedSy if (ElfSym::bss) ElfSym::bss->section = findSection(".bss"); + if (ElfSym::data) + ElfSym::data->section = findSection(".data"); + // Setup MIPS _gp_disp/__gnu_local_gp symbols which should // be equal to the _gp symbol's value. if (ElfSym::mipsGp) { @@ -2369,6 +2377,12 @@ SmallVector Writer::createPhdrs( 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)) @@ -2392,6 +2406,11 @@ SmallVector Writer::createPhdrs( if (config->zWxneeded) addHdr(PT_OPENBSD_WXNEEDED, PF_X); + // PT_OPENBSD_NOBTCFI is an OpenBSD-specific header to mark that the + // executable is expected to violate branch-target CFI checks. + if (config->zNoBtCfi) + addHdr(PT_OPENBSD_NOBTCFI, PF_X); + if (OutputSection *cmd = findSection(".note.gnu.property", partNo)) addHdr(PT_GNU_PROPERTY, PF_R)->add(cmd); @@ -2484,6 +2503,31 @@ template void Writer::fixSectionAli }; } }; + +#ifdef __OpenBSD__ + // On i386, produce binaries that are compatible with our W^X implementation + if (config->emachine == EM_386) { + auto NXAlign = [](OutputSection *Cmd) { + if (Cmd && !Cmd->addrExpr) + Cmd->addrExpr = [=] { + return alignTo(script->getDot(), 0x20000000); + }; + }; + + for (Partition &part : partitions) { + PhdrEntry *firstRW = nullptr; + for (PhdrEntry *P : part.phdrs) { + if (P->p_type == PT_LOAD && (P->p_flags & PF_W)) { + firstRW = P; + break; + } + } + + if (firstRW) + NXAlign(firstRW->firstSec); + } + } +#endif for (Partition &part : partitions) { prev = nullptr;