Qemu vs sstrip – /dev/ttyS0

Qemu usually does a great job emulating embedded Linux applications, but as with anything you will occasionally run into bugs. While attempting to debug an embedded application in Qemu the other day, I ran into the following error:

eve@eve:~/firmware$ sudo chroot . ./qemu-mips bin/ls 
bin/ls: Invalid ELF image for this architecture

This error is usually indicative of using the wrong endian emulator, but I knew that the target binary was big endian MIPS. The file utility began to shed some light on the issue:

eve@eve:~/firmware$ file bin/busybox 
bin/busybox: ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked (uses shared libs), corrupted section header size

Hmmm, a corrupted section header? Let’s take a closer look at the binary.

Readelf will give us some more detailed information:

ELF Header:
  Magic:   7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, big endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           MIPS R3000
  Version:                           0x1
  Entry point address:               0x4052a0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x1007, noreorder, pic, cpic, o32, mips1
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         6
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

Sure enough, the section headers had been stripped out of the ELF binary. This is commonly done by tools such as sstrip in order to save precious storage space on embedded devices, and since section headers are not required in order to execute the program this shouldn’t prevent Qemu from loading the binary.

A quick grep of Qemu’s source quickly found the culprit in linux-user/elfload.c:

static bool elf_check_ehdr(struct elfhdr *ehdr)
    return (elf_check_arch(ehdr->e_machine)
            && ehdr->e_ehsize == sizeof(struct elfhdr)
            && ehdr->e_phentsize == sizeof(struct elf_phdr)
            && ehdr->e_shentsize == sizeof(struct elf_shdr)
            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));

Even though section headers aren’t required to load an ELF file, the elf_check_ehdr function expects the section header size to equal the size of the elf_shdr structure; simply commenting out this line and re-compiling did the trick:

eve@eve:~/firmware$ sudo chroot . ./qemu-mips bin/ls 
bin        lib        qemu-mips  tmp       var
dev        home       sbin       usr       

A patch has been submitted, but if you need this to work now it’s a quick and easy fix.

Bookmark the permalink.

Comments are closed.