Index: ELF/Config.h
===================================================================
--- ELF/Config.h
+++ ELF/Config.h
@@ -30,6 +30,20 @@
   ELF64BEKind
 };
 
+struct OutputSectionDescription {
+  llvm::StringRef Name;
+  std::vector<llvm::StringRef> InputSections;
+  std::vector<llvm::StringRef> Phdrs;
+};
+
+struct Phdr {
+  llvm::StringRef Name;
+  uint32_t Flags = (uint32_t)-1;
+  uint32_t Type;
+  bool HasFileHdr;
+  bool HasPhdrs;
+};
+
 // This struct contains the global configuration for the linker.
 // Most fields are direct mapping from the command line options
 // and such fields have the same name as the corresponding options.
@@ -47,7 +61,8 @@
   llvm::StringRef SoName;
   llvm::StringRef Sysroot;
   std::string RPath;
-  llvm::MapVector<llvm::StringRef, std::vector<llvm::StringRef>> OutputSections;
+  llvm::MapVector<llvm::StringRef, OutputSectionDescription> OutputSections;
+  std::vector<Phdr> Phdrs;
   std::vector<llvm::StringRef> SearchPaths;
   std::vector<llvm::StringRef> Undefined;
   bool AllowMultipleDefinition;
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -16,12 +16,14 @@
 #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;
 
@@ -36,6 +38,7 @@
   static std::vector<StringRef> tokenize(StringRef S);
   static StringRef skipSpace(StringRef S);
   StringRef next();
+  StringRef peek();
   bool skip(StringRef Tok);
   bool atEOF() { return Tokens.size() == Pos; }
   void expect(StringRef Expect);
@@ -50,10 +53,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<StringRef> Tokens;
@@ -81,6 +87,8 @@
       readOutputArch();
     } else if (Tok == "OUTPUT_FORMAT") {
       readOutputFormat();
+    } else if (Tok == "PHDRS") {
+      readPhdrs();
     } else if (Tok == "SEARCH_DIR") {
       readSearchDir();
     } else if (Tok == "SECTIONS") {
@@ -145,6 +153,12 @@
   return Tokens[Pos++];
 }
 
+StringRef LinkerScript::peek() {
+  if (atEOF())
+    error("unexpected EOF");
+  return Tokens[Pos];
+}
+
 bool LinkerScript::skip(StringRef Tok) {
   if (atEOF())
     fatal("unexpected EOF");
@@ -276,6 +290,38 @@
   expect(")");
 }
 
+uint32_t LinkerScript::readInteger() {
+  StringRef Tok = next();
+  uint32_t Val;
+  if (Tok.getAsInteger(0, Val))
+    error("Integer can't be parsed: " + Tok);
+  return Val;
+}
+
+void LinkerScript::readPhdrs() {
+  expect("{");
+  while (!skip("}")) {
+    Phdr &Hdr = *Config->Phdrs.emplace(Config->Phdrs.end(), Phdr{});
+    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);
+    }
+  }
+}
+
 void LinkerScript::readSearchDir() {
   expect("(");
   Config->SearchPaths.push_back(next());
@@ -290,7 +336,8 @@
 
 void LinkerScript::readOutputSectionDescription() {
   StringRef Name = next();
-  std::vector<StringRef> &InputSections = Config->OutputSections[Name];
+  OutputSectionDescription &OutSec = Config->OutputSections[Name];
+  OutSec.Name = Name;
 
   expect(":");
   expect("{");
@@ -298,10 +345,49 @@
     next(); // Skip input file name.
     expect("(");
     while (!skip(")"))
-      InputSections.push_back(next());
+      OutSec.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);
+    OutSec.Phdrs.emplace_back(Tok);
   }
 }
 
+uint32_t LinkerScript::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;
+}
+
 static bool isUnderSysroot(StringRef Path) {
   if (Config->Sysroot == "")
     return false;
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -19,6 +19,9 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/StringSaver.h"
 
+#include <list>
+#include <map>
+
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
@@ -41,6 +44,30 @@
   void run();
 
 private:
+  // This describes the programm header that will be created in output.
+  // Each contains type, access flags and list of output sections that will be
+  // placed in segment.
+  struct Phdr {
+    Phdr(unsigned Type = 0, unsigned Flags = 0, bool HasPhdrs = false,
+         bool HasFileHdr = false)
+        : Type(Type), Flags(Flags), HasPhdrs(HasPhdrs), HasFileHdr(HasFileHdr) {
+    }
+    unsigned Type;
+    unsigned Flags;
+    bool HasPhdrs = false;
+    bool HasFileHdr = false;
+    std::list<OutputSectionBase<ELFT> *> OutSections;
+  };
+  // Its a headers map which contains list of headers and also some additional
+  // parameters, like prefound IDs of specific headers.
+  struct PhdrMap {
+    std::vector<std::unique_ptr<Phdr>> PhdrList;
+    size_t FirstLoadId = (size_t)-1;
+    size_t TlsPhdrId = (size_t)-1;
+    size_t RelroPhdrId = (size_t)-1;
+    size_t PhdrHdrId = (size_t)-1;
+  };
+
   void copyLocalSymbols();
   void addReservedSymbols();
   bool createSections();
@@ -53,7 +80,10 @@
   void scanRelocs(InputSection<ELFT> &C);
   void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
   void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, uintX_t VA);
+  PhdrMap scanHeaders();
+  PhdrMap scanHeadersLinkerScript();
   void assignAddresses();
+  void finalizeHeaders(Elf_Phdr *PH, const Phdr &Map);
   void buildSectionMap();
   void fixAbsoluteSymbols();
   void openFile(StringRef OutputPath);
@@ -67,7 +97,6 @@
   bool isOutputDynamic() const {
     return !Symtab.getSharedFiles().empty() || Config->Shared;
   }
-  int getPhdrsNum() const;
 
   OutputSection<ELFT> *getBss();
   void addCommonSymbols(std::vector<DefinedCommon *> &Syms);
@@ -1123,138 +1152,341 @@
 void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
                                uintX_t VA) {
   if (!GnuRelroPhdr->p_type)
-    setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
+    setPhdr(GnuRelroPhdr, PT_GNU_RELRO, 0, Cur->p_offset, Cur->p_vaddr,
             VA - Cur->p_vaddr, 1 /*p_align*/);
   GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
   GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
 }
 
-// Visits all sections to create PHDRs and to assign incremental,
-// non-overlapping addresses to output sections.
-template <class ELFT> void Writer<ELFT>::assignAddresses() {
-  uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr);
-  uintX_t FileOff = sizeof(Elf_Ehdr);
-
-  // Calculate and reserve the space for the program header first so that
-  // the first section can start right after the program header.
-  Phdrs.resize(getPhdrsNum());
-  size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size();
+// This method generates some kind of map where each phdr
+// is associated with zero or more output sections.
+// Output structure contains final list of phdrs used.
+// assignAddresses() will use this structure to assign addressed to sections.
+template <class ELFT>
+typename Writer<ELFT>::PhdrMap Writer<ELFT>::scanHeaders() {
+  PhdrMap Map;
+  auto AddHdr = [this, &Map](unsigned Type, unsigned Flags) {
+    std::unique_ptr<Phdr> U = std::unique_ptr<Phdr>(new Phdr(Type, Flags));
+    return Map.PhdrList.emplace(Map.PhdrList.end(), std::move(U))->get();
+  };
 
   // The first phdr entry is PT_PHDR which describes the program header itself.
-  setPhdr(&Phdrs[0], PT_PHDR, PF_R, FileOff, VA, PhdrSize, /*Align=*/8);
-  FileOff += PhdrSize;
-  VA += PhdrSize;
+  Phdr *PhdrHdr = AddHdr(PT_PHDR, PF_R);
+  PhdrHdr->HasPhdrs = true;
+  Map.PhdrHdrId = Map.PhdrList.size() - 1;
 
   // PT_INTERP must be the second entry if exists.
-  int PhdrIdx = 0;
-  Elf_Phdr *Interp = nullptr;
-  if (needsInterpSection())
-    Interp = &Phdrs[++PhdrIdx];
+  if (needsInterpSection()) {
+    Phdr *Hdr = AddHdr(PT_INTERP, toPhdrFlags(Out<ELFT>::Interp->getFlags()));
+    Hdr->OutSections.push_back(Out<ELFT>::Interp);
+  }
 
   // Add the first PT_LOAD segment for regular output sections.
-  setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff,
-          Target->PageSize);
+  uintX_t Flags = PF_R;
+  Map.FirstLoadId = Map.PhdrList.size();
+  Phdr *Load = AddHdr(PT_LOAD, Flags);
+  Load->HasPhdrs = true;
+  Load->HasFileHdr = true;
 
-  Elf_Phdr GnuRelroPhdr = {};
-  Elf_Phdr TlsPhdr{};
-  bool RelroAligned = false;
-  uintX_t ThreadBssOffset = 0;
-  // Create phdrs as we assign VAs and file offsets to all output sections.
+  std::unique_ptr<Phdr> TlsHdr;
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
-    Elf_Phdr *PH = &Phdrs[PhdrIdx];
     if (needsPhdr<ELFT>(Sec)) {
-      uintX_t Flags = toPhdrFlags(Sec->getFlags());
-      bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec);
-      bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned;
-      if (FirstNonRelRo || PH->p_flags != Flags) {
-        VA = alignTo(VA, Target->PageSize);
-        FileOff = alignTo(FileOff, Target->PageSize);
-        if (FirstNonRelRo)
-          RelroAligned = true;
-      }
-
-      if (PH->p_flags != Flags) {
-        // Flags changed. Create a new PT_LOAD.
-        PH = &Phdrs[++PhdrIdx];
-        uint32_t PTType = (Config->EMachine != EM_AMDGPU) ? (uint32_t)PT_LOAD
-                                                          : getAmdgpuPhdr(Sec);
-        setPhdr(PH, PTType, Flags, FileOff, VA, 0, Target->PageSize);
+      // If flags changed then we want new load segment.
+      uintX_t NewFlags = toPhdrFlags(Sec->getFlags());
+      if (Flags != NewFlags) {
+        uint32_t LoadType = (Config->EMachine == EM_AMDGPU) ? getAmdgpuPhdr(Sec)
+                                                            : (uint32_t)PT_LOAD;
+        Load = AddHdr(LoadType, NewFlags);
+        Flags = NewFlags;
       }
-
+      // If we meet TLS section then we create TLS header
+      // and put all TLS sections inside for futher use when
+      // assign addresses.
       if (Sec->getFlags() & SHF_TLS) {
-        if (!TlsPhdr.p_vaddr)
-          setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
-        if (Sec->getType() != SHT_NOBITS)
-          VA = alignTo(VA, Sec->getAlign());
-        uintX_t TVA = alignTo(VA + ThreadBssOffset, Sec->getAlign());
-        Sec->setVA(TVA);
-        TlsPhdr.p_memsz += Sec->getSize();
-        if (Sec->getType() == SHT_NOBITS) {
-          ThreadBssOffset = TVA - VA + Sec->getSize();
-        } else {
-          TlsPhdr.p_filesz += Sec->getSize();
-          VA += Sec->getSize();
-        }
-        TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
-      } else {
-        VA = alignTo(VA, Sec->getAlign());
-        Sec->setVA(VA);
-        VA += Sec->getSize();
-        if (InRelRo)
-          updateRelro(PH, &GnuRelroPhdr, VA);
+        if (!TlsHdr)
+          TlsHdr = std::unique_ptr<Phdr>(new Phdr(PT_TLS, PF_R));
+        TlsHdr->OutSections.push_back(Sec);
       }
     }
-
-    FileOff = alignTo(FileOff, Sec->getAlign());
-    Sec->setFileOffset(FileOff);
-    if (Sec->getType() != SHT_NOBITS)
-      FileOff += Sec->getSize();
-    if (needsPhdr<ELFT>(Sec)) {
-      PH->p_filesz = FileOff - PH->p_offset;
-      PH->p_memsz = VA - PH->p_vaddr;
-    }
+    Load->OutSections.push_back(Sec);
   }
 
-  if (TlsPhdr.p_vaddr) {
-    // The TLS pointer goes after PT_TLS. At least glibc will align it,
-    // so round up the size to make sure the offsets are correct.
-    TlsPhdr.p_memsz = alignTo(TlsPhdr.p_memsz, TlsPhdr.p_align);
-    Phdrs[++PhdrIdx] = TlsPhdr;
-    Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
+  // TLS header.
+  if (TlsHdr) {
+    Map.TlsPhdrId = Map.PhdrList.size();
+    Map.PhdrList.push_back(std::move(TlsHdr));
   }
 
   // Add an entry for .dynamic.
   if (isOutputDynamic()) {
-    Elf_Phdr *PH = &Phdrs[++PhdrIdx];
-    PH->p_type = PT_DYNAMIC;
-    copyPhdr(PH, Out<ELFT>::Dynamic);
+    Phdr *Hdr = AddHdr(PT_DYNAMIC, toPhdrFlags(Out<ELFT>::Dynamic->getFlags()));
+    Hdr->OutSections.push_back(Out<ELFT>::Dynamic);
   }
 
+  // PT_GNU_RELRO includes all sections that should be marked as
+  // read-only by dynamic linker after proccessing relocations.
   if (HasRelro) {
-    Elf_Phdr *PH = &Phdrs[++PhdrIdx];
-    *PH = GnuRelroPhdr;
+    Map.RelroPhdrId = Map.PhdrList.size();
+    AddHdr(PT_GNU_RELRO, PF_R);
   }
 
+  // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
   if (Out<ELFT>::EhFrameHdr->Live) {
-    Elf_Phdr *PH = &Phdrs[++PhdrIdx];
-    PH->p_type = PT_GNU_EH_FRAME;
-    copyPhdr(PH, Out<ELFT>::EhFrameHdr);
+    Phdr *Hdr = AddHdr(PT_GNU_EH_FRAME, toPhdrFlags(Out<ELFT>::EhFrameHdr->getFlags()));
+    Hdr->OutSections.push_back(Out<ELFT>::EhFrameHdr);
   }
 
   // PT_GNU_STACK is a special section to tell the loader to make the
   // pages for the stack non-executable.
-  if (!Config->ZExecStack) {
-    Elf_Phdr *PH = &Phdrs[++PhdrIdx];
-    PH->p_type = PT_GNU_STACK;
-    PH->p_flags = PF_R | PF_W;
+  if (!Config->ZExecStack)
+    AddHdr(PT_GNU_STACK, PF_R | PF_W);
+
+  return Map;
+}
+
+template <class ELFT>
+typename Writer<ELFT>::PhdrMap Writer<ELFT>::scanHeadersLinkerScript() {
+  PhdrMap Map;
+  auto AddHdr = [this, &Map](unsigned Type, bool HasPhdrs, bool HasFileHdr) {
+    std::unique_ptr<Phdr> U =
+        std::unique_ptr<Phdr>(new Phdr(Type, 0, HasPhdrs, HasFileHdr));
+    return Map.PhdrList.emplace(Map.PhdrList.end(), std::move(U))->get();
+  };
+
+  // Adds section Sec to each segment from the list Seg. If OnlyLoads is
+  // specified then all segments except PT_LOADS are ignored.
+  auto AddSec = [](std::vector<Phdr *> &Seg, OutputSectionBase<ELFT> *Sec,
+                   bool OnlyLoads = false) {
+    if (Seg.empty())
+      error("No sections assigned to PHDRS");
+    for (Phdr *Dest : Seg) {
+      if (Dest->Type != PT_LOAD && OnlyLoads)
+        continue;
+      Dest->OutSections.push_back(Sec);
+      Dest->Flags |= toPhdrFlags(Sec->getFlags());
+    }
+  };
+
+  // Relro is not supported for linker script yet.
+  HasRelro = false;
+
+  // Add each header specified in PHDRS, build
+  // association map for phdrs lookup by name.
+  llvm::DenseMap<StringRef, Phdr *> NameToPhdr;
+  for (size_t I = 0, E = Config->Phdrs.size(); I != E; ++I) {
+    lld::elf2::Phdr &PH = Config->Phdrs[I];
+    if (!I) {
+      if (PH.Type != PT_PHDR)
+        error("First header is not PT_PHDR");
+      if (!PH.HasPhdrs)
+        error("PHDRS is not set for PT_PHDR");
+    }
+
+    NameToPhdr[PH.Name] = AddHdr(PH.Type, PH.HasPhdrs, PH.HasFileHdr);
+
+    // Remember indices of specific header types.
+    if (PH.Type == PT_LOAD && Map.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");
+      Map.FirstLoadId = I;
+    }
+    if (PH.Type == PT_PHDR)
+      Map.PhdrHdrId = I;
+    if (PH.Type == PT_TLS)
+      Map.TlsPhdrId = I;
+  }
+
+  // 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, false, false);
+  size_t SynNoneNdx = Map.PhdrList.size() - 1;
+
+  // Build list of segments to attach the section to
+  auto CreateSegmentList = [&](StringRef Sec, std::vector<StringRef> Names) {
+    bool HasLoad = false;
+    std::vector<Phdr *> Out;
+    for (StringRef N : Names) {
+      auto HdrInMap = NameToPhdr.find(N);
+      if (HdrInMap == NameToPhdr.end()) {
+        error("Section " + Sec + " assigned to non-existent header " + N);
+        return std::vector<Phdr *>{};
+      }
+      if (HdrInMap->second->Type == PT_LOAD) {
+        if (HasLoad)
+          error("Output section " + Sec + " 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<Phdr *> LastSeg;
+  for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+    StringRef Name = Sec->getName();
+    auto S = Config->OutputSections.find(Sec->getName());
+    if (S == Config->OutputSections.end())
+      continue;
+    LastSeg = CreateSegmentList(Name, S->second.Phdrs);
+    break;
+  }
+
+  // Iterate over all output sections. Main aim is to assign
+  // them to the headers they belong to.
+  for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+    if (HasError)
+      return PhdrMap();
+    // Find the section with the same name in linker script parameters.
+    StringRef Name = Sec->getName();
+    auto S = Config->OutputSections.find(Name);
+
+    // 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.
+    if (S == Config->OutputSections.end() || S->second.Phdrs.empty()) {
+      AddSec(LastSeg, Sec, S == Config->OutputSections.end());
+      continue;
+    }
+
+    // Build list of segments to attach the current section.
+    // And add the output section to each segment.
+    LastSeg = CreateSegmentList(Name, S->second.Phdrs);
+    AddSec(LastSeg, Sec);
   }
 
-  // Fix up PT_INTERP as we now know the address of .interp section.
-  if (Interp) {
-    Interp->p_type = PT_INTERP;
-    copyPhdr(Interp, Out<ELFT>::Interp);
+  // Erase synthetic "NONE" from final map.
+  Map.PhdrList.erase(Map.PhdrList.begin() + SynNoneNdx);
+
+  // Assign flags that were set directly from linker script.
+  for (lld::elf2::Phdr &PH : Config->Phdrs) {
+    if (PH.Flags != (uint32_t)-1)
+      NameToPhdr[PH.Name]->Flags = PH.Flags;
   }
 
+  return Map;
+}
+
+// Returns true if PHDRS command with headers is defined in linker script.
+static bool hasCustomPhdrs() { return !Config->Phdrs.empty(); }
+
+static bool isLoadPhdr(unsigned H) {
+  return H == PT_LOAD || H == PT_AMDGPU_HSA_LOAD_CODE_AGENT ||
+         H == PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM;
+}
+
+// Visits all headers in PhdrMap and assigns the adresses to
+// the output sections. Also creates common and special headers.
+template <class ELFT> void Writer<ELFT>::assignAddresses() {
+  // We know the final amount of program headers here.
+  PhdrMap Map = hasCustomPhdrs() ? scanHeadersLinkerScript() : scanHeaders();
+  if (HasError)
+    return;
+  Phdrs.resize(Map.PhdrList.size());
+
+  bool RelroAligned = false;
+  uintX_t ThreadBssOffset = 0;
+  size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size();
+  uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr) + PhdrSize;
+  uintX_t FileOff = sizeof(Elf_Ehdr) + PhdrSize;
+
+  // Set up PT_PHDR right after ELF file header.
+  setPhdr(&Phdrs[0], 0, 0, FileOff - PhdrSize, VA - PhdrSize, PhdrSize, 8);
+
+  // Main pass, here all load segments are processed and
+  // final addresses are assigned to all sections.
+  // Flags and header types are not assigned during pass.
+  // Them are assigned once for all headers at second pass.
+  for (size_t I = 0, E = Map.PhdrList.size(); I != E; ++I) {
+    std::unique_ptr<Phdr> &PHdr = Map.PhdrList[I];
+    if (!isLoadPhdr(PHdr->Type))
+      continue;
+
+    Elf_Phdr *PH = &Phdrs[I];
+    // New PT_LOAD is usually created when access flags were changed.
+    // If it is the very first load then it is special case,
+    // it contains elf header and program headers.
+    // Otherwise we need to align VA and FileOff to new memory page
+    // and create a new load.
+    const bool FirstLoad = (Map.FirstLoadId == I);
+    if (!FirstLoad) {
+      VA = alignTo(VA, Target->PageSize);
+      FileOff = alignTo(FileOff, Target->PageSize);
+    }
+    uintX_t Offset = FirstLoad ? 0 : FileOff;
+    uintX_t LoadVA = FirstLoad ? Target->getVAStart() : VA;
+    uintX_t LoadSize = FirstLoad ? FileOff : 0;
+    setPhdr(PH, 0, 0, Offset, LoadVA, LoadSize, Target->PageSize);
+
+    for (OutputSectionBase<ELFT> *Sec : PHdr->OutSections) {
+      bool InRelRo = HasRelro && (PHdr->Flags & PF_W) && isRelroSection(Sec);
+      bool FirstNonRelRo = HasRelro && Phdrs[Map.RelroPhdrId].p_type &&
+                           needsPhdr<ELFT>(Sec) && !RelroAligned && !InRelRo;
+      // If this is a first non relro section after relro sequence then
+      // we want to align to page boundaries. We do this because we dont want
+      // any other sections except relro were marked as read only by dynamic
+      // loader. Them should be placed on a different memory page for that.
+      if (FirstNonRelRo) {
+        VA = alignTo(VA, Target->PageSize);
+        FileOff = alignTo(FileOff, Target->PageSize);
+        RelroAligned = true;
+      }
+
+      if (needsPhdr<ELFT>(Sec)) {
+        bool IsTls = Sec->getFlags() & SHF_TLS;
+        // If we found TLS section we want to fill phdr parameters early
+        // because later we will not have its VA and FileOff.
+        if (IsTls && !Phdrs[Map.TlsPhdrId].p_vaddr)
+          setPhdr(&Phdrs[Map.TlsPhdrId], 0, 0, FileOff, VA, 0, 0);
+
+        // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
+        // responsible for allocating space for them, not the PT_LOAD that
+        // contains the TLS initialization image.
+        if (!IsTls || Sec->getType() != SHT_NOBITS)
+          VA = alignTo(VA, Sec->getAlign());
+
+        uintX_t TVA = alignTo(VA + ThreadBssOffset, Sec->getAlign());
+        Sec->setVA(IsTls ? TVA : VA);
+
+        if (IsTls && Sec->getType() == SHT_NOBITS)
+          ThreadBssOffset = TVA - VA + Sec->getSize();
+        else
+          VA += Sec->getSize();
+
+        // If we are in relro then we need to update
+        // the GnuRelroPhdr header.
+        if (InRelRo)
+          updateRelro(PH, &Phdrs[Map.RelroPhdrId], VA);
+      }
+
+      FileOff = alignTo(FileOff, Sec->getAlign());
+      Sec->setFileOffset(FileOff);
+      if (Sec->getType() != SHT_NOBITS)
+        FileOff += Sec->getSize();
+      if (needsPhdr<ELFT>(Sec)) {
+        PH->p_filesz = FileOff - PH->p_offset;
+        PH->p_memsz = VA - PH->p_vaddr;
+      }
+    }
+  }
+
+  // Assign phdrs values in according to sections parameters attached.
+  // Each segment can contain zero, one or multiple sections assigned.
+  // Not just load segments but any others as well. That can be achieved usually
+  // with linker script. finalizeHeaders modifies each segment parameters and
+  // size
+  // in the way to cover all sections inside.
+  for (size_t I = 0, E = Map.PhdrList.size(); I != E; ++I)
+    finalizeHeaders(&Phdrs[I], *Map.PhdrList[I].get());
+
   // Add space for section headers.
   SectionHeaderOff = alignTo(FileOff, sizeof(uintX_t));
   FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
@@ -1264,35 +1496,36 @@
   ElfSym<ELFT>::End.st_value = VA;
 }
 
-// Returns the number of PHDR entries.
-template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
-  bool Tls = false;
-  int I = 2; // 2 for PT_PHDR and first PT_LOAD
-  if (needsInterpSection())
-    ++I;
-  if (isOutputDynamic())
-    ++I;
-  if (!Config->ZExecStack)
-    ++I;
-  uintX_t Last = PF_R;
-  for (OutputSectionBase<ELFT> *Sec : OutputSections) {
-    if (!needsPhdr<ELFT>(Sec))
-      continue;
-    if (Sec->getFlags() & SHF_TLS)
-      Tls = true;
-    uintX_t Flags = toPhdrFlags(Sec->getFlags());
-    if (Last != Flags) {
-      Last = Flags;
-      ++I;
+template <class ELFT>
+void Writer<ELFT>::finalizeHeaders(Elf_Phdr *PH, const Phdr &PHdr) {
+  // We already handled PT_LOAD and PT_PHDR and do not proccess them.
+  if (!isLoadPhdr(PHdr.Type) && PHdr.Type != PT_PHDR) {
+    for (OutputSectionBase<ELFT> *Sec : PHdr.OutSections) {
+      // Initially we initialize the header with parameters
+      // of first output section attached.
+      if (PH->p_memsz == 0 && PHdr.Type != PT_TLS) {
+        copyPhdr(PH, Sec);
+        continue;
+      }
+      // Here we extending the header size to cover all sections inside it.
+      if (Sec->getType() != SHT_NOBITS)
+        PH->p_filesz += Sec->getSize();
+      PH->p_memsz += Sec->getSize();
+      PH->p_align = std::max<uintX_t>(PH->p_align, Sec->getAlign());
     }
   }
-  if (Tls)
-    ++I;
-  if (HasRelro)
-    ++I;
-  if (Out<ELFT>::EhFrameHdr->Live)
-    ++I;
-  return I;
+
+  // Set type and flags.
+  PH->p_type = PHdr.Type;
+  PH->p_flags = PHdr.Flags;
+
+  // The TLS pointer goes after PT_TLS. At least glibc will align it,
+  // so round up the size to make sure the offsets are correct.
+  if (PHdr.Type == PT_TLS) {
+    if (PH->p_align)
+      PH->p_memsz = alignTo(PH->p_memsz, PH->p_align);
+    Out<ELFT>::TlsPhdr = PH;
+  }
 }
 
 static uint32_t getELFFlags() {
@@ -1422,10 +1655,11 @@
 }
 
 template <class ELFT> void Writer<ELFT>::buildSectionMap() {
-  for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
+  for (const std::pair<StringRef, OutputSectionDescription> &OutSec :
        Config->OutputSections)
-    for (StringRef Name : OutSec.second)
+    for (StringRef Name : OutSec.second.InputSections) {
       InputToOutputSection[Name] = OutSec.first;
+    }
 }
 
 template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
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,85 @@
+# 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:     ]
+# 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,585 @@
+# 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:     ]
+# 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:     ]
+# 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:     ]
+# 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:     ]
+# 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