25

When I try to execute a 32-bit file compiled with gcc -m32 main.c -o main on Windows Subsystem for Linux, I get the following error: bash: ./main: cannot execute binary file: Exec format error.

If I compile it without -m32 it runs.

Any solution for running 32-bit executable on WSL?

phuclv
  • 37,963
  • 15
  • 156
  • 475
Ford1892
  • 741
  • 2
  • 9
  • 20
  • 1
    `.c` and `.s` are source code files. They cannot be executed directly and they are typically not the output of a C compiler or assembler program. – too honest for this site Feb 08 '17 at 18:37
  • I know, I meant that I compile a main.c file and execute the 32 bit executable ./main – Ford1892 Feb 08 '17 at 18:39
  • I am not certain enough of this to post it as an answer, but I *believe* WSL is, itself, a 64-bit process. You can't run a 32-bit executable (or load a 32-bit library) in a 64-bit process. – David W Feb 08 '17 at 18:42
  • Related: WSL doesn't support 32-bit `int 0x80` system calls in 64-bit executables, so building asm as 64-bit doesn't help unless you also use the proper `syscall` system call ABI. [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730) – Peter Cordes Feb 04 '21 at 05:31

3 Answers3

47

QEMU and binfmt support light the way :)

https://github.com/microsoft/wsl/issues/2468#issuecomment-374904520

After reading that the WSLInterop between WSL and Windows processes used binfmt, I was tinkering with QEMU to try some ARM development, and incidentally discovered how to get 32-bit support working.

Edit: requires "Fall Creators Update", 1709, build 16299 or newer

Install qemu and binfmt config:

sudo apt install qemu-user-static
sudo update-binfmts --install i386 /usr/bin/qemu-i386-static --magic '\x7fELF\x01\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x01\x00\x00\x00' --mask '\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xff\xff\xff\xff\xff\xff\xff'

You'll need to reactivate binfmt support every time you start WSL:

sudo service binfmt-support start

Enable i386 architecture packages:

sudo dpkg --add-architecture i386
sudo apt update
sudo apt install gcc:i386

Try it out:

$ file /usr/bin/gcc-5
/usr/bin/gcc-5: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=2637bb7cb85f8f12b40f03cd015d404930c3c790, stripped

$ /usr/bin/gcc-5 --version
gcc-5 (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc helloworld.c -o helloworld

$ ./helloworld
Hello, world!

$ file helloworld
helloworld: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=3a0c7be5c6a8d45613e4ef2b7b3474df6224a5da, not stripped

And to prove it really was working, disable i386 support and try again:

$ sudo service binfmt-support stop
 * Disabling additional executable binary formats binfmt-support [ OK ]

$ ./helloworld
-bash: ./helloworld: cannot execute binary file: Exec format error
Froosh
  • 1,025
  • 1
  • 10
  • 13
  • 2
    works for me, WIN10 1803, WSL, ubuntu 18.04 LTS linux g++-8 – zhaorufei Aug 02 '18 at 04:56
  • 1
    Works great, thanks! Windows 10 v1803 WSL Ubuntu 16.04 – Octa9on Jan 15 '19 at 03:35
  • If I have installed 64bit gcc, then when I run `sudo apt install gcc:i386`, it gave me the following errors: ```The following packages have unmet dependencies: gcc:i386 : Depends: cpp:i386 (>= 4:7.3.0-3ubuntu2.1) but it is not going to be installed Depends: gcc-7:i386 (>= 7.3.0-27~) but it is not going to be installed E: Unable to correct problems, you have held broken packages ``` I will try to use the method mention here (https://askubuntu.com/questions/510269/how-to-install-build-essentiali386-to-compile-a-32-bit-executable-on-a-64-bit-s#answer-828458) – Donghua Liu Jan 16 '19 at 02:51
  • I'm not great at handling apt install issues so I keep several WSL installs around for different needs (e.g. i386 vs x64, etc). Separate chroot/containers should do the job too, as you referenced. – Froosh Jan 18 '19 at 01:50
  • 1
    For WSL OpenSuse put `qemu-i386-binfmt` (from 'qemu-linux-user' package) instead of `qemu-i386-static` in the update-binfmts line. – Nathan Mills Apr 02 '19 at 07:34
  • I need to uninstall the 64bit version of gcc then install 32bit. – Donghua Liu Apr 03 '19 at 06:17
  • 1
    Works great for me in order to execute 32-bit binaries on WSL Ubuntu 18.04 LTS built with g++ v7.40 using `-m32` compiler flag. In essence, all that is required for running 32-bit binaries is the `apt install qemu-user-static`, `update-binfmts --install i386 ...`, and `service binfmt-support start`. gcc:i386 is not required since you can cross compile for x86 using gcc-multilib – Francois B Oct 22 '19 at 12:37
  • This works without the "sudo apt install gcc:i386" step. I tried installing gcc:i386 and it wanted to delete all my 64-bit compiler packages and replace them with 32-bit ones. No thanks. – teadotjay Nov 08 '19 at 18:17
15

32-bit ELF support isn't provided by WSL (yet). There doesn't seem to be any progress since the UserVoice was raised - you are out luck.

See UserVoice: Please add 32 bit ELF support to the kernel and Support for 32-bit i386 ELF binaries.

If possible, switch to a real Linux ;-)


Since this was originally posted, the support has been available on WSL2 which does support real Linux kernel! So that should be the preferred way.

As noted in the linked github issue, there's also qemu-user which can be used if WSL1 is still used.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • This answer appears to be outdated. – Nate Eldredge May 25 '21 at 16:56
  • See also [Does WSL 2 really support 32 bit program?](https://stackoverflow.com/q/61300194) re: how to actually make sure your WSL is WSL2. Apparently some people think they have WSL2 but 32-bit executables still don't work because it's actually WSL1. – Peter Cordes Aug 24 '21 at 03:02
10

WSL2 runs in a real virtual machine using a real Linux kernel, therefore it's actually possible to do anything a Linux VM can do, including running 32-bit code. Just install 32-bit libs by running

sudo dpkg --add-architecture i386
sudo apt-get update

For more information read

phuclv
  • 37,963
  • 15
  • 156
  • 475
  • 1
    You may also need `sudo apt-get install gcc-multilib g++-multilib libc6:i386`, as per http://www.smlnj.org/dist/working/110.95/install.html#install-64 – iono Jan 26 '21 at 08:58
  • That's right, it doesn't work without the install line. – Leila Apr 07 '21 at 09:09