How can i emulate an x86 32 bits program on an ARM host?

2.8k views Asked by At

I am running a Kali Linux distribution on an arm cpu (aarch64).

I have successfully install x86_64-linux-gnux32-gcc and x86_64-linux-gnu-gcc.

I have wrote a basic c program:

#include <stdio.h>

void main()
{
   printf("Hello world\n");
}

I have compiled 2 versions:

x86_64-linux-gnu-gcc test1.c -o test1_64
x86_64-linux-gnux32-gcc test1.c -o test1_32

The first binary (64 bits) works fine when i run it with this command:

qemu-x86_64-static ./test1_64

But i have an error with the second binary (32 bits):

qemu-x86_64-static ./test1_32 
qemu-x86_64-static: ./test1_32: Invalid ELF image for this architecture

I have tried to force a 32 bits cpu with this command:

qemu-x86_64-static -cpu qemu32 ./test1_32

I have also tried to compile the binary with -static option. I got the same result.

How can i run my 32 bits executable ?

Thanks a lot

2

There are 2 answers

3
Nate Eldredge On BEST ANSWER

x86_64-linux-gnux32-gcc is not what you want for building 32-bit programs. This is actually a 64-bit compiler that targets the x32 ABI, a scheme to have 64-bit code that needs only 32 bits for pointers. It never really caught on and is fairly obscure these days, so I'm not surprised that qemu wouldn't support it.

The x86_64 target of gcc supports building 32-bit programs as well, using the -m32 option. So you ought to be able to build your 32-bit Hello World with

x86_64-linux-gnu-gcc test1.c -o test1_32 -m32

(You might have to separately install 32-bit x86 libraries to successfully cross compile.)

Then to run it, use qemu-i386 instead of qemu-x86_64.

0
Peter Cordes On

file ./test1_32 should show you that you've still made an x86-64 executable, not i386, with a compiler for the x32 ABI as Nate noticed.

Unfortunately the file output says "ELF 32-bit LSB executable, x86-64, version 1 (SYSV), ..." so the 32-bit part could be misleading.

An actual 32-bit build has "ELF 32-bit LSB executable, Intel 80386,".

A single install of GCC/GAS can build for 32 or 64-bit x86, unlike for ARM32 vs. AArch64 where you need different builds of GCC, so I expect that was part of the confusion. GCC treats i386 and x86-64 as flavours of the same architecture, while AArch64 is treated as a totally separate architecture from ARM. (IDK if GCC did that because x86-64 machine code is similar to 32-bit, so the same assembler can pretty easily handle both. But AArch64 uses a totally different machine code format from ARM32, no point in trying to share code in the assembler between the two architectures.)

So you were probably expecting to need a GCC with 32 in its name to make 32-bit x86 executables. That is not the case.