-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[Object,ELF] Implement PN_XNUM extension for program headers #162288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 12 commits
d2740bc
6c38a39
eb602ee
c107bc3
b13b26d
ab63770
322cbea
8522aa9
e58255a
0c7c1d4
389b52c
feeb81a
a4c05f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -278,9 +278,43 @@ class ELFFile { | |||||
std::vector<Elf_Shdr> FakeSections; | ||||||
SmallString<0> FakeSectionStrings; | ||||||
|
||||||
// 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; | ||||||
// 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); | ||||||
|
||||||
Error readShdrZero(); | ||||||
|
||||||
public: | ||||||
Expected<uint32_t> getPhNum() const { | ||||||
if (!RealPhNum) { | ||||||
if (Error E = const_cast<ELFFile<ELFT> *>(this)->readShdrZero()) | ||||||
return std::move(E); | ||||||
} | ||||||
return *RealPhNum; | ||||||
} | ||||||
Expected<uint64_t> getShNum() const { | ||||||
if (!RealShNum) { | ||||||
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 = const_cast<ELFFile<ELFT> *>(this)->readShdrZero()) | ||||||
return std::move(E); | ||||||
} | ||||||
return *RealShStrNdx; | ||||||
} | ||||||
|
||||||
const Elf_Ehdr &getHeader() const { | ||||||
return *reinterpret_cast<const Elf_Ehdr *>(base()); | ||||||
} | ||||||
|
@@ -379,22 +413,26 @@ class ELFFile { | |||||
|
||||||
/// Iterate over program header table. | ||||||
Expected<Elf_Phdr_Range> program_headers() const { | ||||||
if (getHeader().e_phnum && 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)getHeader().e_phnum * 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(getHeader().e_phnum) + | ||||||
", e_phnum = " + Twine(NumPh) + | ||||||
", 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 + NumPh); | ||||||
} | ||||||
|
||||||
/// Get an iterator over notes in a program header. | ||||||
|
@@ -772,19 +810,14 @@ 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; | ||||||
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 = *ShStrNdxOrErr; | ||||||
// There is no section name string table. Return FakeSectionStrings which | ||||||
// is non-empty if we have created fake sections. | ||||||
if (!Index) | ||||||
|
@@ -891,6 +924,39 @@ Expected<uint64_t> ELFFile<ELFT>::getDynSymtabSize() const { | |||||
|
||||||
template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} | ||||||
|
||||||
template <class ELFT> Error ELFFile<ELFT>::readShdrZero() { | ||||||
const Elf_Ehdr &Header = getHeader(); | ||||||
|
||||||
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 | ||||||
|
// become an infinite recursion | |
// become an infinite recursion. |
Nit: comments should be full sentences, with trailing full stops.
There was a problem hiding this comment.
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.