Index: llvm/include/llvm/ObjectYAML/ELFYAML.h
===================================================================
--- llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -202,6 +202,7 @@
     SpecialChunksStart,
     Fill = SpecialChunksStart,
     SectionHeaderTable,
+    ProgramHeaderTable
   };
 
   ChunkKind Kind;
@@ -308,6 +309,35 @@
   static constexpr StringRef TypeStr = "SectionHeaderTable";
 };
 
+struct ProgramHeader {
+  ELF_PT Type;
+  ELF_PF Flags;
+  llvm::yaml::Hex64 VAddr;
+  llvm::yaml::Hex64 PAddr;
+  Optional<llvm::yaml::Hex64> Align;
+  Optional<llvm::yaml::Hex64> FileSize;
+  Optional<llvm::yaml::Hex64> MemSize;
+  Optional<llvm::yaml::Hex64> Offset;
+  Optional<StringRef> FirstSec;
+  Optional<StringRef> LastSec;
+
+  // This vector contains all chunks from [FirstSec, LastSec].
+  std::vector<Chunk *> Chunks;
+};
+
+struct ProgramHeaderTable : Chunk {
+  ProgramHeaderTable(bool IsImplicit)
+      : Chunk(ChunkKind::ProgramHeaderTable, IsImplicit) {}
+
+  static bool classof(const Chunk *S) {
+    return S->Kind == ChunkKind::ProgramHeaderTable;
+  }
+
+  std::vector<ProgramHeader> Segments;
+
+  static constexpr StringRef TypeStr = "ProgramHeaderTable";
+};
+
 struct BBAddrMapSection : Section {
   Optional<std::vector<BBAddrMapEntry>> Entries;
 
@@ -674,25 +704,8 @@
   }
 };
 
-struct ProgramHeader {
-  ELF_PT Type;
-  ELF_PF Flags;
-  llvm::yaml::Hex64 VAddr;
-  llvm::yaml::Hex64 PAddr;
-  Optional<llvm::yaml::Hex64> Align;
-  Optional<llvm::yaml::Hex64> FileSize;
-  Optional<llvm::yaml::Hex64> MemSize;
-  Optional<llvm::yaml::Hex64> Offset;
-  Optional<StringRef> FirstSec;
-  Optional<StringRef> LastSec;
-
-  // This vector contains all chunks from [FirstSec, LastSec].
-  std::vector<Chunk *> Chunks;
-};
-
 struct Object {
   FileHeader Header;
-  std::vector<ProgramHeader> ProgramHeaders;
 
   // An object might contain output section descriptions as well as
   // custom data that does not belong to any section.
@@ -721,10 +734,17 @@
     llvm_unreachable("the section header table chunk must always be present");
   }
 
+  ProgramHeaderTable *getProgramHeaderTable() {
+    for (std::unique_ptr<Chunk> &C : Chunks)
+      if (auto *S = dyn_cast<ELFYAML::ProgramHeaderTable>(C.get()))
+        return S;
+    return nullptr;
+  }
+
   unsigned getMachine() const;
 };
 
-bool shouldAllocateFileSpace(ArrayRef<ProgramHeader> Phdrs,
+bool shouldAllocateFileSpace(const ELFYAML::ProgramHeaderTable *PHT,
                              const NoBitsSection &S);
 
 } // end namespace ELFYAML
Index: llvm/lib/ObjectYAML/ELFEmitter.cpp
===================================================================
--- llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -314,14 +314,6 @@
 };
 } // end anonymous namespace
 
-template <class T> static size_t arrayDataSize(ArrayRef<T> A) {
-  return A.size() * sizeof(T);
-}
-
-template <class T> static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
-  OS.write((const char *)A.data(), arrayDataSize(A));
-}
-
 template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
 
 template <class ELFT>
@@ -337,6 +329,7 @@
 
   StringSet<> DocSections;
   ELFYAML::SectionHeaderTable *SecHdrTable = nullptr;
+  bool HasProgramHeaderTable = false;
   for (size_t I = 0; I < Doc.Chunks.size(); ++I) {
     const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I];
 
@@ -348,6 +341,13 @@
       continue;
     }
 
+    if (isa<ELFYAML::ProgramHeaderTable>(C.get())) {
+      if (HasProgramHeaderTable)
+        reportError("multiple program header tables are not allowed");
+      HasProgramHeaderTable = true;
+      continue;
+    }
+
     // We add a technical suffix for each unnamed section/fill. It does not
     // affect the output, but allows us to map them by name in the code and
     // report better error messages.
@@ -439,24 +439,27 @@
   Header.e_flags = Doc.Header.Flags;
   Header.e_ehsize = sizeof(Elf_Ehdr);
 
+  const ELFYAML::ProgramHeaderTable *ProgramHeaders =
+      Doc.getProgramHeaderTable();
+
   if (Doc.Header.EPhOff)
     Header.e_phoff = *Doc.Header.EPhOff;
-  else if (!Doc.ProgramHeaders.empty())
-    Header.e_phoff = sizeof(Header);
+  else if (ProgramHeaders)
+    Header.e_phoff = *ProgramHeaders->Offset;
   else
     Header.e_phoff = 0;
 
   if (Doc.Header.EPhEntSize)
     Header.e_phentsize = *Doc.Header.EPhEntSize;
-  else if (!Doc.ProgramHeaders.empty())
+  else if (ProgramHeaders)
     Header.e_phentsize = sizeof(Elf_Phdr);
   else
     Header.e_phentsize = 0;
 
   if (Doc.Header.EPhNum)
     Header.e_phnum = *Doc.Header.EPhNum;
-  else if (!Doc.ProgramHeaders.empty())
-    Header.e_phnum = Doc.ProgramHeaders.size();
+  else if (ProgramHeaders)
+    Header.e_phnum = ProgramHeaders->Segments.size();
   else
     Header.e_phnum = 0;
 
@@ -498,9 +501,12 @@
     NameToIndex[Doc.Chunks[I]->Name] = I + 1;
   }
 
-  std::vector<ELFYAML::Section *> Sections = Doc.getSections();
-  for (size_t I = 0, E = Doc.ProgramHeaders.size(); I != E; ++I) {
-    ELFYAML::ProgramHeader &YamlPhdr = Doc.ProgramHeaders[I];
+  ELFYAML::ProgramHeaderTable *ProgramHeaders = Doc.getProgramHeaderTable();
+  if (!ProgramHeaders)
+    return;
+
+  for (size_t I = 0, E = ProgramHeaders->Segments.size(); I != E; ++I) {
+    ELFYAML::ProgramHeader &YamlPhdr = ProgramHeaders->Segments[I];
     Elf_Phdr Phdr;
     zero(Phdr);
     Phdr.p_type = YamlPhdr.Type;
@@ -747,6 +753,22 @@
       continue;
     }
 
+    if (ELFYAML::ProgramHeaderTable *PHT =
+            dyn_cast<ELFYAML::ProgramHeaderTable>(D.get())) {
+      if (!PHT->Offset)
+        PHT->Offset = alignToOffset(CBA, sizeof(typename ELFT::uint),
+                                    /*Offset=*/None);
+      else
+        PHT->Offset = alignToOffset(CBA, /*Align=*/1, PHT->Offset);
+
+      uint64_t Size = sizeof(Elf_Phdr) * PHT->Segments.size();
+      // The full program header information might not be available here, so
+      // fill the space with zeroes as a placeholder.
+      CBA.writeZeros(Size);
+      LocationCounter += Size;
+      continue;
+    }
+
     ELFYAML::Section *Sec = cast<ELFYAML::Section>(D.get());
     bool IsFirstUndefSection = Sec == Doc.getSections().front();
     if (IsFirstUndefSection && Sec->IsImplicit)
@@ -1123,8 +1145,12 @@
 template <class ELFT>
 void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
                                             std::vector<Elf_Shdr> &SHeaders) {
+  ELFYAML::ProgramHeaderTable *ProgramHeaders = Doc.getProgramHeaderTable();
+  if (!ProgramHeaders)
+    return;
+
   uint32_t PhdrIdx = 0;
-  for (auto &YamlPhdr : Doc.ProgramHeaders) {
+  for (ELFYAML::ProgramHeader &YamlPhdr : ProgramHeaders->Segments) {
     Elf_Phdr &PHeader = PHeaders[PhdrIdx++];
     std::vector<Fragment> Fragments = getPhdrFragments(YamlPhdr, SHeaders);
     if (!llvm::is_sorted(Fragments, [](const Fragment &A, const Fragment &B) {
@@ -1179,8 +1205,10 @@
 }
 
 bool llvm::ELFYAML::shouldAllocateFileSpace(
-    ArrayRef<ELFYAML::ProgramHeader> Phdrs, const ELFYAML::NoBitsSection &S) {
-  for (const ELFYAML::ProgramHeader &PH : Phdrs) {
+    const ELFYAML::ProgramHeaderTable *PHT, const ELFYAML::NoBitsSection &S) {
+  if (!PHT)
+    return false;
+  for (const ELFYAML::ProgramHeader &PH : PHT->Segments) {
     auto It = llvm::find_if(
         PH.Chunks, [&](ELFYAML::Chunk *C) { return C->Name == S.Name; });
     if (std::any_of(It, PH.Chunks.end(), [](ELFYAML::Chunk *C) {
@@ -1204,7 +1232,8 @@
   // When a nobits section is followed by a non-nobits section or fill
   // in the same segment, we allocate the file space for it. This behavior
   // matches linkers.
-  if (shouldAllocateFileSpace(Doc.ProgramHeaders, S))
+  const ELFYAML::ProgramHeaderTable *PHT = Doc.getProgramHeaderTable();
+  if (shouldAllocateFileSpace(PHT, S))
     CBA.writeZeros(*S.Size);
 }
 
@@ -1891,15 +1920,11 @@
   std::vector<Elf_Phdr> PHeaders;
   State.initProgramHeaders(PHeaders);
 
-  // XXX: This offset is tightly coupled with the order that we write
-  // things to `OS`.
-  const size_t SectionContentBeginOffset =
-      sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
   // It is quite easy to accidentally create output with yaml2obj that is larger
   // than intended, for example, due to an issue in the YAML description.
   // We limit the maximum allowed output size, but also provide a command line
   // option to change this limitation.
-  ContiguousBlobAccumulator CBA(SectionContentBeginOffset, MaxSize);
+  ContiguousBlobAccumulator CBA(sizeof(Elf_Ehdr), MaxSize);
 
   std::vector<Elf_Shdr> SHeaders;
   State.initSectionHeaders(SHeaders, CBA);
@@ -1923,7 +1948,10 @@
     return false;
 
   State.writeELFHeader(OS);
-  writeArrayData(OS, makeArrayRef(PHeaders));
+
+  if (const ELFYAML::ProgramHeaderTable *PHT = Doc.getProgramHeaderTable())
+    CBA.updateDataAt(*PHT->Offset, PHeaders.data(),
+                     PHeaders.size() * sizeof(Elf_Phdr));
 
   const ELFYAML::SectionHeaderTable &SHT = Doc.getSectionHeaderTable();
   if (!SHT.NoHeaders.getValueOr(false))
Index: llvm/lib/ObjectYAML/ELFYAML.cpp
===================================================================
--- llvm/lib/ObjectYAML/ELFYAML.cpp
+++ llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -35,6 +35,7 @@
 }
 
 constexpr StringRef SectionHeaderTable::TypeStr;
+constexpr StringRef ProgramHeaderTable::TypeStr;
 } // namespace ELFYAML
 
 namespace yaml {
@@ -1245,6 +1246,12 @@
   IO.mapOptional("NoHeaders", SHT.NoHeaders);
 }
 
+static void sectionHeaderTableMapping(IO &IO,
+                                      ELFYAML::ProgramHeaderTable &PHT) {
+  IO.mapOptional("Offset", PHT.Offset);
+  IO.mapOptional("Segments", PHT.Segments);
+}
+
 static void sectionMapping(IO &IO, ELFYAML::LinkerOptionsSection &Section) {
   commonSectionMapping(IO, Section);
   IO.mapOptional("Options", Section.Options);
@@ -1315,6 +1322,8 @@
       Type = S->Type;
     else if (auto *SHT = dyn_cast<ELFYAML::SectionHeaderTable>(Section.get()))
       TypeStr = SHT->TypeStr;
+    else if (auto *PHT = dyn_cast<ELFYAML::ProgramHeaderTable>(Section.get()))
+      TypeStr = PHT->TypeStr;
   } else {
     // When the Type string does not have a "SHT_" prefix, we know it is not a
     // description of a regular ELF output section.
@@ -1341,6 +1350,17 @@
     return;
   }
 
+  if (TypeStr == ELFYAML::ProgramHeaderTable::TypeStr) {
+    if (IO.outputting())
+      setStringValue(IO, "Type", TypeStr);
+    else
+      Section.reset(new ELFYAML::ProgramHeaderTable(/*IsImplicit=*/false));
+
+    sectionHeaderTableMapping(
+        IO, *cast<ELFYAML::ProgramHeaderTable>(Section.get()));
+    return;
+  }
+
   const auto &Obj = *static_cast<ELFYAML::Object *>(IO.getContext());
   if (Obj.getMachine() == ELF::EM_MIPS && Type == ELF::SHT_MIPS_ABIFLAGS) {
     if (!IO.outputting())
@@ -1477,6 +1497,9 @@
     return "";
   }
 
+  if (isa<ELFYAML::ProgramHeaderTable>(C.get()))
+    return "";
+
   const ELFYAML::Section &Sec = *cast<ELFYAML::Section>(C.get());
   if (Sec.Size && Sec.Content &&
       (uint64_t)(*Sec.Size) < Sec.Content->binary_size())
@@ -1676,7 +1699,6 @@
   IO.setContext(&Object);
   IO.mapTag("!ELF", true);
   IO.mapRequired("FileHeader", Object.Header);
-  IO.mapOptional("ProgramHeaders", Object.ProgramHeaders);
   IO.mapOptional("Sections", Object.Chunks);
   IO.mapOptional("Symbols", Object.Symbols);
   IO.mapOptional("DynamicSymbols", Object.DynamicSymbols);
Index: llvm/test/DebugInfo/symbolize-build-id-error.test
===================================================================
--- llvm/test/DebugInfo/symbolize-build-id-error.test
+++ llvm/test/DebugInfo/symbolize-build-id-error.test
@@ -12,12 +12,13 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        Flags:    [ PF_R ]
+        FirstSec: .note.invalid
+        LastSec:  .note.invalid
   - Name:    .note.invalid
     Type:    SHT_NOTE
     Flags:   [ SHF_ALLOC ]
     Content: 0123456789
-ProgramHeaders:
-  - Type:     PT_NOTE
-    Flags:    [ PF_R ]
-    FirstSec: .note.invalid
-    LastSec:  .note.invalid
Index: llvm/test/DebugInfo/symbolize-build-id.test
===================================================================
--- llvm/test/DebugInfo/symbolize-build-id.test
+++ llvm/test/DebugInfo/symbolize-build-id.test
@@ -17,12 +17,13 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        Flags:    [ PF_R ]
+        FirstSec: .note.gnu.build-id
+        LastSec:  .note.gnu.build-id
   - Name:    .note.gnu.build-id
     Type:    SHT_NOTE
     Flags:   [ SHF_ALLOC ]
     Content: 040000000800000003000000474e5500abb50d82b6bdc861
-ProgramHeaders:
-  - Type:     PT_NOTE
-    Flags:    [ PF_R ]
-    FirstSec: .note.gnu.build-id
-    LastSec:  .note.gnu.build-id
Index: llvm/test/Object/invalid.test
===================================================================
--- llvm/test/Object/invalid.test
+++ llvm/test/Object/invalid.test
@@ -446,6 +446,12 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Address: 0x1000
@@ -454,11 +460,6 @@
         Value: 0xFFFF0000
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Check that llvm-readobj reports a warning when a dynamic relocation section
 ## has sh_entsize field with size != sizeof(Elf_Rela).
@@ -502,9 +503,11 @@
   Data:    ELFDATA2LSB
   Type:    ET_EXEC
   Machine: EM_X86_64
-ProgramHeaders:
-  - Type:   PT_DYNAMIC
-    Offset: 0xffff0000
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:   PT_DYNAMIC
+        Offset: 0xffff0000
 
 ## PT_DYNAMIC's p_filesz field is so large that p_offset + p_filesz is larger
 ## than the object size. Check llvm-readobj reports it.
@@ -522,16 +525,17 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_DYNAMIC
+        FileSize: 0xffff0000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_DYNAMIC
-    FileSize: 0xffff0000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # RUN: yaml2obj --docnum=24 %s -o %t24
 # RUN: not obj2yaml 2>&1 %t24 | FileCheck %s -DFILE=%t24 --check-prefix=INVALID-SHSTRNDX
Index: llvm/test/Object/obj2yaml.test
===================================================================
--- llvm/test/Object/obj2yaml.test
+++ llvm/test/Object/obj2yaml.test
@@ -686,19 +686,20 @@
 # ELF-AVR-NEXT:   Type:            ET_EXEC
 # ELF-AVR-NEXT:   Machine:         EM_AVR
 # ELF-AVR-NEXT:   Flags:           [ EF_AVR_ARCH_AVR2 ]
-# ELF-AVR-NEXT: ProgramHeaders:
-# ELF-AVR-NEXT:  - Type:     PT_LOAD
-# ELF-AVR-NEXT:    Flags:    [ PF_X, PF_R ]
-# ELF-AVR-NEXT:    FirstSec: .text
-# ELF-AVR-NEXT:    LastSec:  .text
-# ELF-AVR-NEXT:    Align:    0x2
-# ELF-AVR-NEXT:  - Type:     PT_LOAD
-# ELF-AVR-NEXT:    Flags:    [ PF_W, PF_R ]
-# ELF-AVR-NEXT:    FirstSec: .data
-# ELF-AVR-NEXT:    LastSec:  .data
-# ELF-AVR-NEXT:    VAddr:    0x800060
-# ELF-AVR-NEXT:    PAddr:    0x4
 # ELF-AVR-NEXT: Sections:
+# ELF-AVR-NEXT:   - Type:            ProgramHeaderTable
+# ELF-AVR-NEXT:     Segments:
+# ELF-AVR-NEXT:       - Type:            PT_LOAD
+# ELF-AVR-NEXT:         Flags:           [ PF_X, PF_R ]
+# ELF-AVR-NEXT:         FirstSec:        .text
+# ELF-AVR-NEXT:         LastSec:         .text
+# ELF-AVR-NEXT:         Align:           0x2
+# ELF-AVR-NEXT:       - Type:            PT_LOAD
+# ELF-AVR-NEXT:         Flags:           [ PF_W, PF_R ]
+# ELF-AVR-NEXT:         FirstSec:        .data
+# ELF-AVR-NEXT:         LastSec:         .data
+# ELF-AVR-NEXT:         VAddr:           0x800060
+# ELF-AVR-NEXT:         PAddr:           0x4
 # ELF-AVR-NEXT:   - Name:            .text
 # ELF-AVR-NEXT:     Type:            SHT_PROGBITS
 # ELF-AVR-NEXT:     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
Index: llvm/test/tools/llvm-elfabi/binary-read-add-soname.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-add-soname.test
+++ llvm/test/tools/llvm-elfabi/binary-read-add-soname.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_AARCH64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x0000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x0008
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -29,18 +42,6 @@
         Value:           0x0000000000000000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x0000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type: PT_DYNAMIC
-    Flags: [ PF_X, PF_R ]
-    VAddr: 0x0008
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK:      --- !tapi-tbe
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
Index: llvm/test/tools/llvm-elfabi/binary-read-arch.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-arch.test
+++ llvm/test/tools/llvm-elfabi/binary-read-arch.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x0000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x0008
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -29,18 +42,6 @@
         Value:           0x0000000000000000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x0000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x0008
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK:      --- !tapi-tbe
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
Index: llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test
+++ llvm/test/tools/llvm-elfabi/binary-read-bad-soname.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x0000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x0008
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -31,17 +44,5 @@
         Value:           0x0000000000000000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x0000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x0008
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK: DT_SONAME string offset (0x000000000000000d) outside of dynamic string table
Index: llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test
+++ llvm/test/tools/llvm-elfabi/binary-read-bad-vaddr.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1008
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -31,17 +44,5 @@
         Value:           0x0000000000001000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1008
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK: virtual address is not in any segment: 0x260 when locating .dynstr section contents
Index: llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test
+++ llvm/test/tools/llvm-elfabi/binary-read-neededlibs-bad-offset.test
@@ -8,6 +8,17 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:  PT_DYNAMIC
+        Flags: [ PF_X, PF_R ]
+        VAddr: 0x1024
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -35,15 +46,5 @@
         Value:           0x0000000000001000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:  PT_DYNAMIC
-    Flags: [ PF_X, PF_R ]
-    VAddr: 0x1024
 
 # CHECK: DT_NEEDED string offset (0x000000000000ffff) outside of dynamic string table
Index: llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test
+++ llvm/test/tools/llvm-elfabi/binary-read-neededlibs.test
@@ -8,6 +8,17 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:  PT_DYNAMIC
+        Flags: [ PF_X, PF_R ]
+        VAddr: 0x1024
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -34,16 +45,6 @@
         Value:           0x0000000000001000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type: PT_DYNAMIC
-    Flags: [ PF_X, PF_R ]
-    VAddr: 0x1024
 
 # CHECK:      NeededLibs:
 # CHECK-NEXT:   - libfoo.so{{$}}
Index: llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test
+++ llvm/test/tools/llvm-elfabi/binary-read-no-dt-strsz.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x0000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x0008
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -26,17 +39,5 @@
         Value:           0x0000000000000000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x0000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x0008
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK: Couldn't determine dynamic string table size (no DT_STRSZ entry)
Index: llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test
+++ llvm/test/tools/llvm-elfabi/binary-read-no-dt-strtab.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x0000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x0008
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -25,17 +38,5 @@
         Value:           0x0000000000000001
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x0000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x0008
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK: Couldn't locate dynamic string table (no DT_STRTAB entry)
Index: llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test
+++ llvm/test/tools/llvm-elfabi/binary-read-replace-soname.test
@@ -9,6 +9,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1018
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -33,18 +46,6 @@
         Value:           0x0000000000001000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1018
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # ORIGINAL: SoName: somelib.so{{$}}
 
Index: llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test
+++ llvm/test/tools/llvm-elfabi/binary-read-soname-no-null.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1018
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -32,17 +45,5 @@
         Value:           0x0000000000001000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1018
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK: String overran bounds of string table (no null terminator) when reading DT_SONAME
Index: llvm/test/tools/llvm-elfabi/binary-read-soname.test
===================================================================
--- llvm/test/tools/llvm-elfabi/binary-read-soname.test
+++ llvm/test/tools/llvm-elfabi/binary-read-soname.test
@@ -8,6 +8,19 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        Align:    8
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1018
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynstr
     Type:            SHT_STRTAB
     Flags:           [ SHF_ALLOC ]
@@ -32,18 +45,6 @@
         Value:           0x0000000000001000
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    Align:    8
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1018
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # CHECK:      --- !tapi-tbe
 # CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}}
Index: llvm/test/tools/llvm-elfabi/read-elf-dynsym.test
===================================================================
--- llvm/test/tools/llvm-elfabi/read-elf-dynsym.test
+++ llvm/test/tools/llvm-elfabi/read-elf-dynsym.test
@@ -38,6 +38,16 @@
   Type:       ET_DYN
   Machine:    EM_AARCH64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x400
+        FirstSec: .dynsym
+        LastSec:  .gnu.hash
+      - Type:     PT_DYNAMIC
+        VAddr:    0x800
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:         .text
     Type:         SHT_PROGBITS
   - Name:         .data
@@ -104,12 +114,3 @@
     Type:    STT_OBJECT
     Value:   0x200
     Binding: 1
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x400
-    FirstSec: .dynsym
-    LastSec:  .gnu.hash
-  - Type:     PT_DYNAMIC
-    VAddr:    0x800
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-gsymutil/X86/elf-dwarf.yaml
===================================================================
--- llvm/test/tools/llvm-gsymutil/X86/elf-dwarf.yaml
+++ llvm/test/tools/llvm-gsymutil/X86/elf-dwarf.yaml
@@ -113,6 +113,14 @@
   Machine:         EM_X86_64
   Entry:           0x00000000004003E0
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x0000000000400000
+        Align:    1024
+        FirstSec: .interp
+        LastSec:  .dynstr
   - Name:            .interp
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC ]
@@ -384,13 +392,6 @@
     AddressAlign:    0x0000000000000001
     EntSize:         0x0000000000000001
     Content:         61726776002F746D70006D61696E006D61696E2E637070006172676300474E5520432B2B20342E382E3520323031353036323320285265642048617420342E382E352D333629202D6D74756E653D67656E65726963202D6D617263683D7838362D3634202D67202D4F30006368617200
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_X, PF_R ]
-    VAddr: 0x0000000000400000
-    Align: 1024
-    FirstSec: .interp
-    LastSec:  .dynstr
 Symbols:
   - Name:            .interp
     Type:            STT_SECTION
Index: llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-pt-null.yaml
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-pt-null.yaml
+++ llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-pt-null.yaml
@@ -5,16 +5,17 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NULL
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0xF00000000
+        PAddr:    0x100000
+        FirstSec: .text
+        LastSec:  .text
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
     Address:         0x0
     AddressAlign:    0x8
     Content:         "0001020304"
-ProgramHeaders:
-  - Type:     PT_NULL
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0xF00000000
-    PAddr:    0x100000
-    FirstSec: .text
-    LastSec:  .text
Index: llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-segments.yaml
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-segments.yaml
+++ llvm/test/tools/llvm-objcopy/ELF/Inputs/ihex-elf-segments.yaml
@@ -11,6 +11,14 @@
   Machine:         EM_X86_64
   Entry:           0x100000
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0xF00000000
+        PAddr:    0x100000
+        FirstSec: .text
+        LastSec:  .bss
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -47,10 +55,3 @@
     Address:         0x20FFF8
     Size:            65536
     AddressAlign:    0x8
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0xF00000000
-    PAddr:    0x100000
-    FirstSec: .text
-    LastSec:  .bss
Index: llvm/test/tools/llvm-objcopy/ELF/add-symbol.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/add-symbol.test
+++ llvm/test/tools/llvm-objcopy/ELF/add-symbol.test
@@ -31,6 +31,20 @@
   Type:            ET_EXEC
   Machine:         EM_ARM
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1000
+        Align:    0x1000
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x2000
+        Align:    0x1000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -43,19 +57,6 @@
     Address:         0x2000
     AddressAlign:    0x0000000000001000
     Size:            64
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1000
-    Align:    0x1000
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x2000
-    Align:    0x1000
-    FirstSec: .data
-    LastSec:  .data
 ## TODO (grimar): llvm-objcopy seems produce a broken output without
 ## the following line, i.e. when there is no symbol table in the input.
 Symbols: []
Index: llvm/test/tools/llvm-objcopy/ELF/adjacent-segments.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/adjacent-segments.test
+++ llvm/test/tools/llvm-objcopy/ELF/adjacent-segments.test
@@ -12,6 +12,16 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text2
+        LastSec:  .text2
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -22,15 +32,6 @@
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
     AddressAlign:    0x10
     Size:            16
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text2
-    LastSec:  .text2
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:  ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/bad-build-id.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/bad-build-id.test
+++ llvm/test/tools/llvm-objcopy/ELF/bad-build-id.test
@@ -10,12 +10,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        Flags:    [ PF_R ]
+        FirstSec: .note.gnu.build-id
+        LastSec:  .note.gnu.build-id
   - Name:            .note.gnu.build-id
     Type:            SHT_NOTE
     Flags:           [ SHF_ALLOC ]
     Content:         040000000100000003000000474E55004F000000
-ProgramHeaders:
-  - Type:     PT_NOTE
-    Flags:    [ PF_R ]
-    FirstSec: .note.gnu.build-id
-    LastSec:  .note.gnu.build-id
Index: llvm/test/tools/llvm-objcopy/ELF/basic-binary-copy.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/basic-binary-copy.test
+++ llvm/test/tools/llvm-objcopy/ELF/basic-binary-copy.test
@@ -10,16 +10,17 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
     AddressAlign:    0x0000000000001000
     Content:         "c3c3c3c3"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text
 
 # CHECK: 0000000 c3c3 c3c3
 # SIZE:  4
Index: llvm/test/tools/llvm-objcopy/ELF/binary-first-seg-offset-zero.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/binary-first-seg-offset-zero.test
+++ llvm/test/tools/llvm-objcopy/ELF/binary-first-seg-offset-zero.test
@@ -9,6 +9,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .note
+        LastSec:  .rodata
   - Name:            .note
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC ]
@@ -22,11 +29,5 @@
     Address:         0x1020
     Size:            4064
     Content:         "DEADBEEF"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .note
-    LastSec:  .rodata
 
 # CHECK: 000000 de ad be ef
Index: llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test
+++ llvm/test/tools/llvm-objcopy/ELF/binary-no-paddr.test
@@ -19,6 +19,20 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1000
+        PAddr:    [[PADDR]]
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x1004
+        PAddr:    [[PADDR]]
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -31,19 +45,6 @@
     Address:         0x1004
     AddressAlign:    0x0000000000000004
     Content:         "3232"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1000
-    PAddr:    [[PADDR]]
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x1004
-    PAddr:    [[PADDR]]
-    FirstSec: .data
-    LastSec:  .data
 
 # CHECK: 0000000 3232 c3c3
 # SIZE:  4
Index: llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test
+++ llvm/test/tools/llvm-objcopy/ELF/binary-paddr.test
@@ -22,6 +22,12 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        FirstSec: .text
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -34,11 +40,6 @@
     Address:         0x2000
     AddressAlign:    0x1000
     Content:         "3232"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    FirstSec: .text
-    LastSec:  .data
 
 ## The computed LMA of a section not in a PT_LOAD equals its sh_addr.
 
@@ -62,6 +63,15 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x2000
+        ## p_vaddr is increased from 0x2000 to 0x4000.
+        PAddr:    0x4000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -76,14 +86,6 @@
     Address:         0x2000
     AddressAlign:    0x1000
     Content:         "3232"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x2000
-    ## p_vaddr is increased from 0x2000 to 0x4000.
-    PAddr:    0x4000
-    FirstSec: .data
-    LastSec:  .data
 
 ## Check that we use sh_offset instead of sh_addr to decide where to write section contents.
 
@@ -107,6 +109,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x3000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -122,12 +131,6 @@
     Address:         0x3000
     AddressAlign:    0x1000
     Content:         "3232"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x3000
-    FirstSec: .data
-    LastSec:  .data
 
 ## The first section (.text) is empty. Test that we skip its LMA until the first
 ## non-empty section, otherwise we would leave a large number of leading zeroes.
Index: llvm/test/tools/llvm-objcopy/ELF/binary-remove-all-but-one.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/binary-remove-all-but-one.test
+++ llvm/test/tools/llvm-objcopy/ELF/binary-remove-all-but-one.test
@@ -10,6 +10,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text3
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -31,12 +38,6 @@
     AddressAlign:    0x1000
     Content:         "32323232"
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text3
 
 # CHECK: 000000 de ad be ef
 
Index: llvm/test/tools/llvm-objcopy/ELF/binary-remove-end.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/binary-remove-end.test
+++ llvm/test/tools/llvm-objcopy/ELF/binary-remove-end.test
@@ -10,6 +10,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text3
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -31,12 +38,6 @@
     AddressAlign:    0x1000
     Content:         "32323232"
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text3
 
 # CHECK: 000000 c3 c3 c3 c3
 # CHECK: 001000 de ad be ef
Index: llvm/test/tools/llvm-objcopy/ELF/binary-remove-middle.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/binary-remove-middle.test
+++ llvm/test/tools/llvm-objcopy/ELF/binary-remove-middle.test
@@ -10,6 +10,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text3
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -31,12 +38,6 @@
     AddressAlign:    0x1000
     Content:         "32323232"
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text3
 
 # CHECK: 000000 c3 c3 c3 c3
 # CHECK: 001000 00 00 00 00
Index: llvm/test/tools/llvm-objcopy/ELF/binary-segment-layout.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/binary-segment-layout.test
+++ llvm/test/tools/llvm-objcopy/ELF/binary-segment-layout.test
@@ -10,6 +10,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x00
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x08
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -22,17 +34,6 @@
     AddressAlign:    0x0000000000000008
     Address:         0x08
     Content:         "3232"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x00
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x08
-    FirstSec: .data
-    LastSec:  .data
 
 # CHECK:       0000000 c3c3 c3c3 0000 0000 3232
 # SIZE:        10
Index: llvm/test/tools/llvm-objcopy/ELF/build-id-link-dir.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/build-id-link-dir.test
+++ llvm/test/tools/llvm-objcopy/ELF/build-id-link-dir.test
@@ -45,12 +45,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        Flags:    [ PF_R ]
+        FirstSec: .note.gnu.build-id
+        LastSec:  .note.gnu.build-id
   - Name:            .note.gnu.build-id
     Type:            SHT_NOTE
     Flags:           [ SHF_ALLOC ]
     Content:         040000001000000003000000474E55004FCB712AA6387724A9F465A32CD8C14B
-ProgramHeaders:
-  - Type:     PT_NOTE
-    Flags:    [ PF_R ]
-    FirstSec: .note.gnu.build-id
-    LastSec:  .note.gnu.build-id
Index: llvm/test/tools/llvm-objcopy/ELF/check-addr-offset-align-binary.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/check-addr-offset-align-binary.test
+++ llvm/test/tools/llvm-objcopy/ELF/check-addr-offset-align-binary.test
@@ -9,6 +9,20 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1000
+        Align:    0x1000
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x1008
+        Align:    0x1000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -21,18 +35,5 @@
     Address:         0x1008
     AddressAlign:    0x0000000000000008
     Content:         "3232"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1000
-    Align:    0x1000
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x1008
-    Align:    0x1000
-    FirstSec: .data
-    LastSec:  .data
 
 # CHECK: 0000000 c3 c3 c3 c3 00 00 00 00 32 32
Index: llvm/test/tools/llvm-objcopy/ELF/check-addr-offset-align.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/check-addr-offset-align.test
+++ llvm/test/tools/llvm-objcopy/ELF/check-addr-offset-align.test
@@ -9,6 +9,20 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1000
+        Align:    0x1000
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x1008
+        Align:    0x1000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -21,19 +35,6 @@
     Address:         0x1008
     AddressAlign:    0x0000000000000008
     Content:         "3232"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1000
-    Align:    0x1000
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x1008
-    Align:    0x1000
-    FirstSec: .data
-    LastSec:  .data
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:   ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/copy-after-strip-sections.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/copy-after-strip-sections.test
+++ llvm/test/tools/llvm-objcopy/ELF/copy-after-strip-sections.test
@@ -17,10 +17,11 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .text
+        LastSec:  .text
   - Name: .text
     Type: SHT_PROGBITS
     Content: 'facefeed'
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .text
-    LastSec:  .text
Index: llvm/test/tools/llvm-objcopy/ELF/dump-section.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/dump-section.test
+++ llvm/test/tools/llvm-objcopy/ELF/dump-section.test
@@ -19,6 +19,12 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -34,11 +40,6 @@
   - Name:            .bar
     Type:            SHT_NOBITS
     Flags:           [ SHF_WRITE ]
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text
 
 # CHECK: 0000000 de ad be ef
 
Index: llvm/test/tools/llvm-objcopy/ELF/empty-section.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/empty-section.test
+++ llvm/test/tools/llvm-objcopy/ELF/empty-section.test
@@ -59,6 +59,18 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0
+        Align:    0x100
+        FirstSec: .foo
+        LastSec:  .foo
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        Align:    0x1000
+        FirstSec: .empty
+        LastSec:  .baz
   - Name:         gap
     Type:         Fill
     Size:         0xE00
@@ -78,14 +90,3 @@
     AddressAlign: 0x1000
     Address:      0x1000
     Size:         0x100
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0
-    Align:    0x100
-    FirstSec: .foo
-    LastSec:  .foo
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    Align:    0x1000
-    FirstSec: .empty
-    LastSec:  .baz
Index: llvm/test/tools/llvm-objcopy/ELF/identical-segments.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/identical-segments.test
+++ llvm/test/tools/llvm-objcopy/ELF/identical-segments.test
@@ -13,6 +13,20 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text2
+        LastSec:  .text2
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text2
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text2
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -23,19 +37,6 @@
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
     AddressAlign:    0x1000
     Size:            4096
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text2
-    LastSec:  .text2
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text2
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text2
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:  ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/invalid-e_phoff.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/invalid-e_phoff.test
+++ llvm/test/tools/llvm-objcopy/ELF/invalid-e_phoff.test
@@ -27,7 +27,9 @@
   Data:    ELFDATA2LSB
   Type:    ET_EXEC
   Machine: EM_X86_64
-ProgramHeaders:
-  - Type: PT_LOAD
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
 
 # CASE2: error: program headers are longer than binary of size 120: e_phoff = 0x40000000, e_phnum = 1, e_phentsize = 56
Index: llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test
+++ llvm/test/tools/llvm-objcopy/ELF/invalid-p_filesz-p_offset.test
@@ -13,13 +13,14 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FileSize: 0x100000
+        FirstSec: .foo
+        LastSec:  .foo
   - Name: .foo
     Type: SHT_PROGBITS
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FileSize: 0x100000
-    FirstSec: .foo
-    LastSec:  .foo
 
 ## A similar case, but now the p_offset property of the program header is too large.
 
@@ -33,7 +34,9 @@
   Data:    ELFDATA2LSB
   Type:    ET_EXEC
   Machine: EM_X86_64
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Offset:   0x100000
-    FileSize: 1
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Offset:   0x100000
+        FileSize: 1
Index: llvm/test/tools/llvm-objcopy/ELF/marker-segment.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/marker-segment.test
+++ llvm/test/tools/llvm-objcopy/ELF/marker-segment.test
@@ -9,6 +9,29 @@
   Type:            ET_EXEC
   Machine:         EM_ARM
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1000
+        Align:    0x1000
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x2000
+        Align:    0x1000
+        FirstSec: .data
+        LastSec:  .data
+      - Type: PT_GNU_STACK
+        Flags: [ PF_R, PF_W ]
+        VAddr: 0x0000
+        Align: 0x0000
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x2010
+        FirstSec: .xdata
+        LastSec:  .after
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -28,28 +51,6 @@
     Type:            SHT_NOBITS
     Flags:           [ SHF_ALLOC ]
     Size:            64
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1000
-    Align:    0x1000
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x2000
-    Align:    0x1000
-    FirstSec: .data
-    LastSec:  .data
-  - Type: PT_GNU_STACK
-    Flags: [ PF_R, PF_W ]
-    VAddr: 0x0000
-    Align: 0x0000
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x2010
-    FirstSec: .xdata
-    LastSec:  .after
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:   ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/no-build-id.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/no-build-id.test
+++ llvm/test/tools/llvm-objcopy/ELF/no-build-id.test
@@ -10,12 +10,13 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        Flags:    [ PF_R ]
+        FirstSec: .note.foo
+        LastSec:  .note.foo
   - Name:            .note.foo
     Type:            SHT_NOTE
     Flags:           [ SHF_ALLOC ]
     Content:         000000000000000000000000
-ProgramHeaders:
-  - Type:     PT_NOTE
-    Flags:    [ PF_R ]
-    FirstSec: .note.foo
-    LastSec:  .note.foo
Index: llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test
+++ llvm/test/tools/llvm-objcopy/ELF/only-keep-debug.test
@@ -45,6 +45,29 @@
   Type:      ET_DYN
   Machine:   EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        Offset:   0
+        Align:    0x1000
+        FirstSec: .note1
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x1480    # Ensure Offset=VAddr (mod Align) if Offset changes
+        Align:    0x1000
+        FirstSec: .tdata
+        LastSec:  .bss
+      - Type:     PT_TLS
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x1480    # Ensure Offset=VAddr (mod Align) if Offset changes
+        FirstSec: .tdata
+        LastSec:  .tbss
+      - Type:     PT_NOTE
+        VAddr:    0x400
+        FirstSec: .note1
+        LastSec:  .note2
   - Name:         .note1
     Type:         SHT_NOTE
     Flags:        [ SHF_ALLOC ]
@@ -92,28 +115,6 @@
   - Name:         .debug_info
     Type:         SHT_PROGBITS
     Content:      05
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    Offset:   0
-    Align:    0x1000
-    FirstSec: .note1
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x1480    # Ensure Offset=VAddr (mod Align) if Offset changes
-    Align:    0x1000
-    FirstSec: .tdata
-    LastSec:  .bss
-  - Type:     PT_TLS
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x1480    # Ensure Offset=VAddr (mod Align) if Offset changes
-    FirstSec: .tdata
-    LastSec:  .tbss
-  - Type:     PT_NOTE
-    VAddr:    0x400
-    FirstSec: .note1
-    LastSec:  .note2
 ...
 
 # RUN: yaml2obj --docnum=2 %s -o %t2
@@ -142,6 +143,28 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_PHDR
+        Flags:    [ PF_R ]
+        Offset:   0x40
+        VAddr:    0x40
+        # 3 * sizeof(Elf64_Phdr) = 0xa8
+        FileSize: 0xa8
+        MemSize:  0xa8
+        Align:    8
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        Offset:   0
+        Align:    4096
+        FirstSec: .text
+        LastSec:  .note
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        Offset:   0x202
+        VAddr:    0x202
+        FileSize: 14
+        MemSize:  14
   - Name:         .text
     Type:         SHT_PROGBITS
     Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -157,27 +180,6 @@
     Type:         SHT_PROGBITS
     AddressAlign: 0x20
     Content:      02
-ProgramHeaders:
-  - Type:     PT_PHDR
-    Flags:    [ PF_R ]
-    Offset:   0x40
-    VAddr:    0x40
-    # 3 * sizeof(Elf64_Phdr) = 0xa8
-    FileSize: 0xa8
-    MemSize:  0xa8
-    Align:    8
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    Offset:   0
-    Align:    4096
-    FirstSec: .text
-    LastSec:  .note
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    Offset:   0x202
-    VAddr:    0x202
-    FileSize: 14
-    MemSize:  14
 ...
 
 ## If .symtab or .strtab has the SHF_ALLOC flag, it will be changed to SHT_NOBITS.
@@ -244,6 +246,29 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        VAddr:    0x200
+        Align:    0x1000
+        FirstSec: .text
+        LastSec:  .text
+## Add .got so that the PT_LOAD does not have zero p_memsz. We don't add
+## sections to zero-sized segments so zero-sized segments may have strange
+## offsets. In practice, the Linux kernel errors when mmapping a p_memsz
+## PT_LOAD,so for practical so this assumption can generally be made.
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x1240
+        Align:    0x1000
+        FirstSec: .tdata
+        LastSec:  .got
+      - Type:     PT_TLS
+        Flags:    [ PF_R ]
+        VAddr:    0x1240
+        FirstSec: .tdata
+        LastSec:  .tdata
   - Name:         .text
     Type:         SHT_PROGBITS
     Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -258,25 +283,3 @@
     Type:         SHT_PROGBITS
     Flags:        [ SHF_ALLOC, SHF_WRITE ]
     Size:         8
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    VAddr:    0x200
-    Align:    0x1000
-    FirstSec: .text
-    LastSec:  .text
-  ## Add .got so that the PT_LOAD does not have zero p_memsz. We don't add
-  ## sections to zero-sized segments so zero-sized segments may have strange
-  ## offsets. In practice, the Linux kernel errors when mmapping a p_memsz
-  ## PT_LOAD,so for practical so this assumption can generally be made.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x1240
-    Align:    0x1000
-    FirstSec: .tdata
-    LastSec:  .got
-  - Type:     PT_TLS
-    Flags:    [ PF_R ]
-    VAddr:    0x1240
-    FirstSec: .tdata
-    LastSec:  .tdata
Index: llvm/test/tools/llvm-objcopy/ELF/overlap-chain.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/overlap-chain.test
+++ llvm/test/tools/llvm-objcopy/ELF/overlap-chain.test
@@ -14,6 +14,24 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text2
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text4
+        LastSec:  .text5
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text3
+        LastSec:  .text4
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text2
+        LastSec:  .text3
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -39,23 +57,6 @@
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
     AddressAlign:    0x1000
     Size:            4096
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text2
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text4
-    LastSec:  .text5
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text3
-    LastSec:  .text4
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text2
-    LastSec:  .text3
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:  ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/overlapping-sections-in-segments.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/overlapping-sections-in-segments.test
+++ llvm/test/tools/llvm-objcopy/ELF/overlapping-sections-in-segments.test
@@ -31,6 +31,12 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FileSize: 5
+        Offset:   0x1000
+        Align:    0x1000
   - Name: .first
     Type: SHT_PROGBITS
     Content: '01234567'
@@ -39,8 +45,3 @@
     Type: SHT_PROGBITS
     Content: '89abcdef'
     ShOffset: 0x1001
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FileSize: 5
-    Offset:   0x1000
-    Align:    0x1000
Index: llvm/test/tools/llvm-objcopy/ELF/parent-loop-check.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/parent-loop-check.test
+++ llvm/test/tools/llvm-objcopy/ELF/parent-loop-check.test
@@ -19,6 +19,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .note
+        LastSec:  .rodata
+      - Type:     PT_NOTE
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .note
+        LastSec:  .note
   - Name:            .note
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC ]
@@ -32,16 +44,5 @@
     Address:         0x1020
     Size:            4064
     Content:         "DEADBEEF"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .note
-    LastSec:  .rodata
-  - Type:     PT_NOTE
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .note
-    LastSec:  .note
 
 # CHECK: 000000 de ad be ef
Index: llvm/test/tools/llvm-objcopy/ELF/preserve-segment-contents-ehdr-phdrs.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/preserve-segment-contents-ehdr-phdrs.test
+++ llvm/test/tools/llvm-objcopy/ELF/preserve-segment-contents-ehdr-phdrs.test
@@ -26,17 +26,18 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Offset:   0
+        FileSize: 176 # sizeof(Elf64_Ehdr) + 2 * sizeof(Elf64_Phdr)
+      - Type:     PT_LOAD
+        FirstSec: .keep_me
+        LastSec:  .keep_me
   - Name: .remove_me
     Type: SHT_PROGBITS
     Size: 0x10
   - Name: .keep_me
     Type: SHT_PROGBITS
     Size: 0x10
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Offset:   0
-    FileSize: 176 # sizeof(Elf64_Ehdr) + 2 * sizeof(Elf64_Phdr)
-  - Type:     PT_LOAD
-    FirstSec: .keep_me
-    LastSec:  .keep_me
 Symbols: []
Index: llvm/test/tools/llvm-objcopy/ELF/preserve-segment-contents.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/preserve-segment-contents.test
+++ llvm/test/tools/llvm-objcopy/ELF/preserve-segment-contents.test
@@ -66,6 +66,245 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## First segment has unlabelled space at start and end.
+      - Type:     0x6ABCDEF0 # Non-specific segment type.
+        VAddr:    0x2000
+        Align:    0x2000
+        FirstSec: blob1
+        LastSec:  blob4
+## Second segment has sections at start and end.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x2100
+        Align:    0x100
+        FirstSec: section4
+        LastSec:  section5
+## Third segment is all covered by a section.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x2200
+        Align:    0x100
+        FirstSec: section6
+        LastSec:  section6
+## Fourth segment has no sections (after removing blob headers).
+      - Type:     0x6ABCDEF0
+        VAddr:    0x2300
+        Align:    0x100
+        FirstSec: blob6
+        LastSec:  blob6
+## Fifth segment is empty.
+      - Type:   0x6ABCDEF0
+        VAddr:  0x2308
+        Offset: 0x2308
+## The next few segments test behaviour of fully nested segments.
+## Sixth segment is the "parent" segment.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x3000
+        Align:    0x1000
+        FirstSec: sectionA
+        LastSec:  sectionI
+## Seventh segment is empty and nested.
+      - Type:   0x6ABCDEF0
+        VAddr:  0x3002
+        Offset: 0x3002
+## Eighth segment contains only a section and is nested.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x3004
+        FirstSec: sectionB
+        LastSec:  sectionB
+## Ninth segment contains only unlabelled space and is nested.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x3008
+        FirstSec: blobA
+        LastSec:  blobA
+## Tenth segment contains two sections with space between and is nested.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x300C
+        FirstSec: sectionC
+        LastSec:  sectionD
+## Eleventh segment contains two sections with space between and at ends and is nested.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x3018
+        FirstSec: blobC
+        LastSec:  blobE
+## Twelfth segment contains one section with space at ends adjacent to space in parent segment.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x302E
+        Offset:   0x302E
+        FileSize: 8
+        FirstSec: sectionG
+        LastSec:  sectionG
+## Thirteenth segment contains overlaps sections at either end in parent segment.
+      - Type:     0x6ABCDEF0
+        VAddr:    0x303A
+        Offset:   0x303A
+        FileSize: 0x8
+        FirstSec: blobH
+        LastSec:  blobH
+
+## The next batch of segments are segments that only partially overlap other segments.
+
+## Segment14: |-unlabelled-|-Sec-|
+## Segment15:           |--|-Sec-|-unlabelled-|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x4000
+        FirstSec: blobz
+        LastSec:  sectionz
+      - Type:     0x6ABCDEF0
+        VAddr:    0x4002
+        Offset:   0x4002
+        FirstSec: sectionz
+        LastSec:  bloby
+
+## Segment16: |-Sec-|--|
+## Segment17:    |--|----unlabelled---|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x400C
+        FileSize: 6
+        FirstSec: sectiony
+        LastSec:  sectiony
+      - Type:     0x6ABCDEF0
+        VAddr:    0x400E
+        Offset:   0x400E
+        FirstSec: blobx
+        LastSec:  blobx
+
+## Segment18: |-unlabelled-|-Sec-|
+## Segment19:              |-Sec-|-unlabelled-|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x4014
+        FirstSec: blobw
+        LastSec:  sectionx
+      - Type:     0x6ABCDEF0
+        VAddr:    0x4018
+        FirstSec: sectionx
+        LastSec:  blobv
+
+## Segment20: |-Sec-|
+## Segment21:    |--|-unlabelled-|-Sec-|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x4020
+        FirstSec: sectionw
+        LastSec:  sectionw
+
+      - Type:   0x6ABCDEF0
+        VAddr:  0x4022
+        Offset: 0x4022
+        FirstSec: blobu
+        LastSec:  sectionv
+
+## Segment22: |-Sec-|
+## Segment23:    |--|-Sec-|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x402C
+        FirstSec: sectionu
+        LastSec:  sectionu
+      - Type:     0x6ABCDEF0
+        VAddr:    0x402E
+        Offset:   0x402E
+        FirstSec: sectiont
+        LastSec:  sectiont
+
+## Segment24: |-unlabelled-|--|
+## Segment25:              |--Sec--|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x4034
+        FileSize: 6
+        FirstSec: blobt
+        LastSec:  blobt
+      - Type:     0x6ABCDEF0
+        VAddr:    0x4038
+        FirstSec: sections
+        LastSec:  sections
+
+## The next batch of segments represent groups of three nested/overlapping segments,
+## with one parent segment containing two overlapping segments.
+
+## Segment26: |-unlabelled-|-Sec-|-unlabelled-|
+## Segment27: |------------|--|
+## Segment28:              |-Sec-|------------|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5000
+        Align:    0x1000
+        FirstSec: bloba
+        LastSec:  blobb
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5000
+        FileSize: 6
+        FirstSec: bloba
+        LastSec:  bloba
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5004
+        FirstSec: sectiona
+        LastSec:  blobb
+
+## Segment29: |-Sec-|-unlabelled-|-Sec-|
+## Segment30: |-Sec-|--------|
+## Segment31:          |---------|-Sec-|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x500C
+        FirstSec: sectionb
+        LastSec:  sectionc
+      - Type:     0x6ABCDEF0
+        VAddr:    0x500C
+        FileSize: 7
+        FirstSec: sectionb
+        LastSec:  sectionb
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5011
+        Offset:   0x5011
+        FirstSec: sectionc
+        LastSec:  sectionc
+
+## Segment32: |-Sec-|-unlabelled-|-Sec-|
+## Segment33: |-Sec-|------------|
+## Segment34:       |------------|-Sec-|
+      - Type:    0x6ABCDEF0
+        VAddr:   0x5018
+        FirstSec: sectiond
+        LastSec:  sectione
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5018
+        FirstSec: sectiond
+        LastSec:  blobd
+      - Type:     0x6ABCDEF0
+        VAddr:    0x501C
+        FirstSec: blobd
+        LastSec:  sectione
+
+## Segment35: |-unlabelled-|-Sec-|-unlabelled-|
+## Segment36: |------------|-Sec-|
+## Segment37:              |-Sec-|------------|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5024
+        FirstSec: blobe
+        LastSec:  blobf
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5024
+        FirstSec: blobe
+        LastSec:  sectionf
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5028
+        FirstSec: sectionf
+        LastSec:  blobf
+
+## Segment38: |-unlabelled-|-Sec-|-unlabelled-|
+## Segment39: |------------|---|
+## Segment40:                |---|------------|
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5030
+        FirstSec: blobg
+        LastSec:  blobh
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5030
+        FileSize: 7
+        FirstSec: blobg
+        LastSec:  blobg
+      - Type:     0x6ABCDEF0
+        VAddr:    0x5035
+        Offset:   0x5035
+        FirstSec: blobh
+        LastSec:  blobh
   - Name: blob1
     Type: SHT_PROGBITS
     Content: 'abbababa'
@@ -309,241 +548,3 @@
     Type: SHT_PROGBITS
     Content: 'abbababa'
     Address: 0x5038
-ProgramHeaders:
-  # First segment has unlabelled space at start and end.
-  - Type:     0x6ABCDEF0 # Non-specific segment type.
-    VAddr:    0x2000
-    Align:    0x2000
-    FirstSec: blob1
-    LastSec:  blob4
-  # Second segment has sections at start and end.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x2100
-    Align:    0x100
-    FirstSec: section4
-    LastSec:  section5
-  # Third segment is all covered by a section.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x2200
-    Align:    0x100
-    FirstSec: section6
-    LastSec:  section6
-  # Fourth segment has no sections (after removing blob headers).
-  - Type:     0x6ABCDEF0
-    VAddr:    0x2300
-    Align:    0x100
-    FirstSec: blob6
-    LastSec:  blob6
-  # Fifth segment is empty.
-  - Type:   0x6ABCDEF0
-    VAddr:  0x2308
-    Offset: 0x2308
-  # The next few segments test behaviour of fully nested segments.
-  # Sixth segment is the "parent" segment.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x3000
-    Align:    0x1000
-    FirstSec: sectionA
-    LastSec:  sectionI
-  # Seventh segment is empty and nested.
-  - Type:   0x6ABCDEF0
-    VAddr:  0x3002
-    Offset: 0x3002
-  # Eighth segment contains only a section and is nested.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x3004
-    FirstSec: sectionB
-    LastSec:  sectionB
-  # Ninth segment contains only unlabelled space and is nested.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x3008
-    FirstSec: blobA
-    LastSec:  blobA
-  # Tenth segment contains two sections with space between and is nested.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x300C
-    FirstSec: sectionC
-    LastSec:  sectionD
-  # Eleventh segment contains two sections with space between and at ends and is nested.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x3018
-    FirstSec: blobC
-    LastSec:  blobE
-  # Twelfth segment contains one section with space at ends adjacent to space in parent segment.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x302E
-    Offset:   0x302E
-    FileSize: 8
-    FirstSec: sectionG
-    LastSec:  sectionG
-  # Thirteenth segment contains overlaps sections at either end in parent segment.
-  - Type:     0x6ABCDEF0
-    VAddr:    0x303A
-    Offset:   0x303A
-    FileSize: 0x8
-    FirstSec: blobH
-    LastSec:  blobH
-
-  # The next batch of segments are segments that only partially overlap other segments.
-
-  # Segment14: |-unlabelled-|-Sec-|
-  # Segment15:           |--|-Sec-|-unlabelled-|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x4000
-    FirstSec: blobz
-    LastSec:  sectionz
-  - Type:     0x6ABCDEF0
-    VAddr:    0x4002
-    Offset:   0x4002
-    FirstSec: sectionz
-    LastSec:  bloby
-
-  # Segment16: |-Sec-|--|
-  # Segment17:    |--|----unlabelled---|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x400C
-    FileSize: 6
-    FirstSec: sectiony
-    LastSec:  sectiony
-  - Type:     0x6ABCDEF0
-    VAddr:    0x400E
-    Offset:   0x400E
-    FirstSec: blobx
-    LastSec:  blobx
-
-  # Segment18: |-unlabelled-|-Sec-|
-  # Segment19:              |-Sec-|-unlabelled-|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x4014
-    FirstSec: blobw
-    LastSec:  sectionx
-  - Type:     0x6ABCDEF0
-    VAddr:    0x4018
-    FirstSec: sectionx
-    LastSec:  blobv
-
-  # Segment20: |-Sec-|
-  # Segment21:    |--|-unlabelled-|-Sec-|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x4020
-    FirstSec: sectionw
-    LastSec:  sectionw
-
-  - Type:   0x6ABCDEF0
-    VAddr:  0x4022
-    Offset: 0x4022
-    FirstSec: blobu
-    LastSec:  sectionv
-
-  # Segment22: |-Sec-|
-  # Segment23:    |--|-Sec-|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x402C
-    FirstSec: sectionu
-    LastSec:  sectionu
-  - Type:     0x6ABCDEF0
-    VAddr:    0x402E
-    Offset:   0x402E
-    FirstSec: sectiont
-    LastSec:  sectiont
-
-  # Segment24: |-unlabelled-|--|
-  # Segment25:              |--Sec--|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x4034
-    FileSize: 6
-    FirstSec: blobt
-    LastSec:  blobt
-  - Type:     0x6ABCDEF0
-    VAddr:    0x4038
-    FirstSec: sections
-    LastSec:  sections
-
-  # The next batch of segments represent groups of three nested/overlapping segments,
-  # with one parent segment containing two overlapping segments.
-
-  # Segment26: |-unlabelled-|-Sec-|-unlabelled-|
-  # Segment27: |------------|--|
-  # Segment28:              |-Sec-|------------|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5000
-    Align:    0x1000
-    FirstSec: bloba
-    LastSec:  blobb
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5000
-    FileSize: 6
-    FirstSec: bloba
-    LastSec:  bloba
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5004
-    FirstSec: sectiona
-    LastSec:  blobb
-
-  # Segment29: |-Sec-|-unlabelled-|-Sec-|
-  # Segment30: |-Sec-|--------|
-  # Segment31:          |---------|-Sec-|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x500C
-    FirstSec: sectionb
-    LastSec:  sectionc
-  - Type:     0x6ABCDEF0
-    VAddr:    0x500C
-    FileSize: 7
-    FirstSec: sectionb
-    LastSec:  sectionb
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5011
-    Offset:   0x5011
-    FirstSec: sectionc
-    LastSec:  sectionc
-
-  # Segment32: |-Sec-|-unlabelled-|-Sec-|
-  # Segment33: |-Sec-|------------|
-  # Segment34:       |------------|-Sec-|
-  - Type:    0x6ABCDEF0
-    VAddr:   0x5018
-    FirstSec: sectiond
-    LastSec:  sectione
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5018
-    FirstSec: sectiond
-    LastSec:  blobd
-  - Type:     0x6ABCDEF0
-    VAddr:    0x501C
-    FirstSec: blobd
-    LastSec:  sectione
-
-  # Segment35: |-unlabelled-|-Sec-|-unlabelled-|
-  # Segment36: |------------|-Sec-|
-  # Segment37:              |-Sec-|------------|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5024
-    FirstSec: blobe
-    LastSec:  blobf
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5024
-    FirstSec: blobe
-    LastSec:  sectionf
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5028
-    FirstSec: sectionf
-    LastSec:  blobf
-
-  # Segment38: |-unlabelled-|-Sec-|-unlabelled-|
-  # Segment39: |------------|---|
-  # Segment40:                |---|------------|
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5030
-    FirstSec: blobg
-    LastSec:  blobh
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5030
-    FileSize: 7
-    FirstSec: blobg
-    LastSec:  blobg
-  - Type:     0x6ABCDEF0
-    VAddr:    0x5035
-    Offset:   0x5035
-    FirstSec: blobh
-    LastSec:  blobh
Index: llvm/test/tools/llvm-objcopy/ELF/program-headers.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/program-headers.test
+++ llvm/test/tools/llvm-objcopy/ELF/program-headers.test
@@ -9,6 +9,20 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0xAAAA1000
+        PAddr:    0xFFFF1000
+        FirstSec: .text
+        LastSec:  .init
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0xAAAA2000
+        PAddr:    0xFFFF2000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -27,19 +41,6 @@
     Content:         "00000000"
     Address:         0xAAAA2000
     AddressAlign:    0x0000000000001000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0xAAAA1000
-    PAddr:    0xFFFF1000
-    FirstSec: .text
-    LastSec:  .init
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0xAAAA2000
-    PAddr:    0xFFFF2000
-    FirstSec: .data
-    LastSec:  .data
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:   ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/remove-section-in-segment.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/remove-section-in-segment.test
+++ llvm/test/tools/llvm-objcopy/ELF/remove-section-in-segment.test
@@ -31,6 +31,12 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## Use an arbitrary segment type to show that the segment type is unimportant.
+      - Type: 0x61234567
+        FirstSec: shf_alloc
+        LastSec:  non_alloc
   - Name:    shf_alloc
     Type:    SHT_PROGBITS
     Flags:   [SHF_ALLOC]
@@ -39,8 +45,3 @@
     Type:    SHT_PROGBITS
     Flags:   []
     Content: '55667788'
-ProgramHeaders:
-  # Use an arbitrary segment type to show that the segment type is unimportant.
-  - Type: 0x61234567
-    FirstSec: shf_alloc
-    LastSec:  non_alloc
Index: llvm/test/tools/llvm-objcopy/ELF/segment-shift-section-remove.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/segment-shift-section-remove.test
+++ llvm/test/tools/llvm-objcopy/ELF/segment-shift-section-remove.test
@@ -9,6 +9,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x3000
+        FirstSec: .text3
+        LastSec:  .text3
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -27,17 +39,6 @@
     Address:         0x3000
     AddressAlign:    0x1000
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x3000
-    FirstSec: .text3
-    LastSec:  .text3
 ## TODO (grimar): without the following line (i.e. without an empty symbol table),
 ## llvm-objcopy adds an empty .strtab section. It doesn't look correct.
 Symbols: []
Index: llvm/test/tools/llvm-objcopy/ELF/segment-shift.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/segment-shift.test
+++ llvm/test/tools/llvm-objcopy/ELF/segment-shift.test
@@ -9,6 +9,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x3000
+        FirstSec: .text3
+        LastSec:  .text3
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -27,17 +39,6 @@
     Address:         0x3000
     AddressAlign:    0x1000
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x3000
-    FirstSec: .text3
-    LastSec:  .text3
 
 # CHECK:     ProgramHeaders [
 # CHECK-NEXT:  ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/segment-test-remove-section.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/segment-test-remove-section.test
+++ llvm/test/tools/llvm-objcopy/ELF/segment-test-remove-section.test
@@ -16,6 +16,12 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text3
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -35,11 +41,6 @@
     Address:         0x3000
     AddressAlign:    0x1000
     Size:            4096
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text3
 ## TODO (grimar): without the following line (i.e. without an empty symbol table),
 ## llvm-objcopy adds an empty .strtab section. It doesn't look correct.
 Symbols: []
Index: llvm/test/tools/llvm-objcopy/ELF/strip-all-gnu.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/strip-all-gnu.test
+++ llvm/test/tools/llvm-objcopy/ELF/strip-all-gnu.test
@@ -17,6 +17,12 @@
   Type:            ET_REL
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## Use an arbitrary segment type to show that the segment type is unimportant.
+      - Type:     0x61234567
+        FirstSec: .debug_in_segment
+        LastSec:  .debug_in_segment
   - Name:            .debug_in_segment
     Type:            SHT_PROGBITS
     Flags:           [ ]
@@ -54,11 +60,6 @@
   - Name:            .rela.text
     Type:            SHT_RELA
     Info:            .text
-ProgramHeaders:
-  # Use an arbitrary segment type to show that the segment type is unimportant.
-  - Type:     0x61234567
-    FirstSec: .debug_in_segment
-    LastSec:  .debug_in_segment
 
 # CHECK: SectionHeaderCount: 8
 
Index: llvm/test/tools/llvm-objcopy/ELF/strip-all.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/strip-all.test
+++ llvm/test/tools/llvm-objcopy/ELF/strip-all.test
@@ -53,6 +53,12 @@
   Type:            ET_REL
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## Use an arbitrary segment type to show that the segment type is unimportant.
+      - Type:     0x61234567
+        FirstSec: non_alloc_in_segment
+        LastSec:  non_alloc_in_segment
   - Name:            non_alloc_in_segment
     Type:            SHT_PROGBITS
     Flags:           [ ]
@@ -68,11 +74,6 @@
     Flags:           [ ]
   - Name:            .gnu.warning.foo
     Type:            SHT_PROGBITS
-ProgramHeaders:
-  # Use an arbitrary segment type to show that the segment type is unimportant.
-  - Type:     0x61234567
-    FirstSec: non_alloc_in_segment
-    LastSec:  non_alloc_in_segment
 
 # CHECK: SectionHeaderCount: 6
 
Index: llvm/test/tools/llvm-objcopy/ELF/strip-non-alloc.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/strip-non-alloc.test
+++ llvm/test/tools/llvm-objcopy/ELF/strip-non-alloc.test
@@ -15,6 +15,12 @@
   Type:            ET_REL
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## Use an arbitrary segment type to show that the segment type is unimportant.
+      - Type:     0x61234567
+        FirstSec: non_alloc_in_segment
+        LastSec:  non_alloc_in_segment
   - Name:            non_alloc_in_segment
     Type:            SHT_PROGBITS
     Flags:           [ ]
@@ -25,11 +31,6 @@
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-ProgramHeaders:
-  # Use an arbitrary segment type to show that the segment type is unimportant.
-  - Type:     0x61234567
-    FirstSec: non_alloc_in_segment
-    LastSec:  non_alloc_in_segment
 
 # RUN: yaml2obj --docnum=2 %s -o %t2
 # RUN: llvm-objcopy --strip-non-alloc %t2 %t2.out
@@ -46,6 +47,11 @@
   Type:      ET_REL
   Machine:   EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     0x61234567
+        FirstSec: .text
+        LastSec:  .text
   - Name:    .text
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -56,7 +62,3 @@
   - Name:    trailing_non_alloc
     Type:    SHT_PROGBITS
     Content: 00
-ProgramHeaders:
-  - Type:     0x61234567
-    FirstSec: .text
-    LastSec:  .text
Index: llvm/test/tools/llvm-objcopy/ELF/strip-sections.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/strip-sections.test
+++ llvm/test/tools/llvm-objcopy/ELF/strip-sections.test
@@ -20,6 +20,12 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .non_alloc_in_segment
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -33,11 +39,6 @@
     Type:            SHT_PROGBITS
     Flags:           [ ]
     Content:         "FEEDFACE"
-ProgramHeaders:
-- Type:     PT_LOAD
-  Flags:    [ PF_X, PF_R ]
-  FirstSec: .text
-  LastSec:  .non_alloc_in_segment
 
 # DATA: {{^[^[:blank:]]+}} de ad be ef ca fe ba be
 # DATA-NOT: fe ed fa ce
Index: llvm/test/tools/llvm-objcopy/ELF/triple-overlap.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/triple-overlap.test
+++ llvm/test/tools/llvm-objcopy/ELF/triple-overlap.test
@@ -14,6 +14,24 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text4
+        LastSec:  .text5
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text3
+        LastSec:  .text5
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text5
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text2
+        LastSec:  .text5
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -39,23 +57,6 @@
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
     AddressAlign:    0x1000
     Size:            4096
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text4
-    LastSec:  .text5
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text3
-    LastSec:  .text5
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text5
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text2
-    LastSec:  .text5
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:  ProgramHeader {
Index: llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-end.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-end.test
+++ llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-end.test
@@ -10,6 +10,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text2
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x3000
+        FirstSec: .text3
+        LastSec:  .text4
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -38,17 +50,6 @@
     AddressAlign:    0x1000
     Content:         "FFFFFFFF"
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text2
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x3000
-    FirstSec: .text3
-    LastSec:  .text4
 
 # CHECK: 000000 c3 c3 c3 c3
 # CHECK: 001000 de ad be ef
Index: llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-first.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-first.test
+++ llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-first.test
@@ -10,6 +10,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text2
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x3000
+        FirstSec: .text3
+        LastSec:  .text4
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -38,17 +50,6 @@
     AddressAlign:    0x1000
     Content:         "FFFFFFFF"
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text2
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x3000
-    FirstSec: .text3
-    LastSec:  .text4
 
 # CHECK: 000000 de ad be ef
 # CHECK: 001000 32 32 32 32
Index: llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-third-sec.test
===================================================================
--- llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-third-sec.test
+++ llvm/test/tools/llvm-objcopy/ELF/two-seg-remove-third-sec.test
@@ -10,6 +10,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text2
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x3000
+        FirstSec: .text3
+        LastSec:  .text4
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -38,17 +50,6 @@
     AddressAlign:    0x1000
     Content:         "FFFFFFFF"
     Size:            0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text2
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x3000
-    FirstSec: .text3
-    LastSec:  .text4
 
 # CHECK: 000000 c3 c3 c3 c3
 # CHECK: 001000 de ad be ef
Index: llvm/test/tools/llvm-objdump/ELF/dynamic-section-machine-specific.test
===================================================================
--- llvm/test/tools/llvm-objdump/ELF/dynamic-section-machine-specific.test
+++ llvm/test/tools/llvm-objdump/ELF/dynamic-section-machine-specific.test
@@ -16,6 +16,14 @@
   Type:    ET_EXEC
   Machine: EM_HEXAGON
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -27,13 +35,6 @@
         Value: 0x1000
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 2: Test that MIPS machine-specific tags can be dumped.
 ##         MIPS has a few long tag names. Show that we indent columns properly.
@@ -94,6 +95,14 @@
   Type:    ET_EXEC
   Machine: EM_MIPS
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -189,13 +198,6 @@
         Value: 0x1000
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 3: Test that PPC machine-specific tags can be dumped.
 # RUN: yaml2obj --docnum=3 -o %t.ppc %s
@@ -212,6 +214,14 @@
   Type:    ET_EXEC
   Machine: EM_PPC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -221,13 +231,6 @@
         Value: 1
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 4: Test that PPC64 machine-specific tags can be dumped.
 # RUN: yaml2obj --docnum=4 -o %t.ppc64 %s
@@ -243,6 +246,14 @@
   Type:    ET_EXEC
   Machine: EM_PPC64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:      PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -250,13 +261,6 @@
         Value: 0x1000
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:      PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 5: Test that AARCH64 machine-specific tags can be dumped.
 # RUN: yaml2obj --docnum=5 -o %t.aarch64 %s
@@ -273,6 +277,14 @@
   Type:    ET_EXEC
   Machine: EM_AARCH64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -282,10 +294,3 @@
         Value: 2
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
===================================================================
--- llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
+++ llvm/test/tools/llvm-objdump/ELF/dynamic-section.test
@@ -70,6 +70,16 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1010
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynstr
     Type:    SHT_STRTAB
     Address: 0x1000
@@ -204,15 +214,6 @@
        Value: 0x5555666677778888
      - Tag:   DT_NULL
        Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1010
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # RUN: yaml2obj --docnum=2 %s -o %t2
 # RUN: llvm-objdump -p %t2 | FileCheck %s --strict-whitespace --match-full-lines --check-prefix=ELF32
@@ -285,6 +286,16 @@
   Type:    ET_EXEC
   Machine: EM_386
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1010
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynstr
     Type:    SHT_STRTAB
     Address: 0x1000
@@ -419,15 +430,6 @@
        Value: 0x55556666
      - Tag:   DT_NULL
        Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1010
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## When printing the value column we want to have the minimal possible indentation.
 ## Use an arbitrary dynamic tag to demonstrate that.
Index: llvm/test/tools/llvm-objdump/ELF/pt-gnu-property.test
===================================================================
--- llvm/test/tools/llvm-objdump/ELF/pt-gnu-property.test
+++ llvm/test/tools/llvm-objdump/ELF/pt-gnu-property.test
@@ -10,5 +10,7 @@
   Data:    ELFDATA2LSB
   Type:    ET_EXEC
   Machine: EM_AARCH64
-ProgramHeaders:
-  - Type: PT_GNU_PROPERTY
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_GNU_PROPERTY
Index: llvm/test/tools/llvm-objdump/X86/elf-disassemble-dynamic-symbols.test
===================================================================
--- llvm/test/tools/llvm-objdump/X86/elf-disassemble-dynamic-symbols.test
+++ llvm/test/tools/llvm-objdump/X86/elf-disassemble-dynamic-symbols.test
@@ -50,16 +50,17 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text
   - Name:    .text
     Type:    SHT_PROGBITS
     Flags:   [SHF_ALLOC, SHF_EXECINSTR]
     Address: 0x1000
     Content: 909090909090909090909090
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text
 Symbols:
   - Name:    both_static
     Value:   0x1001
Index: llvm/test/tools/llvm-objdump/X86/elf-dynamic-relocs.test
===================================================================
--- llvm/test/tools/llvm-objdump/X86/elf-dynamic-relocs.test
+++ llvm/test/tools/llvm-objdump/X86/elf-dynamic-relocs.test
@@ -19,6 +19,18 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x100000
+        Align:    0x100
+        FirstSec: .foo
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x100500
+        Align:    0x100
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:         .foo
     Type:         SHT_PROGBITS
     Size:         16
@@ -90,17 +102,6 @@
         Value: 16
       - Tag: DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x100000
-    Align:    0x100
-    FirstSec: .foo
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x100500
-    Align:    0x100
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 DynamicSymbols:
   - Name:    foo
     Section: .foo
Index: llvm/test/tools/llvm-objdump/X86/phdrs-lma.test
===================================================================
--- llvm/test/tools/llvm-objdump/X86/phdrs-lma.test
+++ llvm/test/tools/llvm-objdump/X86/phdrs-lma.test
@@ -17,6 +17,20 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x00001000
+        PAddr:    0x00002000
+        FirstSec: .text
+        LastSec:  .init
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x00002000
+        PAddr:    0x00003000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -32,16 +46,3 @@
     Flags:           [ SHF_ALLOC ]
     Content:         "00000000"
     Address:         0x00002000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x00001000
-    PAddr:    0x00002000
-    FirstSec: .text
-    LastSec:  .init
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x00002000
-    PAddr:    0x00003000
-    FirstSec: .data
-    LastSec:  .data
Index: llvm/test/tools/llvm-objdump/X86/phdrs-lma2.test
===================================================================
--- llvm/test/tools/llvm-objdump/X86/phdrs-lma2.test
+++ llvm/test/tools/llvm-objdump/X86/phdrs-lma2.test
@@ -29,6 +29,18 @@
   Type:            ET_EXEC
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x00001000
+        FirstSec: .text
+        LastSec:  .init
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x00002000
+        FirstSec: .data
+        LastSec:  .data
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -44,14 +56,3 @@
     Flags:           [ SHF_ALLOC ]
     Content:         "00000000"
     Address:         0x00002000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x00001000
-    FirstSec: .text
-    LastSec:  .init
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x00002000
-    FirstSec: .data
-    LastSec:  .data
Index: llvm/test/tools/llvm-objdump/openbsd-headers.test
===================================================================
--- llvm/test/tools/llvm-objdump/openbsd-headers.test
+++ llvm/test/tools/llvm-objdump/openbsd-headers.test
@@ -16,7 +16,9 @@
   Data:    ELFDATA2LSB
   Type:    ET_EXEC
   Machine: EM_X86_64
-ProgramHeaders:
-  - Type: 0x65a3dbe6 ## PT_OPENBSD_RANDOMIZE
-  - Type: 0x65a3dbe7 ## PT_OPENBSD_WXNEEDED
-  - Type: 0x65a41be6 ## PT_OPENBSD_BOOTDATA
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: 0x65a3dbe6 ## PT_OPENBSD_RANDOMIZE
+      - Type: 0x65a3dbe7 ## PT_OPENBSD_WXNEEDED
+      - Type: 0x65a41be6 ## PT_OPENBSD_BOOTDATA
Index: llvm/test/tools/llvm-objdump/section-filter.test
===================================================================
--- llvm/test/tools/llvm-objdump/section-filter.test
+++ llvm/test/tools/llvm-objdump/section-filter.test
@@ -16,6 +16,23 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x400
+        PAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text2
+      - Type:     PT_LOAD
+        VAddr:    0x410
+        PAddr:    0x2000
+        FirstSec: .data
+        LastSec:  .data
+      - Type:     PT_LOAD
+        VAddr:    0x420
+        PAddr:    0x3000
+        FirstSec: .bss
+        LastSec:  .bss
   - Name:         .text
     Type:         SHT_PROGBITS
     Flags:        [SHF_ALLOC, SHF_EXECINSTR]
@@ -39,22 +56,6 @@
     Address:      0x420
     AddressAlign: 0x10
     Size:         1
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x400
-    PAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text2
-  - Type:     PT_LOAD
-    VAddr:    0x410
-    PAddr:    0x2000
-    FirstSec: .data
-    LastSec:  .data
-  - Type:     PT_LOAD
-    VAddr:    0x420
-    PAddr:    0x3000
-    FirstSec: .bss
-    LastSec:  .bss
 
 ## Test that --section works with --fault-map-section.
 # RUN: yaml2obj %s --docnum=2 -o %t.o
Index: llvm/test/tools/llvm-objdump/warn-on-out-of-range-start-stop-address.test
===================================================================
--- llvm/test/tools/llvm-objdump/warn-on-out-of-range-start-stop-address.test
+++ llvm/test/tools/llvm-objdump/warn-on-out-of-range-start-stop-address.test
@@ -136,6 +136,14 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1000
+        FileSize: 0x500
+        FirstSec: .text
+        LastSec:  .text2
   - Name:    .text
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -146,13 +154,6 @@
     Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
     Address: 0x1400
     Size:    4
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1000
-    FileSize: 0x500
-    FirstSec: .text
-    LastSec:  .text2
 
 --- !ELF
 FileHeader:
@@ -161,18 +162,19 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x1000
+        FileSize: 0x4
+        FirstSec: .text
+        LastSec:  .text
   - Name:    .text
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
     Address: 0x2000
     Size:    4
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x1000
-    FileSize: 0x4
-    FirstSec: .text
-    LastSec:  .text
 
 --- !ELF
 FileHeader:
Index: llvm/test/tools/llvm-readobj/ELF/all.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/all.test
+++ llvm/test/tools/llvm-readobj/ELF/all.test
@@ -45,6 +45,21 @@
   Type:    ET_REL
   Machine: EM_386
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .hash
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_GNU_EH_FRAME
+        FirstSec: .eh_frame_hdr
+        LastSec:  .eh_frame_hdr
+      - Type:     PT_NOTE
+        FirstSec: .note.gnu.build-id
+        LastSec:  .note.gnu.build-id
   - Name: .data
     Type: SHT_PROGBITS
   - Name: .rela.data
@@ -93,20 +108,6 @@
     Address: 0x1500
 ## An arbitrary linker-generated valid content.
     Content: 040000001000000003000000474E55004FCB712AA6387724A9F465A32CD8C14B
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .hash
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_GNU_EH_FRAME
-    FirstSec: .eh_frame_hdr
-    LastSec:  .eh_frame_hdr
-  - Type:     PT_NOTE
-    FirstSec: .note.gnu.build-id
-    LastSec:  .note.gnu.build-id
 Symbols: []
 DynamicSymbols:
   - Name: foo
Index: llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
+++ llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test
@@ -24,6 +24,11 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.dyn
+        LastSec:  .dynamic
   - Name:    .rela.dyn
     Type:    SHT_RELA
     Link:    .dynsym
@@ -43,10 +48,6 @@
         Value: 0x0000000000000000
 DynamicSymbols:
   - StName: 0x1234
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.dyn
-    LastSec:  .dynamic
 
 ## Show we print a warning for an invalid relocation table size stored in a DT_RELASZ entry.
 
@@ -66,6 +67,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .relx.dyn
+        LastSec:  .dynamic
   - Name:  .relx.dyn
     Type:  SHT_[[RELTYPE]]
   - Name: .dynamic
@@ -80,10 +86,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .relx.dyn
-    LastSec:  .dynamic
 
 ## Case B: the DT_RELASZ has value of 0x251, what is too large, because the relocation table goes past the EOF.
 
@@ -172,6 +174,11 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.plt
+        LastSec:  .dynamic
   - Name:  .rela.plt
     Type:  SHT_RELA
     Relocations:
@@ -188,10 +195,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.plt
-    LastSec:  .dynamic
 
 ## Case B: the DT_PLTRELSZ (PLT size) has value of 0x269, what is too large, because PLT goes past the EOF.
 
@@ -235,6 +238,11 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.dyn
+        LastSec:  .dynamic
   - Name:    .rela.dyn
     Type:    SHT_RELA
     Relocations:
@@ -252,10 +260,6 @@
         Value: 0x18
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.dyn
-    LastSec:  .dynamic
 
 ## Show we print a warning when the symbol index of a dynamic relocation is too
 ## large (goes past the end of the dynamic symbol table).
@@ -284,6 +288,11 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.dyn
+        LastSec:  .dynamic
   - Name:    .rela.dyn
     Type:    SHT_RELA
     Relocations:
@@ -304,10 +313,6 @@
         Value: 0x0
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.dyn
-    LastSec:  .dynamic
 
 ## Show that when we have both REL and RELA relocations, we dump both sets.
 # RUN: yaml2obj --docnum=6 %s -o %t13
@@ -334,6 +339,11 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.dyn
+        LastSec:  .dynamic
   - Name: .rela.dyn
     Type: SHT_RELA
     Relocations:
@@ -363,10 +373,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.dyn
-    LastSec:  .dynamic
 
 ## Check that llvm-readobj/llvm-readelf reports a warning when dumping a relocation
 ## which refers to a symbol past the end of the file.
@@ -402,6 +408,15 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Offset:   0x0
+        FirstSec: .dynamic
+        LastSec:  .dynsym
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Flags:   [ SHF_ALLOC ]
@@ -451,11 +466,3 @@
     NoHeaders: true
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Offset:   0x0
-    FirstSec: .dynamic
-    LastSec:  .dynsym
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/check-output-order.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/check-output-order.test
+++ llvm/test/tools/llvm-readobj/ELF/check-output-order.test
@@ -33,13 +33,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Entries:
       - Tag: DT_NULL
         Value: 0
 Symbols: []
-ProgramHeaders:
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/demangle.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/demangle.test
+++ llvm/test/tools/llvm-readobj/ELF/demangle.test
@@ -124,6 +124,18 @@
   Type:            ET_DYN
   Machine:         EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        VAddr:    0x0
+        FirstSec: .dynstr
+        LastSec:  .text.foo
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:         .dynstr
     Type:         SHT_STRTAB
     Flags:        [ SHF_ALLOC ]
@@ -215,14 +227,3 @@
 DynamicSymbols:
   - Name:    _Z3fooi
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    VAddr:    0x0
-    FirstSec: .dynstr
-    LastSec:  .text.foo
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/dyn-symbols-size-from-hash-table.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dyn-symbols-size-from-hash-table.test
+++ llvm/test/tools/llvm-readobj/ELF/dyn-symbols-size-from-hash-table.test
@@ -76,6 +76,20 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0
+        FirstSec: .text
+        LastSec:  .data
+      - Type:     PT_LOAD
+        VAddr:    0x400
+        FirstSec: .dynsym
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0xA00
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:         .text
     Type:         SHT_PROGBITS
   - Name:         .data
@@ -122,19 +136,6 @@
     Type:    STT_OBJECT
     Section: .data
     Value:   0x200
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0
-    FirstSec: .text
-    LastSec:  .data
-  - Type:     PT_LOAD
-    VAddr:    0x400
-    FirstSec: .dynsym
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0xA00
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 2: Table size from DT_HASH does not match size from section header.
 # RUN: yaml2obj --docnum=2 %s -o %t2-smaller -DCHAIN="[1, 2]"
@@ -232,6 +233,20 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0
+        FirstSec: .text
+        LastSec:  .data
+      - Type:     PT_LOAD
+        VAddr:    0x400
+        FirstSec: .dynsym
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0xA00
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:         .text
     Type:         SHT_PROGBITS
   - Name:         .data
@@ -285,19 +300,6 @@
     Type:    STT_OBJECT
     Section: .data
     Value:   0x300
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0
-    FirstSec: .text
-    LastSec:  .data
-  - Type:     PT_LOAD
-    VAddr:    0x400
-    FirstSec: .dynsym
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0xA00
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 3: DT_HASH is missing.
 ## Show that no warning occurs if there are section headers.
@@ -368,6 +370,12 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.plt
+        LastSec:  .hash
+        VAddr: 0x1000
   - Name:    .rela.plt
     Type:    SHT_RELA
     Flags:   [ SHF_ALLOC ]
@@ -400,8 +408,3 @@
     Chain:  [ 0 ]
     NChain: 0xFFFFFFFF
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.plt
-    LastSec:  .hash
-    VAddr: 0x1000
Index: llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
+++ llvm/test/tools/llvm-readobj/ELF/dyn-symbols.test
@@ -49,6 +49,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x100
+        FirstSec: .dynsym
+        LastSec:  .dynsym
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Entries:
@@ -62,11 +68,6 @@
 DynamicSymbols:
   - Name: foo
   - Name: bar
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x100
-    FirstSec: .dynsym
-    LastSec:  .dynsym
 
 ## Case 2: Check the output for aliases.
 ## a) Check the two-letter alias --dt is equivalent to the --dyn-symbols
@@ -191,6 +192,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x0000
+        FirstSec: .dynsym
+        LastSec:  .dynsym
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Entries:
@@ -200,11 +207,6 @@
         Value: 0
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x0000
-    FirstSec: .dynsym
-    LastSec:  .dynsym
 
 ## Case 6: Check that if we can get the location of the dynamic symbol table using both the DT_SYMTAB value
 ## and the section headers table then we prefer the former and report a warning.
@@ -222,6 +224,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x0000
+        FirstSec: .mydynsym
+        LastSec:  .mydynsym
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Entries:
@@ -237,11 +245,6 @@
     Content: "000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000"
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x0000
-    FirstSec: .mydynsym
-    LastSec:  .mydynsym
 
 ## Case 7: Check how we dump versioned symbols. Use both -V and --dyn-symbols
 ## to check that printed version is consistent.
@@ -605,6 +608,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x100
+        FirstSec: .dynsym
+        LastSec:  .dynsym
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Entries:
@@ -616,11 +625,6 @@
     Type:    SHT_DYNSYM
     Address: 0x100
     Size:    0x1
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x100
-    FirstSec: .dynsym
-    LastSec:  .dynsym
 
 --- !ELF
 FileHeader:
@@ -693,6 +697,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .dynstr
+        LastSec:  .dynamic
   - Name:    .dynstr
     Type:    SHT_STRTAB
     Flags:   [ SHF_ALLOC ]
@@ -712,11 +722,6 @@
   - StName:  0xffffff00
 ## An arbitrary valid symbol to document we report an error before dumping it.
   - StName:  0x1
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .dynstr
-    LastSec:  .dynamic
 
 ## Case 11: check various warnings we report when fields of the SHT_DYNSYM section are broken.
 
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-empty.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-empty.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-empty.test
@@ -14,15 +14,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:         .dynamic
     Type:         SHT_DYNAMIC
     Address:      0x1000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-malformed.test
@@ -29,20 +29,21 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Address: 0x1000
     Content: "01234567"
 Symbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Test handling of a .dynamic section with an invalid entsize (i.e. not 2 * sizeof(Elf_Dyn)).
 # RUN: yaml2obj %s --docnum=2 -o %t.bad-entsize
@@ -66,6 +67,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Address: 0x1000
@@ -76,15 +87,6 @@
       - Tag:   DT_NULL
         Value: 0
 Symbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Test handling of string references pointing past the end of the dynamic string table.
 # RUN: yaml2obj %s --docnum=3 -o %t.bad-string
@@ -142,6 +144,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1010
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynstr
     Type:    SHT_STRTAB
     Address: 0x1000
@@ -170,15 +182,6 @@
       - Tag:   DT_NULL
         Value: 0
 Symbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1010
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Test handling of DT_STRTAB pointing outside the file's address space.
 # RUN: yaml2obj %s --docnum=4 -o %t.bad-strtab
@@ -211,6 +214,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Address: 0x1000
@@ -227,15 +240,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 Symbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Test handling of other d_ptr tags pointing outside the file's address space.
 # RUN: yaml2obj %s --docnum=5 -o %t.bad-rela
@@ -260,6 +264,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Address: 0x1000
@@ -269,15 +283,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 Symbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Check how we handle cases when the dynamic string table is not null-terminated.
 
@@ -335,6 +340,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1100
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynstr
     Type:    SHT_STRTAB
     Address: 0x1000
@@ -366,15 +381,6 @@
         Value: 6
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1100
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Check that we emit an appropriate warning when the dynamic string table ends past the end of the file.
 
@@ -444,6 +450,20 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1010
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynstr
+        LastSec:  .dynstr
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1010
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynstr
     Type:    SHT_STRTAB
     Address: 0x1000
@@ -456,16 +476,3 @@
       - Tag:   DT_NULL
         Value: 0
 Symbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1010
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynstr
-    LastSec:  .dynstr
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1010
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-no-pt-dynamic.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-no-pt-dynamic.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-no-pt-dynamic.test
@@ -25,14 +25,15 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynamic
     Type:    SHT_DYNAMIC
     Address: 0x1000
     Entries:
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-not-in-pt-dynamic.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-not-in-pt-dynamic.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-not-in-pt-dynamic.test
@@ -33,6 +33,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .text
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Flags: [SHF_ALLOC]
@@ -49,15 +59,6 @@
     Address: 0x1100
     AddressAlign: 0x100
     Content: "00"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .text
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text
 
 ## Case 2: The dynamic table found using the dynamic program header is different from the
 ##         table found using the section header table.
@@ -86,6 +87,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:      PT_LOAD
+        VAddr:     0x1000
+        FirstSec:  .dynamic
+        LastSec:   .text
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Flags: [SHF_ALLOC]
@@ -102,15 +113,6 @@
     Address: 0x1100
     AddressAlign: 0x100
     Content: "00000000000000000000000000000000"
-ProgramHeaders:
-  - Type:      PT_LOAD
-    VAddr:     0x1000
-    FirstSec:  .dynamic
-    LastSec:   .text
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text
 
 ## Case 3: Both dynamic tables found using SHT_DYNAMIC/PT_DYNAMIC are corrupted.
 
@@ -130,6 +132,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .text
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .text
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Flags: [SHF_ALLOC]
@@ -142,12 +154,3 @@
     Address: 0x1100
     AddressAlign: 0x100
     Content: "00"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .text
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .text
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-reloc-no-section-headers.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-reloc-no-section-headers.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-reloc-no-section-headers.test
@@ -22,6 +22,14 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.dyn
+        LastSec:  .dynstr
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .rela.dyn
     Type:    SHT_RELA
     Relocations:
@@ -54,10 +62,3 @@
     NoHeaders: true
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.dyn
-    LastSec:  .dynstr
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-reloc.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-reloc.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-reloc.test
@@ -66,6 +66,11 @@
   Type:    ET_DYN
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .rela.dyn
+        LastSec:  .dynamic
   - Name: .rela.dyn
     Type: SHT_RELA
     Relocations:
@@ -124,10 +129,6 @@
   - Name: foo
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .rela.dyn
-    LastSec:  .dynamic
 
 ## Check we report a warning when the value of the DT_PLTREL dynamic tag is invalid.
 ## We currently accept DT_RELA(7) and DT_REL(17) values. This test case uses 0xff.
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-table-dtnull.s
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-table-dtnull.s
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-table-dtnull.s
@@ -19,18 +19,19 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
       - Tag:   DT_DEBUG
         Value: 0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # Sometimes .dynamic section content length can be greater than the
 # length of its entries. In this case, we should not try to dump anything
@@ -57,6 +58,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -66,10 +75,3 @@
         Value: 0x0000000000000000
       - Tag:   DT_NULL
         Value: 0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test
@@ -27,6 +27,14 @@
   Type:    ET_EXEC
   Machine: EM_HEXAGON
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -38,13 +46,6 @@
         Value: 0x1000
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 2: Test that MIPS machine-specific tags can be dumped.
 # RUN: yaml2obj --docnum=2 %s -o %t.mips
@@ -161,6 +162,14 @@
   Type:    ET_EXEC
   Machine: EM_MIPS
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -258,13 +267,6 @@
         Value: 0x1000
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 3: Test that PPC machine-specific tags can be dumped.
 # RUN: yaml2obj --docnum=3 %s -o %t.ppc
@@ -291,6 +293,14 @@
   Type:    ET_EXEC
   Machine: EM_PPC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -300,13 +310,6 @@
         Value: 1
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 4: Test that PPC64 machine-specific tags can be dumped.
 # RUN: yaml2obj --docnum=4 %s -o %t.ppc64
@@ -331,6 +334,14 @@
   Type:    ET_EXEC
   Machine: EM_PPC64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -338,13 +349,6 @@
         Value: 0x1000
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Case 5: Test that AARCH64 machine-specific tags can be dumped.
 # RUN: yaml2obj --docnum=5 %s -o %t.aarch64
@@ -373,6 +377,14 @@
   Type:    ET_EXEC
   Machine: EM_AARCH64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Entries:
@@ -384,10 +396,3 @@
         Value: 3
       - Tag:   DT_NULL
         Value: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/dynamic-tags.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/dynamic-tags.test
+++ llvm/test/tools/llvm-readobj/ELF/dynamic-tags.test
@@ -145,6 +145,16 @@
   Type:       ET_EXEC
   EPhEntSize: [[PHENTSIZE=<none>]]
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynstr
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1010
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:    .dynstr
     Type:    SHT_STRTAB
     Address: 0x1000
@@ -280,15 +290,6 @@
         Value: [[PROCSPEC=0x5555666677778888]]
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynstr
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1010
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 # RUN: yaml2obj %s --docnum=1 -DBITS=32 -DSYMBOLIC=0x12345678 -DDEBUG=0xfedcba09 \
 # RUN:   -DTEXTREL=0x11223344 -DBINDNOW=0x88776655 -DFLAGS=0xffffffff \
Index: llvm/test/tools/llvm-readobj/ELF/gnu-file-headers.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/gnu-file-headers.test
+++ llvm/test/tools/llvm-readobj/ELF/gnu-file-headers.test
@@ -37,11 +37,12 @@
   Machine: EM_386
   Entry:   0x11223344
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+        Flags: [ PF_R ]
   - Name: .foo
     Type: SHT_PROGBITS
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_R ]
 
 ## Case 2: Test EM_X86_64 object.
 # RUN: yaml2obj %s --docnum=2 -o %t2
@@ -80,11 +81,12 @@
   Machine: EM_X86_64
   Entry:   0x1122334455667788
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+        Flags: [ PF_R ]
   - Name: .foo
     Type: SHT_PROGBITS
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_R ]
 
 ## Case 3: Use an arbitrary machine type that allows to show how we print Flags.
 ##         Here we use an EM_MIPS object for that.
@@ -124,8 +126,9 @@
   Machine: EM_MIPS
   Flags:   [ EF_MIPS_ARCH_32, EF_MIPS_ABI_O32 ]
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+        Flags: [ PF_R ]
   - Name: .foo
     Type: SHT_PROGBITS
-ProgramHeaders:
-  - Type: PT_LOAD
-    Flags: [ PF_R ]
Index: llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
+++ llvm/test/tools/llvm-readobj/ELF/gnu-notes.test
@@ -89,6 +89,12 @@
   EPhEntSize: [[PHENTSIZE=<none>]]
   EShNum:     [[SHNUM=<none>]]
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        FileSize: 0x20
+        FirstSec: .note.gnu.build-id
+        LastSec:  .note.gnu.build-id
   - Name:         .note.ABI-tag
     Type:         SHT_NOTE
     AddressAlign: 0x0000000000000004
@@ -103,11 +109,6 @@
     Type:         SHT_NOTE
     AddressAlign: 0x0000000000000004
     Content:      040000000900000004000000474E5500676F6C6420312E3131000000
-ProgramHeaders:
-  - Type:     PT_NOTE
-    FileSize: 0x20
-    FirstSec: .note.gnu.build-id
-    LastSec:  .note.gnu.build-id
 
 ## Test tools report an error if a note section has an invalid offset
 ## that goes past the end of file.
@@ -189,10 +190,12 @@
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_CORE
-ProgramHeaders:
-  - Type:     PT_NOTE
-    Offset:   [[PHOFFSET=<none>]]
-    FileSize: [[PHFILESIZE=<none>]]
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        Offset:   [[PHOFFSET=<none>]]
+        FileSize: [[PHFILESIZE=<none>]]
 
 ## Test tools report an error if a note program header has an invalid size that
 ## goes past the end of file.
Index: llvm/test/tools/llvm-readobj/ELF/gnu-section-mapping.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/gnu-section-mapping.test
+++ llvm/test/tools/llvm-readobj/ELF/gnu-section-mapping.test
@@ -19,6 +19,20 @@
   Type:       ET_EXEC
   EPhEntSize: [[PHENTSIZE=<none>]]
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## Case 1: an arbitrary segment with sections.
+      - Type:     PT_PHDR
+        Flags:    [ PF_W ]
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 2: another segment with different sections.
+      - Type:     PT_PHDR
+        Flags:    [ PF_X ]
+        VAddr:    0x2000
+        FirstSec: .bar.begin
+        LastSec:  .bar.end
   - Name:    .foo.begin
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
@@ -37,19 +51,6 @@
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
     Size:    0x4
-ProgramHeaders:
-## Case 1: an arbitrary segment with sections.
-  - Type:     PT_PHDR
-    Flags:    [ PF_W ]
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 2: another segment with different sections.
-  - Type:     PT_PHDR
-    Flags:    [ PF_X ]
-    VAddr:    0x2000
-    FirstSec: .bar.begin
-    LastSec:  .bar.end
 
 ## Check that --section-mapping=false --program-headers produces just program headers.
 # RUN: llvm-readelf --section-mapping=false --program-headers %t64.elf \
Index: llvm/test/tools/llvm-readobj/ELF/gnuhash.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/gnuhash.test
+++ llvm/test/tools/llvm-readobj/ELF/gnuhash.test
@@ -25,6 +25,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -56,11 +62,6 @@
     Binding: STB_GLOBAL
   - Name:    ddd
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Check we report a warning if there is no dynamic symbol section in the object.
 
@@ -84,6 +85,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -101,11 +108,6 @@
         Value: 0x0
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Check what we do when the index of the first symbol in the dynamic symbol table
 ## included in the hash table is larger than the number of dynamic symbols.
@@ -132,6 +134,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -153,11 +161,6 @@
 DynamicSymbols:
   - Name:    aaa
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Check we emit a warning when the dynamic symbol table is empty.
 ## A valid dynamic symbol table should have at least one symbol: the symbol with index 0.
@@ -184,6 +187,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -205,11 +214,6 @@
   - Name: .dynsym
     Type: SHT_DYNSYM
     Size: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Linkers might produce an empty no-op SHT_GNU_HASH section when
 ## there are no dynamic symbols or when all dynamic symbols are undefined.
@@ -253,6 +257,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -272,11 +282,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Check we report a proper warning when a hash table goes past the end of the file.
 
Index: llvm/test/tools/llvm-readobj/ELF/hash-histogram.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/hash-histogram.test
+++ llvm/test/tools/llvm-readobj/ELF/hash-histogram.test
@@ -32,6 +32,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:   .hash
     Type:   SHT_HASH
     Flags:  [ SHF_ALLOC ]
@@ -62,10 +67,6 @@
   - Name: b
   - Name: c
   - Name: d
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Show that we report a warning for a hash table which contains an entry of
 ## the bucket array pointing to a cycle.
@@ -86,6 +87,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_REL
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:   .hash
     Type:   SHT_HASH
     Link:   .dynsym
@@ -104,10 +110,6 @@
         Value: 0
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Each SHT_HASH section starts with two 32-bit fields: nbucket and nchain.
 ## Check we report an error when a DT_HASH value points to data that has size less than 8 bytes.
@@ -123,6 +125,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FileSize: 0x23a
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:   .hash
     Type:   SHT_HASH
     Flags:  [ SHF_ALLOC ]
@@ -137,11 +145,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FileSize: 0x23a
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Check we report a warning when the hash table goes past the end of the file.
 
@@ -181,6 +184,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Flags:   [ SHF_ALLOC ]
@@ -197,10 +205,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Check we dump a histogram for the .gnu.hash table even when the .hash table is skipped.
 
@@ -224,6 +228,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Flags:   [ SHF_ALLOC ]
@@ -253,10 +262,6 @@
         Value: 0x0
 DynamicSymbols:
   - Name: foo
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Check we report a proper warning when the GNU hash table goes past the end of the file.
 
@@ -278,6 +283,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -301,10 +311,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Linkers might produce an empty no-op SHT_GNU_HASH section when
 ## there are no dynamic symbols or when all dynamic symbols are undefined.
@@ -342,6 +348,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -361,10 +372,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Check we report warnings when the dynamic symbol table is absent or empty.
 
@@ -387,6 +394,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .gnu.hash
+        LastSec:  .gnu.hash
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -407,7 +419,3 @@
   - Name: .dynsym
     Type: [[TYPE]]
     Size: 0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .gnu.hash
-    LastSec:  .gnu.hash
Index: llvm/test/tools/llvm-readobj/ELF/hash-symbols.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/hash-symbols.test
+++ llvm/test/tools/llvm-readobj/ELF/hash-symbols.test
@@ -47,6 +47,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:      PT_LOAD
+        Flags:     [ PF_R, PF_X ]
+        FirstSec:  .hash
+        LastSec:   .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Flags:   [ SHF_ALLOC ]
@@ -103,11 +109,6 @@
     Binding: STB_WEAK
     Value:   0x0000000000001001
     Type:    [[TYPE=STT_NOTYPE]]
-ProgramHeaders:
-  - Type:      PT_LOAD
-    Flags:     [ PF_R, PF_X ]
-    FirstSec:  .hash
-    LastSec:   .dynamic
 
 ## Check what we print for unnamed section symbols.
 # RUN: yaml2obj --docnum=1 -DBITS=64 -DTYPE=STT_SECTION -DNAME="''" %s -o %t1-sec-syms.so
@@ -152,6 +153,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Flags:   [ SHF_ALLOC ]
@@ -185,11 +192,6 @@
     Section: .hash
     Binding: STB_WEAK
     Value:   0x0000000000001001
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Check the output when only .gnu.hash section is present.
 
@@ -211,6 +213,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:    .gnu.hash
     Type:    SHT_GNU_HASH
     Flags:   [ SHF_ALLOC ]
@@ -248,11 +256,6 @@
     Section: .dynamic
     Binding: STB_WEAK
     Value:   0x0000000000001001
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Show that if there are no hash sections, we do not print anything.
 # RUN: yaml2obj --docnum=4 %s -o %t4.so
@@ -273,6 +276,18 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        VAddr:    0x0
+        FirstSec: .dynstr
+        LastSec:  .text.foo
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_R ]
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:         .dynstr
     Type:         SHT_STRTAB
     Flags:        [ SHF_ALLOC ]
@@ -312,17 +327,6 @@
 DynamicSymbols:
   - Name:    _Z3fooi
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    VAddr:    0x0
-    FirstSec: .dynstr
-    LastSec:  .text.foo
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_R ]
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Show that we report a warning for a hash table which contains an entry of
 ## the bucket array pointing to a cycle.
@@ -344,6 +348,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Link:    .dynsym
@@ -359,10 +368,6 @@
         Value: 0x0
 DynamicSymbols:
   - Name: aaa
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Each SHT_HASH section starts with two 32-bit fields: nbucket and nchain.
 ## Check we report an error when a DT_HASH value points to data that has size less than 8 bytes.
@@ -378,6 +383,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FileSize: 0x23a
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:   .hash
     Type:   SHT_HASH
     Flags:  [ SHF_ALLOC ]
@@ -392,11 +403,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FileSize: 0x23a
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Check we report a warning when the hash table goes past the end of the file.
 
@@ -441,6 +447,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Flags:   [ SHF_ALLOC ]
@@ -457,10 +468,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Check we report a proper warning when a GNU hash table goes past the end of the file.
 
@@ -484,6 +491,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -515,11 +528,6 @@
     Binding: STB_GLOBAL
   - Name:    ddd
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## Check the behavior when the dynamic symbol table is empty or not found.
 
@@ -540,6 +548,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .hash
+        LastSec:  .dynstr
   - Name:   .hash
     Type:   SHT_HASH
     Flags:  [ SHF_ALLOC ]
@@ -566,11 +580,6 @@
     Type:  [[DYNSYMTYPE=SHT_DYNSYM]]
     Flags: [ SHF_ALLOC ]
     Size:  0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .hash
-    LastSec:  .dynstr
 
 ## Case A.2: similar to A.1, but now check that we report a warning when the dynamic symbol table was not found.
 ##           To do that, set the type of the .dynsym to SHT_PROGBITS to hide it.
@@ -608,6 +617,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynstr
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -637,11 +652,6 @@
     Type:  [[DYNSYMTYPE=SHT_DYNSYM]]
     Flags: [ SHF_ALLOC ]
     Size:  0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynstr
 
 ## In this case we have a broken value in the hash buckets array. Normally it contains an
 ## index into the dynamic symbol table and also is used to get a hash value from the hash values array.
@@ -663,6 +673,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R, PF_X ]
+        FirstSec: .gnu.hash
+        LastSec:  .dynamic
   - Name:  .gnu.hash
     Type:  SHT_GNU_HASH
     Flags: [ SHF_ALLOC ]
@@ -685,11 +701,6 @@
 DynamicSymbols:
   - Name:    foo
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R, PF_X ]
-    FirstSec: .gnu.hash
-    LastSec:  .dynamic
 
 ## In this case we are unable to read a hash value for a symbol with
 ## an index that is less than the index of the first hashed symbol.
Index: llvm/test/tools/llvm-readobj/ELF/hash-table.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/hash-table.test
+++ llvm/test/tools/llvm-readobj/ELF/hash-table.test
@@ -23,6 +23,11 @@
   Type:    ET_DYN
   Machine: [[MACHINE]]
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Flags:   [ SHF_ALLOC ]
@@ -37,10 +42,6 @@
         Value: 0x0
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Document that we ignore the sh_entsize value when dumping the hash section.
 ## Implementation assumes that the size of entries is 4, matching the ELF specification.
@@ -115,14 +116,15 @@
         Value: 0x0
   - Type: SectionHeaderTable
     NoHeaders: [[NOHEADERS=false]]
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x10
-    FirstSec: .dynamic
-    LastSec:  .dynamic
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x10
+        FirstSec: .dynamic
+        LastSec:  .dynamic
 
 ## Document we don't report a warning when the value of the sh_entsize field of the SHT_HASH section is not 4.
 
@@ -160,6 +162,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FileSize: 0x23a
+        FirstSec: .hash
+        LastSec:  .dynamic
   - Name:   .hash
     Type:   SHT_HASH
     Flags:  [ SHF_ALLOC ]
@@ -174,11 +182,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FileSize: 0x23a
-    FirstSec: .hash
-    LastSec:  .dynamic
 
 ## Check we report a warning when the hash table goes past the end of the file.
 
@@ -254,6 +257,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .hash
+        LastSec: .dynamic
   - Name:    .hash
     Type:    SHT_HASH
     Flags:   [ SHF_ALLOC ]
@@ -270,10 +278,6 @@
       - Tag:   DT_NULL
         Value: 0x0
 DynamicSymbols: []
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .hash
-    LastSec: .dynamic
 
 ## Show we do not duplicate warnings when printing both the hash table and the hash histogram.
 ## Note that --elf-hash-histogram is only implemented for llvm-readelf currently.
Index: llvm/test/tools/llvm-readobj/ELF/headers.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/headers.test
+++ llvm/test/tools/llvm-readobj/ELF/headers.test
@@ -41,7 +41,8 @@
   Data:  ELFDATA2LSB
   Type:  ET_REL
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
   - Name: .foo
     Type: SHT_PROGBITS
-ProgramHeaders:
-  - Type: PT_LOAD
Index: llvm/test/tools/llvm-readobj/ELF/loadname.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/loadname.test
+++ llvm/test/tools/llvm-readobj/ELF/loadname.test
@@ -25,6 +25,14 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x0000
+        FileSize: [[PHDRFILESIZE]]
+        FirstSec: .dynstr
+        LastSec:  .dynamic
   - Name:  .dynstr
     Type:  SHT_STRTAB
     Flags: [ SHF_ALLOC ]
@@ -42,13 +50,6 @@
         Value: 0x0000000000000000
       - Tag:   DT_NULL
         Value: 0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x0000
-    FileSize: [[PHDRFILESIZE]]
-    FirstSec: .dynstr
-    LastSec:  .dynamic
 
 ## Check we do not crash when an object contains a DT_STRTAB entry whose address
 ## is past the end of the object.
Index: llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
+++ llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
@@ -129,6 +129,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_DYNAMIC
+        FileSize: [[FILESIZE=<none>]]
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:     .dynamic
     Type:     SHT_DYNAMIC
     Address:  0x1000
@@ -139,8 +145,3 @@
         Value: 0
   - Type: SectionHeaderTable
     NoHeaders: [[NOHEADERS=false]]
-ProgramHeaders:
-  - Type:     PT_DYNAMIC
-    FileSize: [[FILESIZE=<none>]]
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/needed-libs.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/needed-libs.test
+++ llvm/test/tools/llvm-readobj/ELF/needed-libs.test
@@ -25,6 +25,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+        VAddr: 0x0
+        FirstSec: .dynstr
+        LastSec:  .dynamic
   - Name:  .dynstr
     Type:  SHT_STRTAB
     Flags: [ SHF_ALLOC ]
@@ -48,11 +54,6 @@
         Value: [[SIZE=0xD]]
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type: PT_LOAD
-    VAddr: 0x0
-    FirstSec: .dynstr
-    LastSec:  .dynamic
 
 ## Check what we print when the dynamic string table is empty.
 # RUN: yaml2obj %s --docnum=2 -o %t2
@@ -74,6 +75,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x0
+        FirstSec: .dynstr
+        LastSec:  .dynamic
   - Name:  .dynstr
     Type:  SHT_STRTAB
     Flags: [ SHF_ALLOC ]
@@ -92,8 +99,3 @@
         Value: 0x0
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x0
-    FirstSec: .dynstr
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/non-dynamic-in-pt-dynamic.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/non-dynamic-in-pt-dynamic.test
+++ llvm/test/tools/llvm-readobj/ELF/non-dynamic-in-pt-dynamic.test
@@ -32,6 +32,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .text
+        LastSec:  .dynamic
   - Name: .text
     Type: SHT_PROGBITS
     Flags: [SHF_ALLOC]
@@ -47,15 +57,6 @@
         Value: 0x1
       - Tag:   DT_NULL
         Value: 0x0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .text
-    LastSec:  .dynamic
 
 ## In this case .text goes after .dynamic and we don't display any warnings,
 ## though the content of the .text is used for dumping the dynamic table.
@@ -83,6 +84,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .text
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .text
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Flags: [SHF_ALLOC]
@@ -99,15 +110,6 @@
     Address: 0x1100
     AddressAlign: 0x100
     Content: "00000000000000000000000000000000"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .text
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .text
 
 ## In this case .text goes after .dynamic, but (PT_DYNAMIC segment size % dynamic entry size != 0)
 ## and we have to use the information from the section header instead.
@@ -136,6 +138,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .text
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .text
   - Name: .dynamic
     Type: SHT_DYNAMIC
     Flags: [SHF_ALLOC]
@@ -152,12 +164,3 @@
     Address: 0x1100
     AddressAlign: 0x100
     Content: "00"
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .text
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .text
Index: llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test
+++ llvm/test/tools/llvm-readobj/ELF/note-core-ntfile-bad.test
@@ -30,13 +30,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_CORE
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        FirstSec: .note.foo
+        LastSec:  .note.foo
   - Name:    .note.foo
     Type:    SHT_NOTE
     Content: 0500000008000000454C4946434F5245000000000000000000000000
-ProgramHeaders:
-  - Type:     PT_NOTE
-    FirstSec: .note.foo
-    LastSec:  .note.foo
 
 # RUN: yaml2obj --docnum=2 %s -o %t2.o
 # RUN: llvm-readelf -n %t2.o 2>&1 | FileCheck -DFILE=%t2.o %s --check-prefix=ERR-NULL-TERM
@@ -66,13 +67,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_CORE
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        FirstSec: .note.foo
+        LastSec:  .note.foo
   - Name:    .note.foo
     Type:    SHT_NOTE
     Content: 050000002C000000454C4946434F5245000000000100000000000000001000000000000000100000000000000020000000000000003000000000000078787878
-ProgramHeaders:
-  - Type:     PT_NOTE
-    FirstSec: .note.foo
-    LastSec:  .note.foo
 
 # RUN: yaml2obj --docnum=3 %s -o %t3.o
 # RUN: llvm-readelf -n %t3.o 2>&1 | FileCheck -DFILE=%t3.o %s --check-prefix=ERR-FILE-COUNT
@@ -102,13 +104,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_CORE
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        FirstSec: .note.foo
+        LastSec:  .note.foo
   - Name:    .note.foo
     Type:    SHT_NOTE
     Content: 050000002C000000454C4946434F5245000000000200000000000000001000000000000000100000000000000020000000000000003000000000000078797A00
-ProgramHeaders:
-  - Type:     PT_NOTE
-    FirstSec: .note.foo
-    LastSec:  .note.foo
 
 # RUN: yaml2obj --docnum=4 %s -o %t4.o
 # RUN: llvm-readelf -n %t4.o 2>&1 | FileCheck -DFILE=%t4.o %s --check-prefix=ERR-FILE-END-EARLY
@@ -141,10 +144,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_CORE
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        FirstSec: .note.foo
+        LastSec:  .note.foo
   - Name:    .note.foo
     Type:    SHT_NOTE
     Content: 0500000044000000454C4946434F5245000000000200000000000000001000000000000000100000000000000020000000000000003000000000000000400000000000000050000000000000006000000000000078797A00
-ProgramHeaders:
-  - Type:     PT_NOTE
-    FirstSec: .note.foo
-    LastSec:  .note.foo
Index: llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test
+++ llvm/test/tools/llvm-readobj/ELF/note-core-ntfile.test
@@ -41,13 +41,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_CORE
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        FirstSec: .note.foo
+        LastSec:  .note.foo
   - Name:        .note.foo
     Type:        SHT_NOTE
     Content:     0500000080000000454C4946434F524500000000030000000000000000100000000000000010000000000000002000000000000000300000000000000040000000000000005000000000000000600000000000000070000000000000008000000000000000900000000000002F706174682F746F2F612E6F7574002F706174682F746F2F6C6962632E736F005B737461636B5D00
-ProgramHeaders:
-  - Type:     PT_NOTE
-    FirstSec: .note.foo
-    LastSec:  .note.foo
 
 # GNU:      Displaying notes found
 # GNU-NEXT:   Owner                 Data size       Description
Index: llvm/test/tools/llvm-readobj/ELF/note-core.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/note-core.test
+++ llvm/test/tools/llvm-readobj/ELF/note-core.test
@@ -265,12 +265,13 @@
   Data:  ELFDATA2LSB
   Type:  ET_CORE
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_NOTE
+        FirstSec: .note.foo
+        LastSec:  .note.foo
   - Name: .note.foo
     Type: SHT_NOTE
     Notes:
       - Name: CORE
         Type: [[TYPE]]
-ProgramHeaders:
-  - Type:     PT_NOTE
-    FirstSec: .note.foo
-    LastSec:  .note.foo
Index: llvm/test/tools/llvm-readobj/ELF/program-headers.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/program-headers.test
+++ llvm/test/tools/llvm-readobj/ELF/program-headers.test
@@ -410,6 +410,128 @@
   Type:    ET_EXEC
   Machine: [[MACHINE]]
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## Case 1: an arbitrary segment with sections.
+      - Type:     PT_PHDR
+        Flags:    [ PF_W ]
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 2: another segment with different sections.
+      - Type:     PT_PHDR
+        Flags:    [ PF_X ]
+        VAddr:    0x2000
+        FirstSec: .bar.begin
+        LastSec:  .bar.end
+## Case 3: the PT_NULL segment.
+      - Type:     PT_NULL
+        Flags:    [ PF_X ]
+        VAddr:    0x2000
+        FirstSec: .bar.begin
+        LastSec:  .bar.end
+## Case 4: the PT_DYNAMIC segment.
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_R, PF_W, PF_X ]
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 5: the PT_INTERP segment.
+      - Type:     PT_INTERP
+        Flags:    [ PF_R, PF_W ]
+        VAddr:    0x3000
+        FirstSec: .interp
+        LastSec:  .interp
+## Case 6: the PT_NOTE segment.
+      - Type:     PT_NOTE
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 7: the PT_SHLIB segment.
+      - Type:     PT_SHLIB
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.begin
+## Case 8: the PT_TLS segment.
+      - Type:     PT_TLS
+        VAddr:    0x4000
+        FirstSec: .tls
+        LastSec:  .tls
+## Case 9: the PT_LOOS segment.
+      - Type:     0x60000000 ## PT_LOOS
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 10: the PT_GNU_EH_FRAME segment.
+      - Type:     PT_GNU_EH_FRAME
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 11: the PT_SUNW_UNWIND segment.
+      - Type:     0x6464e550 ## PT_SUNW_UNWIND
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 12: the PT_GNU_STACK segment.
+      - Type:     PT_GNU_STACK
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 13: the PT_GNU_RELRO segment.
+      - Type:     PT_GNU_RELRO
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 14: the PT_GNU_PROPERTY segment.
+      - Type:     PT_GNU_PROPERTY
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 15: the PT_OPENBSD_RANDOMIZE segment.
+      - Type:     0x65a3dbe6 ## PT_OPENBSD_RANDOMIZE
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 16: the PT_OPENBSD_WXNEEDED segment.
+      - Type:     0x65a3dbe7 ## PT_OPENBSD_WXNEEDED
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 17: the PT_OPENBSD_BOOTDATA segment.
+      - Type:     0x65a41be6 ## PT_OPENBSD_BOOTDATA
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 18: the PT_HIOS segment.
+      - Type:     0x6fffffff ## PT_HIOS
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 19: the PT_LOPROC/PT_ARM_ARCHEXT/PT_MIPS_REGINFO segment.
+      - Type:     0x70000000 ## PT_LOPROC/PT_ARM_ARCHEXT/PT_MIPS_REGINFO
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 20: the PT_ARM_EXIDX/PT_MIPS_RTPROC segment.
+      - Type:     0x70000001 ## PT_ARM_EXIDX, PT_MIPS_RTPROC
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 20: the PT_MIPS_OPTIONS segment.
+      - Type:     0x70000002 ## PT_MIPS_OPTIONS
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 21: the PT_MIPS_ABIFLAGS segment.
+      - Type:     0x70000003 ## PT_MIPS_ABIFLAGS
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec:  .foo.end
+## Case 22: the PT_HIPROC segment.
+      - Type:     0x7fffffff ## PT_HIPROC
+        VAddr:    0x1000
+        FirstSec: .foo.begin
+        LastSec: .foo.end
   - Name:    .foo.begin
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
@@ -443,127 +565,6 @@
     Flags:   [ SHF_ALLOC, SHF_TLS ]
     Address: 0x5000
     Size:    0x1
-ProgramHeaders:
-## Case 1: an arbitrary segment with sections.
-  - Type:     PT_PHDR
-    Flags:    [ PF_W ]
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 2: another segment with different sections.
-  - Type:     PT_PHDR
-    Flags:    [ PF_X ]
-    VAddr:    0x2000
-    FirstSec: .bar.begin
-    LastSec:  .bar.end
-## Case 3: the PT_NULL segment.
-  - Type:     PT_NULL
-    Flags:    [ PF_X ]
-    VAddr:    0x2000
-    FirstSec: .bar.begin
-    LastSec:  .bar.end
-## Case 4: the PT_DYNAMIC segment.
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_R, PF_W, PF_X ]
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 5: the PT_INTERP segment.
-  - Type:     PT_INTERP
-    Flags:    [ PF_R, PF_W ]
-    VAddr:    0x3000
-    FirstSec: .interp
-    LastSec:  .interp
-## Case 6: the PT_NOTE segment.
-  - Type:     PT_NOTE
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 7: the PT_SHLIB segment.
-  - Type:     PT_SHLIB
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.begin
-## Case 8: the PT_TLS segment.
-  - Type:     PT_TLS
-    VAddr:    0x4000
-    FirstSec: .tls
-    LastSec:  .tls
-## Case 9: the PT_LOOS segment.
-  - Type:     0x60000000 ## PT_LOOS
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 10: the PT_GNU_EH_FRAME segment.
-  - Type:     PT_GNU_EH_FRAME
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 11: the PT_SUNW_UNWIND segment.
-  - Type:     0x6464e550 ## PT_SUNW_UNWIND
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 12: the PT_GNU_STACK segment.
-  - Type:     PT_GNU_STACK
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 13: the PT_GNU_RELRO segment.
-  - Type:     PT_GNU_RELRO
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 14: the PT_GNU_PROPERTY segment.
-  - Type:     PT_GNU_PROPERTY
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 15: the PT_OPENBSD_RANDOMIZE segment.
-  - Type:     0x65a3dbe6 ## PT_OPENBSD_RANDOMIZE
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 16: the PT_OPENBSD_WXNEEDED segment.
-  - Type:     0x65a3dbe7 ## PT_OPENBSD_WXNEEDED
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 17: the PT_OPENBSD_BOOTDATA segment.
-  - Type:     0x65a41be6 ## PT_OPENBSD_BOOTDATA
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 18: the PT_HIOS segment.
-  - Type:     0x6fffffff ## PT_HIOS
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 19: the PT_LOPROC/PT_ARM_ARCHEXT/PT_MIPS_REGINFO segment.
-  - Type:     0x70000000 ## PT_LOPROC/PT_ARM_ARCHEXT/PT_MIPS_REGINFO
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 20: the PT_ARM_EXIDX/PT_MIPS_RTPROC segment.
-  - Type:     0x70000001 ## PT_ARM_EXIDX, PT_MIPS_RTPROC
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 20: the PT_MIPS_OPTIONS segment.
-  - Type:     0x70000002 ## PT_MIPS_OPTIONS
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 21: the PT_MIPS_ABIFLAGS segment.
-  - Type:     0x70000003 ## PT_MIPS_ABIFLAGS
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec:  .foo.end
-## Case 22: the PT_HIPROC segment.
-  - Type:     0x7fffffff ## PT_HIPROC
-    VAddr:    0x1000
-    FirstSec: .foo.begin
-    LastSec: .foo.end
 
 ## Check how we dump ARM specific program headers.
 # RUN: yaml2obj --docnum=1 -DBITS=64 -DMACHINE=EM_ARM %s -o %tarm.elf
@@ -633,28 +634,30 @@
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
-ProgramHeaders:
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
 ## Case 1: the offset points to the first additional byte.
-  - Type:   PT_INTERP
-    Offset: 616
+      - Type:   PT_INTERP
+        Offset: 616
 ## Case 1: the offset points to the second additional byte,
 ##         which is a null byte.
-  - Type:   PT_INTERP
-    Offset: 617
+      - Type:   PT_INTERP
+        Offset: 617
 ## Case 3: the offset points to the third additional
 ##         byte, which is the last byte in the file.
-  - Type:   PT_INTERP
-    Offset: 618
+      - Type:   PT_INTERP
+        Offset: 618
 ## Case 4: the offset goes 1 byte past the end of the file.
-  - Type:   PT_INTERP
-    Offset: 619
+      - Type:   PT_INTERP
+        Offset: 619
 ## Case 5: an arbitrary large offset that goes past the end of the file.
-  - Type:   PT_INTERP
-    Offset: 0xAABBCCDDEEFF1122
+      - Type:   PT_INTERP
+        Offset: 0xAABBCCDDEEFF1122
 ## Case 6: the same as case 5. Used to demonstrate that we don't report
 ##         the same warning twice.
-  - Type:   PT_INTERP
-    Offset: 0xAABBCCDDEEFF1122
+      - Type:   PT_INTERP
+        Offset: 0xAABBCCDDEEFF1122
 
 ## Check we report a warning when we are unable to read program headers.
 ## Case A: the e_phentsize field is invalid.
@@ -683,12 +686,13 @@
   EPhEntSize: [[PHENTSIZE=<none>]]
   EPhOff:     [[PHOFF=<none>]]
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_PHDR
+        FirstSec: .foo
+        LastSec:  .foo
   - Name: .foo
     Type: SHT_PROGBITS
-ProgramHeaders:
-  - Type:     PT_PHDR
-    FirstSec: .foo
-    LastSec:  .foo
 
 ## Case B: the value of the e_phoff field is invalid.
 
Index: llvm/test/tools/llvm-readobj/ELF/reloc-negative-addend-no-sym.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/reloc-negative-addend-no-sym.test
+++ llvm/test/tools/llvm-readobj/ELF/reloc-negative-addend-no-sym.test
@@ -24,6 +24,16 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .rela.dyn
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .text
     Type: SHT_PROGBITS
     Size: 0x10
@@ -61,12 +71,3 @@
 DynamicSymbols:
   - Name:    force_dynsym
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .rela.dyn
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/reloc-zero-name-or-value.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/reloc-zero-name-or-value.test
+++ llvm/test/tools/llvm-readobj/ELF/reloc-zero-name-or-value.test
@@ -37,6 +37,16 @@
   Type:    ET_EXEC
   Machine: EM_X86_64
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .rela.dyn
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .text
     Type: SHT_PROGBITS
     Size: 0x10
@@ -132,12 +142,3 @@
   - Value:   0x0
     Section: .text
     Binding: STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .rela.dyn
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/symtab-shndx.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/symtab-shndx.test
+++ llvm/test/tools/llvm-readobj/ELF/symtab-shndx.test
@@ -55,6 +55,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_REL
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .bar
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .section1
     Type: SHT_PROGBITS
   - Name: .section2
@@ -97,15 +107,6 @@
     Index: SHN_XINDEX
   - Name:  dynsym2
     Index: SHN_XINDEX
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .bar
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
 
 ## Check that we locate the SHT_SYMTAB_SHNDX section using the DT_SYMTAB_SHNDX
 ## dynamic tag when dumping dynamic symbols. In this case we make the value of
@@ -264,6 +265,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_REL
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .symtab_shndx
+      - Type:     PT_DYNAMIC
+        VAddr:    0x1000
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name: .section1
     Type: SHT_PROGBITS
   - Name: .section2
@@ -320,12 +331,3 @@
     Index: SHN_XINDEX
   - Name:  dynsym2
     Index: SHN_XINDEX
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .symtab_shndx
-  - Type:     PT_DYNAMIC
-    VAddr:    0x1000
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/llvm-readobj/ELF/unwind.test
===================================================================
--- llvm/test/tools/llvm-readobj/ELF/unwind.test
+++ llvm/test/tools/llvm-readobj/ELF/unwind.test
@@ -188,6 +188,22 @@
   Machine:         EM_X86_64
   Entry:           0x0000000000400000
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x00400000
+        PAddr:    0x00400000
+        FirstSec: .text
+        LastSec:  .text
+      - Type:     PT_GNU_EH_FRAME
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x004013C0
+        PAddr:    0x004013C0
+        MemSize:  [[MEMSIZE]]
+        FileSize: [[FILESIZE]]
+        FirstSec: .eh_frame_hdr
+        LastSec:  .eh_frame_hdr
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -212,21 +228,6 @@
     Section:         .text
     Value:           0x0000000000400000
     Binding:         STB_GLOBAL
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x00400000
-    PAddr:    0x00400000
-    FirstSec: .text
-    LastSec:  .text
-  - Type:     PT_GNU_EH_FRAME
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x004013C0
-    PAddr:    0x004013C0
-    MemSize:  [[MEMSIZE]]
-    FileSize: [[FILESIZE]]
-    FirstSec: .eh_frame_hdr
-    LastSec:  .eh_frame_hdr
 
 ## Document we report a error when the memory size of the PT_GNU_EH_FRAME does not match its file size.
 ## TODO: we want to report a warning and continue dumping instead.
@@ -325,11 +326,13 @@
   Class: ELFCLASS[[BITS]]
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
-ProgramHeaders:
-  - Type:     PT_GNU_EH_FRAME
-    MemSize:  [[SIZE]]
-    FileSize: [[SIZE]]
-    Offset:   [[OFFSET]]
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_GNU_EH_FRAME
+        MemSize:  [[SIZE]]
+        FileSize: [[SIZE]]
+        Offset:   [[OFFSET]]
 
 ## Case B: test we report an error when the file size of the PT_GNU_EH_FRAME
 ##         is invalid (goes past the end of the file).
Index: llvm/test/tools/llvm-xray/ARM/extract-instrmap.test
===================================================================
--- llvm/test/tools/llvm-xray/ARM/extract-instrmap.test
+++ llvm/test/tools/llvm-xray/ARM/extract-instrmap.test
@@ -16,25 +16,26 @@
   Machine:         EM_ARM
   Flags:           [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]
   Entry:           0x00000000000012B0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .rel.dyn
-    LastSec:  .rel.dyn
-    Align:    0x0000000000001000
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .text
-    LastSec:  .text
-    VAddr:    0x00000000000012B0
-    Align:    0x0000000000001000
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: xray_instr_map
-    LastSec:  xray_fn_idx
-    VAddr:    0x00000000000033CC
-    Align:    0x0000000000001000
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .rel.dyn
+        LastSec:  .rel.dyn
+        Align:    0x0000000000001000
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .text
+        LastSec:  .text
+        VAddr:    0x00000000000012B0
+        Align:    0x0000000000001000
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: xray_instr_map
+        LastSec:  xray_fn_idx
+        VAddr:    0x00000000000033CC
+        Align:    0x0000000000001000
   - Name:            .rel.dyn
     Type:            SHT_REL
     Flags:           [ SHF_ALLOC ]
Index: llvm/test/tools/obj2yaml/ELF/offset.yaml
===================================================================
--- llvm/test/tools/obj2yaml/ELF/offset.yaml
+++ llvm/test/tools/obj2yaml/ELF/offset.yaml
@@ -163,6 +163,10 @@
 # RUN: obj2yaml %t4c.o | FileCheck %s --check-prefixes=FIRSTSECPHDRS,FIRSTSECPHDRSOFFSET
 
 #       FIRSTSECPHDRS:      Sections:
+#       FIRSTSECPHDRS-NEXT:   - Type: ProgramHeaderTable
+#       FIRSTSECPHDRS-NEXT:     Segments:
+#       FIRSTSECPHDRS-NEXT:       - Type: PT_LOAD
+#       FIRSTSECPHDRS-NEXT:       - Type: PT_LOAD
 #       FIRSTSECPHDRS-NEXT:   - Name:   .foo
 #       FIRSTSECPHDRS-NEXT:     Type:   SHT_PROGBITS
 # FIRSTSECPHDRSOFFSET-NEXT:     Offset: 0xB1
@@ -174,12 +178,13 @@
   Data:  ELFDATA2LSB
   Type:  ET_REL
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+      - Type: PT_LOAD
   - Name:   .foo
     Type:   SHT_PROGBITS
     Offset: [[FIRSTOFF=<none>]]
-ProgramHeaders:
-  - Type: PT_LOAD
-  - Type: PT_LOAD
 
 ## Test that when there are no program headers in the file, we don't take SHT_NOBITS
 ## section sizes into account, but respect their alignment when calculating the expected
@@ -244,7 +249,7 @@
 # RUN: obj2yaml %t6.o | FileCheck %s --check-prefix=NOBITS-PHDRS
 
 # NOBITS-PHDRS:      Sections:
-# NOBITS-PHDRS-NEXT:   - Name:    .nobits1
+# NOBITS-PHDRS:        - Name:    .nobits1
 # NOBITS-PHDRS-NEXT:     Type:    SHT_NOBITS
 # NOBITS-PHDRS-NEXT:     Size:    0x1
 # NOBITS-PHDRS-NEXT:   - Name:    .progbits
@@ -268,6 +273,17 @@
   Data:  ELFDATA2LSB
   Type:  ET_REL
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .nobits1
+        LastSec:  .progbits
+      - Type:     PT_LOAD
+        FirstSec: .nobits3
+        LastSec:  .nobits4
+      - Type:     PT_LOAD
+        FirstSec: .nobits5
+        LastSec:  .nobits5
 ## sh_offset == 0xe8.
   - Name: .nobits1
     Type: SHT_NOBITS
@@ -289,13 +305,3 @@
     Type:   SHT_NOBITS
     Size:   0x300
     Offset: 0x100
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .nobits1
-    LastSec:  .progbits
-  - Type:     PT_LOAD
-    FirstSec: .nobits3
-    LastSec:  .nobits4
-  - Type:     PT_LOAD
-    FirstSec: .nobits5
-    LastSec:  .nobits5
Index: llvm/test/tools/obj2yaml/ELF/program-headers.yaml
===================================================================
--- llvm/test/tools/obj2yaml/ELF/program-headers.yaml
+++ llvm/test/tools/obj2yaml/ELF/program-headers.yaml
@@ -33,138 +33,146 @@
 # SEGMENT-MAPPING-NEXT:   None   .symtab .strtab .shstrtab {{$}}
 
 ## Check that obj2yaml produced a correct program headers description.
+## Document that obj2yaml is unable to dump the "Offset" key properly at this moment.
 
 # RUN: obj2yaml %t1 | FileCheck %s --check-prefix=YAML
 
-# YAML:      ProgramHeaders:
-# YAML-NEXT:  - Type:     PT_LOAD
-# YAML-NEXT:    Flags:    [ PF_R ]
-# YAML-NEXT:    FirstSec: .hash
-# YAML-NEXT:    LastSec:  .dynstr
-# YAML-NEXT:    Align:    0x1000
-# YAML-NEXT:  - Type:     PT_LOAD
-# YAML-NEXT:    Flags:    [ PF_X, PF_R ]
-# YAML-NEXT:    FirstSec: .foo
-# YAML-NEXT:    LastSec:  .zed
-# YAML-NEXT:    VAddr:    0x1000
-# YAML-NEXT:    Align:    0x1000
-# YAML-NEXT:  - Type:     PT_LOAD
-# YAML-NEXT:    Flags:    [ PF_R ]
-# YAML-NEXT:    FirstSec: '.foo (1)'
-# YAML-NEXT:    LastSec:  .baz
-# YAML-NEXT:    VAddr:    0x2000
-# YAML-NEXT:    Align:    0x1000
-# YAML-NEXT:  - Type:     PT_LOAD
-# YAML-NEXT:    Flags:    [ PF_W, PF_R ]
-# YAML-NEXT:    FirstSec: .dynamic
-# YAML-NEXT:    LastSec:  .dynamic.tail
-# YAML-NEXT:    VAddr:    0x3EF0
-# YAML-NEXT:    Align:    0x1000
-# YAML-NEXT:  - Type:     PT_DYNAMIC
-# YAML-NEXT:    Flags:    [ PF_W, PF_R ]
-# YAML-NEXT:    FirstSec: .dynamic
-# YAML-NEXT:    LastSec:  .dynamic
-# YAML-NEXT:    VAddr:    0x3EF0
-# YAML-NEXT:    Align:    0x8
-# YAML-NEXT:  - Type:     PT_GNU_RELRO
-# YAML-NEXT:    Flags:    [ PF_R ]
-# YAML-NEXT:    FirstSec: .dynamic
-# YAML-NEXT:    LastSec:  .dynamic
-# YAML-NEXT:    VAddr:    0x3EF0
-# YAML-NEXT:  - Type:  PT_LOAD
-# YAML-NEXT:    Flags: [ PF_R ]
-# YAML-NEXT:    VAddr: 0x4000
-# YAML-NEXT:  - Type:     PT_LOAD
-# YAML-NEXT:    Flags:    [ PF_R ]
-# YAML-NEXT:    FirstSec: .gnu.hash
-# YAML-NEXT:    LastSec:  .gnu.hash
-# YAML-NEXT:    VAddr:    0x1A0
-# YAML-NEXT:  - Type:     PT_LOAD
-# YAML-NEXT:    Flags:    [ PF_R ]
-# YAML-NEXT:    FirstSec: .gnu.hash
-# YAML-NEXT:    LastSec:  .gnu.hash
-# YAML-NEXT:    VAddr:    0x1A0
-# YAML-NEXT: Sections:
+# RUN: yaml2obj %s -DOFFSET=0x100 -o %t1.offset
+# RUN: obj2yaml %t1.offset | FileCheck %s --check-prefix=YAML
+
+# YAML:     Sections:
+# YAML-NEXT:  - Type: ProgramHeaderTable
+# YAML-NEXT:    Segments:
+# YAML-NEXT:      - Type:     PT_LOAD
+# YAML-NEXT:        Flags:    [ PF_R ]
+# YAML-NEXT:        FirstSec: .hash
+# YAML-NEXT:        LastSec:  .dynstr
+# YAML-NEXT:        Align:    0x1000
+# YAML-NEXT:      - Type:     PT_LOAD
+# YAML-NEXT:        Flags:    [ PF_X, PF_R ]
+# YAML-NEXT:        FirstSec: .foo
+# YAML-NEXT:        LastSec:  .zed
+# YAML-NEXT:        VAddr:    0x1000
+# YAML-NEXT:        Align:    0x1000
+# YAML-NEXT:      - Type:     PT_LOAD
+# YAML-NEXT:        Flags:    [ PF_R ]
+# YAML-NEXT:        FirstSec: '.foo (1)'
+# YAML-NEXT:        LastSec:  .baz
+# YAML-NEXT:        VAddr:    0x2000
+# YAML-NEXT:        Align:    0x1000
+# YAML-NEXT:      - Type:     PT_LOAD
+# YAML-NEXT:        Flags:    [ PF_W, PF_R ]
+# YAML-NEXT:        FirstSec: .dynamic
+# YAML-NEXT:        LastSec:  .dynamic.tail
+# YAML-NEXT:        VAddr:    0x3EF0
+# YAML-NEXT:        Align:    0x1000
+# YAML-NEXT:      - Type:     PT_DYNAMIC
+# YAML-NEXT:        Flags:    [ PF_W, PF_R ]
+# YAML-NEXT:        FirstSec: .dynamic
+# YAML-NEXT:        LastSec:  .dynamic
+# YAML-NEXT:        VAddr:    0x3EF0
+# YAML-NEXT:        Align:    0x8
+# YAML-NEXT:      - Type:     PT_GNU_RELRO
+# YAML-NEXT:        Flags:    [ PF_R ]
+# YAML-NEXT:        FirstSec: .dynamic
+# YAML-NEXT:        LastSec:  .dynamic
+# YAML-NEXT:        VAddr:    0x3EF0
+# YAML-NEXT:      - Type:  PT_LOAD
+# YAML-NEXT:        Flags: [ PF_R ]
+# YAML-NEXT:        VAddr: 0x4000
+# YAML-NEXT:      - Type:     PT_LOAD
+# YAML-NEXT:        Flags:    [ PF_R ]
+# YAML-NEXT:        FirstSec: .gnu.hash
+# YAML-NEXT:        LastSec:  .gnu.hash
+# YAML-NEXT:        VAddr:    0x1A0
+# YAML-NEXT:      - Type:     PT_LOAD
+# YAML-NEXT:        Flags:    [ PF_R ]
+# YAML-NEXT:        FirstSec: .gnu.hash
+# YAML-NEXT:        LastSec:  .gnu.hash
+# YAML-NEXT:        VAddr:    0x1A0
+# YAML-NEXT:  - Name:
 
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_DYN
-ProgramHeaders:
+Sections:
+  - Type:   ProgramHeaderTable
+    Offset: [[OFFSET=<none>]]
+    Segments:
 ## Check we can create a PT_LOAD with arbitrary (we used .hash, .gnu.hash)
 ## and implicit sections (we use .dynsym, .dynstr). It also checks that the
 ## SHT_NULL section at index 0 is not included in the segment.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .hash
-    LastSec:  .dynstr
-    Align:  0x1000
-    Offset: 0x0
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .hash
+        LastSec:  .dynstr
+        Align:  0x1000
+        Offset: 0x0
 ## Check we can create a PT_LOAD with a different set of properties and sections.
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .foo
-    LastSec:  .zed
-    VAddr:    0x1000
-    Align:    0x1000
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .foo
+        LastSec:  .zed
+        VAddr:    0x1000
+        Align:    0x1000
 ## Create a PT_LOAD to demonstate we are able to refer to output sections with the same name.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: '.foo (1)'
-    LastSec:  .baz
-    VAddr:    0x2000
-    Align:    0x1000
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: '.foo (1)'
+        LastSec:  .baz
+        VAddr:    0x2000
+        Align:    0x1000
 ## Show we can create a writeable PT_LOAD segment and put an arbitrary section into it.
 ## Here we test both regular (SHT_PROGBITS) and a special section (SHT_DYNAMIC).
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .dynamic
-    LastSec:  .dynamic.tail
-    VAddr:    0x3EF0
-    Align:    0x1000
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .dynamic
+        LastSec:  .dynamic.tail
+        VAddr:    0x3EF0
+        Align:    0x1000
 ## Show we can create a nested dynamic segment and put a section into it.
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-    VAddr:    0x3EF0
-    Align:    0x8
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+        VAddr:    0x3EF0
+        Align:    0x8
 ## Show we can create a relro segment and put a section into it.
 ## We used .dynamic here and in tests above to demonstrate that
 ## we can place a section in any number of segments.
 ## Also, we explicitly set the "Align" property to 1 to demonstate
 ## that we do not dump it, because it is the default alignment
 ## value set by yaml2obj.
-  - Type:     PT_GNU_RELRO
-    Flags:    [ PF_R ]
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-    VAddr:    0x3EF0
-    Align:    0x1
+      - Type:     PT_GNU_RELRO
+        Flags:    [ PF_R ]
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+        VAddr:    0x3EF0
+        Align:    0x1
 ## Show we can dump a standalone empty segment.
-  - Type:  PT_LOAD
-    Flags: [ PF_R ]
-    VAddr: 0x4000
-    Align: 0x1
+      - Type:  PT_LOAD
+        Flags: [ PF_R ]
+        VAddr: 0x4000
+        Align: 0x1
 ## ELF specification says that loadable segment entries in the
 ## program header are sorted by virtual address.
 ## Show we can dump an out of order segment.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .gnu.hash
-    LastSec:  .gnu.hash
-    VAddr:    0x1A0
-    Align:    0x1
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .gnu.hash
+        LastSec:  .gnu.hash
+        VAddr:    0x1A0
+        Align:    0x1
 ## Test we are able to dump duplicated segments.
 ## We use a segment that is the same as the previous one for this.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .gnu.hash
-    LastSec:  .gnu.hash
-    VAddr:    0x1A0
-    Align:    0x1
-Sections:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .gnu.hash
+        LastSec:  .gnu.hash
+        VAddr:    0x1A0
+        Align:    0x1
   - Name:    .hash
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
@@ -227,60 +235,64 @@
 # RUN: yaml2obj --docnum=2 %s -o %t2
 # RUN: obj2yaml %t2 | FileCheck %s --check-prefix=EMPTY
 
-# EMPTY:      - Type:     PT_LOAD
-# EMPTY-NEXT:   Flags:    [ PF_W, PF_R ]
-# EMPTY-NEXT:   FirstSec: .empty.tls.start
-# EMPTY-NEXT:   LastSec:  .empty.tls.end
-# EMPTY-NEXT:   VAddr:    0x1000
-# EMPTY-NEXT:   Align:    0x1000
-# EMPTY-NEXT: - Type:     PT_TLS
-# EMPTY-NEXT:   Flags:    [ PF_W, PF_R ]
-# EMPTY-NEXT:   FirstSec: .empty.tls.start
-# EMPTY-NEXT:   LastSec:  .empty.tls.start
-# EMPTY-NEXT:   VAddr:    0x1000
-# EMPTY-NEXT: - Type:     PT_TLS
-# EMPTY-NEXT:   Flags:    [ PF_W, PF_R ]
-# EMPTY-NEXT:   FirstSec: .empty.tls.middle
-# EMPTY-NEXT:   LastSec:  .empty.tls.middle
-# EMPTY-NEXT:   VAddr:    0x1100
-# EMPTY-NEXT: - Type:     PT_TLS
-# EMPTY-NEXT:   Flags:    [ PF_W, PF_R ]
-# EMPTY-NEXT:   FirstSec: .empty.tls.end
-# EMPTY-NEXT:   LastSec:  .empty.tls.end
-# EMPTY-NEXT:   VAddr:    0x1200
-# EMPTY-NEXT: Sections:
+# EMPTY:      Sections:
+# EMPTY-NEXT:   - Type: ProgramHeaderTable
+# EMPTY-NEXT:     Segments:
+# EMPTY-NEXT:   - Type:     PT_LOAD
+# EMPTY-NEXT:     Flags:    [ PF_W, PF_R ]
+# EMPTY-NEXT:     FirstSec: .empty.tls.start
+# EMPTY-NEXT:     LastSec:  .empty.tls.end
+# EMPTY-NEXT:     VAddr:    0x1000
+# EMPTY-NEXT:     Align:    0x1000
+# EMPTY-NEXT:   - Type:     PT_TLS
+# EMPTY-NEXT:     Flags:    [ PF_W, PF_R ]
+# EMPTY-NEXT:     FirstSec: .empty.tls.start
+# EMPTY-NEXT:     LastSec:  .empty.tls.start
+# EMPTY-NEXT:     VAddr:    0x1000
+# EMPTY-NEXT:   - Type:     PT_TLS
+# EMPTY-NEXT:     Flags:    [ PF_W, PF_R ]
+# EMPTY-NEXT:     FirstSec: .empty.tls.middle
+# EMPTY-NEXT:     LastSec:  .empty.tls.middle
+# EMPTY-NEXT:     VAddr:    0x1100
+# EMPTY-NEXT:   - Type:     PT_TLS
+# EMPTY-NEXT:     Flags:    [ PF_W, PF_R ]
+# EMPTY-NEXT:     FirstSec: .empty.tls.end
+# EMPTY-NEXT:     LastSec:  .empty.tls.end
+# EMPTY-NEXT:     VAddr:    0x1200
+# EMPTY-NEXT: - Name:
 
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_DYN
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .empty.tls.start
-    LastSec:  .empty.tls.end
-    VAddr:    0x1000
-    Align:    0x1000
-  - Type:     PT_TLS
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .empty.tls.start
-    LastSec:  .empty.tls.start
-    VAddr:    0x1000
-    Align:    0x1
-  - Type:     PT_TLS
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .empty.tls.middle
-    LastSec:  .empty.tls.middle
-    VAddr:    0x1100
-    Align:    0x1
-  - Type:     PT_TLS
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .empty.tls.end
-    LastSec:  .empty.tls.end
-    VAddr:    0x1200
-    Align:    0x1
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .empty.tls.start
+        LastSec:  .empty.tls.end
+        VAddr:    0x1000
+        Align:    0x1000
+      - Type:     PT_TLS
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .empty.tls.start
+        LastSec:  .empty.tls.start
+        VAddr:    0x1000
+        Align:    0x1
+      - Type:     PT_TLS
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .empty.tls.middle
+        LastSec:  .empty.tls.middle
+        VAddr:    0x1100
+        Align:    0x1
+      - Type:     PT_TLS
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .empty.tls.end
+        LastSec:  .empty.tls.end
+        VAddr:    0x1200
+        Align:    0x1
   - Name:    .empty.tls.start
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC, SHF_TLS ]
@@ -315,29 +327,31 @@
 # MISALIGNED-READELF:      Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
 # MISALIGNED-READELF-NEXT: LOAD 0x000077 0x0000000000001000 0x0000000000001000 0x000078 0x000078 R   0x1000
 
-# MISALIGNED-YAML:      ProgramHeaders:
-# MISALIGNED-YAML-NEXT:  - Type:     PT_LOAD
-# MISALIGNED-YAML-NEXT:    Flags:    [ PF_R ]
-# MISALIGNED-YAML-NEXT:    FirstSec: .foo
-# MISALIGNED-YAML-NEXT:    LastSec:  .foo
-# MISALIGNED-YAML-NEXT:    VAddr:    0x1000
-# MISALIGNED-YAML-NEXT:    Align:    0x1000
-# MISALIGNED-YAML-NEXT: Sections:
+# MISALIGNED-YAML:       - Type: ProgramHeaderTable
+# MISALIGNED-YAML-NEXT:    Segments:
+# MISALIGNED-YAML-NEXT:      - Type:     PT_LOAD
+# MISALIGNED-YAML-NEXT:        Flags:    [ PF_R ]
+# MISALIGNED-YAML-NEXT:        FirstSec: .foo
+# MISALIGNED-YAML-NEXT:        LastSec:  .foo
+# MISALIGNED-YAML-NEXT:        VAddr:    0x1000
+# MISALIGNED-YAML-NEXT:        Align:    0x1000
+# MISALIGNED-YAML-NEXT:  - Name:
 
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_DYN
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .foo
-    LastSec:  .foo
-    VAddr:    0x1000
-    Align:    0x1000
-    Offset:   0x000077
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .foo
+        LastSec:  .foo
+        VAddr:    0x1000
+        Align:    0x1000
+        Offset:   0x000077
   - Name:    .foo
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
@@ -349,48 +363,51 @@
 # RUN: yaml2obj --docnum=4 %s -o %t4
 # RUN: obj2yaml %t4 | FileCheck %s --check-prefix=NON-ALLOC
 
-# NON-ALLOC:      ProgramHeaders:
-# NON-ALLOC-NEXT: - Type:     PT_LOAD
-# NON-ALLOC-NEXT:   Flags:    [ PF_R ]
-# NON-ALLOC-NEXT:   FirstSec: .alloc.1
-# NON-ALLOC-NEXT:   LastSec:  .non-alloc.1
-# NON-ALLOC-NEXT: - Type:     PT_LOAD
-# NON-ALLOC-NEXT:   Flags:    [ PF_R ]
-# NON-ALLOC-NEXT:   FirstSec: .alloc.1
-# NON-ALLOC-NEXT:   LastSec:  .non-alloc.1
-# NON-ALLOC-NEXT: - Type:     PT_LOAD
-# NON-ALLOC-NEXT:   Flags:    [ PF_R ]
-# NON-ALLOC-NEXT:   FirstSec: .alloc.2
-# NON-ALLOC-NEXT:   LastSec:  .alloc.2
-# NON-ALLOC-NEXT: - Type:     PT_LOAD
-# NON-ALLOC-NEXT:   Flags:    [ PF_R ]
-# NON-ALLOC-NEXT:   FirstSec: .alloc.1
-# NON-ALLOC-NEXT:   LastSec:  .alloc.2
-# NON-ALLOC-NEXT: Sections:
+# NON-ALLOC:      Sections:
+# NON-ALLOC-NEXT:   - Type: ProgramHeaderTable
+# NON-ALLOC-NEXT:     Segments:
+# NON-ALLOC-NEXT:       - Type:     PT_LOAD
+# NON-ALLOC-NEXT:         Flags:    [ PF_R ]
+# NON-ALLOC-NEXT:         FirstSec: .alloc.1
+# NON-ALLOC-NEXT:         LastSec:  .non-alloc.1
+# NON-ALLOC-NEXT:       - Type:     PT_LOAD
+# NON-ALLOC-NEXT:         Flags:    [ PF_R ]
+# NON-ALLOC-NEXT:         FirstSec: .alloc.1
+# NON-ALLOC-NEXT:         LastSec:  .non-alloc.1
+# NON-ALLOC-NEXT:       - Type:     PT_LOAD
+# NON-ALLOC-NEXT:         Flags:    [ PF_R ]
+# NON-ALLOC-NEXT:         FirstSec: .alloc.2
+# NON-ALLOC-NEXT:         LastSec:  .alloc.2
+# NON-ALLOC-NEXT:       - Type:     PT_LOAD
+# NON-ALLOC-NEXT:         Flags:    [ PF_R ]
+# NON-ALLOC-NEXT:         FirstSec: .alloc.1
+# NON-ALLOC-NEXT:         LastSec:  .alloc.2
+# NON-ALLOC-NEXT:   - Name:
 
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_DYN
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .alloc.1
-    LastSec:  .non-alloc.1
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .alloc.1
-    LastSec:  .non-alloc.2
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .non-alloc.2
-    LastSec:  .alloc.2
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .alloc.1
-    LastSec:  .alloc.2
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .alloc.1
+        LastSec:  .non-alloc.1
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .alloc.1
+        LastSec:  .non-alloc.2
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .non-alloc.2
+        LastSec:  .alloc.2
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .alloc.1
+        LastSec:  .alloc.2
   - Name:    .alloc.1
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
@@ -413,63 +430,65 @@
 # RUN: yaml2obj --docnum=5 %s -o %t5
 # RUN: obj2yaml %t5 | FileCheck %s --check-prefix=NOBITS
 
-# NOBITS:      ProgramHeaders:
-# NOBITS-NEXT:   - Type:     PT_LOAD
-# NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
-# NOBITS-NEXT:     FirstSec: .bss
-# NOBITS-NEXT:     LastSec:  .bss
-# NOBITS-NEXT:   - Type:     PT_LOAD
-# NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
-# NOBITS-NEXT:     FirstSec: .data.1
-# NOBITS-NEXT:     LastSec:  .bss
-# NOBITS-NEXT:   - Type:     PT_LOAD
-# NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
-# NOBITS-NEXT:     FirstSec: .data.1
-# NOBITS-NEXT:     LastSec:  .data.2
-# NOBITS-NEXT:   - Type:     PT_LOAD
-# NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
-# NOBITS-NEXT:     FirstSec: .bss
-# NOBITS-NEXT:     LastSec:  .data.2
-# NOBITS-NEXT:   - Type:     PT_LOAD
-# NOBITS-NEXT:     Flags:    [ PF_W, PF_R ]
-# NOBITS-NEXT:     FirstSec: .foo.bss
-# NOBITS-NEXT:     LastSec:  .bar.bss
-# NOBITS-NEXT:     VAddr:    0x200000000
-# NOBITS-NEXT: Sections:
+# NOBITS:       - Type: ProgramHeaderTable
+# NOBITS-NEXT:    Segments:
+# NOBITS-NEXT:      - Type:     PT_LOAD
+# NOBITS-NEXT:        Flags:    [ PF_W, PF_R ]
+# NOBITS-NEXT:        FirstSec: .bss
+# NOBITS-NEXT:        LastSec:  .bss
+# NOBITS-NEXT:      - Type:     PT_LOAD
+# NOBITS-NEXT:        Flags:    [ PF_W, PF_R ]
+# NOBITS-NEXT:        FirstSec: .data.1
+# NOBITS-NEXT:        LastSec:  .bss
+# NOBITS-NEXT:      - Type:     PT_LOAD
+# NOBITS-NEXT:        Flags:    [ PF_W, PF_R ]
+# NOBITS-NEXT:        FirstSec: .data.1
+# NOBITS-NEXT:        LastSec:  .data.2
+# NOBITS-NEXT:      - Type:     PT_LOAD
+# NOBITS-NEXT:        Flags:    [ PF_W, PF_R ]
+# NOBITS-NEXT:        FirstSec: .bss
+# NOBITS-NEXT:        LastSec:  .data.2
+# NOBITS-NEXT:      - Type:     PT_LOAD
+# NOBITS-NEXT:        Flags:    [ PF_W, PF_R ]
+# NOBITS-NEXT:        FirstSec: .foo.bss
+# NOBITS-NEXT:        LastSec:  .bar.bss
+# NOBITS-NEXT:        VAddr:    0x200000000
+# NOBITS-NEXT: - Name:
 
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
-ProgramHeaders:
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
 ## Case 1: the segment contains a single SHT_NOBITS section.
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .bss
-    LastSec:  .bss
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .bss
+        LastSec:  .bss
 ## Case 2: the SHT_NOBITS section is the last section in the segment.
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .data.1
-    LastSec:  .bss
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .data.1
+        LastSec:  .bss
 ## Case 3: the SHT_NOBITS section is in the middle of the segment.
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .data.1
-    LastSec:  .data.2
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .data.1
+        LastSec:  .data.2
 ## Case 4: the SHT_NOBITS section is the first section in the segment.
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .bss
-    LastSec:  .data.2
-## Case 5: another two SHT_NOBITS sections in a different segment.
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .foo.bss
-    LastSec:  .bar.bss
-    VAddr:    0x200000000
-Sections:
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .bss
+        LastSec:  .data.2
+ ## Case 5: another two SHT_NOBITS sections in a different segment.
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .foo.bss
+        LastSec:  .bar.bss
+        VAddr:    0x200000000
   - Name:    .data.1
     Type:    SHT_PROGBITS
     Flags:   [ SHF_WRITE, SHF_ALLOC ]
@@ -514,31 +533,32 @@
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_DYN
-ProgramHeaders:
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
 ## Case 1: the .bar section is placed after the .foo section in the file.
 ##         Check we report an error about the violation of the order.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .bar
-    LastSec:  .foo
-    VAddr:    0x1000
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .bar
+        LastSec:  .foo
+        VAddr:    0x1000
 ## There is nothing wrong with this segment. We have it to show that
 ## we report correct program header indices in error messages.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .foo
-    LastSec:  .bar
-    VAddr:    0x1000
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .foo
+        LastSec:  .bar
+        VAddr:    0x1000
 ## Case 2: the .bar section is placed before the .zed section in the file,
 ##         but the sh_offset of .zed is less than the sh_offset of
 ##         the .bar section because of the "ShOffset" property.
 ##         Document we report an error for such a case.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .bar
-    LastSec:  .zed
-    VAddr:    0x1001
-Sections:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .bar
+        LastSec:  .zed
+        VAddr:    0x1001
   - Name:    .foo
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
@@ -575,26 +595,28 @@
 
 # RUN: obj2yaml %t7 | FileCheck %s --check-prefix=ZERO-SIZE
 
-# ZERO-SIZE:      ProgramHeaders:
-# ZERO-SIZE-NEXT:   - Type:     PT_LOAD
-# ZERO-SIZE-NEXT:     Flags:    [ PF_W, PF_R ]
-# ZERO-SIZE-NEXT:     FirstSec: .empty.bar1
-# ZERO-SIZE-NEXT:     LastSec:  .empty.bar2
-# ZERO-SIZE-NEXT:     VAddr:    0x2000
-# ZERO-SIZE-NEXT: Sections:
+# ZERO-SIZE:      - Type: ProgramHeaderTable
+# ZERO-SIZE-NEXT:    Segments:
+# ZERO-SIZE-NEXT:      - Type:     PT_LOAD
+# ZERO-SIZE-NEXT:        Flags:    [ PF_W, PF_R ]
+# ZERO-SIZE-NEXT:        FirstSec: .empty.bar1
+# ZERO-SIZE-NEXT:        LastSec:  .empty.bar2
+# ZERO-SIZE-NEXT:        VAddr:    0x2000
+# ZERO-SIZE-NEXT: - Name:
 
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    FirstSec: .bar
-    LastSec:  .bar
-    VAddr:    0x2000
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        FirstSec: .bar
+        LastSec:  .bar
+        VAddr:    0x2000
   - Name:    .empty.foo
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -624,25 +646,29 @@
 # RUN: yaml2obj --docnum=8 %s -o %t8
 # RUN: obj2yaml %t8 | FileCheck %s --check-prefix=BROKEN-VA
 
-# BROKEN-VA:      ProgramHeaders:
-# BROKEN-VA-NEXT:  - Type:     PT_LOAD
-# BROKEN-VA-NEXT:    Flags:    [ PF_W, PF_R ]
-# BROKEN-VA-NEXT:    FirstSec: .empty_middle
-# BROKEN-VA-NEXT:    LastSec:  .empty_middle
-# BROKEN-VA-NEXT:    VAddr:    0x1000
+# BROKEN-VA:      Sections:
+# BROKEN-VA-NEXT:   - Type: ProgramHeaderTable
+# BROKEN-VA-NEXT:     Segments:
+# BROKEN-VA-NEXT:       - Type:     PT_LOAD
+# BROKEN-VA-NEXT:         Flags:    [ PF_W, PF_R ]
+# BROKEN-VA-NEXT:         FirstSec: .empty_middle
+# BROKEN-VA-NEXT:         LastSec:  .empty_middle
+# BROKEN-VA-NEXT:         VAddr:    0x1000
+# BROKEN-VA-NEXT:   - Name:
 
 --- !ELF
 FileHeader:
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_W, PF_R ]
-    VAddr:    0x1000
-    FirstSec: .empty_begin
-    LastSec:  .empty_end
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_W, PF_R ]
+        VAddr:    0x1000
+        FirstSec: .empty_begin
+        LastSec:  .empty_end
   - Name:    .empty_begin
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -662,3 +688,29 @@
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
     Address: 0xFEFEFEFE
+
+## Document that obj2yaml currently always dumps the program header
+## table at the begining of the sections list.
+## FIXME: we should preserve the right chunks order.
+
+# RUN: yaml2obj --docnum=9 %s -o %t9
+# RUN: obj2yaml %t9 | FileCheck %s --check-prefix=ORDER
+
+# ORDER:      Sections:
+# ORDER-NEXT:   - Type: ProgramHeaderTable
+# ORDER-NEXT:     Segments:
+# ORDER-NEXT:       - Type: PT_LOAD
+# ORDER-NEXT:   - Name: .foo
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Name: .foo
+    Type: SHT_PROGBITS
+    Size: 0x1
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
Index: llvm/test/tools/yaml2obj/ELF/custom-fill.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/custom-fill.yaml
+++ llvm/test/tools/yaml2obj/ELF/custom-fill.yaml
@@ -105,6 +105,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x100
+        FirstSec: fill1
+        LastSec:  fill2
+      - Type:     PT_GNU_RELRO
+        VAddr:    0x105
+        FirstSec: fill2
+        LastSec:  fill2
   - Type:    Fill
     Name:    fill1
     Pattern: ""
@@ -118,15 +128,6 @@
     Name:    fill2
     Pattern: ""
     Size:    0x45
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x100
-    FirstSec: fill1
-    LastSec:  fill2
-  - Type:     PT_GNU_RELRO
-    VAddr:    0x105
-    FirstSec: fill2
-    LastSec:  fill2
 
 ## Check that the "Pattern" field is not mandatory.
 # RUN: yaml2obj --docnum=4 2>&1 -o %t4 %s
@@ -276,13 +277,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: fill
+        LastSec:  fill
   - Type:    Fill
     Pattern: ""
     Size:    0
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: fill
-    LastSec:  fill
 
 ## Show that we can use the "Offset" key to set an arbitrary offset for a Fill.
 
Index: llvm/test/tools/yaml2obj/ELF/dynamic-section-i386.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/dynamic-section-i386.yaml
+++ llvm/test/tools/yaml2obj/ELF/dynamic-section-i386.yaml
@@ -15,6 +15,19 @@
   Data:  ELFDATA2LSB
   Type:  ET_DYN
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0x0000
+        Align:    8
+        FirstSec: .dynamic
+        LastSec:  .dynamic
+      - Type:     PT_DYNAMIC
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0x0008
+        FirstSec: .dynamic
+        LastSec:  .dynamic
   - Name:            .dynamic
     Type:            SHT_DYNAMIC
     Flags:           [ SHF_ALLOC ]
@@ -26,15 +39,3 @@
         Value:           0x0000000000000001
       - Tag:             DT_NULL
         Value:           0x0000000000000000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0x0000
-    Align:    8
-    FirstSec: .dynamic
-    LastSec:  .dynamic
-  - Type:     PT_DYNAMIC
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0x0008
-    FirstSec: .dynamic
-    LastSec:  .dynamic
Index: llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml
+++ llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml
@@ -19,9 +19,11 @@
   Class: ELFCLASS64
   Data:  ELFDATA2LSB
   Type:  ET_REL
-ProgramHeaders:
-  - Type: PT_LOAD
-  - Type: PT_LOAD
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+      - Type: PT_LOAD
 
 ## Check we can override all default values using the same values
 ## and that this does not change the output.
@@ -40,9 +42,11 @@
   EPhOff:     [[PHOFF=64]]
   EPhEntSize: [[PHENTSIZE=56]]
   EPhNum:     [[PHNUM=2]]
-ProgramHeaders:
-  - Type: PT_LOAD
-  - Type: PT_LOAD
+Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+      - Type: PT_LOAD
 
 ## Override different fields to check the output produced.
 
Index: llvm/test/tools/yaml2obj/ELF/program-header-address.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/program-header-address.yaml
+++ llvm/test/tools/yaml2obj/ELF/program-header-address.yaml
@@ -20,35 +20,36 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
-  - Name:    .foo
-    Type:    SHT_PROGBITS
-    Flags:   [ SHF_ALLOC ]
-    Size:    0x1
-    Address: 0x1234
-ProgramHeaders:
+  - Type: ProgramHeaderTable
+    Segments:
 ## Show what virtual and physical address we set by default for the case where
 ## a program header has no sections.
-  - Type:  PT_LOAD
-    Flags: [ PF_X, PF_R ]
+      - Type:  PT_LOAD
+        Flags: [ PF_X, PF_R ]
 ## Show what virtual and physical address we set by default for the case
 ## where a program header includes a section with a virtual address that
 ## is explicitly set.
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    FirstSec: .foo
-    LastSec:  .foo
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        FirstSec: .foo
+        LastSec:  .foo
 ## Now we have a program header that has a virtual address different to
 ## the address of the section included. Show that the default physical address
 ## is equal to the program header's virtual address.
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0xAAAA1000
-    FirstSec: .foo
-    LastSec:  .foo
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0xAAAA1000
+        FirstSec: .foo
+        LastSec:  .foo
 ## Show that we are able to set different virtual and physical addresses.
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0xAAAA1000
-    PAddr:    0xBBBB2000
-    FirstSec: .foo
-    LastSec:  .foo
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0xAAAA1000
+        PAddr:    0xBBBB2000
+        FirstSec: .foo
+        LastSec:  .foo
+  - Name:    .foo
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC ]
+    Size:    0x1
+    Address: 0x1234
Index: llvm/test/tools/yaml2obj/ELF/program-header-align.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/program-header-align.yaml
+++ llvm/test/tools/yaml2obj/ELF/program-header-align.yaml
@@ -16,17 +16,18 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:  PT_TLS
+        Align: 16
+        FirstSec: .tdata
+        LastSec:  .tbss
   - Name:         .tdata
     Type:         SHT_PROGBITS
     AddressAlign: 4
   - Name:         .tbss
     Type:         SHT_NOBITS
     AddressAlign: 64
-ProgramHeaders:
-  - Type:  PT_TLS
-    Align: 16
-    FirstSec: .tdata
-    LastSec:  .tbss
 
 ## If Align is not specified, p_align is inferred from the maximum alignment
 ## of contained sections.
@@ -40,13 +41,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .text
+        LastSec:  .text.hot
   - Name:         .text
     Type:         SHT_PROGBITS
     AddressAlign: 4
   - Name:         .text.hot
     Type:         SHT_PROGBITS
     AddressAlign: 16
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .text
-    LastSec:  .text.hot
Index: llvm/test/tools/yaml2obj/ELF/program-header-nobits.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/program-header-nobits.yaml
+++ llvm/test/tools/yaml2obj/ELF/program-header-nobits.yaml
@@ -9,12 +9,12 @@
 # RUN: llvm-readelf --sections --segments %t1 | FileCheck %s --check-prefix=NO-ALLOC
 
 # NO-ALLOC:      [Nr] Name         Type     Address          Off    Size
-# NO-ALLOC:      [ 1] .data.before PROGBITS 0000000000000000 0000b0 000001
-# NO-ALLOC-NEXT: [ 2] .nobits.1    NOBITS   0000000000000001 0000b1 000002
-# NO-ALLOC-NEXT: [ 3] .data.after  PROGBITS 0000000000000003 0000b1 000003
-# NO-ALLOC-NEXT: [ 4] .nobits.2    NOBITS   0000000000000006 0000b4 000004
+# NO-ALLOC:      [ 1] .data.before PROGBITS 0000000000000070 0000b0 000001
+# NO-ALLOC-NEXT: [ 2] .nobits.1    NOBITS   0000000000000071 0000b1 000002
+# NO-ALLOC-NEXT: [ 3] .data.after  PROGBITS 0000000000000073 0000b1 000003
+# NO-ALLOC-NEXT: [ 4] .nobits.2    NOBITS   0000000000000076 0000b4 000004
 ## .fill of size 0x5 is placed here.
-# NO-ALLOC-NEXT: [ 5] .data.last   PROGBITS 000000000000000f 0000b9 000006
+# NO-ALLOC-NEXT: [ 5] .data.last   PROGBITS 000000000000007f 0000b9 000006
 
 # NO-ALLOC:       Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz
 # NO-ALLOC-NEXT:  LOAD 0x0000b0 0x0000000000000000 0x0000000000000000 0x000001 0x000003
@@ -27,12 +27,12 @@
 # RUN: llvm-readelf --sections --segments %t2 | FileCheck %s --check-prefix=ALLOC-FIRST
 
 # ALLOC-FIRST:      [Nr] Name         Type     Address          Off    Size
-# ALLOC-FIRST:      [ 1] .data.before PROGBITS 0000000000000000 0000b0 000001
-# ALLOC-FIRST-NEXT: [ 2] .nobits.1    NOBITS   0000000000000001 0000b1 000002
-# ALLOC-FIRST-NEXT: [ 3] .data.after  PROGBITS 0000000000000003 0000b3 000003
-# ALLOC-FIRST-NEXT: [ 4] .nobits.2    NOBITS   0000000000000006 0000b6 000004
+# ALLOC-FIRST:      [ 1] .data.before PROGBITS 0000000000000070 0000b0 000001
+# ALLOC-FIRST-NEXT: [ 2] .nobits.1    NOBITS   0000000000000071 0000b1 000002
+# ALLOC-FIRST-NEXT: [ 3] .data.after  PROGBITS 0000000000000073 0000b3 000003
+# ALLOC-FIRST-NEXT: [ 4] .nobits.2    NOBITS   0000000000000076 0000b6 000004
 ## .fill of size 0x5 is placed here.
-# ALLOC-FIRST-NEXT: [ 5] .data.last   PROGBITS 000000000000000f 0000bb 000006
+# ALLOC-FIRST-NEXT: [ 5] .data.last   PROGBITS 000000000000007f 0000bb 000006
 
 # ALLOC-FIRST:       Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz
 # ALLOC-FIRST-NEXT:  LOAD 0x0000b0 0x0000000000000000 0x0000000000000000 0x000001 0x000003
@@ -44,9 +44,9 @@
 # RUN: llvm-readelf --sections --segments %t3 | FileCheck %s --check-prefix=FILL-AT-END
 
 # FILL-AT-END: [Nr] Name       Type     Address          Off    Size
-# FILL-AT-END: [ 4] .nobits.2  NOBITS   0000000000000006 0000b4 000004
+# FILL-AT-END: [ 4] .nobits.2  NOBITS   0000000000000076 0000b4 000004
 ## .fill of size 0x5 is placed here.
-# FILL-AT-END: [ 5] .data.last PROGBITS 000000000000000f 0000bd 000006
+# FILL-AT-END: [ 5] .data.last PROGBITS 000000000000007f 0000bd 000006
 
 # FILL-AT-END:      Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz
 # FILL-AT-END-NEXT: LOAD 0x0000b0 0x0000000000000000 0x0000000000000000 0x000001 0x000003
@@ -58,6 +58,19 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## We have 2 segments, the first is predefined and the second can be customized.
+## We want to have more than one segment to show we check all of them when
+## trying to find a non-nobits section after a nobits one.
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .data.before
+        LastSec:  .nobits.1
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: [[SEC1]]
+        LastSec:  [[SEC2]]
   - Name:  .data.before
     Type:  SHT_PROGBITS
     Flags: [ SHF_ALLOC ]
@@ -82,18 +95,6 @@
     Type:  SHT_PROGBITS
     Flags: [ SHF_ALLOC ]
     Size:  0x6
-ProgramHeaders:
-## We have 2 segments, the first is predefined and the second can be customized.
-## We want to have more than one segment to show we check all of them when
-## trying to find a non-nobits section after a nobits one.
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .data.before
-    LastSec:  .nobits.1
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: [[SEC1]]
-    LastSec:  [[SEC2]]
 
 ## Case D. We have a segment with SHT_NOBITS sections on its borders and one
 ##         non-nobits in the middle. Check we allocate the file space only for
@@ -103,9 +104,9 @@
 # RUN: llvm-readelf --sections --segments %t4 | FileCheck %s --check-prefix=MIDDLE
 
 # MIDDLE:      [Nr] Name      Type     Address          Off    Size
-# MIDDLE:      [ 1] .nobits.1 NOBITS   0000000000000000 000078 000001
-# MIDDLE-NEXT: [ 2] .data     PROGBITS 0000000000000001 000079 000010
-# MIDDLE-NEXT: [ 3] .nobits.2 NOBITS   0000000000000011 000089 000100
+# MIDDLE:      [ 1] .nobits.1 NOBITS   0000000000000038 000078 000001
+# MIDDLE-NEXT: [ 2] .data     PROGBITS 0000000000000039 000079 000010
+# MIDDLE-NEXT: [ 3] .nobits.2 NOBITS   0000000000000049 000089 000100
 # MIDDLE-NEXT: [ 4] .strtab   STRTAB   0000000000000000 000089 000001
 
 # MIDDLE:      Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz
@@ -117,6 +118,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        FirstSec: .nobits.1
+        LastSec:  .nobits.2
   - Name:  .nobits.1
     Type:  SHT_NOBITS
     Flags: [ SHF_ALLOC ]
@@ -129,8 +136,3 @@
     Type:  SHT_NOBITS
     Flags: [ SHF_ALLOC ]
     Size:  0x100
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    FirstSec: .nobits.1
-    LastSec:  .nobits.2
Index: llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml
+++ llvm/test/tools/yaml2obj/ELF/program-header-size-offset.yaml
@@ -41,6 +41,45 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+## Program header with no sections.
+      - Type:     0x6abcdef0 # arbitrary type
+        Offset:   0x1234
+        FileSize: 1111
+        MemSize:  9999
+## Program header with only file size set.
+      - Type:     0x6abcdef0
+        FileSize: 6
+        FirstSec: .rodata
+        LastSec:  .rodata
+## Program header with only mem size set.
+      - Type:     0x6abcdef0
+        MemSize:  6
+        FirstSec: .rodata
+        LastSec:  .rodata
+## Program header with only offset set.
+      - Type:     0x6abcdef0
+        Offset:   0x1fff
+        FirstSec: .rodata
+        LastSec:  .rodata
+## Program header with sections, valid properties.
+      - Type:     0x6abcdef0
+        Offset:   0xffe
+        FileSize: 7
+        MemSize:  9
+        FirstSec: .text
+        LastSec:  .text
+## Program header with invalid properties.
+      - Type:     0x6abcdef0
+        Offset:   0x3000
+        FileSize: 3
+        MemSize:  2
+## Program header with 2 SHT_NOBITS sections.
+      - Type:     0x6abcdef0
+        Offset:   0x2004
+        FirstSec: .data
+        LastSec:  .nobits2
   - Name: .text
     Type: SHT_PROGBITS
     Size: 4
@@ -64,44 +103,6 @@
     # Intentionally set to 0x2009 though the previous section is SHT_NOBITS.
     ShOffset: 0x2009
     Size: 1
-ProgramHeaders:
-  # Program header with no sections.
-  - Type:     0x6abcdef0 # arbitrary type
-    Offset:   0x1234
-    FileSize: 1111
-    MemSize:  9999
-  # Program header with only file size set.
-  - Type:     0x6abcdef0
-    FileSize: 6
-    FirstSec: .rodata
-    LastSec:  .rodata
-  # Program header with only mem size set.
-  - Type:     0x6abcdef0
-    MemSize:  6
-    FirstSec: .rodata
-    LastSec:  .rodata
-  # Program header with only offset set.
-  - Type:     0x6abcdef0
-    Offset:   0x1fff
-    FirstSec: .rodata
-    LastSec:  .rodata
-  # Program header with sections, valid properties.
-  - Type:     0x6abcdef0
-    Offset:   0xffe
-    FileSize: 7
-    MemSize:  9
-    FirstSec: .text
-    LastSec:  .text
-  # Program header with invalid properties.
-  - Type:     0x6abcdef0
-    Offset:   0x3000
-    FileSize: 3
-    MemSize:  2
-  # Program header with 2 SHT_NOBITS sections.
-  - Type:     0x6abcdef0
-    Offset:   0x2004
-    FirstSec: .data
-    LastSec:  .nobits2
 
 ## Test the "Offset" property.
 
@@ -125,6 +126,14 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: .foo
+        LastSec:  .bar
+      - Type:     PT_LOAD
+        FirstSec: .bar
+        LastSec:  .bar
   - Name:    .foo
     Type:    SHT_PROGBITS
     Flags:   [ SHF_ALLOC ]
@@ -134,13 +143,6 @@
     Type:  SHT_PROGBITS
     Flags: [ SHF_ALLOC ]
     Size:  0x1
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: .foo
-    LastSec:  .bar
-  - Type:     PT_LOAD
-    FirstSec: .bar
-    LastSec:  .bar
 
 ## Check we can set the "Offset" value explicitly to be less than or equal to
 ## the offset of a section in the segment.
@@ -152,7 +154,7 @@
 # RUN:   FileCheck %s --check-prefixes=VALID-OFFSET,VALID-OFFSET-EQ
 
 # VALID-OFFSET: [Nr] Name Type     Address          Off
-# VALID-OFFSET: [ 1] .foo PROGBITS 0000000000000000 000078
+# VALID-OFFSET: [ 1] .foo PROGBITS 0000000000000038 000078
 
 # VALID-OFFSET:      Type Offset
 # VALID-OFFSET-EQ:   LOAD 0x000078
@@ -164,15 +166,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:    PT_LOAD
+        Offset:  [[OFFSET]]
+        FirstSec: .foo
+        LastSec:  .foo
   - Name:  .foo
     Type:  SHT_PROGBITS
     Flags: [ SHF_ALLOC ]
     Size:  0x1
-ProgramHeaders:
-  - Type:    PT_LOAD
-    Offset:  [[OFFSET]]
-    FirstSec: .foo
-    LastSec:  .foo
 
 ## Check we report an error when the "Offset" value is larger than the offset of a section in the segment.
 # RUN: not yaml2obj --docnum=3 -DOFFSET=0x79 %s -o /dev/null 2>&1 | \
@@ -185,7 +188,7 @@
 # RUN: llvm-readelf %t5 --sections --program-headers | FileCheck %s --check-prefix=SHOFFSET
 
 # SHOFFSET: [Nr] Name Type     Address          Off
-# SHOFFSET: [ 1] .foo PROGBITS 0000000000000000 ffffffff
+# SHOFFSET: [ 1] .foo PROGBITS 0000000000000038 ffffffff
 
 # SHOFFSET:      Type Offset
 # SHOFFSET-NEXT: LOAD 0xffffff00
@@ -196,6 +199,12 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Offset:   0xFFFFFF00
+        FirstSec: .foo
+        LastSec:  .foo
   - Name:     .foo
     Type:     SHT_PROGBITS
     Flags:    [ SHF_ALLOC ]
@@ -203,8 +212,3 @@
 ## Note: the real .foo offset is much less than 0xFFFFFFFF or
 ##       0xFFFFFF00, but no error is reported.
     ShOffset: 0xFFFFFFFF
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Offset:   0xFFFFFF00
-    FirstSec: .foo
-    LastSec:  .foo
Index: llvm/test/tools/yaml2obj/ELF/program-header.yaml
===================================================================
--- llvm/test/tools/yaml2obj/ELF/program-header.yaml
+++ llvm/test/tools/yaml2obj/ELF/program-header.yaml
@@ -7,6 +7,24 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        Flags:    [ PF_X, PF_R ]
+        VAddr:    0xAAAA1000
+        PAddr:    0xFFFF1000
+        FirstSec: .text
+        LastSec:  .init
+      - Type:     PT_LOAD
+        Flags:    [ PF_R ]
+        VAddr:    0xAAAA2000
+        PAddr:    0xFFFF2000
+        FirstSec: .data
+        LastSec:  .data
+      - Type: PT_GNU_EH_FRAME
+      - Type: PT_GNU_STACK
+      - Type: PT_GNU_RELRO
+      - Type: PT_GNU_PROPERTY
   - Name:            .text
     Type:            SHT_PROGBITS
     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
@@ -22,23 +40,6 @@
     Flags:           [ SHF_ALLOC ]
     Content:         "00000000"
     AddressAlign:    0x0000000000001000
-ProgramHeaders:
-  - Type:     PT_LOAD
-    Flags:    [ PF_X, PF_R ]
-    VAddr:    0xAAAA1000
-    PAddr:    0xFFFF1000
-    FirstSec: .text
-    LastSec:  .init
-  - Type:     PT_LOAD
-    Flags:    [ PF_R ]
-    VAddr:    0xAAAA2000
-    PAddr:    0xFFFF2000
-    FirstSec: .data
-    LastSec:  .data
-  - Type: PT_GNU_EH_FRAME
-  - Type: PT_GNU_STACK
-  - Type: PT_GNU_RELRO
-  - Type: PT_GNU_PROPERTY
 
 #CHECK:     ProgramHeaders [
 #CHECK-NEXT:   ProgramHeader {
@@ -93,6 +94,11 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        FirstSec: [[FIRST=<none>]]
+        LastSec:  [[LAST=<none>]]
   - Name:   .foo
     Type:   SHT_PROGBITS
     Offset: 0x100
@@ -113,10 +119,6 @@
     Type:   Fill
     Offset: 0x500
     Size:   0x50
-ProgramHeaders:
-  - Type:     PT_LOAD
-    FirstSec: [[FIRST=<none>]]
-    LastSec:  [[LAST=<none>]]
 
 ## Check we report an error when the index of the section specified by the "FirstSec" key
 ## is greater than the index of the section specified by the "LastSec" key.
@@ -170,3 +172,206 @@
 
 # FILL2: Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz
 # FILL2: LOAD 0x000100 0x0000000000000000 0x0000000000000000 0x000450 0x000450
+
+## Check that the size of the program header might affect the virtual
+## addresses and offsets of following sections.
+
+# RUN: yaml2obj --docnum=3 %s -o %t6.1
+# RUN: llvm-readelf --sections %t6.1 | FileCheck %s --check-prefix=SECTIONS-VA1
+# RUN: yaml2obj --docnum=3 -DTYPE2="" %s -o %t6.2
+# RUN: llvm-readelf --sections %t6.2 | FileCheck %s --check-prefix=SECTIONS-VA2
+
+##              [Nr] Name Type     Address          Off
+# SECTIONS-VA1: [ 1] .foo PROGBITS 0000000000000070 0000b0
+# SECTIONS-VA2: [ 1] .foo PROGBITS 0000000000000038 000078
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Type:   ProgramHeaderTable
+    Offset: [[OFFSET=<none>]]
+    Segments:
+      - Type: PT_LOAD
+      [[TYPE2=- Type: PT_LOAD]]
+  - Name:  .foo
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC ]
+
+## Check that we can place the program header table at an
+## arbitrary offset before other sections.
+
+# RUN: yaml2obj --docnum=3 -DOFFSET=0x100 %s -o %t6.3
+# RUN: llvm-readelf --file-header --sections %t6.3 | \
+# RUN:   FileCheck %s --check-prefix=OFFSET
+
+# OFFSET: Start of program headers:          256 (bytes into file)
+# OFFSET: Size of program headers:           56 (bytes)
+# OFFSET: Number of program headers:         2
+
+## 256 + 56 * 2 == 368 == 0x170.
+# OFFSET: [Nr] Name  Type     Address          Off
+# OFFSET: [ 1] .foo  PROGBITS 0000000000000070 000170
+
+## Check that we can place the program header table at an
+## arbitrary offset that is not alligned to the platform address size.
+
+# RUN: yaml2obj --docnum=3 -DOFFSET=0x101 %s -o %t6.4
+# RUN: llvm-readelf --file-header --sections %t6.4 | \
+# RUN:   FileCheck %s --check-prefix=MISALIGNED-OFFSET
+
+## 257 == 0x101.
+# MISALIGNED-OFFSET: Start of program headers: 257 (bytes into file)
+
+## Check we can place the program header table somewhere in
+## the middle of the sections list.
+
+# RUN: yaml2obj --docnum=4 %s -o %t7.1
+# RUN: llvm-readelf --file-header --sections %t7.1 | \
+# RUN:   FileCheck %s --check-prefixes=MIDDLE,MIDDLE1 -DSTART=64
+
+# RUN: yaml2obj --docnum=4 -DOFFSET=0x100 %s -o %t7.2
+# RUN: llvm-readelf --file-header --sections %t7.2 | \
+# RUN:   FileCheck %s --check-prefixes=MIDDLE,MIDDLE2 -DSTART=256
+
+# MIDDLE: Start of program headers: [[START]] (bytes into file)
+# MIDDLE:  [Nr] Name Type     Address          Off
+# MIDDLE:  [ 1] .foo PROGBITS 0000000000000000 000040
+# MIDDLE1: [ 2] .bar PROGBITS 0000000000000038 000078
+# MIDDLE2: [ 2] .bar PROGBITS 0000000000000038 000138
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Name:  .foo
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC ]
+    Offset: [[FOOOFF=<none>]]
+  - Type:   ProgramHeaderTable
+    Offset: [[OFFSET=<none>]]
+    Segments:
+      - Type: PT_LOAD
+  - Name:  .bar
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC ]
+
+## Check we align the start of the program headers to the
+## platform address size automatically.
+
+# RUN: yaml2obj --docnum=4 %s -DFOOOFF=0x101 -o %t7.3
+# RUN: llvm-readelf --file-header %t7.3 | FileCheck %s --check-prefix=ALIGN
+
+## alignTo(8, 0x101) == 0x108 == 264.
+# ALIGN: Start of program headers: 264 (bytes into file)
+
+## Check we can omit the "Segments" key to create an empty program header table.
+
+# RUN: yaml2obj --docnum=5 %s -o %t8
+# RUN: llvm-readelf --file-header %t8 | FileCheck %s --check-prefix=EMPTY
+
+# EMPTY: Start of program headers:  64 (bytes into file)
+# EMPTY: Number of program headers: 0
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Type: ProgramHeaderTable
+
+## Check we don`t allow having multiple ProgramHeaderTable chunks.
+
+# RUN: not yaml2obj %s --docnum=6 -o /dev/null 2>&1 | FileCheck %s --check-prefix=MULTIPLE
+
+# MULTIPLE: error: multiple program header tables are not allowed
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_REL
+Sections:
+  - Type: ProgramHeaderTable
+  - Type: ProgramHeaderTable
+
+## Check that implicit sections are placed after the program header table by default. 
+
+# RUN: yaml2obj --docnum=7 %s -o %t9
+# RUN: llvm-readelf --file-header --sections %t9 | FileCheck %s --check-prefix=IMPLICIT
+
+## 72 == 0x48.
+# IMPLICIT: Start of program headers: 72 (bytes into file)
+
+# IMPLICIT:      [Nr] Name      Type     Address          Off    Size
+# IMPLICIT:      [ 1] .foo      PROGBITS 0000000000000000 000040 000001
+# IMPLICIT-NEXT: [ 2] .strtab   STRTAB   0000000000000000 000048 000001
+# IMPLICIT-NEXT: [ 3] .shstrtab STRTAB   0000000000000000 000049 000018
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Name: .foo
+    Type: SHT_PROGBITS
+    Size: 0x1
+  - Type: ProgramHeaderTable
+
+## Check we are able to explicitly place the program header table at the end of file.
+
+# RUN: yaml2obj --docnum=8 %s -o %t10
+# RUN: llvm-readelf --file-header --sections %t10 | FileCheck %s --check-prefix=LAST1
+
+# LAST1: Start of program headers:  280 (bytes into file)
+# LAST1: Size of program headers:   56 (bytes)
+# LAST1: Number of program headers: 2
+
+# LAST1: There are 3 section headers, starting at offset 0x40:
+# LAST1: [Nr] Name      Type   Address          Off    Size
+# LAST1: [ 2] .shstrtab STRTAB 0000000000000000 000101 000013
+## The program header table is placed here, at alignTo(8, 0x101 + 0x13) ==
+## alignTo(8, 0x114) = 0x118 == 280.
+
+## Check the size of the file: start of program headers (280) +
+## size of program headers(56) * number of program headers(2) == 392.
+
+# RUN: wc -c < %t10 | FileCheck %s --check-prefix=SIZE1
+# SIZE1: 392{{$}}
+
+## Check that the size of the program header table affects the file size.
+
+# RUN: yaml2obj --docnum=8 -DTYPE2="" %s -o %t11
+# RUN: llvm-readelf --file-header %t11 | FileCheck %s --check-prefix=LAST2
+
+# LAST2: Start of program headers:  280 (bytes into file)
+# LAST2: Size of program headers:   56 (bytes)
+# LAST2: Number of program headers: 1
+
+## Check the size of the file: start of program headers (280) +
+## size of program headers(56) * number of program headers(1) == 392.
+
+# RUN: wc -c < %t11 | FileCheck %s --check-prefix=SIZE2
+# SIZE2: 336{{$}}
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_EXEC
+Sections:
+  - Type: SectionHeaderTable
+  - Name: .strtab
+    Type: SHT_STRTAB
+  - Name: .shstrtab
+    Type: SHT_STRTAB
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type: PT_LOAD
+      [[TYPE2=- Type: PT_LOAD]]
Index: llvm/tools/obj2yaml/elf2yaml.cpp
===================================================================
--- llvm/tools/obj2yaml/elf2yaml.cpp
+++ llvm/tools/obj2yaml/elf2yaml.cpp
@@ -231,7 +231,7 @@
 
 template <class ELFT>
 static void dumpSectionOffsets(const typename ELFT::Ehdr &Header,
-                               ArrayRef<ELFYAML::ProgramHeader> Phdrs,
+                               ELFYAML::ProgramHeaderTable *Phdrs,
                                std::vector<std::unique_ptr<ELFYAML::Chunk>> &V,
                                ArrayRef<typename ELFT::Shdr> S) {
   if (V.empty())
@@ -365,9 +365,15 @@
       dumpProgramHeaders(Chunks);
   if (!PhdrsOrErr)
     return PhdrsOrErr.takeError();
-  Y->ProgramHeaders = std::move(*PhdrsOrErr);
 
-  dumpSectionOffsets<ELFT>(Obj.getHeader(), Y->ProgramHeaders, Chunks,
+  std::unique_ptr<ELFYAML::ProgramHeaderTable> ProgramHeaders;
+  if (PhdrsOrErr->size()) {
+    ProgramHeaders =
+        std::make_unique<ELFYAML::ProgramHeaderTable>(/*IsImplicit=*/false);
+    ProgramHeaders->Segments = std::move(*PhdrsOrErr);
+  }
+
+  dumpSectionOffsets<ELFT>(Obj.getHeader(), ProgramHeaders.get(), Chunks,
                            Sections);
 
   // Dump DWARF sections.
@@ -390,8 +396,14 @@
     Chunks.push_back(std::move(SHT));
   }
 
+  // Currently we insert the program header table right after the SHT_NULL
+  // section.
+  // TODO: we should insert it at a proper position.
+  if (ProgramHeaders)
+    Chunks.insert(Chunks.begin() + 1, std::move(ProgramHeaders));
+
   llvm::erase_if(Chunks, [this, &Y](const std::unique_ptr<ELFYAML::Chunk> &C) {
-    if (isa<ELFYAML::SectionHeaderTable>(*C.get()))
+    if (C->Kind >= ELFYAML::Chunk::ChunkKind::SpecialChunksStart)
       return false;
 
     const ELFYAML::Section &S = cast<ELFYAML::Section>(*C.get());
Index: llvm/unittests/Object/ELFObjectFileTest.cpp
===================================================================
--- llvm/unittests/Object/ELFObjectFileTest.cpp
+++ llvm/unittests/Object/ELFObjectFileTest.cpp
@@ -346,6 +346,16 @@
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:
+  - Type: ProgramHeaderTable
+    Segments:
+      - Type:     PT_LOAD
+        VAddr:    0x2000
+        FirstSec: .bar
+        LastSec:  .bar
+      - Type:     PT_LOAD
+        VAddr:    0x1000
+        FirstSec: .foo
+        LastSec:  .foo
   - Name:         .foo
     Type:         SHT_PROGBITS
     Address:      0x1000
@@ -356,15 +366,6 @@
     Address:      0x2000
     Offset:       0x4000
     ContentArray: [ 0x99 ]
-ProgramHeaders:
-  - Type:     PT_LOAD
-    VAddr:    0x2000
-    FirstSec: .bar
-    LastSec:  .bar
-  - Type:     PT_LOAD
-    VAddr:    0x1000
-    FirstSec: .foo
-    LastSec:  .foo
 )");
 
   ASSERT_THAT_EXPECTED(ExpectedFile, Succeeded());