jdx/mise · error · eyre::Report
unexpected ELF e_phentsize {e_phentsize}
Error message
unexpected ELF e_phentsize {e_phentsize} What it means
While pouring a Linux bottle, the ELF rewriter (elf::patch) walks the program header table and requires e_phentsize to equal 56 (sizeof Elf64_Phdr for 64-bit). Any other value means the file is corrupt, truncated, or produced by nonstandard tooling, and the parser refuses to continue rather than compute bogus offsets.
Source
Thrown at src/system/packages/brew/elf.rs:114
b[off..off + 8].copy_from_slice(&v.to_le_bytes());
}
#[derive(Clone, Copy)]
struct Phdr {
p_type: u32,
p_offset: u64,
p_vaddr: u64,
p_filesz: u64,
p_memsz: u64,
p_align: u64,
}
fn read_phdrs(content: &[u8]) -> Result<Vec<Phdr>> {
let e_phoff = rd_u64(content, 32)? as usize;
let e_phentsize = rd_u16(content, 54)? as usize;
let e_phnum = rd_u16(content, 56)? as usize;
if e_phentsize != PHDR_SIZE {
bail!("unexpected ELF e_phentsize {e_phentsize}");
}
if e_phnum >= 0xffff {
bail!("ELF uses PN_XNUM program header counts");
}
let mut phdrs = Vec::with_capacity(e_phnum);
for i in 0..e_phnum {
let off = e_phoff + i * PHDR_SIZE;
phdrs.push(Phdr {
p_type: rd_u32(content, off)?,
p_offset: rd_u64(content, off + 8)?,
p_vaddr: rd_u64(content, off + 16)?,
p_filesz: rd_u64(content, off + 32)?,
p_memsz: rd_u64(content, off + 40)?,
p_align: rd_u64(content, off + 48)?,
});
}
Ok(phdrs)
}View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Clear the cached bottle and re-download it, verifying the sha256 matches the API manifest
- Inspect the file with readelf -h <file> — if e_phentsize is not 56 outside this tool, the binary itself is broken
- If readelf shows a valid file, report the binary to the project — the parser may need extending for this producer
Defensive patterns
Strategy: validation
Validate before calling
// Cheap pre-check before relocation: sane ELF64 header fields.
fn elf_phentsize_ok(content: &[u8]) -> bool {
content.len() >= 56
&& content[..4] == [0x7f, b'E', b'L', b'F']
&& content[4] == 2 && content[5] == 1
&& u16::from_le_bytes(content[54..56].try_into().unwrap()) == 56
} Type guard
fn is_wellformed_elf64(content: &[u8]) -> bool {
content.len() >= 64 && content[..4] == [0x7f, b'E', b'L', b'F']
&& content[4] == 2 && content[5] == 1
&& u16::from_le_bytes(content[54..56].try_into().unwrap()) == 56
&& u16::from_le_bytes(content[56..58].try_into().unwrap()) < 0xffff
} Try / catch
// Treat per-file patch failures as fatal for that formula but report the path:
match elf::patch(&mut content, &opts, &path) {
Ok(changed) => { /* ... */ }
Err(err) => return Err(err.wrap_err_with(|| format!("relocating {}", path.display()))),
} Prevention
- Verify bottle checksums before extraction so truncated ELFs never reach the rewriter
- Run readelf -h on suspicious bottles; e_phentsize != 56 means the file, not the tool, is wrong
- Keep pour caches clean — re-extract from a verified download on any ELF parse failure
When it happens
Trigger: elf::patch -> read_phdrs after the 64-bit LE checks pass: rd_u16(content, 54) != PHDR_SIZE (56). Triggered by a truncated/corrupted bottle download, a file with forged ELF magic, or an ELF built by a linker emitting nonstandard program header entry sizes.
Common situations: Broken bottle cache after an interrupted download; upstream bottle built with experimental tooling; disk corruption; a text file accidentally named as the binary.
Related errors
- ELF uses PN_XNUM program header counts
- cannot relocate {}: rpath must grow but the dynamic string t
- malformed Mach-O in {}
- malformed load command table in {}
- malformed load command in {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/e28cad677a9768c8.
Report an issue: GitHub.