Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -21,6 +21,25 @@ class ScriptParser; +// Struct for SECTIONS command, each one +// contains list of input section names and +// list of PHDR's names this sections are attachecd to. +struct OutSecDesc { + std::vector InputSections; + std::vector Phdrs; +}; + +// Entity of header description for PHDRS command. +// Each PHDR can contain custom flags, elf and program header +// flags. Name and type are mandatory to have. +struct PhdrDesc { + StringRef Name; + uint32_t Type; + uint32_t Flags = (uint32_t)-1; + bool HasFileHdr = false; + bool HasPhdrs = false; +}; + class LinkerScript { friend class ScriptParser; @@ -34,11 +53,17 @@ int compareSections(StringRef A, StringRef B); void finalize(); -private: + bool hasCustomPhdrs() { return !Phdrs.empty(); } + // Map for SECTIONS command. The key is output section name - // and a value is a list of input section names. - llvm::MapVector> Sections; + // and a value is a OutSecDesc which contains list of input sections and + // also a list of program headers if PHDRS command is used. + llvm::MapVector Sections; + // List of Phdrs for PHDRS command. + std::vector Phdrs; + +private: // Inverse map of Sections. llvm::DenseMap RevSections; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -17,20 +17,22 @@ #include "Config.h" #include "Driver.h" #include "SymbolTable.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/StringSaver.h" using namespace llvm; +using namespace llvm::ELF; using namespace lld; using namespace lld::elf2; LinkerScript *elf2::Script; void LinkerScript::finalize() { - for (const std::pair> &P : Sections) - for (StringRef S : P.second) + for (const std::pair &P : Sections) + for (StringRef S : P.second.InputSections) RevSections[S] = P.first; } @@ -65,6 +67,7 @@ static StringRef skipSpace(StringRef S); bool atEOF(); StringRef next(); + StringRef peek(); bool skip(StringRef Tok); void expect(StringRef Expect); @@ -78,10 +81,13 @@ void readOutput(); void readOutputArch(); void readOutputFormat(); + void readPhdrs(); void readSearchDir(); void readSections(); void readOutputSectionDescription(); + uint32_t readInteger(); + uint32_t readPhdrType(); StringSaver Saver; std::vector Tokens; @@ -109,6 +115,8 @@ readOutputArch(); } else if (Tok == "OUTPUT_FORMAT") { readOutputFormat(); + } else if (Tok == "PHDRS") { + readPhdrs(); } else if (Tok == "SEARCH_DIR") { readSearchDir(); } else if (Tok == "SECTIONS") { @@ -183,6 +191,12 @@ // An errneous token is handled as if it were the last token before EOF. bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; } +StringRef ScriptParser::peek() { + if (atEOF()) + error("unexpected EOF"); + return Tokens[Pos]; +} + StringRef ScriptParser::next() { if (Error) return ""; @@ -336,6 +350,60 @@ expect(")"); } +uint32_t ScriptParser::readInteger() { + StringRef Tok = next(); + uint32_t Val; + if (Tok.getAsInteger(0, Val)) + error("Integer can't be parsed: " + Tok); + return Val; +} + +void ScriptParser::readPhdrs() { + expect("{"); + while (!skip("}")) { + PhdrDesc &Hdr = *Script->Phdrs.emplace(Script->Phdrs.end(), PhdrDesc{}); + Hdr.Name = next(); + Hdr.Type = readPhdrType(); + while (!skip(";")) { + StringRef Tok = next(); + if (Tok == "FLAGS") { + expect("("); + Hdr.Flags = readInteger(); + expect(")"); + continue; + } + if (Tok == "PHDRS") + Hdr.HasPhdrs = true; + else if (Tok == "FILEHDR") + Hdr.HasFileHdr = true; + else + error("Unknown header attribute " + Tok); + } + } +} + +uint32_t ScriptParser::readPhdrType() { + StringRef Tok = next(); + if (Tok == "PT_NULL") + return PT_NULL; + if (Tok == "PT_LOAD") + return PT_LOAD; + if (Tok == "PT_DYNAMIC") + return PT_DYNAMIC; + if (Tok == "PT_INTERP") + return PT_INTERP; + if (Tok == "PT_NOTE") + return PT_NOTE; + if (Tok == "PT_SHLIB") + return PT_SHLIB; + if (Tok == "PT_PHDR") + return PT_PHDR; + if (Tok == "PT_TLS") + return PT_TLS; + error("Wrong header type " + Tok); + return PT_NULL; +} + void ScriptParser::readSearchDir() { expect("("); Config->SearchPaths.push_back(next()); @@ -349,14 +417,30 @@ } void ScriptParser::readOutputSectionDescription() { - std::vector &V = Script->Sections[next()]; + OutSecDesc &Sec = Script->Sections[next()]; expect(":"); expect("{"); while (!Error && !skip("}")) { next(); // Skip input file name. expect("("); while (!Error && !skip(")")) - V.push_back(next()); + Sec.InputSections.push_back(next()); + } + + // Read headers of the section as zero or more tokens in the form of ':phdr'. + for (;;) { + StringRef Tok = peek(); + if (Tok[0] != ':') + break; + // Swallow peeked token. + next(); + // If token is of one symbol, it's a separate ':', so go to the next token. + // Otherwise, skip starting ':' in header name. + if (Tok.size() == 1) + Tok = next(); + else + Tok = Tok.substr(1); + Sec.Phdrs.emplace_back(Tok); } } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -68,6 +68,7 @@ void scanRelocs(InputSection &C); void scanRelocs(InputSectionBase &S, const Elf_Shdr &RelSec); void createPhdrs(); + void createPhdrsFromScript(); void assignAddresses(); void fixAbsoluteSymbols(); bool openFile(); @@ -193,7 +194,10 @@ addReservedSymbols(); if (!createSections()) return; - createPhdrs(); + if (Script->hasCustomPhdrs()) + createPhdrsFromScript(); + else + createPhdrs(); assignAddresses(); fixAbsoluteSymbols(); if (!openFile()) @@ -1201,6 +1205,132 @@ return PT_LOAD; } +template void Writer::createPhdrsFromScript() { + // Reserve for total PHDRS amount + 1 for "NONE" synthetic PHDR. + Phdrs.reserve(Script->Phdrs.size() + 1); + + auto AddHdr = [this](unsigned Type) { + return &*Phdrs.emplace(Phdrs.end(), Type, 0); + }; + + auto AttachSec = [](Phdr &Hdr, OutputSectionBase *Sec) { + Hdr.Last = Sec; + if (!Hdr.First) + Hdr.First = Sec; + Hdr.H.p_align = std::max(Hdr.H.p_align, Sec->getAlign()); + Hdr.H.p_flags |= toPhdrFlags(Sec->getFlags()); + }; + + // Add each header specified in PHDRS command, build + // association map for phdrs lookup by name. + llvm::DenseMap NameToPhdr; + size_t FirstLoadId = (size_t)-1; + for (size_t I = 0, E = Script->Phdrs.size(); I != E; ++I) { + PhdrDesc &PH = Script->Phdrs[I]; + Phdr *Phdr = AddHdr(PH.Type); + NameToPhdr[PH.Name] = Phdr; + + if (I == 0) { + if (PH.Type != PT_PHDR) + error("First header is not PT_PHDR"); + if (!PH.HasPhdrs) + error("PHDRS is not set for PT_PHDR"); + AttachSec(*Phdr, Out::ProgramHeaders); + } + + if (PH.Type == PT_LOAD && FirstLoadId == (size_t)-1) { + // This is a restriction of current implementation: + // both FILEHDR and PHDRS must be set for first load segment. + if (!PH.HasFileHdr || !PH.HasPhdrs) + error("FILEHDR and PHDRS must be set for first PT_LOAD"); + FirstLoadId = I; + AttachSec(*Phdr, Out::ElfHeader); + } + } + + // Add synthetic NONE header. Sectons can be assigned to it, + // but it will not be emited. + if (NameToPhdr.count("NONE")) + error("'NONE' is reserved alias for PHDRS"); + NameToPhdr["NONE"] = AddHdr(PT_NULL); + size_t None = Phdrs.size() - 1; + + // Given a set of PHDR Names it returns the list + // of program headers to assign the output section Sec to. + // Performs validation that section not assigned to multiple PT_LOAD + // and that PHDR name itself is valid. + auto CreateSegmentList = [&](OutputSectionBase *Sec, + std::vector Names) { + bool HasLoad = false; + std::vector Out; + for (StringRef N : Names) { + auto HdrInMap = NameToPhdr.find(N); + if (HdrInMap == NameToPhdr.end()) { + error("Section " + Sec->getName() + + " assigned to non-existent header " + N); + return std::vector{}; + } + Phdr *Phdr = HdrInMap->second; + if (Phdr->H.p_type == PT_LOAD) { + if (HasLoad) + error("Output section " + Sec->getName() + + " in two PT_LOAD segments"); + HasLoad = true; + } + Out.push_back((*HdrInMap).second); + } + return Out; + }; + + // At first we should find the appropriate segments list for first output + // section(s). All sections will be put into this segment until we met the + // section that directly specifies where it should be placed to. + std::vector SegList; + for (OutputSectionBase *Sec : getSections()) { + auto S = Script->Sections.find(Sec->getName()); + if (S == Script->Sections.end()) + continue; + SegList = CreateSegmentList(Sec, S->second.Phdrs); + break; + } + + // Iterate over all output sections. Main aim is to assign + // them to the headers they belong to. + for (OutputSectionBase *Sec : getSections()) { + if (HasError || !(Sec->getFlags() & SHF_ALLOC)) + break; + // Find the section with the same name in linker script parameters. + auto S = Script->Sections.find(Sec->getName()); + auto E = Script->Sections.end(); + + // If section do not list any phdrs to attach to, then it should be attached + // to lastest ones. The same is when there is no description at all for + // section, but we attach only to LOAD segments then. We don't attach it to + // other headers types because otherwise for example PT_INTERP segment will + // pick up following orphan sections, which does not make sense. + // Otherwise - build list of segments to attach the current section. + // And add the output section to each segment. + bool UpdateList = S != E && !S->second.Phdrs.empty(); + if (UpdateList) + SegList = CreateSegmentList(Sec, S->second.Phdrs); + + if (SegList.empty()) + error("No sections assigned to PHDRS"); + + for (Phdr *Phdr : SegList) + if (Phdr->H.p_type == PT_LOAD || S != E) + AttachSec(*Phdr, Sec); + } + + // Erase synthetic "NONE" from final map. + Phdrs.erase(Phdrs.begin() + None); + + // Force use of flags that were set directly from linker script. + for (PhdrDesc &PH : Script->Phdrs) + if (PH.Flags != (uint32_t)-1) + NameToPhdr[PH.Name]->H.p_flags = PH.Flags; +} + // Decide which program headers to create and which sections to include in each // one. template void Writer::createPhdrs() { @@ -1368,7 +1498,8 @@ // so round up the size to make sure the offsets are correct. if (PHdr.H.p_type == PT_TLS) { Out::TlsPhdr = &H; - H.p_memsz = alignTo(H.p_memsz, H.p_align); + if (H.p_memsz) + H.p_memsz = alignTo(H.p_memsz, H.p_align); } } } Index: test/ELF/linkerscript-phdrs-errors.s =================================================================== --- test/ELF/linkerscript-phdrs-errors.s +++ test/ELF/linkerscript-phdrs-errors.s @@ -0,0 +1,106 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Unknown header type causes error. +# RUN: echo "PHDRS { \ +# RUN: unknown PT_UNKNOWN; \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=PHDRS-ERRTYPE %s < %t.log +# PHDRS-ERRTYPE: Wrong header type PT_UNKNOWN + +# Error if first header is not PT_PHDR. +# That the restriction of current implementation. +# RUN: echo "PHDRS { \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=PHDRS-NOT-PHDR %s < %t.log +# PHDRS-NOT-PHDR: First header is not PT_PHDR + +# Unknown header name causes error. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: .data : { *(.data) } :unknown \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=PHDRS-ERRNAME %s < %t.log +# PHDRS-ERRNAME: Section .data assigned to non-existent header unknown + +# In current implementation PHDRS should be set for PT_PHDR +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=PHDRS-ERRFLAG %s < %t.log +# PHDRS-ERRFLAG: PHDRS is not set for PT_PHDR + +# In current implementation FILEHDR and PHDRS +# keywords should be set for first PT_LOAD +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR; \ +# RUN: load PT_LOAD; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=LOADS-NOFLAGS %s < %t.log +# LOADS-NOFLAGS: FILEHDR and PHDRS must be set for first PT_LOAD + +# Error if sections are not assigned to any headers. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=PHDRS-NOTASSIGNED %s < %t.log +# PHDRS-NOTASSIGNED: No sections assigned to PHDRS + +# Error if NONE is used as phdr alias. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: NONE PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :NONE \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=NONE-RESERVED %s < %t.log +# NONE-RESERVED: 'NONE' is reserved alias for PHDRS + +# Error if section is in two or more PT_LOAD segments +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: text PT_LOAD FILEHDR PHDRS; \ +# RUN: data PT_LOAD; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :text :data \ +# RUN: }" > %t.script +# RUN: not ld.lld -o %t1 --script %t.script %t > %t.log 2>&1 +# RUN: FileCheck -check-prefix=TWO-LOADS %s < %t.log +# TWO-LOADS: Output section .text in two PT_LOAD segments + +.globl _start; +_start: + nop + +.section .data,"aw" +.quad 10, 10, 20, 20 +.section .bss,"",@nobits +.short 0 Index: test/ELF/linkerscript-phdrs-flags.s =================================================================== --- test/ELF/linkerscript-phdrs-flags.s +++ test/ELF/linkerscript-phdrs-flags.s @@ -0,0 +1,64 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Check FLAGS attribute for header (HEX). +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS FLAGS(0x2); \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t +# RUN: llvm-readobj -program-headers %t | \ +# RUN: FileCheck -check-prefix=PHDRS-FLAGS-HEX %s +# PHDRS-FLAGS-HEX: ProgramHeader { +# PHDRS-FLAGS-HEX: Type: PT_LOAD +# PHDRS-FLAGS-HEX: Flags [ (0x2) +# PHDRS-FLAGS-HEX-NEXT: PF_W (0x2) +# PHDRS-FLAGS-HEX-NEXT: ] + +# Check FLAGS attribute for header (OCT). +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS FLAGS(01); \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t +# RUN: llvm-readobj -program-headers %t | \ +# RUN: FileCheck -check-prefix=PHDRS-FLAGS-OCT %s +# PHDRS-FLAGS-OCT: ProgramHeader { +# PHDRS-FLAGS-OCT: Type: PT_LOAD +# PHDRS-FLAGS-OCT: Flags [ (0x1) +# PHDRS-FLAGS-OCT-NEXT: PF_X (0x1) +# PHDRS-FLAGS-OCT-NEXT: ] + +# Check FLAGS attribute for header (DEC). +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS FLAGS(7); \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t +# RUN: llvm-readobj -program-headers %t | \ +# RUN: FileCheck -check-prefix=PHDRS-FLAGS-DEC %s +# PHDRS-FLAGS-DEC: ProgramHeader { +# PHDRS-FLAGS-DEC: Type: PT_LOAD +# PHDRS-FLAGS-DEC: Flags [ (0x7) +# PHDRS-FLAGS-DEC-NEXT: PF_R (0x4) +# PHDRS-FLAGS-DEC-NEXT: PF_W (0x2) +# PHDRS-FLAGS-DEC-NEXT: PF_X (0x1) +# PHDRS-FLAGS-DEC-NEXT: ] + +.globl _start; +_start: + nop + +.section .data,"aw" +.quad 10, 10, 20, 20 +.section .bss,"",@nobits +.short 0 Index: test/ELF/linkerscript-phdrs-tls.s =================================================================== --- test/ELF/linkerscript-phdrs-tls.s +++ test/ELF/linkerscript-phdrs-tls.s @@ -0,0 +1,86 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t-tls + +# Map TLS sections to the specific header. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: tls PT_TLS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .tdata : { *(.tdata) } :tls :load \ +# RUN: .tbss : { *(.tbss) } \ +# RUN: .text : { *(.text) } :load \ +# RUN: .data : { *(.data) } \ +# RUN: .bss : { *(.bss) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %ttls_1 --script %t.script %t-tls +# RUN: llvm-readobj -program-headers %ttls_1 | \ +# RUN: FileCheck -check-prefix=PHDRS-TLS %s +# RUN: llvm-objdump -section-headers %ttls_1 | \ +# RUN: FileCheck -check-prefix=SEC-TLS %s +# PHDRS-TLS: ProgramHeaders [ +# PHDRS-TLS-NEXT: ProgramHeader { +# PHDRS-TLS-NEXT: Type: PT_PHDR +# PHDRS-TLS-NEXT: Offset: 0x40 +# PHDRS-TLS-NEXT: VirtualAddress: 0x10040 +# PHDRS-TLS-NEXT: PhysicalAddress: 0x10040 +# PHDRS-TLS-NEXT: FileSize: 168 +# PHDRS-TLS-NEXT: MemSize: 168 +# PHDRS-TLS-NEXT: Flags [ +# PHDRS-TLS-NEXT: PF_R +# PHDRS-TLS-NEXT: ] +# PHDRS-TLS-NEXT: Alignment: 8 +# PHDRS-TLS-NEXT: } +# PHDRS-TLS-NEXT: ProgramHeader { +# PHDRS-TLS-NEXT: Type: PT_LOAD +# PHDRS-TLS-NEXT: Offset: 0x0 +# PHDRS-TLS-NEXT: VirtualAddress: 0x10000 +# PHDRS-TLS-NEXT: PhysicalAddress: 0x10000 +# PHDRS-TLS-NEXT: FileSize: 297 +# PHDRS-TLS-NEXT: MemSize: 299 +# PHDRS-TLS-NEXT: Flags [ +# PHDRS-TLS-NEXT: PF_R +# PHDRS-TLS-NEXT: PF_W +# PHDRS-TLS-NEXT: PF_X +# PHDRS-TLS-NEXT: ] +# PHDRS-TLS-NEXT: Alignment: 4096 +# PHDRS-TLS-NEXT: } +# PHDRS-TLS-NEXT: ProgramHeader { +# PHDRS-TLS-NEXT: Type: PT_TLS +# PHDRS-TLS-NEXT: Offset: 0xE8 +# PHDRS-TLS-NEXT: VirtualAddress: 0x100E8 +# PHDRS-TLS-NEXT: PhysicalAddress: 0x100E8 +# PHDRS-TLS-NEXT: FileSize: 32 +# PHDRS-TLS-NEXT: MemSize: 34 +# PHDRS-TLS-NEXT: Flags [ +# PHDRS-TLS-NEXT: PF_R +# PHDRS-TLS-NEXT: PF_W +# PHDRS-TLS-NEXT: ] +# PHDRS-TLS-NEXT: Alignment: 1 +# PHDRS-TLS-NEXT: } +# PHDRS-TLS-NEXT: ] + +# Idx Name Size Address +# SEC-TLS: 0 00000000 0000000000000000 +# SEC-TLS-NEXT: 1 .tdata 00000020 00000000000100e8 DATA +# SEC-TLS-NEXT: 2 .tbss 00000002 0000000000010108 BSS +# SEC-TLS-NEXT: 3 .text 00000001 0000000000010108 TEXT DATA +# SEC-TLS-NEXT: 4 .data 00000020 0000000000010109 DATA +# SEC-TLS-NEXT: 5 .bss 00000002 0000000000010129 BSS +# SEC-TLS-NEXT: 6 .symtab 00000060 0000000000000000 +# SEC-TLS-NEXT: 7 .shstrtab 00000039 0000000000000000 +# SEC-TLS-NEXT: 8 .strtab 00000015 0000000000000000 + +.globl _start; +_start: + nop + +.section .data,"aw" +.quad 10, 10, 20, 20 +.section .bss,"",@nobits +.short 0 +.section .tbss,"awT",@nobits +.short 0 +.section .tdata,"awT" +.quad 20, 20, 10, 10 Index: test/ELF/linkerscript-phdrs.s =================================================================== --- test/ELF/linkerscript-phdrs.s +++ test/ELF/linkerscript-phdrs.s @@ -0,0 +1,589 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# Empty PHDRS command. +# RUN: echo "PHDRS {}" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -s -program-headers %t1 | \ +# RUN: FileCheck -check-prefix=PHDRS-DEFAULT %s +# PHDRS-DEFAULT: Sections [ +# PHDRS-DEFAULT-NEXT: Section { +# PHDRS-DEFAULT-NEXT: Index: 0 +# PHDRS-DEFAULT-NEXT: Name: (0) +# PHDRS-DEFAULT-NEXT: Type: SHT_NULL +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Address: 0x0 +# PHDRS-DEFAULT-NEXT: Offset: 0x0 +# PHDRS-DEFAULT-NEXT: Size: 0 +# PHDRS-DEFAULT-NEXT: Link: 0 +# PHDRS-DEFAULT-NEXT: Info: 0 +# PHDRS-DEFAULT-NEXT: AddressAlignment: 0 +# PHDRS-DEFAULT-NEXT: EntrySize: 0 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: Section { +# PHDRS-DEFAULT-NEXT: Index: 1 +# PHDRS-DEFAULT-NEXT: Name: .text +# PHDRS-DEFAULT-NEXT: Type: SHT_PROGBITS +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: SHF_ALLOC +# PHDRS-DEFAULT-NEXT: SHF_EXECINSTR +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Address: 0x11000 +# PHDRS-DEFAULT-NEXT: Offset: 0x1000 +# PHDRS-DEFAULT-NEXT: Size: 14 +# PHDRS-DEFAULT-NEXT: Link: 0 +# PHDRS-DEFAULT-NEXT: Info: 0 +# PHDRS-DEFAULT-NEXT: AddressAlignment: 4 +# PHDRS-DEFAULT-NEXT: EntrySize: 0 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: Section { +# PHDRS-DEFAULT-NEXT: Index: 2 +# PHDRS-DEFAULT-NEXT: Name: .data +# PHDRS-DEFAULT-NEXT: Type: SHT_PROGBITS +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: SHF_ALLOC +# PHDRS-DEFAULT-NEXT: SHF_WRITE +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Address: 0x12000 +# PHDRS-DEFAULT-NEXT: Offset: 0x2000 +# PHDRS-DEFAULT-NEXT: Size: 32 +# PHDRS-DEFAULT-NEXT: Link: 0 +# PHDRS-DEFAULT-NEXT: Info: 0 +# PHDRS-DEFAULT-NEXT: AddressAlignment: 1 +# PHDRS-DEFAULT-NEXT: EntrySize: 0 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: Section { +# PHDRS-DEFAULT-NEXT: Index: 3 +# PHDRS-DEFAULT-NEXT: Name: .bss +# PHDRS-DEFAULT-NEXT: Type: SHT_NOBITS +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: SHF_ALLOC +# PHDRS-DEFAULT-NEXT: SHF_WRITE +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Address: 0x12020 +# PHDRS-DEFAULT-NEXT: Offset: 0x2020 +# PHDRS-DEFAULT-NEXT: Size: 2 +# PHDRS-DEFAULT-NEXT: Link: 0 +# PHDRS-DEFAULT-NEXT: Info: 0 +# PHDRS-DEFAULT-NEXT: AddressAlignment: 1 +# PHDRS-DEFAULT-NEXT: EntrySize: 0 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: Section { +# PHDRS-DEFAULT-NEXT: Index: 4 +# PHDRS-DEFAULT-NEXT: Name: .symtab +# PHDRS-DEFAULT-NEXT: Type: SHT_SYMTAB +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Address: 0x0 +# PHDRS-DEFAULT-NEXT: Offset: 0x2020 +# PHDRS-DEFAULT-NEXT: Size: 48 +# PHDRS-DEFAULT-NEXT: Link: 6 +# PHDRS-DEFAULT-NEXT: Info: 1 +# PHDRS-DEFAULT-NEXT: AddressAlignment: 8 +# PHDRS-DEFAULT-NEXT: EntrySize: 24 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: Section { +# PHDRS-DEFAULT-NEXT: Index: 5 +# PHDRS-DEFAULT-NEXT: Name: .shstrtab +# PHDRS-DEFAULT-NEXT: Type: SHT_STRTAB +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Address: 0x0 +# PHDRS-DEFAULT-NEXT: Offset: 0x2050 +# PHDRS-DEFAULT-NEXT: Size: 44 +# PHDRS-DEFAULT-NEXT: Link: 0 +# PHDRS-DEFAULT-NEXT: Info: 0 +# PHDRS-DEFAULT-NEXT: AddressAlignment: 1 +# PHDRS-DEFAULT-NEXT: EntrySize: 0 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: Section { +# PHDRS-DEFAULT-NEXT: Index: 6 +# PHDRS-DEFAULT-NEXT: Name: .strtab +# PHDRS-DEFAULT-NEXT: Type: SHT_STRTAB +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Address: 0x0 +# PHDRS-DEFAULT-NEXT: Offset: 0x207C +# PHDRS-DEFAULT-NEXT: Size: 8 +# PHDRS-DEFAULT-NEXT: Link: 0 +# PHDRS-DEFAULT-NEXT: Info: 0 +# PHDRS-DEFAULT-NEXT: AddressAlignment: 1 +# PHDRS-DEFAULT-NEXT: EntrySize: 0 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: ProgramHeaders [ +# PHDRS-DEFAULT-NEXT: ProgramHeader { +# PHDRS-DEFAULT-NEXT: Type: PT_PHDR +# PHDRS-DEFAULT-NEXT: Offset: 0x40 +# PHDRS-DEFAULT-NEXT: VirtualAddress: 0x10040 +# PHDRS-DEFAULT-NEXT: PhysicalAddress: 0x10040 +# PHDRS-DEFAULT-NEXT: FileSize: 280 +# PHDRS-DEFAULT-NEXT: MemSize: 280 +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: PF_R +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Alignment: 8 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: ProgramHeader { +# PHDRS-DEFAULT-NEXT: Type: PT_LOAD +# PHDRS-DEFAULT-NEXT: Offset: 0x0 +# PHDRS-DEFAULT-NEXT: VirtualAddress: 0x10000 +# PHDRS-DEFAULT-NEXT: PhysicalAddress: 0x10000 +# PHDRS-DEFAULT-NEXT: FileSize: 344 +# PHDRS-DEFAULT-NEXT: MemSize: 344 +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: PF_R +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Alignment: 4096 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: ProgramHeader { +# PHDRS-DEFAULT-NEXT: Type: PT_LOAD +# PHDRS-DEFAULT-NEXT: Offset: 0x1000 +# PHDRS-DEFAULT-NEXT: VirtualAddress: 0x11000 +# PHDRS-DEFAULT-NEXT: PhysicalAddress: 0x11000 +# PHDRS-DEFAULT-NEXT: FileSize: 14 +# PHDRS-DEFAULT-NEXT: MemSize: 14 +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: PF_R +# PHDRS-DEFAULT-NEXT: PF_X +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Alignment: 4096 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: ProgramHeader { +# PHDRS-DEFAULT-NEXT: Type: PT_LOAD +# PHDRS-DEFAULT-NEXT: Offset: 0x2000 +# PHDRS-DEFAULT-NEXT: VirtualAddress: 0x12000 +# PHDRS-DEFAULT-NEXT: PhysicalAddress: 0x12000 +# PHDRS-DEFAULT-NEXT: FileSize: 32 +# PHDRS-DEFAULT-NEXT: MemSize: 34 +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: PF_R +# PHDRS-DEFAULT-NEXT: PF_W +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Alignment: 4096 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: ProgramHeader { +# PHDRS-DEFAULT-NEXT: Type: PT_GNU_STACK +# PHDRS-DEFAULT-NEXT: Offset: 0x0 +# PHDRS-DEFAULT-NEXT: VirtualAddress: 0x0 +# PHDRS-DEFAULT-NEXT: PhysicalAddress: 0x0 +# PHDRS-DEFAULT-NEXT: FileSize: 0 +# PHDRS-DEFAULT-NEXT: MemSize: 0 +# PHDRS-DEFAULT-NEXT: Flags [ +# PHDRS-DEFAULT-NEXT: PF_R +# PHDRS-DEFAULT-NEXT: PF_W +# PHDRS-DEFAULT-NEXT: ] +# PHDRS-DEFAULT-NEXT: Alignment: 0 +# PHDRS-DEFAULT-NEXT: } +# PHDRS-DEFAULT-NEXT: ] + +# Map all sections to one header. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t2 --script %t.script %t +# RUN: llvm-readobj -program-headers %t2 | \ +# RUN: FileCheck -check-prefix=PHDRS-ONE-ALL %s +# RUN: llvm-objdump -section-headers %t2 | \ +# RUN: FileCheck -check-prefix=SEC-ONE-ALL %s +# PHDRS-ONE-ALL: ProgramHeaders [ +# PHDRS-ONE-ALL-NEXT: ProgramHeader { +# PHDRS-ONE-ALL-NEXT: Type: PT_PHDR +# PHDRS-ONE-ALL-NEXT: Offset: 0x40 +# PHDRS-ONE-ALL-NEXT: VirtualAddress: 0x10040 +# PHDRS-ONE-ALL-NEXT: PhysicalAddress: 0x10040 +# PHDRS-ONE-ALL-NEXT: FileSize: 112 +# PHDRS-ONE-ALL-NEXT: MemSize: 112 +# PHDRS-ONE-ALL-NEXT: Flags [ +# PHDRS-ONE-ALL-NEXT: PF_R (0x4) +# PHDRS-ONE-ALL-NEXT: ] +# PHDRS-ONE-ALL-NEXT: Alignment: 8 +# PHDRS-ONE-ALL-NEXT: } +# PHDRS-ONE-ALL-NEXT: ProgramHeader { +# PHDRS-ONE-ALL-NEXT: Type: PT_LOAD +# PHDRS-ONE-ALL-NEXT: Offset: 0x0 +# PHDRS-ONE-ALL-NEXT: VirtualAddress: 0x10000 +# PHDRS-ONE-ALL-NEXT: PhysicalAddress: 0x10000 +# PHDRS-ONE-ALL-NEXT: FileSize: 222 +# PHDRS-ONE-ALL-NEXT: MemSize: 224 +# PHDRS-ONE-ALL-NEXT: Flags [ +# PHDRS-ONE-ALL-NEXT: PF_R (0x4) +# PHDRS-ONE-ALL-NEXT: PF_W (0x2) +# PHDRS-ONE-ALL-NEXT: PF_X (0x1) +# PHDRS-ONE-ALL-NEXT: ] +# PHDRS-ONE-ALL-NEXT: Alignment: 4096 +# PHDRS-ONE-ALL-NEXT: } +# PHDRS-ONE-ALL-NEXT: ] +# Idx Name Size Address +# SEC-ONE-ALL: 0 00000000 0000000000000000 +# SEC-ONE-ALL-NEXT: 1 .text 0000000e 00000000000100b0 TEXT DATA +# SEC-ONE-ALL-NEXT: 2 .data 00000020 00000000000100be DATA +# SEC-ONE-ALL-NEXT: 3 .bss 00000002 00000000000100de BSS +# SEC-ONE-ALL-NEXT: 4 .symtab 00000030 0000000000000000 +# SEC-ONE-ALL-NEXT: 5 .shstrtab 0000002c 0000000000000000 +# SEC-ONE-ALL-NEXT: 6 .strtab 00000008 0000000000000000 + +# Map all sections to one header, +# but separate the header name from the ':' sign. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } : load \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t2_1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t2_1 | \ +# RUN: FileCheck -check-prefix=PHDRS-ONE-ALL %s +# RUN: llvm-objdump -section-headers %t2_1 | \ +# RUN: FileCheck -check-prefix=SEC-ONE-ALL %s + +# Map all sections to one header skipping 'NONE' header +# if it's not the only available. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load :NONE \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t2_2 --script %t.script %t +# RUN: llvm-readobj -program-headers %t2_2 | \ +# RUN: FileCheck -check-prefix=PHDRS-ONE-ALL %s +# RUN: llvm-objdump -section-headers %t2_2 | \ +# RUN: FileCheck -check-prefix=SEC-ONE-ALL %s + +# Map sections to different headers explicitly. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: load2 PT_LOAD; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: .data : { *(.data) } :load \ +# RUN: .bss : { *(.bss) } :load2 \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t4 --script %t.script %t +# RUN: llvm-readobj -program-headers %t4 | \ +# RUN: FileCheck -check-prefix=PHDRS-DIFF %s +# RUN: llvm-objdump -section-headers %t4 | \ +# RUN: FileCheck -check-prefix=SEC-DIFF %s +# PHDRS-DIFF: ProgramHeaders [ +# PHDRS-DIFF-NEXT: ProgramHeader { +# PHDRS-DIFF-NEXT: Type: PT_PHDR +# PHDRS-DIFF-NEXT: Offset: 0x40 +# PHDRS-DIFF-NEXT: VirtualAddress: 0x10040 +# PHDRS-DIFF-NEXT: PhysicalAddress: 0x10040 +# PHDRS-DIFF-NEXT: FileSize: 168 +# PHDRS-DIFF-NEXT: MemSize: 168 +# PHDRS-DIFF-NEXT: Flags [ +# PHDRS-DIFF-NEXT: PF_R (0x4) +# PHDRS-DIFF-NEXT: ] +# PHDRS-DIFF-NEXT: Alignment: 8 +# PHDRS-DIFF-NEXT: } +# PHDRS-DIFF-NEXT: ProgramHeader { +# PHDRS-DIFF-NEXT: Type: PT_LOAD +# PHDRS-DIFF-NEXT: Offset: 0x0 +# PHDRS-DIFF-NEXT: VirtualAddress: 0x10000 +# PHDRS-DIFF-NEXT: PhysicalAddress: 0x10000 +# PHDRS-DIFF-NEXT: FileSize: 278 +# PHDRS-DIFF-NEXT: MemSize: 278 +# PHDRS-DIFF-NEXT: Flags [ +# PHDRS-DIFF-NEXT: PF_R +# PHDRS-DIFF-NEXT: PF_W +# PHDRS-DIFF-NEXT: PF_X +# PHDRS-DIFF-NEXT: ] +# PHDRS-DIFF-NEXT: Alignment: 4096 +# PHDRS-DIFF-NEXT: } +# PHDRS-DIFF-NEXT: ProgramHeader { +# PHDRS-DIFF-NEXT: Type: PT_LOAD +# PHDRS-DIFF-NEXT: Offset: 0x1000 +# PHDRS-DIFF-NEXT: VirtualAddress: 0x11000 +# PHDRS-DIFF-NEXT: PhysicalAddress: 0x11000 +# PHDRS-DIFF-NEXT: FileSize: 0 +# PHDRS-DIFF-NEXT: MemSize: 2 +# PHDRS-DIFF-NEXT: Flags [ +# PHDRS-DIFF-NEXT: PF_R +# PHDRS-DIFF-NEXT: PF_W +# PHDRS-DIFF-NEXT: ] +# PHDRS-DIFF-NEXT: Alignment: 4096 +# PHDRS-DIFF-NEXT: } +# PHDRS-DIFF-NEXT: ] +# SEC-DIFF: Idx Name Size Address Type +# SEC-DIFF-NEXT: 0 00000000 0000000000000000 +# SEC-DIFF-NEXT: 1 .text 0000000e 00000000000100e8 TEXT DATA +# SEC-DIFF-NEXT: 2 .data 00000020 00000000000100f6 DATA +# SEC-DIFF-NEXT: 3 .bss 00000002 0000000000011000 BSS +# SEC-DIFF-NEXT: 4 .symtab 00000030 0000000000000000 +# SEC-DIFF-NEXT: 5 .shstrtab 0000002c 0000000000000000 +# SEC-DIFF-NEXT: 6 .strtab 00000008 0000000000000000 + +# Map sections to different headers implicitly. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: load2 PT_LOAD; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: .data : { *(.data) } \ +# RUN: .bss : { *(.bss) } :load2 \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t5 --script %t.script %t +# RUN: llvm-readobj -program-headers %t5 | \ +# RUN: FileCheck -check-prefix=PHDRS-DIFF %s +# RUN: llvm-objdump -section-headers %t5 | \ +# RUN: FileCheck -check-prefix=SEC-DIFF %s + +# Map sections appearing before the section with first assigned header +# to that header (.text is mapped to the 'load' header). +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: load2 PT_LOAD; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .data : { *(.data) } :load \ +# RUN: .bss : { *(.bss) } :load2 \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t6 --script %t.script %t +# RUN: llvm-readobj -program-headers %t6 | \ +# RUN: FileCheck -check-prefix=PHDRS-DIFF %s +# RUN: llvm-objdump -section-headers %t6 | \ +# RUN: FileCheck -check-prefix=SEC-DIFF %s + +# This shows that: +# 1) .interp is mapped to PT_INTERP segment. +# 2) Following sections like .text is an orphan section and not listed explicitely. +# They does not inherit any segment type other than PT_LOAD. +# That is reasonable behavior because otherwise PT_INTERP segment will pick up +# following orphan sections, which does not make sense. +# 3) .data is placed to data as specified. +# 4) .dynamic is placed both in dynamic and data segments. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: interp PT_INTERP; \ +# RUN: text PT_LOAD FILEHDR PHDRS; \ +# RUN: data PT_LOAD; \ +# RUN: dynamic PT_DYNAMIC; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .interp : { *(.interp) } :interp :text \ +# RUN: .data : { *(.data) } :data \ +# RUN: .dynamic : { *(.dynamic) } :data :dynamic \ +# RUN: }" > %t.script +# RUN: ld.lld -shared -o %t7.so %t +# RUN: ld.lld %t7.so -o %t7 -dynamic-linker /lib64/ld-linux-x86-64.so.2 --script %t.script %t +# RUN: llvm-readobj -program-headers %t7 | \ +# RUN: FileCheck -check-prefix=PHDRS-COMPLEX %s +# RUN: llvm-objdump -section-headers %t7 | \ +# RUN: FileCheck -check-prefix=SEC-COMPLEX %s +# PHDRS-COMPLEX: ProgramHeaders [ +# PHDRS-COMPLEX-NEXT: ProgramHeader { +# PHDRS-COMPLEX-NEXT: Type: PT_PHDR +# PHDRS-COMPLEX-NEXT: Offset: 0x40 +# PHDRS-COMPLEX-NEXT: VirtualAddress: 0x10040 +# PHDRS-COMPLEX-NEXT: PhysicalAddress: 0x10040 +# PHDRS-COMPLEX-NEXT: FileSize: 280 +# PHDRS-COMPLEX-NEXT: MemSize: 280 +# PHDRS-COMPLEX-NEXT: Flags [ +# PHDRS-COMPLEX-NEXT: PF_R +# PHDRS-COMPLEX-NEXT: ] +# PHDRS-COMPLEX-NEXT: Alignment: 8 +# PHDRS-COMPLEX-NEXT: } +# PHDRS-COMPLEX-NEXT: ProgramHeader { +# PHDRS-COMPLEX-NEXT: Type: PT_INTERP +# PHDRS-COMPLEX-NEXT: Offset: 0x158 +# PHDRS-COMPLEX-NEXT: VirtualAddress: 0x10158 +# PHDRS-COMPLEX-NEXT: PhysicalAddress: 0x10158 +# PHDRS-COMPLEX-NEXT: FileSize: 28 +# PHDRS-COMPLEX-NEXT: MemSize: 28 +# PHDRS-COMPLEX-NEXT: Flags [ +# PHDRS-COMPLEX-NEXT: PF_R +# PHDRS-COMPLEX-NEXT: ] +# PHDRS-COMPLEX-NEXT: Alignment: 1 +# PHDRS-COMPLEX-NEXT: } +# PHDRS-COMPLEX-NEXT: ProgramHeader { +# PHDRS-COMPLEX-NEXT: Type: PT_LOAD +# PHDRS-COMPLEX-NEXT: Offset: 0x0 +# PHDRS-COMPLEX-NEXT: VirtualAddress: 0x10000 +# PHDRS-COMPLEX-NEXT: PhysicalAddress: 0x10000 +# PHDRS-COMPLEX-NEXT: FileSize: 562 +# PHDRS-COMPLEX-NEXT: MemSize: 562 +# PHDRS-COMPLEX-NEXT: Flags [ +# PHDRS-COMPLEX-NEXT: PF_R +# PHDRS-COMPLEX-NEXT: PF_X +# PHDRS-COMPLEX-NEXT: ] +# PHDRS-COMPLEX-NEXT: Alignment: 4096 +# PHDRS-COMPLEX-NEXT: } +# PHDRS-COMPLEX-NEXT: ProgramHeader { +# PHDRS-COMPLEX-NEXT: Type: PT_LOAD +# PHDRS-COMPLEX-NEXT: Offset: 0x1000 +# PHDRS-COMPLEX-NEXT: VirtualAddress: 0x11000 +# PHDRS-COMPLEX-NEXT: PhysicalAddress: 0x11000 +# PHDRS-COMPLEX-NEXT: FileSize: 160 +# PHDRS-COMPLEX-NEXT: MemSize: 162 +# PHDRS-COMPLEX-NEXT: Flags [ +# PHDRS-COMPLEX-NEXT: PF_R +# PHDRS-COMPLEX-NEXT: PF_W +# PHDRS-COMPLEX-NEXT: ] +# PHDRS-COMPLEX-NEXT: Alignment: 4096 +# PHDRS-COMPLEX-NEXT: } +# PHDRS-COMPLEX-NEXT: ProgramHeader { +# PHDRS-COMPLEX-NEXT: Type: PT_DYNAMIC +# PHDRS-COMPLEX-NEXT: Offset: 0x1020 +# PHDRS-COMPLEX-NEXT: VirtualAddress: 0x11020 +# PHDRS-COMPLEX-NEXT: PhysicalAddress: 0x11020 +# PHDRS-COMPLEX-NEXT: FileSize: 128 +# PHDRS-COMPLEX-NEXT: MemSize: 128 +# PHDRS-COMPLEX-NEXT: Flags [ +# PHDRS-COMPLEX-NEXT: PF_R +# PHDRS-COMPLEX-NEXT: PF_W +# PHDRS-COMPLEX-NEXT: ] +# PHDRS-COMPLEX-NEXT: Alignment: 8 +# PHDRS-COMPLEX-NEXT: } +# PHDRS-COMPLEX-NEXT: ] +# SEC-COMPLEX: Sections: +# SEC-COMPLEX-NEXT: Idx Name Size Address Type +# SEC-COMPLEX-NEXT: 0 00000000 0000000000000000 +# SEC-COMPLEX-NEXT: 1 .interp 0000001c 0000000000010158 DATA +# SEC-COMPLEX-NEXT: 2 .dynsym 00000030 0000000000010178 +# SEC-COMPLEX-NEXT: 3 .hash 00000018 00000000000101a8 +# SEC-COMPLEX-NEXT: 4 .dynstr 00000061 00000000000101c0 +# SEC-COMPLEX-NEXT: 5 .text 0000000e 0000000000010224 TEXT DATA +# SEC-COMPLEX-NEXT: 6 .data 00000020 0000000000011000 DATA +# SEC-COMPLEX-NEXT: 7 .dynamic 00000080 0000000000011020 +# SEC-COMPLEX-NEXT: 8 .bss 00000002 00000000000110a0 BSS +# SEC-COMPLEX-NEXT: 9 .symtab 00000030 0000000000000000 +# SEC-COMPLEX-NEXT: 10 .shstrtab 00000053 0000000000000000 +# SEC-COMPLEX-NEXT: 11 .strtab 00000008 0000000000000000 + +# Check that all header types are allowed and all unused are present. +# RUN: echo "PHDRS { \ +# RUN: phdr PT_PHDR PHDRS; \ +# RUN: null PT_NULL; \ +# RUN: load PT_LOAD FILEHDR PHDRS; \ +# RUN: dynamic PT_DYNAMIC; \ +# RUN: interp PT_INTERP; \ +# RUN: note PT_NOTE; \ +# RUN: shlib PT_SHLIB; \ +# RUN: tls PT_TLS; \ +# RUN: } \ +# RUN: SECTIONS { \ +# RUN: .text : { *(.text) } :load \ +# RUN: .data : { *(.data) } \ +# RUN: .bss : { *(.bss) } \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t8 --script %t.script %t +# RUN: llvm-readobj -program-headers %t8 | \ +# RUN: FileCheck -check-prefix=PHDRS-UNUSED %s +# PHDRS-UNUSED: ProgramHeaders [ +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_PHDR +# PHDRS-UNUSED-NEXT: Offset: 0x40 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x10040 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x10040 +# PHDRS-UNUSED-NEXT: FileSize: 448 +# PHDRS-UNUSED-NEXT: MemSize: 448 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: PF_R (0x4) +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 8 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_NULL +# PHDRS-UNUSED-NEXT: Offset: 0x0 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x0 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x0 +# PHDRS-UNUSED-NEXT: FileSize: 0 +# PHDRS-UNUSED-NEXT: MemSize: 0 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 0 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_LOAD +# PHDRS-UNUSED-NEXT: Offset: 0x0 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x10000 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x10000 +# PHDRS-UNUSED-NEXT: FileSize: 558 +# PHDRS-UNUSED-NEXT: MemSize: 560 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: PF_R (0x4) +# PHDRS-UNUSED-NEXT: PF_W (0x2) +# PHDRS-UNUSED-NEXT: PF_X (0x1) +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 4096 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_DYNAMIC +# PHDRS-UNUSED-NEXT: Offset: 0x0 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x0 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x0 +# PHDRS-UNUSED-NEXT: FileSize: 0 +# PHDRS-UNUSED-NEXT: MemSize: 0 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 0 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_INTERP +# PHDRS-UNUSED-NEXT: Offset: 0x0 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x0 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x0 +# PHDRS-UNUSED-NEXT: FileSize: 0 +# PHDRS-UNUSED-NEXT: MemSize: 0 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 0 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_NOTE +# PHDRS-UNUSED-NEXT: Offset: 0x0 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x0 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x0 +# PHDRS-UNUSED-NEXT: FileSize: 0 +# PHDRS-UNUSED-NEXT: MemSize: 0 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 0 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_SHLIB +# PHDRS-UNUSED-NEXT: Offset: 0x0 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x0 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x0 +# PHDRS-UNUSED-NEXT: FileSize: 0 +# PHDRS-UNUSED-NEXT: MemSize: 0 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 0 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ProgramHeader { +# PHDRS-UNUSED-NEXT: Type: PT_TLS +# PHDRS-UNUSED-NEXT: Offset: 0x0 +# PHDRS-UNUSED-NEXT: VirtualAddress: 0x0 +# PHDRS-UNUSED-NEXT: PhysicalAddress: 0x0 +# PHDRS-UNUSED-NEXT: FileSize: 0 +# PHDRS-UNUSED-NEXT: MemSize: 0 +# PHDRS-UNUSED-NEXT: Flags [ +# PHDRS-UNUSED-NEXT: ] +# PHDRS-UNUSED-NEXT: Alignment: 0 +# PHDRS-UNUSED-NEXT: } +# PHDRS-UNUSED-NEXT: ] + +.globl _start; +_start: + mov $60, %rax + mov $42, %rdi + +.section .data,"aw" +.quad 10, 10, 20, 20 +.section .bss,"",@nobits +.short 0