Skip to content

Commit 6c38a39

Browse files
committed
fixup! [Object, ELF] Implement PN_XNUM extension for program headers
1 parent d2740bc commit 6c38a39

File tree

1 file changed

+28
-21
lines changed
  • llvm/include/llvm/Object

1 file changed

+28
-21
lines changed

llvm/include/llvm/Object/ELF.h

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -278,16 +278,26 @@ 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;
281+
//
282+
// According to the ELF gABI, these three fields can be recorded in section 0
283+
// when possible. Therefore, we store this information when it is available.
284+
//
285+
std::optional<uint32_t> RealPhNum;
286+
std::optional<uint32_t> RealShNum;
287+
std::optional<uint32_t> RealShStrNdx;
284288

285289
ELFFile(StringRef Object);
286290

287291
public:
288-
Elf_Word getPhNum() const { return RealPhNum; }
289-
Elf_Word getShNum() const { return RealShNum; }
290-
Elf_Word getShStrNdx() const { return RealShStrNdx; }
292+
uint32_t getPhNum() const {
293+
return RealPhNum ? *RealPhNum : getHeader().e_phnum;
294+
}
295+
uint32_t getShNum() const {
296+
return RealShNum ? *RealShNum : getHeader().e_shnum;
297+
}
298+
uint32_t getShStrNdx() const {
299+
return RealShStrNdx ? *RealShStrNdx : getHeader().e_shstrndx;
300+
}
291301
const Elf_Ehdr &getHeader() const {
292302
return *reinterpret_cast<const Elf_Ehdr *>(base());
293303
}
@@ -386,21 +396,21 @@ class ELFFile {
386396

387397
/// Iterate over program header table.
388398
Expected<Elf_Phdr_Range> program_headers() const {
389-
if (RealPhNum && getHeader().e_phentsize != sizeof(Elf_Phdr))
399+
if (getPhNum() && getHeader().e_phentsize != sizeof(Elf_Phdr))
390400
return createError("invalid e_phentsize: " +
391401
Twine(getHeader().e_phentsize));
392402

393-
uint64_t HeadersSize = (uint64_t)RealPhNum * getHeader().e_phentsize;
403+
uint64_t HeadersSize = (uint64_t)getPhNum() * getHeader().e_phentsize;
394404
uint64_t PhOff = getHeader().e_phoff;
395405
if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
396406
return createError("program headers are longer than binary of size " +
397407
Twine(getBufSize()) + ": e_phoff = 0x" +
398408
Twine::utohexstr(getHeader().e_phoff) +
399-
", e_phnum = " + Twine(RealPhNum) +
409+
", e_phnum = " + Twine(getPhNum()) +
400410
", e_phentsize = " + Twine(getHeader().e_phentsize));
401411

402412
auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff);
403-
return ArrayRef(Begin, Begin + RealPhNum);
413+
return ArrayRef(Begin, Begin + getPhNum());
404414
}
405415

406416
/// Get an iterator over notes in a program header.
@@ -778,11 +788,11 @@ template <class ELFT>
778788
Expected<StringRef>
779789
ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections,
780790
WarningHandler WarnHandler) const {
781-
uint32_t Index = RealShStrNdx;
782-
if (Index == ELF::SHN_XINDEX)
791+
if (getHeader().e_shstrndx == ELF::SHN_XINDEX && !RealShStrNdx)
783792
return createError(
784793
"e_shstrndx == SHN_XINDEX, but the section header table is empty");
785794

795+
uint32_t Index = getShStrNdx();
786796
// There is no section name string table. Return FakeSectionStrings which
787797
// is non-empty if we have created fake sections.
788798
if (!Index)
@@ -889,14 +899,11 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const {
889899

890900
template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
891901
const Elf_Ehdr &Header = getHeader();
892-
RealPhNum = Header.e_phnum;
893-
RealShNum = Header.e_shnum;
894-
RealShStrNdx = Header.e_shstrndx;
895902
if (!Header.hasPhdrNumExtension())
896903
return;
897904

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
905+
// An ELF binary may report `hasPhdrNumExtension` as true but not actually
906+
// include an section 0. For example, a core dump can contain 65,535
900907
// segments but no sections at all. We defer reporting an error until section
901908
// 0 is accessed. Consumers should handle and emit the error themselves when
902909
// they attempt to access it.
@@ -905,11 +912,11 @@ template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
905912
consumeError(SecOrErr.takeError());
906913
return;
907914
}
908-
if (RealPhNum == 0xFFFF)
915+
if (Header.e_phnum == 0xFFFF)
909916
RealPhNum = (*SecOrErr)->sh_info;
910-
if (RealShNum == ELF::SHN_UNDEF)
917+
if (Header.e_shnum == ELF::SHN_UNDEF)
911918
RealShNum = (*SecOrErr)->sh_size;
912-
if (RealShStrNdx == ELF::SHN_XINDEX)
919+
if (Header.e_shstrndx == ELF::SHN_XINDEX)
913920
RealShStrNdx = (*SecOrErr)->sh_link;
914921
}
915922

@@ -978,7 +985,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
978985
const Elf_Shdr *First =
979986
reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);
980987

981-
uintX_t NumSections = RealShNum;
988+
uintX_t NumSections = getShNum();
982989
if (NumSections == 0)
983990
NumSections = First->sh_size;
984991

0 commit comments

Comments
 (0)