Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -682,6 +682,7 @@ // Process PHDRS and FILEHDR keywords because they are not // real output sections and cannot be added in the following loop. + std::vector DefPhdrIds; for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) { Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags); PhdrEntry &Phdr = Ret.back(); @@ -695,33 +696,33 @@ Phdr.H.p_paddr = Cmd.LMAExpr(0); Phdr.HasLMA = true; } + + // If output section command doesn't specify any segments, + // and we haven't previously assigned any section to segment, + // then we simply assign section to the very first load segment. + // Below is an example of such linker script: + // PHDRS { seg PT_LOAD; } + // SECTIONS { .aaa : { *(.aaa) } } + if (DefPhdrIds.empty() && Phdr.H.p_type == PT_LOAD) + DefPhdrIds.push_back(Ret.size() - 1); } // Add output sections to program headers. - PhdrEntry *Load = nullptr; - uintX_t Flags = PF_R; for (OutputSectionBase *Sec : *OutputSections) { if (!(Sec->getFlags() & SHF_ALLOC)) break; std::vector PhdrIds = getPhdrIndices(Sec->getName()); - if (!PhdrIds.empty()) { - // Assign headers specified by linker script - for (size_t Id : PhdrIds) { - Ret[Id].add(Sec); - if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) - Ret[Id].H.p_flags |= Sec->getPhdrFlags(); - } - } else { - // If we have no load segment or flags've changed then we want new load - // segment. - uintX_t NewFlags = Sec->getPhdrFlags(); - if (Load == nullptr || Flags != NewFlags) { - Load = &*Ret.emplace(Ret.end(), PT_LOAD, NewFlags); - Flags = NewFlags; - } - Load->add(Sec); + if (PhdrIds.empty()) + PhdrIds = std::move(DefPhdrIds); + + // Assign headers specified by linker script + for (size_t Id : PhdrIds) { + Ret[Id].add(Sec); + if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) + Ret[Id].H.p_flags |= Sec->getPhdrFlags(); } + DefPhdrIds = std::move(PhdrIds); } return Ret; } Index: test/ELF/linkerscript/openbsd-randomize.s =================================================================== --- test/ELF/linkerscript/openbsd-randomize.s +++ test/ELF/linkerscript/openbsd-randomize.s @@ -1,15 +1,16 @@ # RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o # RUN: echo "PHDRS { text PT_LOAD FILEHDR PHDRS; rand PT_OPENBSD_RANDOMIZE; } \ # RUN: SECTIONS { . = SIZEOF_HEADERS; \ +# RUN: .text : { *(.text) } \ # RUN: .openbsd.randomdata : { *(.openbsd.randomdata) } : rand }" > %t.script # RUN: ld.lld --script %t.script %t.o -o %t # RUN: llvm-readobj --program-headers -s %t | FileCheck %s # CHECK: ProgramHeader { # CHECK: Type: PT_OPENBSD_RANDOMIZE (0x65A3DBE6) -# CHECK-NEXT: Offset: 0x94 -# CHECK-NEXT: VirtualAddress: 0x94 -# CHECK-NEXT: PhysicalAddress: 0x94 +# CHECK-NEXT: Offset: 0x74 +# CHECK-NEXT: VirtualAddress: 0x74 +# CHECK-NEXT: PhysicalAddress: 0x74 # CHECK-NEXT: FileSize: 8 # CHECK-NEXT: MemSize: 8 # CHECK-NEXT: Flags [ (0x4) Index: test/ELF/linkerscript/phdrs-flags.s =================================================================== --- test/ELF/linkerscript/phdrs-flags.s +++ test/ELF/linkerscript/phdrs-flags.s @@ -6,9 +6,18 @@ # RUN: .text : {*(.text*)} :all \ # RUN: .foo : {*(.foo.*)} :all \ # RUN: .data : {*(.data.*)} :all}" > %t.script - # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-readobj -program-headers %t1 | FileCheck %s + +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS FLAGS (0x1);} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: .text : {*(.text*)} :all \ +# RUN: .foo : {*(.foo.*)} \ +# RUN: .data : {*(.data.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s + # CHECK: ProgramHeaders [ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_LOAD (0x1) @@ -22,6 +31,20 @@ # CHECK-NEXT: PF_X (0x1) # CHECK-NEXT: ] +# DEFHDR: ProgramHeaders [ +# DEFHDR-NEXT: ProgramHeader { +# DEFHDR-NEXT: Type: PT_LOAD (0x1) +# DEFHDR-NEXT: Offset: 0x0 +# DEFHDR-NEXT: VirtualAddress: 0x10000000 +# DEFHDR-NEXT: PhysicalAddress: 0x10000000 +# DEFHDR-NEXT: FileSize: 521 +# DEFHDR-NEXT: MemSize: 521 +# DEFHDR-NEXT: Flags [ (0x1) +# DEFHDR-NEXT: PF_X (0x1) +# DEFHDR-NEXT: ] +# DEFHDR-NEXT: Alignment: 4096 +# DEFHDR-NEXT: } + .global _start _start: nop Index: test/ELF/linkerscript/phdrs.s =================================================================== --- test/ELF/linkerscript/phdrs.s +++ test/ELF/linkerscript/phdrs.s @@ -19,6 +19,15 @@ # RUN: ld.lld -o %t1 --script %t.script %t # RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=AT %s +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS ;} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# RUN: .text : {*(.text*)} :all \ +# RUN: .foo : {*(.foo.*)} \ +# RUN: .data : {*(.data.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s + # CHECK: ProgramHeaders [ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_LOAD (0x1) @@ -70,6 +79,20 @@ # INT-PHDRS-NEXT: } # INT-PHDRS-NEXT: ] +# DEFHDR: ProgramHeaders [ +# DEFHDR-NEXT: ProgramHeader { +# DEFHDR-NEXT: Type: PT_LOAD (0x1) +# DEFHDR-NEXT: Offset: 0x0 +# DEFHDR-NEXT: VirtualAddress: 0x10000000 +# DEFHDR-NEXT: PhysicalAddress: 0x10000000 +# DEFHDR-NEXT: FileSize: 521 +# DEFHDR-NEXT: MemSize: 521 +# DEFHDR-NEXT: Flags [ (0x7) +# DEFHDR-NEXT: PF_R (0x4) +# DEFHDR-NEXT: PF_W (0x2) +# DEFHDR-NEXT: PF_X (0x1) +# DEFHDR-NEXT: ] + .global _start _start: nop