This is the mail archive of the
mailing list for the elfutils project.
Re: failed reading "Smallest x86 ELF Hello World"
- From: Mark Wielaard <mark at klomp dot org>
- To: Josh Stone <jistone at redhat dot com>, elfutils-devel at sourceware dot org
- Date: Wed, 04 Oct 2017 20:55:53 +0200
- Subject: Re: failed reading "Smallest x86 ELF Hello World"
- Authentication-results: sourceware.org; auth=none
- References: <email@example.com>
On Thu, 2017-09-28 at 12:06 -0700, Josh Stone wrote:
> From http://timelessname.com/elfbin/
> Elfutils completely fails to read the file:
> $ eu-readelf --version
> eu-readelf (elfutils) 0.169
> Copyright [...]
> $ eu-readelf -a hello
> eu-readelf: failed reading 'hello': invalid file descriptor
> It's not clear that we should care, since that page even says it's "a
> completely corrupted x86 ELF Binary that still runs." But since it's
> good enough for the kernel to run it, I'd hope for *something* from
> It also seems weird to get the message "invalid file descriptor",
> from ELF_E_INVALID_FILE, which makes it sound like more like
> EBADF. The file descriptor itself is fine - it just doesn't like the
> ELF within.
At first I though it was because eu-readelf uses libdwfl to get more
information about the ELF file. To get all the data about the
Dwfl_Modules we might hit some error that might not be relevant for the
initial showing of data. But that isn't really it in this case.
The first issue is indeed that almost anything that goes wrong when
setting up the initial Elf handle ends up being described as
ELF_E_INVALID_FILE. Which is not always the correct error code. So I
introduced ELF_E_INVALID_ELF which indicates it is bad ELF data being
encountered and not just the inability to read the data from the file
descriptor. Also in a couple of cases we didn't explicitly set the
libelf errno to indicate what really went wrong. I made sure we always
libelf: Add ELF_E_INVALID_ELF error value.
This at least gives a nicer error message:
eu-readelf: failed reading './hello': invalid ELF file data
But while auditing this code it is clear we go out of our way to get
the section (count) making sure we don't touch any bad data. If there
is a change we might read anything bad from the (mmapped) file then we
explicitly set the elf->state.elf[64|32].scns.cnt to zero. Which is
respected throughout libelf whenever we try to touch section headers.
Except... during the initial read we double check e_shoff is sane and
error out early. Even though the code right below it explicitly doesn't
use it when scncnt is zero. So we can fix this sanity check.
libelf: Don't error out when sanity checking e_shoff if scncnt is
This then gives similar output to binutils readelf:
Magic: 7f 45 4c 46 01 01 01 48 69 20 57 6f 72 6c 64 0a
Data: 2's complement, little endian
Ident Version: 1 (current)
OS/ABI: <unknown>: 72
ABI Version: 105
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 1 (current)
Entry point address: 0x8048080
Start of program headers: 52 (bytes into file)
Start of section headers: 309248 (bytes into file)
Size of this header: 22763 (bytes)
Size of program header entries: 32 (bytes)
Number of program headers entries: 2
Size of section header entries: 40 (bytes)
Number of section headers entries: 5
Section header string table index: 4
[Nr] Name Type Addr Off Size ES Flags Lk Inf Al
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x0000a2 0x0000a2 R E 0x1000
LOAD 0x0000a4 0x080490a4 0x080490a4 0x000009 0x000009 W 0x9007b900
Section to Segment mapping:
Maybe it could be improved a little more by adding a warning that 5
section [headers] were expected, but none could be read. But I leave it
at this for now.