Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -56,6 +56,7 @@ bool Mips64EL = false; bool NoInhibitExec; bool NoUndefined; + bool OMagic = false; bool Shared; bool Static = false; bool StripAll; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -215,6 +215,10 @@ case OPT_no_whole_archive: WholeArchive = false; break; + case OPT_omagic: + Config->OMagic = true; + Config->Static = true; + break; } } Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -79,6 +79,10 @@ def o : Separate<["-"], "o">, MetaVarName<"">, HelpText<"Path to file to write output">; +def omagic : Flag<["--"], "omagic">, + HelpText<"Set the text and data sections to be readable and writable. Also, do not " + "page-align the data segment, and disable linking against shared libraries.">; + def rpath : Separate<["-"], "rpath">, HelpText<"Add a DT_RUNPATH to the output">; @@ -122,6 +126,7 @@ def alias_init_init : Joined<["-"], "init=">, Alias; def alias_l__library : Joined<["--"], "library=">, Alias; def alias_o_output : Joined<["--"], "output=">, Alias; +def alias_omagic : Flag<["-"], "N">, Alias; def alias_rpath_rpath : Joined<["-"], "rpath=">, Alias; def alias_shared_Bshareable : Flag<["-"], "Bshareable">, Alias; def alias_soname_h : Separate<["-"], "h">, Alias; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -481,6 +481,8 @@ // This makes each output section simple and keeps a single level // mapping from input to output. auto *IS = dyn_cast>(C); + if (IS && Config->OMagic && getOutputName(C->getSectionName()) == ".text") + OutFlags |= SHF_WRITE; uintX_t EntSize = IS ? 0 : H->sh_entsize; SectionKey Key{getOutputName(C->getSectionName()), H->sh_type, OutFlags, EntSize}; @@ -697,8 +699,10 @@ Interp = &Phdrs[++PhdrIdx]; // Add the first PT_LOAD segment for regular output sections. - setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, getVAStart(), FileOff, - Target->getPageSize()); + uintX_t Flags = PF_R; + uint64_t PageAlign = Config->OMagic ? 1 : Target->getPageSize(); + setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, Flags, 0, getVAStart(), FileOff, + PageAlign); Elf_Phdr TlsPhdr{}; uintX_t ThreadBSSOffset = 0; @@ -706,14 +710,17 @@ for (OutputSectionBase *Sec : OutputSections) { if (needsPhdr(Sec)) { uintX_t Flags = toPhdrFlags(Sec->getFlags()); - if (Phdrs[PhdrIdx].p_flags != Flags) { + if (!Config->OMagic && Phdrs[PhdrIdx].p_flags != Flags) { // Flags changed. Create a new PT_LOAD. - VA = RoundUpToAlignment(VA, Target->getPageSize()); - FileOff = RoundUpToAlignment(FileOff, Target->getPageSize()); + VA = RoundUpToAlignment(VA, PageAlign); + FileOff = RoundUpToAlignment(FileOff, PageAlign); Elf_Phdr *PH = &Phdrs[++PhdrIdx]; - setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize()); + setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, PageAlign); } + if (Config->OMagic) + Phdrs[PhdrIdx].p_flags |= Flags; + if (Sec->getFlags() & SHF_TLS) { if (!TlsPhdr.p_vaddr) { setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign()); @@ -792,7 +799,7 @@ if (Sec->getFlags() & SHF_TLS) Tls = true; uintX_t Flags = toPhdrFlags(Sec->getFlags()); - if (Last != Flags) { + if (!Config->OMagic && Last != Flags) { Last = Flags; ++I; } Index: test/elf2/omagic.s =================================================================== --- test/elf2/omagic.s +++ test/elf2/omagic.s @@ -0,0 +1,138 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 +# RUN: ld.lld2 -N %t1 -o %t2 +# RUN: ld.lld2 %t1 -o %t3 +# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 | FileCheck %s +# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t3 | FileCheck -check-prefix=CHECKNOMAGIC %s + +// Check alias +# RUN: ld.lld2 --omagic %t1 -o %t2 +# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 | FileCheck %s + +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_PHDR +# CHECK-NEXT: Offset: 0x40 +# CHECK-NEXT: VirtualAddress: 0x10040 +# CHECK-NEXT: PhysicalAddress: 0x10040 +# CHECK-NEXT: FileSize: 168 +# CHECK-NEXT: MemSize: 168 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 8 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x10000 +# CHECK-NEXT: PhysicalAddress: 0x10000 +# CHECK-NEXT: FileSize: 288 +# CHECK-NEXT: MemSize: 288 +# CHECK-NEXT: Flags [ (0x7) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: PF_X (0x1) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 1 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_TLS +# CHECK-NEXT: Offset: 0xE8 +# CHECK-NEXT: VirtualAddress: 0x100E8 +# CHECK-NEXT: PhysicalAddress: 0x100E8 +# CHECK-NEXT: FileSize: 8 +# CHECK-NEXT: MemSize: 8 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 1 +# CHECK-NEXT: } + +# CHECKNOMAGIC: ProgramHeaders [ +# CHECKNOMAGIC-NEXT: ProgramHeader { +# CHECKNOMAGIC-NEXT: Type: PT_PHDR +# CHECKNOMAGIC-NEXT: Offset: 0x40 +# CHECKNOMAGIC-NEXT: VirtualAddress: 0x10040 +# CHECKNOMAGIC-NEXT: PhysicalAddress: 0x10040 +# CHECKNOMAGIC-NEXT: FileSize: 280 +# CHECKNOMAGIC-NEXT: MemSize: 280 +# CHECKNOMAGIC-NEXT: Flags [ +# CHECKNOMAGIC-NEXT: PF_R +# CHECKNOMAGIC-NEXT: ] +# CHECKNOMAGIC-NEXT: Alignment: 8 +# CHECKNOMAGIC-NEXT: } +# CHECKNOMAGIC-NEXT: ProgramHeader { +# CHECKNOMAGIC-NEXT: Type: PT_LOAD +# CHECKNOMAGIC-NEXT: Offset: 0x0 +# CHECKNOMAGIC-NEXT: VirtualAddress: 0x10000 +# CHECKNOMAGIC-NEXT: PhysicalAddress: 0x10000 +# CHECKNOMAGIC-NEXT: FileSize: 376 +# CHECKNOMAGIC-NEXT: MemSize: 376 +# CHECKNOMAGIC-NEXT: Flags [ +# CHECKNOMAGIC-NEXT: PF_R +# CHECKNOMAGIC-NEXT: ] +# CHECKNOMAGIC-NEXT: Alignment: 4096 +# CHECKNOMAGIC-NEXT: } +# CHECKNOMAGIC-NEXT: ProgramHeader { +# CHECKNOMAGIC-NEXT: Type: PT_LOAD +# CHECKNOMAGIC-NEXT: Offset: 0x1000 +# CHECKNOMAGIC-NEXT: VirtualAddress: 0x11000 +# CHECKNOMAGIC-NEXT: PhysicalAddress: 0x11000 +# CHECKNOMAGIC-NEXT: FileSize: 8 +# CHECKNOMAGIC-NEXT: MemSize: 8 +# CHECKNOMAGIC-NEXT: Flags [ +# CHECKNOMAGIC-NEXT: PF_R +# CHECKNOMAGIC-NEXT: PF_X +# CHECKNOMAGIC-NEXT: ] +# CHECKNOMAGIC-NEXT: Alignment: 4096 +# CHECKNOMAGIC-NEXT: } +# CHECKNOMAGIC-NEXT: ProgramHeader { +# CHECKNOMAGIC-NEXT: Type: PT_LOAD +# CHECKNOMAGIC-NEXT: Offset: 0x2000 +# CHECKNOMAGIC-NEXT: VirtualAddress: 0x12000 +# CHECKNOMAGIC-NEXT: PhysicalAddress: 0x12000 +# CHECKNOMAGIC-NEXT: FileSize: 16 +# CHECKNOMAGIC-NEXT: MemSize: 16 +# CHECKNOMAGIC-NEXT: Flags [ +# CHECKNOMAGIC-NEXT: PF_R +# CHECKNOMAGIC-NEXT: PF_W +# CHECKNOMAGIC-NEXT: ] +# CHECKNOMAGIC-NEXT: Alignment: 4096 +# CHECKNOMAGIC-NEXT: } +# CHECKNOMAGIC-NEXT: ProgramHeader { +# CHECKNOMAGIC-NEXT: Type: PT_TLS +# CHECKNOMAGIC-NEXT: Offset: 0x158 +# CHECKNOMAGIC-NEXT: VirtualAddress: 0x10158 +# CHECKNOMAGIC-NEXT: PhysicalAddress: 0x10158 +# CHECKNOMAGIC-NEXT: FileSize: 8 +# CHECKNOMAGIC-NEXT: MemSize: 8 +# CHECKNOMAGIC-NEXT: Flags [ +# CHECKNOMAGIC-NEXT: PF_R +# CHECKNOMAGIC-NEXT: ] +# CHECKNOMAGIC-NEXT: Alignment: 1 +# CHECKNOMAGIC-NEXT: } + +.section .r,"ax" +.globl _start +_start: +.quad 0 + +.section .aw1,"aw" +.quad 1 + +.section .a,"a" +.quad 2 + +.section .tls,"aT" +.quad 3 + +.section .s1,"aS" +.quad 4 + +.section .aw2,"aw" +.quad 5 + +.section .s2,"aS" +.quad 6