[llvm] [Object,ELF] Implement PN_XNUM extension for program headers (PR #162288)
James Henderson via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 21 00:53:47 PDT 2025
================
@@ -887,30 +923,49 @@ 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();
- 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 ((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;
----------------
jh7370 wrote:
1. This code should be guarded by an `e_shnum == 0` check. If `e_shnum != 0`, we don't need to do funky things to read the index 0 header, like pre-filling `RealShNum` with a fake value, and can instead just set `RealShNum` to the right value up-front prior to calling `sections()`.
2. Perhaps this should be `1`, not `0` and we should call `getSection(0)`? That would allow sections() (called by `getSection(0)` to read the first section header, if it is within the bounds of the file, or generate an appropriate error otherwise. Note that if there really are no section headers, `getSection(0)` will emit an error (see https://github.com/llvm/llvm-project/blob/ec26f219acce77fb9b3d52abd31b0e639e788514/llvm/include/llvm/Object/ELF.h#L543), indicating that section 0 doesn't exist, which is exactly what we want.
3. sections() should not be referencing e_shnum directly. It should use RealShNum, which will either contain the real value taken directly from e_shnum (because it's non-zero), a previously calculated value (derived from an earlier call to this function), or the fake value we set prior to calling sections() for the first time (i.e. `1` - see point 2)).
https://github.com/llvm/llvm-project/pull/162288
More information about the llvm-commits
mailing list