Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 48 additions & 19 deletions llvm/include/llvm/Object/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,26 @@ class ELFFile {
std::vector<Elf_Shdr> FakeSections;
SmallString<0> FakeSectionStrings;

//
// According to the ELF gABI, these three fields can be recorded in section 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the first // and last // lines. Suggested a separate comment for each variable

// When the number of program headers is >= 0xffff, the actual number is contained in the ... field of the section header at index 0.
std::optional<uint32_t> RealPhNum;
// When the number of section headers is >= 0xff00, the actual number is contained in the sh_size field ...
std::optional<uint32_t> RealShNum;
// ...

// 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:
uint32_t getPhNum() const {
return RealPhNum ? *RealPhNum : getHeader().e_phnum;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: new lines between functions, please.

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());
}
Expand Down Expand Up @@ -379,22 +396,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 (getPhNum() && 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)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(getHeader().e_phnum) +
", e_phnum = " + Twine(getPhNum()) +
", 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 + getPhNum());
}

/// Get an iterator over notes in a program header.
Expand Down Expand Up @@ -772,19 +788,11 @@ 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;
}
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)
Expand Down Expand Up @@ -889,7 +897,28 @@ 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();
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 == 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>
Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) {
Expand Down Expand Up @@ -956,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 = getHeader().e_shnum;
uintX_t NumSections = getShNum();
if (NumSections == 0)
NumSections = First->sh_size;

Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/Object/ELFTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Loading