@@ -278,9 +278,16 @@ class ELFFile {
278278 std::vector<Elf_Shdr> FakeSections;
279279 SmallString<0 > FakeSectionStrings;
280280
281+ Elf_Word RealPhNum;
282+ Elf_Word RealShNum;
283+ Elf_Word RealShStrNdx;
284+
281285 ELFFile (StringRef Object);
282286
283287public:
288+ Elf_Word getPhNum () const { return RealPhNum; }
289+ Elf_Word getShNum () const { return RealShNum; }
290+ Elf_Word getShStrNdx () const { return RealShStrNdx; }
284291 const Elf_Ehdr &getHeader () const {
285292 return *reinterpret_cast <const Elf_Ehdr *>(base ());
286293 }
@@ -379,22 +386,21 @@ class ELFFile {
379386
380387 // / Iterate over program header table.
381388 Expected<Elf_Phdr_Range> program_headers () const {
382- if (getHeader (). e_phnum && getHeader ().e_phentsize != sizeof (Elf_Phdr))
389+ if (RealPhNum && getHeader ().e_phentsize != sizeof (Elf_Phdr))
383390 return createError (" invalid e_phentsize: " +
384391 Twine (getHeader ().e_phentsize ));
385392
386- uint64_t HeadersSize =
387- (uint64_t )getHeader ().e_phnum * getHeader ().e_phentsize ;
393+ uint64_t HeadersSize = (uint64_t )RealPhNum * getHeader ().e_phentsize ;
388394 uint64_t PhOff = getHeader ().e_phoff ;
389395 if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize ())
390396 return createError (" program headers are longer than binary of size " +
391397 Twine (getBufSize ()) + " : e_phoff = 0x" +
392398 Twine::utohexstr (getHeader ().e_phoff ) +
393- " , e_phnum = " + Twine (getHeader (). e_phnum ) +
399+ " , e_phnum = " + Twine (RealPhNum ) +
394400 " , e_phentsize = " + Twine (getHeader ().e_phentsize ));
395401
396402 auto *Begin = reinterpret_cast <const Elf_Phdr *>(base () + PhOff);
397- return ArrayRef (Begin, Begin + getHeader (). e_phnum );
403+ return ArrayRef (Begin, Begin + RealPhNum );
398404 }
399405
400406 // / Get an iterator over notes in a program header.
@@ -772,18 +778,10 @@ template <class ELFT>
772778Expected<StringRef>
773779ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
774780 WarningHandler WarnHandler) const {
775- uint32_t Index = getHeader ().e_shstrndx ;
776- if (Index == ELF::SHN_XINDEX) {
777- // If the section name string table section index is greater than
778- // or equal to SHN_LORESERVE, then the actual index of the section name
779- // string table section is contained in the sh_link field of the section
780- // header at index 0.
781- if (Sections.empty ())
782- return createError (
783- " e_shstrndx == SHN_XINDEX, but the section header table is empty" );
784-
785- Index = Sections[0 ].sh_link ;
786- }
781+ uint32_t Index = RealShStrNdx;
782+ if (Index == ELF::SHN_XINDEX)
783+ return createError (
784+ " e_shstrndx == SHN_XINDEX, but the section header table is empty" );
787785
788786 // There is no section name string table. Return FakeSectionStrings which
789787 // is non-empty if we have created fake sections.
@@ -889,7 +887,31 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
889887 return 0 ;
890888}
891889
892- template <class ELFT > ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {}
890+ template <class ELFT > ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
891+ const Elf_Ehdr &Header = getHeader ();
892+ RealPhNum = Header.e_phnum ;
893+ RealShNum = Header.e_shnum ;
894+ RealShStrNdx = Header.e_shstrndx ;
895+ if (!Header.hasPhdrNumExtension ())
896+ return ;
897+
898+ // An ELF binary may report `hasExtendedHeader` as true but not actually
899+ // include an extended header. For example, a core dump can contain 65,535
900+ // segments but no sections at all. We defer reporting an error until section
901+ // 0 is accessed. Consumers should handle and emit the error themselves when
902+ // they attempt to access it.
903+ auto SecOrErr = getSection (0 );
904+ if (!SecOrErr) {
905+ consumeError (SecOrErr.takeError ());
906+ return ;
907+ }
908+ if (RealPhNum == 0xFFFF )
909+ RealPhNum = (*SecOrErr)->sh_info ;
910+ if (RealShNum == ELF::SHN_UNDEF)
911+ RealShNum = (*SecOrErr)->sh_size ;
912+ if (RealShStrNdx == ELF::SHN_XINDEX)
913+ RealShStrNdx = (*SecOrErr)->sh_link ;
914+ }
893915
894916template <class ELFT >
895917Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) {
@@ -956,7 +978,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
956978 const Elf_Shdr *First =
957979 reinterpret_cast <const Elf_Shdr *>(base () + SectionTableOffset);
958980
959- uintX_t NumSections = getHeader (). e_shnum ;
981+ uintX_t NumSections = RealShNum ;
960982 if (NumSections == 0 )
961983 NumSections = First->sh_size ;
962984
0 commit comments