[llvm] [Object,ELF] Implement PN_XNUM extension for program headers (PR #162288)
    via llvm-commits 
    llvm-commits at lists.llvm.org
       
    Tue Oct 21 03:09:42 PDT 2025
    
    
  
https://github.com/aokblast updated https://github.com/llvm/llvm-project/pull/162288
>From d2740bcf5c84d4f5d71e4058b25169034ec8f5e5 Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Tue, 7 Oct 2025 21:46:52 +0800
Subject: [PATCH 01/10] [Object, ELF] Implement PN_XNUM extension for program
 headers
In ELF file, there is a possible extended header for those phnum, shnum,
and shstrndx larger than the maximum of 16 bits. This extended header
use section 0 to record these fields in 32 bits.  We implment this
feature so that programs rely on ELFFile::program_headers() can get the
correct number of segments. Also, the consumers don't have to check the
section 0 themselve, insteead, they can use the getPhNum() as an
alternative.
---
 llvm/include/llvm/BinaryFormat/ELF.h |  2 +
 llvm/include/llvm/Object/ELF.h       | 60 +++++++++++++++++++---------
 llvm/include/llvm/Object/ELFTypes.h  |  5 +++
 3 files changed, 48 insertions(+), 19 deletions(-)
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index e619b186dfe3d..136f8cfbde818 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1123,6 +1123,8 @@ struct Elf64_Shdr {
   Elf64_Xword sh_entsize;
 };
 
+enum { PN_XNUM = 0xffff };
+
 // Special section indices.
 enum {
   SHN_UNDEF = 0,          // Undefined, missing, irrelevant, or meaningless
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 59f63eb6b5bb6..3b96c0e2b9d1f 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -278,9 +278,16 @@ class ELFFile {
   std::vector<Elf_Shdr> FakeSections;
   SmallString<0> FakeSectionStrings;
 
+  Elf_Word RealPhNum;
+  Elf_Word RealShNum;
+  Elf_Word RealShStrNdx;
+
   ELFFile(StringRef Object);
 
 public:
+  Elf_Word getPhNum() const { return RealPhNum; }
+  Elf_Word getShNum() const { return RealShNum; }
+  Elf_Word getShStrNdx() const { return RealShStrNdx; }
   const Elf_Ehdr &getHeader() const {
     return *reinterpret_cast<const Elf_Ehdr *>(base());
   }
@@ -379,22 +386,21 @@ class ELFFile {
 
   /// Iterate over program header table.
   Expected<Elf_Phdr_Range> program_headers() const {
-    if (getHeader().e_phnum && getHeader().e_phentsize != sizeof(Elf_Phdr))
+    if (RealPhNum && getHeader().e_phentsize != sizeof(Elf_Phdr))
       return createError("invalid e_phentsize: " +
                          Twine(getHeader().e_phentsize));
 
-    uint64_t HeadersSize =
-        (uint64_t)getHeader().e_phnum * getHeader().e_phentsize;
+    uint64_t HeadersSize = (uint64_t)RealPhNum * getHeader().e_phentsize;
     uint64_t PhOff = getHeader().e_phoff;
     if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
       return createError("program headers are longer than binary of size " +
                          Twine(getBufSize()) + ": e_phoff = 0x" +
                          Twine::utohexstr(getHeader().e_phoff) +
-                         ", e_phnum = " + Twine(getHeader().e_phnum) +
+                         ", e_phnum = " + Twine(RealPhNum) +
                          ", e_phentsize = " + Twine(getHeader().e_phentsize));
 
     auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff);
-    return ArrayRef(Begin, Begin + getHeader().e_phnum);
+    return ArrayRef(Begin, Begin + RealPhNum);
   }
 
   /// Get an iterator over notes in a program header.
@@ -772,18 +778,10 @@ template <class ELFT>
 Expected<StringRef>
 ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
                                      WarningHandler WarnHandler) const {
-  uint32_t Index = getHeader().e_shstrndx;
-  if (Index == ELF::SHN_XINDEX) {
-    // If the section name string table section index is greater than
-    // or equal to SHN_LORESERVE, then the actual index of the section name
-    // string table section is contained in the sh_link field of the section
-    // header at index 0.
-    if (Sections.empty())
-      return createError(
-          "e_shstrndx == SHN_XINDEX, but the section header table is empty");
-
-    Index = Sections[0].sh_link;
-  }
+  uint32_t Index = RealShStrNdx;
+  if (Index == ELF::SHN_XINDEX)
+    return createError(
+        "e_shstrndx == SHN_XINDEX, but the section header table is empty");
 
   // There is no section name string table. Return FakeSectionStrings which
   // is non-empty if we have created fake sections.
@@ -889,7 +887,31 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
   return 0;
 }
 
-template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
+template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
+  const Elf_Ehdr &Header = getHeader();
+  RealPhNum = Header.e_phnum;
+  RealShNum = Header.e_shnum;
+  RealShStrNdx = Header.e_shstrndx;
+  if (!Header.hasPhdrNumExtension())
+    return;
+
+  // An ELF binary may report `hasExtendedHeader` as true but not actually
+  // include an extended header. For example, a core dump can contain 65,535
+  // segments but no sections at all. We defer reporting an error until section
+  // 0 is accessed. Consumers should handle and emit the error themselves when
+  // they attempt to access it.
+  auto SecOrErr = getSection(0);
+  if (!SecOrErr) {
+    consumeError(SecOrErr.takeError());
+    return;
+  }
+  if (RealPhNum == 0xFFFF)
+    RealPhNum = (*SecOrErr)->sh_info;
+  if (RealShNum == ELF::SHN_UNDEF)
+    RealShNum = (*SecOrErr)->sh_size;
+  if (RealShStrNdx == ELF::SHN_XINDEX)
+    RealShStrNdx = (*SecOrErr)->sh_link;
+}
 
 template <class ELFT>
 Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) {
@@ -956,7 +978,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
   const Elf_Shdr *First =
       reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
 
-  uintX_t NumSections = getHeader().e_shnum;
+  uintX_t NumSections = RealShNum;
   if (NumSections == 0)
     NumSections = First->sh_size;
 
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index 5a26e2fc31458..b791f7486fe97 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -529,6 +529,11 @@ struct Elf_Ehdr_Impl {
 
   unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
   unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
+  bool hasPhdrNumExtension() const {
+    return (e_phnum == ELF::PN_XNUM || e_shnum == ELF::SHN_UNDEF ||
+            e_shstrndx == ELF::SHN_XINDEX) &&
+           e_shoff != 0;
+  }
 };
 
 template <endianness Endianness>
>From 6c38a39a7dc9bdf803fb301749fea5066c1c30a3 Mon Sep 17 00:00:00 2001
From: SHENG-YI HONG <aokblast at FreeBSD.org>
Date: Fri, 17 Oct 2025 17:45:39 +0800
Subject: [PATCH 02/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELF.h | 49 +++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 21 deletions(-)
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 3b96c0e2b9d1f..47bcc5dbe9899 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -278,16 +278,26 @@ class ELFFile {
   std::vector<Elf_Shdr> FakeSections;
   SmallString<0> FakeSectionStrings;
 
-  Elf_Word RealPhNum;
-  Elf_Word RealShNum;
-  Elf_Word RealShStrNdx;
+  //
+  // According to the ELF gABI, these three fields can be recorded in section 0
+  // when possible. Therefore, we store this information when it is available.
+  //
+  std::optional<uint32_t> RealPhNum;
+  std::optional<uint32_t> RealShNum;
+  std::optional<uint32_t> RealShStrNdx;
 
   ELFFile(StringRef Object);
 
 public:
-  Elf_Word getPhNum() const { return RealPhNum; }
-  Elf_Word getShNum() const { return RealShNum; }
-  Elf_Word getShStrNdx() const { return RealShStrNdx; }
+  uint32_t getPhNum() const {
+    return RealPhNum ? *RealPhNum : getHeader().e_phnum;
+  }
+  uint32_t getShNum() const {
+    return RealShNum ? *RealShNum : getHeader().e_shnum;
+  }
+  uint32_t getShStrNdx() const {
+    return RealShStrNdx ? *RealShStrNdx : getHeader().e_shstrndx;
+  }
   const Elf_Ehdr &getHeader() const {
     return *reinterpret_cast<const Elf_Ehdr *>(base());
   }
@@ -386,21 +396,21 @@ class ELFFile {
 
   /// Iterate over program header table.
   Expected<Elf_Phdr_Range> program_headers() const {
-    if (RealPhNum && getHeader().e_phentsize != sizeof(Elf_Phdr))
+    if (getPhNum() && getHeader().e_phentsize != sizeof(Elf_Phdr))
       return createError("invalid e_phentsize: " +
                          Twine(getHeader().e_phentsize));
 
-    uint64_t HeadersSize = (uint64_t)RealPhNum * getHeader().e_phentsize;
+    uint64_t HeadersSize = (uint64_t)getPhNum() * getHeader().e_phentsize;
     uint64_t PhOff = getHeader().e_phoff;
     if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
       return createError("program headers are longer than binary of size " +
                          Twine(getBufSize()) + ": e_phoff = 0x" +
                          Twine::utohexstr(getHeader().e_phoff) +
-                         ", e_phnum = " + Twine(RealPhNum) +
+                         ", e_phnum = " + Twine(getPhNum()) +
                          ", e_phentsize = " + Twine(getHeader().e_phentsize));
 
     auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff);
-    return ArrayRef(Begin, Begin + RealPhNum);
+    return ArrayRef(Begin, Begin + getPhNum());
   }
 
   /// Get an iterator over notes in a program header.
@@ -778,11 +788,11 @@ template <class ELFT>
 Expected<StringRef>
 ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
                                      WarningHandler WarnHandler) const {
-  uint32_t Index = RealShStrNdx;
-  if (Index == ELF::SHN_XINDEX)
+  if (getHeader().e_shstrndx == ELF::SHN_XINDEX && !RealShStrNdx)
     return createError(
         "e_shstrndx == SHN_XINDEX, but the section header table is empty");
 
+  uint32_t Index = getShStrNdx();
   // There is no section name string table. Return FakeSectionStrings which
   // is non-empty if we have created fake sections.
   if (!Index)
@@ -889,14 +899,11 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
 
 template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
   const Elf_Ehdr &Header = getHeader();
-  RealPhNum = Header.e_phnum;
-  RealShNum = Header.e_shnum;
-  RealShStrNdx = Header.e_shstrndx;
   if (!Header.hasPhdrNumExtension())
     return;
 
-  // An ELF binary may report `hasExtendedHeader` as true but not actually
-  // include an extended header. For example, a core dump can contain 65,535
+  // An ELF binary may report `hasPhdrNumExtension` as true but not actually
+  // include an section 0. For example, a core dump can contain 65,535
   // segments but no sections at all. We defer reporting an error until section
   // 0 is accessed. Consumers should handle and emit the error themselves when
   // they attempt to access it.
@@ -905,11 +912,11 @@ template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
     consumeError(SecOrErr.takeError());
     return;
   }
-  if (RealPhNum == 0xFFFF)
+  if (Header.e_phnum == 0xFFFF)
     RealPhNum = (*SecOrErr)->sh_info;
-  if (RealShNum == ELF::SHN_UNDEF)
+  if (Header.e_shnum == ELF::SHN_UNDEF)
     RealShNum = (*SecOrErr)->sh_size;
-  if (RealShStrNdx == ELF::SHN_XINDEX)
+  if (Header.e_shstrndx == ELF::SHN_XINDEX)
     RealShStrNdx = (*SecOrErr)->sh_link;
 }
 
@@ -978,7 +985,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
   const Elf_Shdr *First =
       reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
 
-  uintX_t NumSections = RealShNum;
+  uintX_t NumSections = getShNum();
   if (NumSections == 0)
     NumSections = First->sh_size;
 
>From eb602eea2ac559441b32bfd0921cd49fce8896f7 Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Tue, 7 Oct 2025 21:46:52 +0800
Subject: [PATCH 03/10] [Object, ELF] Implement PN_XNUM extension for program
 headers
In ELF file, there is a possible extended header for those phnum, shnum,
and shstrndx larger than the maximum of 16 bits. This extended header
use section 0 to record these fields in 32 bits.  We implment this
feature so that programs rely on ELFFile::program_headers() can get the
correct number of segments. Also, the consumers don't have to check the
section 0 themselve, insteead, they can use the getPhNum() as an
alternative.
---
 llvm/include/llvm/BinaryFormat/ELF.h |  2 +
 llvm/include/llvm/Object/ELF.h       | 60 +++++++++++++++++++---------
 llvm/include/llvm/Object/ELFTypes.h  |  5 +++
 3 files changed, 48 insertions(+), 19 deletions(-)
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 8d0dc64199ebf..812618be0e918 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1125,6 +1125,8 @@ struct Elf64_Shdr {
   Elf64_Xword sh_entsize;
 };
 
+enum { PN_XNUM = 0xffff };
+
 // Special section indices.
 enum {
   SHN_UNDEF = 0,          // Undefined, missing, irrelevant, or meaningless
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 59f63eb6b5bb6..3b96c0e2b9d1f 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -278,9 +278,16 @@ class ELFFile {
   std::vector<Elf_Shdr> FakeSections;
   SmallString<0> FakeSectionStrings;
 
+  Elf_Word RealPhNum;
+  Elf_Word RealShNum;
+  Elf_Word RealShStrNdx;
+
   ELFFile(StringRef Object);
 
 public:
+  Elf_Word getPhNum() const { return RealPhNum; }
+  Elf_Word getShNum() const { return RealShNum; }
+  Elf_Word getShStrNdx() const { return RealShStrNdx; }
   const Elf_Ehdr &getHeader() const {
     return *reinterpret_cast<const Elf_Ehdr *>(base());
   }
@@ -379,22 +386,21 @@ class ELFFile {
 
   /// Iterate over program header table.
   Expected<Elf_Phdr_Range> program_headers() const {
-    if (getHeader().e_phnum && getHeader().e_phentsize != sizeof(Elf_Phdr))
+    if (RealPhNum && getHeader().e_phentsize != sizeof(Elf_Phdr))
       return createError("invalid e_phentsize: " +
                          Twine(getHeader().e_phentsize));
 
-    uint64_t HeadersSize =
-        (uint64_t)getHeader().e_phnum * getHeader().e_phentsize;
+    uint64_t HeadersSize = (uint64_t)RealPhNum * getHeader().e_phentsize;
     uint64_t PhOff = getHeader().e_phoff;
     if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
       return createError("program headers are longer than binary of size " +
                          Twine(getBufSize()) + ": e_phoff = 0x" +
                          Twine::utohexstr(getHeader().e_phoff) +
-                         ", e_phnum = " + Twine(getHeader().e_phnum) +
+                         ", e_phnum = " + Twine(RealPhNum) +
                          ", e_phentsize = " + Twine(getHeader().e_phentsize));
 
     auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff);
-    return ArrayRef(Begin, Begin + getHeader().e_phnum);
+    return ArrayRef(Begin, Begin + RealPhNum);
   }
 
   /// Get an iterator over notes in a program header.
@@ -772,18 +778,10 @@ template <class ELFT>
 Expected<StringRef>
 ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
                                      WarningHandler WarnHandler) const {
-  uint32_t Index = getHeader().e_shstrndx;
-  if (Index == ELF::SHN_XINDEX) {
-    // If the section name string table section index is greater than
-    // or equal to SHN_LORESERVE, then the actual index of the section name
-    // string table section is contained in the sh_link field of the section
-    // header at index 0.
-    if (Sections.empty())
-      return createError(
-          "e_shstrndx == SHN_XINDEX, but the section header table is empty");
-
-    Index = Sections[0].sh_link;
-  }
+  uint32_t Index = RealShStrNdx;
+  if (Index == ELF::SHN_XINDEX)
+    return createError(
+        "e_shstrndx == SHN_XINDEX, but the section header table is empty");
 
   // There is no section name string table. Return FakeSectionStrings which
   // is non-empty if we have created fake sections.
@@ -889,7 +887,31 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
   return 0;
 }
 
-template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
+template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
+  const Elf_Ehdr &Header = getHeader();
+  RealPhNum = Header.e_phnum;
+  RealShNum = Header.e_shnum;
+  RealShStrNdx = Header.e_shstrndx;
+  if (!Header.hasPhdrNumExtension())
+    return;
+
+  // An ELF binary may report `hasExtendedHeader` as true but not actually
+  // include an extended header. For example, a core dump can contain 65,535
+  // segments but no sections at all. We defer reporting an error until section
+  // 0 is accessed. Consumers should handle and emit the error themselves when
+  // they attempt to access it.
+  auto SecOrErr = getSection(0);
+  if (!SecOrErr) {
+    consumeError(SecOrErr.takeError());
+    return;
+  }
+  if (RealPhNum == 0xFFFF)
+    RealPhNum = (*SecOrErr)->sh_info;
+  if (RealShNum == ELF::SHN_UNDEF)
+    RealShNum = (*SecOrErr)->sh_size;
+  if (RealShStrNdx == ELF::SHN_XINDEX)
+    RealShStrNdx = (*SecOrErr)->sh_link;
+}
 
 template <class ELFT>
 Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) {
@@ -956,7 +978,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
   const Elf_Shdr *First =
       reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
 
-  uintX_t NumSections = getHeader().e_shnum;
+  uintX_t NumSections = RealShNum;
   if (NumSections == 0)
     NumSections = First->sh_size;
 
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index e9a417d3d4fb3..77a68f95a46ce 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -529,6 +529,11 @@ struct Elf_Ehdr_Impl {
 
   unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
   unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
+  bool hasPhdrNumExtension() const {
+    return (e_phnum == ELF::PN_XNUM || e_shnum == ELF::SHN_UNDEF ||
+            e_shstrndx == ELF::SHN_XINDEX) &&
+           e_shoff != 0;
+  }
 };
 
 template <endianness Endianness>
>From c107bc3d0dc75eea0b9b2ef6a9dd3a41adaec3c2 Mon Sep 17 00:00:00 2001
From: SHENG-YI HONG <aokblast at FreeBSD.org>
Date: Fri, 17 Oct 2025 17:45:39 +0800
Subject: [PATCH 04/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELF.h | 49 +++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 21 deletions(-)
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 3b96c0e2b9d1f..47bcc5dbe9899 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -278,16 +278,26 @@ class ELFFile {
   std::vector<Elf_Shdr> FakeSections;
   SmallString<0> FakeSectionStrings;
 
-  Elf_Word RealPhNum;
-  Elf_Word RealShNum;
-  Elf_Word RealShStrNdx;
+  //
+  // According to the ELF gABI, these three fields can be recorded in section 0
+  // when possible. Therefore, we store this information when it is available.
+  //
+  std::optional<uint32_t> RealPhNum;
+  std::optional<uint32_t> RealShNum;
+  std::optional<uint32_t> RealShStrNdx;
 
   ELFFile(StringRef Object);
 
 public:
-  Elf_Word getPhNum() const { return RealPhNum; }
-  Elf_Word getShNum() const { return RealShNum; }
-  Elf_Word getShStrNdx() const { return RealShStrNdx; }
+  uint32_t getPhNum() const {
+    return RealPhNum ? *RealPhNum : getHeader().e_phnum;
+  }
+  uint32_t getShNum() const {
+    return RealShNum ? *RealShNum : getHeader().e_shnum;
+  }
+  uint32_t getShStrNdx() const {
+    return RealShStrNdx ? *RealShStrNdx : getHeader().e_shstrndx;
+  }
   const Elf_Ehdr &getHeader() const {
     return *reinterpret_cast<const Elf_Ehdr *>(base());
   }
@@ -386,21 +396,21 @@ class ELFFile {
 
   /// Iterate over program header table.
   Expected<Elf_Phdr_Range> program_headers() const {
-    if (RealPhNum && getHeader().e_phentsize != sizeof(Elf_Phdr))
+    if (getPhNum() && getHeader().e_phentsize != sizeof(Elf_Phdr))
       return createError("invalid e_phentsize: " +
                          Twine(getHeader().e_phentsize));
 
-    uint64_t HeadersSize = (uint64_t)RealPhNum * getHeader().e_phentsize;
+    uint64_t HeadersSize = (uint64_t)getPhNum() * getHeader().e_phentsize;
     uint64_t PhOff = getHeader().e_phoff;
     if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
       return createError("program headers are longer than binary of size " +
                          Twine(getBufSize()) + ": e_phoff = 0x" +
                          Twine::utohexstr(getHeader().e_phoff) +
-                         ", e_phnum = " + Twine(RealPhNum) +
+                         ", e_phnum = " + Twine(getPhNum()) +
                          ", e_phentsize = " + Twine(getHeader().e_phentsize));
 
     auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff);
-    return ArrayRef(Begin, Begin + RealPhNum);
+    return ArrayRef(Begin, Begin + getPhNum());
   }
 
   /// Get an iterator over notes in a program header.
@@ -778,11 +788,11 @@ template <class ELFT>
 Expected<StringRef>
 ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
                                      WarningHandler WarnHandler) const {
-  uint32_t Index = RealShStrNdx;
-  if (Index == ELF::SHN_XINDEX)
+  if (getHeader().e_shstrndx == ELF::SHN_XINDEX && !RealShStrNdx)
     return createError(
         "e_shstrndx == SHN_XINDEX, but the section header table is empty");
 
+  uint32_t Index = getShStrNdx();
   // There is no section name string table. Return FakeSectionStrings which
   // is non-empty if we have created fake sections.
   if (!Index)
@@ -889,14 +899,11 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
 
 template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
   const Elf_Ehdr &Header = getHeader();
-  RealPhNum = Header.e_phnum;
-  RealShNum = Header.e_shnum;
-  RealShStrNdx = Header.e_shstrndx;
   if (!Header.hasPhdrNumExtension())
     return;
 
-  // An ELF binary may report `hasExtendedHeader` as true but not actually
-  // include an extended header. For example, a core dump can contain 65,535
+  // An ELF binary may report `hasPhdrNumExtension` as true but not actually
+  // include an section 0. For example, a core dump can contain 65,535
   // segments but no sections at all. We defer reporting an error until section
   // 0 is accessed. Consumers should handle and emit the error themselves when
   // they attempt to access it.
@@ -905,11 +912,11 @@ template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
     consumeError(SecOrErr.takeError());
     return;
   }
-  if (RealPhNum == 0xFFFF)
+  if (Header.e_phnum == 0xFFFF)
     RealPhNum = (*SecOrErr)->sh_info;
-  if (RealShNum == ELF::SHN_UNDEF)
+  if (Header.e_shnum == ELF::SHN_UNDEF)
     RealShNum = (*SecOrErr)->sh_size;
-  if (RealShStrNdx == ELF::SHN_XINDEX)
+  if (Header.e_shstrndx == ELF::SHN_XINDEX)
     RealShStrNdx = (*SecOrErr)->sh_link;
 }
 
@@ -978,7 +985,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
   const Elf_Shdr *First =
       reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
 
-  uintX_t NumSections = RealShNum;
+  uintX_t NumSections = getShNum();
   if (NumSections == 0)
     NumSections = First->sh_size;
 
>From b13b26d83141a0c2a4393c77982d5a03aa0853cb Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Sat, 18 Oct 2025 03:39:24 +0800
Subject: [PATCH 05/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELF.h      | 96 ++++++++++++++++++++---------
 llvm/include/llvm/Object/ELFTypes.h |  5 --
 2 files changed, 66 insertions(+), 35 deletions(-)
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 47bcc5dbe9899..08b294a48d7ab 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -288,16 +288,31 @@ class ELFFile {
 
   ELFFile(StringRef Object);
 
+  Error readShdrZero();
+
 public:
-  uint32_t getPhNum() const {
-    return RealPhNum ? *RealPhNum : getHeader().e_phnum;
+  Expected<uint32_t> getPhNum() const {
+    if (!RealPhNum) {
+      if (Error E = readShdrZero())
+        return std::move(E);
+    }
+    return *RealPhNum;
   }
-  uint32_t getShNum() const {
-    return RealShNum ? *RealShNum : getHeader().e_shnum;
+  Expected<uint32_t> getShNum() const {
+    if (!RealShNum) {
+      if (Error E = readShdrZero())
+        return std::move(E);
+    }
+    return *RealShNum;
   }
-  uint32_t getShStrNdx() const {
-    return RealShStrNdx ? *RealShStrNdx : getHeader().e_shstrndx;
+  Expected<uint32_t> getShStrNdx() const {
+    if (!RealShStrNdx) {
+      if (Error E = readShdrZero())
+        return std::move(E);
+    }
+    return *RealShStrNdx;
   }
+
   const Elf_Ehdr &getHeader() const {
     return *reinterpret_cast<const Elf_Ehdr *>(base());
   }
@@ -396,21 +411,26 @@ class ELFFile {
 
   /// Iterate over program header table.
   Expected<Elf_Phdr_Range> program_headers() const {
-    if (getPhNum() && getHeader().e_phentsize != sizeof(Elf_Phdr))
+    uint32_t NumPh;
+    if (Expected<uint32_t> PhNumOrErr = getPhNum())
+      NumPh = *PhNumOrErr;
+    else
+      return PhNumOrErr.takeError();
+    if (NumPh && getHeader().e_phentsize != sizeof(Elf_Phdr))
       return createError("invalid e_phentsize: " +
                          Twine(getHeader().e_phentsize));
 
-    uint64_t HeadersSize = (uint64_t)getPhNum() * getHeader().e_phentsize;
+    uint64_t HeadersSize = (uint64_t)NumPh * getHeader().e_phentsize;
     uint64_t PhOff = getHeader().e_phoff;
     if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
       return createError("program headers are longer than binary of size " +
                          Twine(getBufSize()) + ": e_phoff = 0x" +
                          Twine::utohexstr(getHeader().e_phoff) +
-                         ", e_phnum = " + Twine(getPhNum()) +
+                         ", e_phnum = " + Twine(NumPh) +
                          ", e_phentsize = " + Twine(getHeader().e_phentsize));
 
     auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff);
-    return ArrayRef(Begin, Begin + getPhNum());
+    return ArrayRef(Begin, Begin + NumPh);
   }
 
   /// Get an iterator over notes in a program header.
@@ -792,7 +812,12 @@ ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
     return createError(
         "e_shstrndx == SHN_XINDEX, but the section header table is empty");
 
-  uint32_t Index = getShStrNdx();
+  uint32_t Index;
+  if (Expected<uint32_t> IndexOrErr = getShStrNdx())
+    Index = *IndexOrErr;
+  else
+    return IndexOrErr.takeError();
+
   // There is no section name string table. Return FakeSectionStrings which
   // is non-empty if we have created fake sections.
   if (!Index)
@@ -897,27 +922,34 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
   return 0;
 }
 
-template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
+template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
+
+template <class ELFT> Error ELFFile<ELFT>::readShdrZero() {
   const Elf_Ehdr &Header = getHeader();
-  if (!Header.hasPhdrNumExtension())
-    return;
 
-  // An ELF binary may report `hasPhdrNumExtension` as true but not actually
-  // include an section 0. For example, a core dump can contain 65,535
-  // segments but no sections at all. We defer reporting an error until section
-  // 0 is accessed. Consumers should handle and emit the error themselves when
-  // they attempt to access it.
-  auto SecOrErr = getSection(0);
-  if (!SecOrErr) {
-    consumeError(SecOrErr.takeError());
-    return;
+  if ((Header.e_phnum == ELF::PN_XNUM || Header.e_shnum == 0 ||
+       Header.e_shstrndx == ELF::SHN_XINDEX) &&
+      Header.e_shoff != 0) {
+    //
+    // Pretend we have section 0 or sections() would call getShNum and thus
+    // become an infinite recursion
+    //
+    RealShNum = 0;
+    auto SecOrErr = getSection(0);
+    if (!SecOrErr) {
+      RealShNum = std::nullopt;
+      return SecOrErr.takeError();
+    }
+    RealPhNum =
+        Header.e_phnum == ELF::PN_XNUM ? (*SecOrErr)->sh_info : Header.e_phnum;
+    RealShNum = Header.e_shnum == 0 ? (*SecOrErr)->sh_size : Header.e_shnum;
+    RealShStrNdx = Header.e_shstrndx == ELF::SHN_XINDEX ? (*SecOrErr)->sh_link
+                                                        : Header.e_shstrndx;
+  } else {
+    RealPhNum = Header.e_phnum;
+    RealShNum = Header.e_shnum;
+    RealShStrNdx = Header.e_shstrndx;
   }
-  if (Header.e_phnum == 0xFFFF)
-    RealPhNum = (*SecOrErr)->sh_info;
-  if (Header.e_shnum == ELF::SHN_UNDEF)
-    RealShNum = (*SecOrErr)->sh_size;
-  if (Header.e_shstrndx == ELF::SHN_XINDEX)
-    RealShStrNdx = (*SecOrErr)->sh_link;
 }
 
 template <class ELFT>
@@ -985,7 +1017,11 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
   const Elf_Shdr *First =
       reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
 
-  uintX_t NumSections = getShNum();
+  uintX_t NumSections = 0;
+  if (Expected<uint32_t> ShNumOrErr = getShNum())
+    NumSections = *ShNumOrErr;
+  else
+    return ShNumOrErr.takeError();
   if (NumSections == 0)
     NumSections = First->sh_size;
 
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index 77a68f95a46ce..e9a417d3d4fb3 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -529,11 +529,6 @@ struct Elf_Ehdr_Impl {
 
   unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
   unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
-  bool hasPhdrNumExtension() const {
-    return (e_phnum == ELF::PN_XNUM || e_shnum == ELF::SHN_UNDEF ||
-            e_shstrndx == ELF::SHN_XINDEX) &&
-           e_shoff != 0;
-  }
 };
 
 template <endianness Endianness>
>From ab6377043e8a05cd15bf5b1bc7caac9f6baf44b3 Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Mon, 20 Oct 2025 23:11:25 +0800
Subject: [PATCH 06/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELF.h      | 5 +----
 llvm/include/llvm/Object/ELFTypes.h | 5 +++++
 2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 08b294a48d7ab..5ac30e0f8e19e 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -278,10 +278,8 @@ class ELFFile {
   std::vector<Elf_Shdr> FakeSections;
   SmallString<0> FakeSectionStrings;
 
-  //
   // According to the ELF gABI, these three fields can be recorded in section 0
   // when possible. Therefore, we store this information when it is available.
-  //
   std::optional<uint32_t> RealPhNum;
   std::optional<uint32_t> RealShNum;
   std::optional<uint32_t> RealShStrNdx;
@@ -930,10 +928,9 @@ template <class ELFT> Error ELFFile<ELFT>::readShdrZero() {
   if ((Header.e_phnum == ELF::PN_XNUM || Header.e_shnum == 0 ||
        Header.e_shstrndx == ELF::SHN_XINDEX) &&
       Header.e_shoff != 0) {
-    //
+
     // Pretend we have section 0 or sections() would call getShNum and thus
     // become an infinite recursion
-    //
     RealShNum = 0;
     auto SecOrErr = getSection(0);
     if (!SecOrErr) {
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index e9a417d3d4fb3..77a68f95a46ce 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -529,6 +529,11 @@ struct Elf_Ehdr_Impl {
 
   unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
   unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
+  bool hasPhdrNumExtension() const {
+    return (e_phnum == ELF::PN_XNUM || e_shnum == ELF::SHN_UNDEF ||
+            e_shstrndx == ELF::SHN_XINDEX) &&
+           e_shoff != 0;
+  }
 };
 
 template <endianness Endianness>
>From 8522aa99f51f6880b0a8727037095061e8f7636a Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Mon, 20 Oct 2025 23:18:41 +0800
Subject: [PATCH 07/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELFTypes.h | 5 -----
 1 file changed, 5 deletions(-)
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index 77a68f95a46ce..e9a417d3d4fb3 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -529,11 +529,6 @@ struct Elf_Ehdr_Impl {
 
   unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
   unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
-  bool hasPhdrNumExtension() const {
-    return (e_phnum == ELF::PN_XNUM || e_shnum == ELF::SHN_UNDEF ||
-            e_shstrndx == ELF::SHN_XINDEX) &&
-           e_shoff != 0;
-  }
 };
 
 template <endianness Endianness>
>From 0c7c1d42ffea8b3d75c3aacbb3eba5be94f65a40 Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Tue, 21 Oct 2025 00:06:08 +0800
Subject: [PATCH 08/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELF.h | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 5ac30e0f8e19e..fc6cfcfe36a07 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -291,21 +291,21 @@ class ELFFile {
 public:
   Expected<uint32_t> getPhNum() const {
     if (!RealPhNum) {
-      if (Error E = readShdrZero())
+      if (Error E = const_cast<ELFFile<ELFT> *>(this)->readShdrZero())
         return std::move(E);
     }
     return *RealPhNum;
   }
   Expected<uint32_t> getShNum() const {
     if (!RealShNum) {
-      if (Error E = readShdrZero())
+      if (Error E = const_cast<ELFFile<ELFT> *>(this)->readShdrZero())
         return std::move(E);
     }
     return *RealShNum;
   }
   Expected<uint32_t> getShStrNdx() const {
     if (!RealShStrNdx) {
-      if (Error E = readShdrZero())
+      if (Error E = const_cast<ELFFile<ELFT> *>(this)->readShdrZero())
         return std::move(E);
     }
     return *RealShStrNdx;
@@ -947,6 +947,8 @@ template <class ELFT> Error ELFFile<ELFT>::readShdrZero() {
     RealShNum = Header.e_shnum;
     RealShStrNdx = Header.e_shstrndx;
   }
+
+  return Error::success();
 }
 
 template <class ELFT>
>From 389b52c070569f9b6c142a95d2320a0ac7eb6c3e Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Tue, 21 Oct 2025 00:49:06 +0800
Subject: [PATCH 09/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELF.h | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index fc6cfcfe36a07..772a20bb52f5d 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -806,9 +806,12 @@ template <class ELFT>
 Expected<StringRef>
 ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
                                      WarningHandler WarnHandler) const {
-  if (getHeader().e_shstrndx == ELF::SHN_XINDEX && !RealShStrNdx)
+  Expected<uint32_t> ShStrNdxOrErr = getShStrNdx();
+  if (!ShStrNdxOrErr || (*ShStrNdxOrErr == ELF::SHN_XINDEX && RealShNum == 0)) {
+    consumeError(ShStrNdxOrErr.takeError());
     return createError(
         "e_shstrndx == SHN_XINDEX, but the section header table is empty");
+  }
 
   uint32_t Index;
   if (Expected<uint32_t> IndexOrErr = getShStrNdx())
@@ -932,15 +935,29 @@ template <class ELFT> Error ELFFile<ELFT>::readShdrZero() {
     // Pretend we have section 0 or sections() would call getShNum and thus
     // become an infinite recursion
     RealShNum = 0;
-    auto SecOrErr = getSection(0);
-    if (!SecOrErr) {
+    auto SecsOrErr = sections();
+    if (!SecsOrErr) {
       RealShNum = std::nullopt;
-      return SecOrErr.takeError();
+      return SecsOrErr.takeError();
     }
+
+    // We can really have 0 number of seciton
+    if ((*SecsOrErr).size() == 0) {
+      if (Header.e_phnum == ELF::PN_XNUM ||
+          Header.e_shstrndx == ELF::SHN_XINDEX) {
+        return createError("Unable to find Section 0");
+      }
+      RealShNum = 0;
+      RealPhNum = Header.e_phnum;
+      RealShStrNdx = Header.e_shstrndx;
+      return Error::success();
+    }
+
+    auto &Section = (*SecsOrErr)[0];
     RealPhNum =
-        Header.e_phnum == ELF::PN_XNUM ? (*SecOrErr)->sh_info : Header.e_phnum;
-    RealShNum = Header.e_shnum == 0 ? (*SecOrErr)->sh_size : Header.e_shnum;
-    RealShStrNdx = Header.e_shstrndx == ELF::SHN_XINDEX ? (*SecOrErr)->sh_link
+        Header.e_phnum == ELF::PN_XNUM ? Section.sh_info : Header.e_phnum;
+    RealShNum = Header.e_shnum == 0 ? Section.sh_size : Header.e_shnum;
+    RealShStrNdx = Header.e_shstrndx == ELF::SHN_XINDEX ? Section.sh_link
                                                         : Header.e_shstrndx;
   } else {
     RealPhNum = Header.e_phnum;
>From feeb81a05d3ee32f95379efe7f1572a9ec7e05ec Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Tue, 21 Oct 2025 17:49:13 +0800
Subject: [PATCH 10/10] fixup! [Object, ELF] Implement PN_XNUM extension for
 program headers
---
 llvm/include/llvm/Object/ELF.h | 53 +++++++++++++---------------------
 1 file changed, 20 insertions(+), 33 deletions(-)
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 772a20bb52f5d..3cee069cabbdb 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -278,10 +278,14 @@ class ELFFile {
   std::vector<Elf_Shdr> FakeSections;
   SmallString<0> FakeSectionStrings;
 
-  // According to the ELF gABI, these three fields can be recorded in section 0
-  // when possible. Therefore, we store this information when it is available.
+  // When the number of program headers is >= 0xffff, the actual number is
+  // contained in the sh_info field of the section header at index 0.
   std::optional<uint32_t> RealPhNum;
-  std::optional<uint32_t> RealShNum;
+  // When the number of section headers is >= 0xff00, the actual number is
+  // contained in the sh_size field of the section header at index 0.
+  std::optional<uint64_t> RealShNum;
+  // When the index of str section is >= 0xff00, the actual number is
+  // contained in the sh_link field of the section header at index 0.
   std::optional<uint32_t> RealShStrNdx;
 
   ELFFile(StringRef Object);
@@ -296,7 +300,7 @@ class ELFFile {
     }
     return *RealPhNum;
   }
-  Expected<uint32_t> getShNum() const {
+  Expected<uint64_t> getShNum() const {
     if (!RealShNum) {
       if (Error E = const_cast<ELFFile<ELFT> *>(this)->readShdrZero())
         return std::move(E);
@@ -813,12 +817,7 @@ ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
         "e_shstrndx == SHN_XINDEX, but the section header table is empty");
   }
 
-  uint32_t Index;
-  if (Expected<uint32_t> IndexOrErr = getShStrNdx())
-    Index = *IndexOrErr;
-  else
-    return IndexOrErr.takeError();
-
+  uint32_t Index = *ShStrNdxOrErr;
   // There is no section name string table. Return FakeSectionStrings which
   // is non-empty if we have created fake sections.
   if (!Index)
@@ -934,30 +933,20 @@ template <class ELFT> Error ELFFile<ELFT>::readShdrZero() {
 
     // Pretend we have section 0 or sections() would call getShNum and thus
     // become an infinite recursion
-    RealShNum = 0;
-    auto SecsOrErr = sections();
-    if (!SecsOrErr) {
+    if (Header.e_shnum == 0)
+      RealShNum = 1;
+    else
+      RealShNum = Header.e_shnum;
+    auto SecOrErr = getSection(0);
+    if (!SecOrErr) {
       RealShNum = std::nullopt;
-      return SecsOrErr.takeError();
-    }
-
-    // We can really have 0 number of seciton
-    if ((*SecsOrErr).size() == 0) {
-      if (Header.e_phnum == ELF::PN_XNUM ||
-          Header.e_shstrndx == ELF::SHN_XINDEX) {
-        return createError("Unable to find Section 0");
-      }
-      RealShNum = 0;
-      RealPhNum = Header.e_phnum;
-      RealShStrNdx = Header.e_shstrndx;
-      return Error::success();
+      return SecOrErr.takeError();
     }
 
-    auto &Section = (*SecsOrErr)[0];
     RealPhNum =
-        Header.e_phnum == ELF::PN_XNUM ? Section.sh_info : Header.e_phnum;
-    RealShNum = Header.e_shnum == 0 ? Section.sh_size : Header.e_shnum;
-    RealShStrNdx = Header.e_shstrndx == ELF::SHN_XINDEX ? Section.sh_link
+        Header.e_phnum == ELF::PN_XNUM ? (*SecOrErr)->sh_info : Header.e_phnum;
+    RealShNum = Header.e_shnum == 0 ? (*SecOrErr)->sh_size : Header.e_shnum;
+    RealShStrNdx = Header.e_shstrndx == ELF::SHN_XINDEX ? (*SecOrErr)->sh_link
                                                         : Header.e_shstrndx;
   } else {
     RealPhNum = Header.e_phnum;
@@ -1034,12 +1023,10 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
       reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
 
   uintX_t NumSections = 0;
-  if (Expected<uint32_t> ShNumOrErr = getShNum())
+  if (Expected<uint64_t> ShNumOrErr = getShNum())
     NumSections = *ShNumOrErr;
   else
     return ShNumOrErr.takeError();
-  if (NumSections == 0)
-    NumSections = First->sh_size;
 
   if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
     return createError("invalid number of sections specified in the NULL "
    
    
More information about the llvm-commits
mailing list