diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 7fa953d3f364..5c9edeaa5a39 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -334,7 +334,7 @@ LinkerScript::createPhdrs(ArrayRef *> Sections) { std::vector Phdrs; for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) { - Phdrs.emplace_back(Cmd.Type, PF_R); + Phdrs.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags); Phdr &Added = Phdrs.back(); if (Cmd.HasFilehdr) @@ -387,6 +387,8 @@ LinkerScript::createPhdrs(ArrayRef *> Sections) { // Assign headers specified by linker script for (size_t Id : PhdrIds) { Phdrs[Id].add(Sec); + if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) + Phdrs[Id].H.p_flags |= toPhdrFlags(Sec->getFlags()); Phdrs[Id].H.p_flags |= toPhdrFlags(Sec->getFlags()); } } else { @@ -669,7 +671,7 @@ void ScriptParser::readPhdrs() { expect("{"); while (!Error && !skip("}")) { StringRef Tok = next(); - Opt.PhdrsCommands.push_back({Tok, PT_NULL, false, false}); + Opt.PhdrsCommands.push_back({Tok, PT_NULL, false, false, UINT_MAX}); PhdrsCommand &PhdrCmd = Opt.PhdrsCommands.back(); PhdrCmd.Type = readPhdrType(); @@ -681,7 +683,11 @@ void ScriptParser::readPhdrs() { PhdrCmd.HasFilehdr = true; else if (Tok == "PHDRS") PhdrCmd.HasPhdrs = true; - else + else if (Tok == "FLAGS") { + expect("("); + next().getAsInteger(0, PhdrCmd.Flags); + expect(")"); + } else setError("unexpected header attribute: " + Tok); } while (!Error); } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 104cfca3ad1c..311bd0bef51d 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -79,6 +79,7 @@ struct PhdrsCommand { unsigned Type; bool HasFilehdr; bool HasPhdrs; + unsigned Flags; }; // ScriptConfiguration holds linker script parse results. diff --git a/lld/test/ELF/linkerscript-phdrs-flags.s b/lld/test/ELF/linkerscript-phdrs-flags.s new file mode 100644 index 000000000000..4d301fec7714 --- /dev/null +++ b/lld/test/ELF/linkerscript-phdrs-flags.s @@ -0,0 +1,36 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS FLAGS (7);} \ +# RUN: SECTIONS { \ +# RUN: . = 0x10000200; \ +# 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 +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x10000000 +# CHECK-NEXT: PhysicalAddress: 0x10000000 +# CHECK-NEXT: FileSize: 521 +# CHECK-NEXT: MemSize: 521 +# CHECK-NEXT: Flags [ (0x7) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: PF_X (0x1) +# CHECK-NEXT: ] + +.global _start +_start: + nop + +.section .foo.1,"a" +foo1: + .long 0 + +.section .foo.2,"a" +foo2: + .long 0