Why an Elf file with a single small segment produces an error?

2026-09-10

Stack Overflow: View Question

Tags: linux, executable, elf

Score: 4 | Views: 132

The asker is hand-crafting a minimal ELF64 executable in NASM, laying out the ELF header and a single PT_LOAD program header that maps a tiny amount of code at virtual address 0x1000. Producing an ELF that runs is a classic golf exercise (see a.out minimizers by Brian Raiter and others), but the Linux kernel loader has become significantly stricter over the years, and small deviations that were once tolerated now yield opaque failures like ENOEXEC, SIGKILL before _start, or a bare "cannot execute" message.

What makes it interesting is that the ELF spec permits a lot, but fs/binfmt_elf.c in the kernel enforces additional invariants that aren't obvious from reading the spec. A few common culprits for "single small segment" failures:

Diagnostic approach:

  1. Run strace -f ./tiny 2>&1 | head — look for the execve return value. EINVAL almost always points to alignment; EACCES to mmap_min_addr.
  2. Enable kernel loader diagnostics: dmesg after the failed exec often prints "requested but not required" or "bad ELF" messages from load_elf_binary.
  3. Use readelf -l and check that VirtAddr and Offset match modulo Align.
  4. Compare against Raiter's "A Whirlwind Tutorial on Creating Really Teensy ELF Executables" — his 45-byte binary works precisely because it satisfies the congruence rule by piling everything into one overlapping segment.

Without the actual error message the answer is speculative, but 9 times out of 10 for this pattern it's the p_offset ≡ p_vaddr (mod p_align) constraint biting.

The challenge: The ELF spec is permissive, but Linux's load_elf_binary silently enforces additional invariants (page-congruent offsets, mmap_min_addr) that turn hand-crafted minimal ELFs into a puzzle of undocumented kernel quirks.

All newsletters