Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -595,8 +595,7 @@ } // Add output sections to program headers. - PhdrEntry *Load = nullptr; - uintX_t Flags = PF_R; + unsigned LoadId = UINT_MAX; for (OutputSectionBase *Sec : *OutputSections) { if (!(Sec->getFlags() & SHF_ALLOC)) break; @@ -608,16 +607,25 @@ Ret[Id].add(Sec); if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) Ret[Id].H.p_flags |= Sec->getPhdrFlags(); + if (Ret[Id].H.p_type == PT_LOAD) + LoadId = Id; } } 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; + uintX_t Flags = 0; + if (LoadId != UINT_MAX) + Flags = Opt.PhdrsCommands[LoadId].Flags == UINT_MAX + ? UINT_MAX + : Ret[LoadId].H.p_flags; + + if ((NewFlags & Flags) != NewFlags) { + Ret.emplace_back(PT_LOAD, 0); + LoadId = Ret.size() - 1; } - Load->add(Sec); + Ret[LoadId].add(Sec); + Ret[LoadId].H.p_flags |= NewFlags; } } return Ret; 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,34 @@ # 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: 513 +# DEFHDR-NEXT: MemSize: 513 +# DEFHDR-NEXT: Flags [ (0x1) +# DEFHDR-NEXT: PF_X (0x1) +# DEFHDR-NEXT: ] +# DEFHDR-NEXT: Alignment: 4096 +# DEFHDR-NEXT: } +# DEFHDR-NEXT: ProgramHeader { +# DEFHDR-NEXT: Type: PT_LOAD (0x1) +# DEFHDR-NEXT: Offset: 0x201 +# DEFHDR-NEXT: VirtualAddress: 0x10000201 +# DEFHDR-NEXT: PhysicalAddress: 0x10000201 +# DEFHDR-NEXT: FileSize: 8 +# DEFHDR-NEXT: MemSize: 8 +# DEFHDR-NEXT: Flags [ (0x6) +# DEFHDR-NEXT: PF_R (0x4) +# DEFHDR-NEXT: PF_W (0x2) +# DEFHDR-NEXT: ] +# DEFHDR-NEXT: Alignment: 4096 +# DEFHDR-NEXT: } +# 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) @@ -47,6 +56,20 @@ # AT-NEXT: PF_X (0x1) # AT-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