Index: include/lld/Core/Error.h =================================================================== --- include/lld/Core/Error.h +++ include/lld/Core/Error.h @@ -41,6 +41,8 @@ extra_program_phdr, misplaced_program_phdr, program_phdr_wrong_phdrs, + load_phdr_wrong_attr, + duplicate_name, }; inline std::error_code make_error_code(LinkerScriptReaderError e) { Index: include/lld/ReaderWriter/LinkerScript.h =================================================================== --- include/lld/ReaderWriter/LinkerScript.h +++ include/lld/ReaderWriter/LinkerScript.h @@ -20,6 +20,7 @@ #include "lld/Core/range.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" @@ -1336,6 +1337,9 @@ /// Retrieve all the headers the given output section is assigned to. std::vector getPHDRsForOutputSection(StringRef name) const; + /// Get the index of given header as it is in the PHDRS command. + int getIndexOfPHDR(const PHDR *phdr) const; + /// Retrieve program header if available. const PHDR *getProgramPHDR() const; @@ -1382,12 +1386,11 @@ /// Convert the PHDRS command into map of names to headers. /// Determine program header during processing. - std::error_code collectPHDRs(const PHDRS *ph, - llvm::StringMap &phdrs); + std::error_code collectPHDRs(const PHDRS *ph); /// Build map that matches output section names to segments they should be /// put into. - std::error_code buildSectionToPHDR(llvm::StringMap &phdrs); + std::error_code buildSectionToPHDR(); /// Our goal with all linearizeAST overloaded functions is to /// traverse the linker script AST while putting nodes in a vector and @@ -1453,6 +1456,9 @@ llvm::DenseSet _deliveredExprs; mutable llvm::StringSet<> _definedSymbols; + llvm::MapVector, + llvm::SmallVector, 8>> + _phdrs; llvm::StringMap> _sectionToPHDR; const PHDR *_programPHDR; Index: lib/Core/Error.cpp =================================================================== --- lib/Core/Error.cpp +++ lib/Core/Error.cpp @@ -64,6 +64,10 @@ return "Program header must precede load segments"; case LinkerScriptReaderError::program_phdr_wrong_phdrs: return "Program header has invalid PHDRS attribute"; + case LinkerScriptReaderError::load_phdr_wrong_attr: + return "Load header has wrong attributes"; + case LinkerScriptReaderError::duplicate_name: + return "Duplicate name is found"; } llvm_unreachable("An enumerator of LinkerScriptReaderError does not have a " "message defined."); Index: lib/ReaderWriter/ELF/HeaderChunks.h =================================================================== --- lib/ReaderWriter/ELF/HeaderChunks.h +++ lib/ReaderWriter/ELF/HeaderChunks.h @@ -58,8 +58,12 @@ void finalize() override; + bool isDiscarded() const { return _discard; } + void setDiscarded(bool discard) { _discard = discard; } + private: Elf_Ehdr _eh; + bool _discard = true; }; /// \brief An ProgramHeader represents the Elf[32/64]_Phdr structure at the @@ -100,12 +104,16 @@ return Chunk::ContentType::Header; } + bool isDiscarded() const { return _discard; } + void setDiscarded(bool discard) { _discard = discard; } + private: Elf_Phdr *allocateProgramHeader(bool &allocatedNew); std::vector _ph; PhIterT _phi; llvm::BumpPtrAllocator _allocator; + bool _discard = true; }; /// \brief An SectionHeader represents the Elf[32/64]_Shdr structure Index: lib/ReaderWriter/ELF/OutputELFWriter.cpp =================================================================== --- lib/ReaderWriter/ELF/OutputELFWriter.cpp +++ lib/ReaderWriter/ELF/OutputELFWriter.cpp @@ -442,8 +442,10 @@ _elfHeader->finalize(); _programHeader->finalize(); - _elfHeader->write(this, _layout, *buffer); - _programHeader->write(this, _layout, *buffer); + if (!_elfHeader->isDiscarded()) + _elfHeader->write(this, _layout, *buffer); + if (!_programHeader->isDiscarded()) + _programHeader->write(this, _layout, *buffer); auto sections = _layout.sections(); parallel_for_each( Index: lib/ReaderWriter/ELF/TargetLayout.h =================================================================== --- lib/ReaderWriter/ELF/TargetLayout.h +++ lib/ReaderWriter/ELF/TargetLayout.h @@ -108,13 +108,18 @@ // Properties used during segment creation struct SegmentKey { - SegmentKey(StringRef name, int64_t type, uint64_t flags, bool segFlags) - : _name(name), _type(type), _flags(flags), - _segmentFlags(segFlags && flags != 0) {} + SegmentKey(StringRef name, int64_t type, uint64_t flags, + const script::PHDR *phdr = nullptr) + : _name(name), _type(type), _flags(flags), _phdr(phdr) { + assert((!_phdr || _phdr->flags() == _flags) && + "Flags should equal segment flags if PHDR is set"); + } + bool hasSegmentFlags() const { return _phdr != nullptr && _flags != 0; } + StringRef _name = ""; int64_t _type = 0; uint64_t _flags = 0; - bool _segmentFlags = false; + const script::PHDR *_phdr = nullptr; }; struct SegmentKeyHash { Index: lib/ReaderWriter/ELF/TargetLayout.cpp =================================================================== --- lib/ReaderWriter/ELF/TargetLayout.cpp +++ lib/ReaderWriter/ELF/TargetLayout.cpp @@ -335,12 +335,12 @@ auto phdrs = _linkerScriptSema.getPHDRsForOutputSection(os->name()); if (!phdrs.empty()) { if (phdrs.size() == 1 && phdrs[0]->isNone()) { - segKeys.emplace_back("NONE", llvm::ELF::PT_NULL, 0, false); + segKeys.emplace_back("NONE", llvm::ELF::PT_NULL, 0, phdrs[0]); return segKeys; } for (auto phdr : phdrs) { - segKeys.emplace_back(phdr->name(), phdr->type(), phdr->flags(), true); + segKeys.emplace_back(phdr->name(), phdr->type(), phdr->flags(), phdr); } return segKeys; } @@ -352,7 +352,7 @@ // We need a separate segment for sections that don't have // the segment type to be PT_LOAD if (segmentType != llvm::ELF::PT_LOAD) - segKeys.emplace_back(segmentName, segmentType, flags, false); + segKeys.emplace_back(segmentName, segmentType, flags); if (segmentType == llvm::ELF::PT_NULL) return segKeys; @@ -366,7 +366,7 @@ flags = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE; - segKeys.emplace_back("LOAD", llvm::ELF::PT_LOAD, flags, false); + segKeys.emplace_back("LOAD", llvm::ELF::PT_LOAD, flags); return segKeys; } @@ -431,7 +431,7 @@ segment = segmentInsert.first->second; } else { segment = new (_allocator) Segment(_ctx, key._name, key._type); - if (key._segmentFlags) + if (key.hasSegmentFlags()) segment->setSegmentFlags(key._flags); segmentInsert.first->second = segment; _segments.push_back(segment); @@ -453,6 +453,8 @@ bool hasElfHeader = true; bool hasProgramHeader = true; uint64_t segmentFlags = 0; + SegmentKey phdrKey("PHDR", llvm::ELF::PT_PHDR, + llvm::ELF::PF_R | llvm::ELF::PF_X); // Check if linker script has PHDRS and program segment defined if (_linkerScriptSema.hasPHDRs()) { @@ -461,6 +463,7 @@ hasElfHeader = p->hasFileHdr(); hasProgramHeader = p->hasPHDRs(); segmentFlags = p->flags(); + phdrKey = SegmentKey(p->name(), p->type(), p->flags(), p); } else { hasProgramSegment = false; hasElfHeader = false; @@ -470,13 +473,18 @@ if (hasProgramSegment) { Segment *segment = new (_allocator) ProgramHeaderSegment(_ctx); + _segmentMap.insert(std::make_pair(phdrKey, segment)); _segments.push_back(segment); if (segmentFlags) segment->setSegmentFlags(segmentFlags); - if (hasElfHeader) + if (hasElfHeader) { segment->append(_elfHeader); - if (hasProgramHeader) + _elfHeader->setDiscarded(false); + } + if (hasProgramHeader) { segment->append(_programHeader); + _programHeader->setDiscarded(false); + } } } @@ -488,7 +496,30 @@ if (_segments.empty()) return; - sortSegments(); + // Build map of segments to PHDRs for lookup + std::map *, const script::PHDR *> segmToPHDR; + if (_linkerScriptSema.hasPHDRs()) { + std::transform(_segmentMap.begin(), _segmentMap.end(), + std::inserter(segmToPHDR, segmToPHDR.begin()), + [](const std::pair *> &p) { + return std::make_pair(p.second, p.first._phdr); + }); + std::sort(_segments.begin(), _segments.end(), + [this, &segmToPHDR](Segment *a, Segment *b) { + const int ind_a = + _linkerScriptSema.getIndexOfPHDR(segmToPHDR[a]); + const int ind_b = + _linkerScriptSema.getIndexOfPHDR(segmToPHDR[b]); + + // Compare missing segments in a usual way + if (ind_a < 0 || ind_b < 0) + return Segment::compareSegments(a, b); + + return ind_a < ind_b; + }); + } else { + sortSegments(); + } uint64_t baseAddress = _ctx.getBaseAddress(); @@ -501,13 +532,31 @@ for (auto si : _segments) { if (si->segmentType() == llvm::ELF::PT_LOAD) { firstLoadSegment = si; - si->firstSection()->setAlign(si->alignment()); break; } } - assert(firstLoadSegment != nullptr && "No loadable segment!"); - firstLoadSegment->prepend(_programHeader); - firstLoadSegment->prepend(_elfHeader); + + // Default values if no linker script is available + bool hasElfHeader = true; + bool hasProgramHeader = true; + if (_linkerScriptSema.hasPHDRs()) { + if (auto loadSegment = segmToPHDR[firstLoadSegment]) { + hasElfHeader = loadSegment->hasFileHdr(); + hasProgramHeader = loadSegment->hasPHDRs(); + } + } + + if (firstLoadSegment) { + firstLoadSegment->firstSection()->setAlign(firstLoadSegment->alignment()); + if (hasProgramHeader) { + firstLoadSegment->prepend(_programHeader); + _programHeader->setDiscarded(false); + } + if (hasElfHeader) { + firstLoadSegment->prepend(_elfHeader); + _elfHeader->setDiscarded(false); + } + } bool newSegmentHeaderAdded = true; bool virtualAddressAssigned = false; bool fileOffsetAssigned = false; Index: lib/ReaderWriter/LinkerScript.cpp =================================================================== --- lib/ReaderWriter/LinkerScript.cpp +++ lib/ReaderWriter/LinkerScript.cpp @@ -2398,19 +2398,17 @@ Sema::Sema() : _programPHDR(nullptr) {} std::error_code Sema::perform() { - llvm::StringMap phdrs; - for (auto &parser : _scripts) { for (const Command *c : parser->get()->_commands) { if (const auto *sec = dyn_cast(c)) { linearizeAST(sec); } else if (const auto *ph = dyn_cast(c)) { - if (auto ec = collectPHDRs(ph, phdrs)) + if (auto ec = collectPHDRs(ph)) return ec; } } } - return buildSectionToPHDR(phdrs); + return buildSectionToPHDR(); } bool Sema::less(const SectionKey &lhs, const SectionKey &rhs) const { @@ -2522,6 +2520,14 @@ return std::vector(std::begin(vec), std::end(vec)); } +int Sema::getIndexOfPHDR(const PHDR *phdr) const { + if (!phdr || phdr->isNone()) + return -1; + auto it = _phdrs.find(phdr->name()); + return it == std::end(_phdrs) ? -1 + : (int)std::distance(std::begin(_phdrs), it); +} + const PHDR *Sema::getProgramPHDR() const { return _programPHDR; } void Sema::dump() const { @@ -2763,11 +2769,12 @@ return false; } -std::error_code Sema::collectPHDRs(const PHDRS *ph, - llvm::StringMap &phdrs) { +std::error_code Sema::collectPHDRs(const PHDRS *ph) { bool loadFound = false; for (auto *p : *ph) { - phdrs[p->name()] = p; + if (_phdrs.count(p->name())) + return LinkerScriptReaderError::duplicate_name; + _phdrs[p->name()] = p; switch (p->type()) { case llvm::ELF::PT_PHDR: @@ -2784,6 +2791,9 @@ // mapped in the first loadable segment. if (!loadFound && _programPHDR && !p->hasPHDRs()) return LinkerScriptReaderError::program_phdr_wrong_phdrs; + // Only first load PHDR may have ELF and/or program headers defined + if (loadFound && (p->hasFileHdr() || p->hasPHDRs())) + return LinkerScriptReaderError::load_phdr_wrong_attr; loadFound = true; break; } @@ -2791,13 +2801,13 @@ return std::error_code(); } -std::error_code Sema::buildSectionToPHDR(llvm::StringMap &phdrs) { - const bool noPhdrs = phdrs.empty(); +std::error_code Sema::buildSectionToPHDR() { + const bool noPhdrs = _phdrs.empty(); // Add NONE header to the map provided there's no user-defined // header with the same name. - if (!phdrs.count(PHDR_NONE.name())) - phdrs[PHDR_NONE.name()] = &PHDR_NONE; + if (!_phdrs.count(PHDR_NONE.name())) + _phdrs[PHDR_NONE.name()] = &PHDR_NONE; // Match output sections to available headers. llvm::SmallVector phdrsCur, phdrsLast { &PHDR_NONE }; @@ -2808,8 +2818,8 @@ phdrsCur.clear(); for (StringRef name : osd->PHDRs()) { - auto it = phdrs.find(name); - if (it == phdrs.end()) { + auto it = _phdrs.find(name); + if (it == _phdrs.end()) { return LinkerScriptReaderError::unknown_phdr_ids; } phdrsCur.push_back(it->second); Index: test/elf/linkerscript/phdrs-all-none.test =================================================================== --- test/elf/linkerscript/phdrs-all-none.test +++ test/elf/linkerscript/phdrs-all-none.test @@ -11,7 +11,7 @@ PHDRS { - text PT_LOAD; + text PT_LOAD FILEHDR PHDRS; } SECTIONS Index: test/elf/linkerscript/phdrs-custom-none.test =================================================================== --- test/elf/linkerscript/phdrs-custom-none.test +++ test/elf/linkerscript/phdrs-custom-none.test @@ -12,7 +12,7 @@ PHDRS { - NONE PT_LOAD; + NONE PT_LOAD FILEHDR PHDRS; } SECTIONS Index: test/elf/linkerscript/phdrs-custom-order.test =================================================================== --- /dev/null +++ test/elf/linkerscript/phdrs-custom-order.test @@ -0,0 +1,45 @@ +/* +Test segments put in order defined by PHDRS command. + +RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o + +RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 +RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix ORDER-PHDRS-SECS %s +RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix ORDER-PHDRS-HDRS %s +*/ + +ENTRY(_start) + +PHDRS +{ + data PT_LOAD FILEHDR PHDRS; + text PT_LOAD; +} + +SECTIONS +{ + .text : { *(.text) } :text + .data : { *(.data) } :data +} + +/* +ORDER-PHDRS-SECS: .text {{[0-9a-f]+}} 0000000000401000 +ORDER-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000e8 + +ORDER-PHDRS-HDRS: ProgramHeader { +ORDER-PHDRS-HDRS: Type: PT_LOAD (0x1) +ORDER-PHDRS-HDRS: VirtualAddress: 0x400000 +ORDER-PHDRS-HDRS: Flags [ (0x6) +ORDER-PHDRS-HDRS: PF_R (0x4) +ORDER-PHDRS-HDRS: PF_W (0x2) +ORDER-PHDRS-HDRS: ] +ORDER-PHDRS-HDRS: } +ORDER-PHDRS-HDRS: ProgramHeader { +ORDER-PHDRS-HDRS: Type: PT_LOAD (0x1) +ORDER-PHDRS-HDRS: VirtualAddress: 0x401000 +ORDER-PHDRS-HDRS: Flags [ (0x5) +ORDER-PHDRS-HDRS: PF_R (0x4) +ORDER-PHDRS-HDRS: PF_X (0x1) +ORDER-PHDRS-HDRS: ] +ORDER-PHDRS-HDRS: } +*/ Index: test/elf/linkerscript/phdrs-different.test =================================================================== --- test/elf/linkerscript/phdrs-different.test +++ test/elf/linkerscript/phdrs-different.test @@ -12,7 +12,7 @@ PHDRS { - text PT_LOAD; + text PT_LOAD FILEHDR PHDRS; data PT_LOAD; } Index: test/elf/linkerscript/phdrs-dup-name.test =================================================================== --- /dev/null +++ test/elf/linkerscript/phdrs-dup-name.test @@ -0,0 +1,27 @@ +/* +Test duplicate header generates error. + +RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o + +RUN: not lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 &> %t1-error +RUN: FileCheck -check-prefix DUPLICATE-PHDR %s < %t1-error +*/ + +ENTRY(_start) + +PHDRS +{ + header PT_PHDR PHDRS; + header PT_PHDR PHDRS; + text PT_LOAD FILEHDR PHDRS; +} + +SECTIONS +{ + .text : { *(.text) } :NONE + .data : { *(.data) } +} + +/* +DUPLICATE-PHDR: Duplicate name is found +*/ Index: test/elf/linkerscript/phdrs-extra-program.test =================================================================== --- test/elf/linkerscript/phdrs-extra-program.test +++ test/elf/linkerscript/phdrs-extra-program.test @@ -13,7 +13,7 @@ { header PT_PHDR PHDRS; header2 PT_PHDR PHDRS; - text PT_LOAD; + text PT_LOAD FILEHDR PHDRS; } SECTIONS Index: test/elf/linkerscript/phdrs-flags.test =================================================================== --- test/elf/linkerscript/phdrs-flags.test +++ test/elf/linkerscript/phdrs-flags.test @@ -12,7 +12,7 @@ PHDRS { - text PT_LOAD FLAGS(0x5); + text PT_LOAD FILEHDR PHDRS FLAGS(0x5); data PT_LOAD FLAGS(0x7); } @@ -23,23 +23,23 @@ } /* -FLAGS-PHDRS-SECS: .text {{[0-9a-f]+}} 0000000000401000 -FLAGS-PHDRS-SECS: .data {{[0-9a-f]+}} 00000000004000e8 +FLAGS-PHDRS-SECS: .text {{[0-9a-f]+}} 00000000004000e8 +FLAGS-PHDRS-SECS: .data {{[0-9a-f]+}} 0000000000401000 FLAGS-PHDRS-HDRS: ProgramHeader { FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1) FLAGS-PHDRS-HDRS: VirtualAddress: 0x400000 -FLAGS-PHDRS-HDRS: Flags [ (0x7) +FLAGS-PHDRS-HDRS: Flags [ (0x5) FLAGS-PHDRS-HDRS: PF_R (0x4) -FLAGS-PHDRS-HDRS: PF_W (0x2) FLAGS-PHDRS-HDRS: PF_X (0x1) FLAGS-PHDRS-HDRS: ] FLAGS-PHDRS-HDRS: } FLAGS-PHDRS-HDRS: ProgramHeader { FLAGS-PHDRS-HDRS: Type: PT_LOAD (0x1) FLAGS-PHDRS-HDRS: VirtualAddress: 0x401000 -FLAGS-PHDRS-HDRS: Flags [ (0x5) +FLAGS-PHDRS-HDRS: Flags [ (0x7) FLAGS-PHDRS-HDRS: PF_R (0x4) +FLAGS-PHDRS-HDRS: PF_W (0x2) FLAGS-PHDRS-HDRS: PF_X (0x1) FLAGS-PHDRS-HDRS: ] FLAGS-PHDRS-HDRS: } Index: test/elf/linkerscript/phdrs-has-program.test =================================================================== --- test/elf/linkerscript/phdrs-has-program.test +++ test/elf/linkerscript/phdrs-has-program.test @@ -12,7 +12,7 @@ PHDRS { header PT_PHDR FILEHDR PHDRS; - text PT_LOAD PHDRS; + text PT_LOAD FILEHDR PHDRS; } SECTIONS Index: test/elf/linkerscript/phdrs-load-empty.test =================================================================== --- /dev/null +++ test/elf/linkerscript/phdrs-load-empty.test @@ -0,0 +1,26 @@ +/* +Test when load segment doesn't contain any attributes and generates wrong binary. + +RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o + +RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 +RUN: not llvm-readobj -program-headers %t1 &> %t1-error +RUN: FileCheck -check-prefix LOAD-EMPTY-PHDR %s < %t1-error +*/ + +ENTRY(_start) + +PHDRS +{ + text PT_LOAD; +} + +SECTIONS +{ + .text : { *(.text) } :text + .data : { *(.data) } +} + +/* +LOAD-EMPTY-PHDR: The file was not recognized as a valid object file +*/ Index: test/elf/linkerscript/phdrs-load-filehdr.test =================================================================== --- /dev/null +++ test/elf/linkerscript/phdrs-load-filehdr.test @@ -0,0 +1,26 @@ +/* +Test when load segment contains only FILEHDR attribute and provides no header information. + +RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o + +RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 +RUN: llvm-readobj -program-headers %t1 | FileCheck -check-prefix LOAD-FILEHDR-PHDR %s +*/ + +ENTRY(_start) + +PHDRS +{ + text PT_LOAD FILEHDR; +} + +SECTIONS +{ + .text : { *(.text) } :text + .data : { *(.data) } +} + +/* +LOAD-FILEHDR-PHDR-NOT: Type: PT_LOAD (0x1) +LOAD-FILEHDR-PHDR-NOT: VirtualAddress: 0x400000 +*/ Index: test/elf/linkerscript/phdrs-load-phdrs.test =================================================================== --- /dev/null +++ test/elf/linkerscript/phdrs-load-phdrs.test @@ -0,0 +1,26 @@ +/* +Test when load segment contains only PHDRS attribute and generates wrong binary. + +RUN: yaml2obj -format=elf %p/Inputs/simple.o.yaml -o=%t.o + +RUN: lld -flavor gnu -target x86_64 -T %s %t.o -static -o %t1 +RUN: not llvm-readobj -program-headers %t1 &> %t1-error +RUN: FileCheck -check-prefix LOAD-PHDRS-PHDR %s < %t1-error +*/ + +ENTRY(_start) + +PHDRS +{ + text PT_LOAD PHDRS; +} + +SECTIONS +{ + .text : { *(.text) } :text + .data : { *(.data) } +} + +/* +LOAD-PHDRS-PHDR: The file was not recognized as a valid object file +*/ Index: test/elf/linkerscript/phdrs-misplaced-program.test =================================================================== --- test/elf/linkerscript/phdrs-misplaced-program.test +++ test/elf/linkerscript/phdrs-misplaced-program.test @@ -11,7 +11,7 @@ PHDRS { - text PT_LOAD; + text PT_LOAD FILEHDR PHDRS; header PT_PHDR PHDRS; } Index: test/elf/linkerscript/phdrs-no-program.test =================================================================== --- test/elf/linkerscript/phdrs-no-program.test +++ test/elf/linkerscript/phdrs-no-program.test @@ -11,7 +11,7 @@ PHDRS { - text PT_LOAD; + text PT_LOAD FILEHDR PHDRS; } SECTIONS Index: test/elf/linkerscript/phdrs-one-none.test =================================================================== --- test/elf/linkerscript/phdrs-one-none.test +++ test/elf/linkerscript/phdrs-one-none.test @@ -12,7 +12,7 @@ PHDRS { - text PT_LOAD; + text PT_LOAD FILEHDR PHDRS; } SECTIONS Index: test/elf/linkerscript/phdrs-program-good-phdrs.test =================================================================== --- test/elf/linkerscript/phdrs-program-good-phdrs.test +++ test/elf/linkerscript/phdrs-program-good-phdrs.test @@ -12,7 +12,7 @@ PHDRS { header PT_PHDR PHDRS; - text PT_LOAD PHDRS; + text PT_LOAD FILEHDR PHDRS; } SECTIONS Index: test/elf/linkerscript/phdrs-same-flags.test =================================================================== --- test/elf/linkerscript/phdrs-same-flags.test +++ test/elf/linkerscript/phdrs-same-flags.test @@ -12,7 +12,7 @@ PHDRS { - text PT_LOAD FLAGS(0x4); + text PT_LOAD FILEHDR PHDRS FLAGS(0x4); } SECTIONS Index: test/elf/linkerscript/phdrs-same.test =================================================================== --- test/elf/linkerscript/phdrs-same.test +++ test/elf/linkerscript/phdrs-same.test @@ -12,7 +12,7 @@ PHDRS { - text PT_LOAD; + text PT_LOAD FILEHDR PHDRS; } SECTIONS