Compiling C programs using -m32 on Arch in 2023
Intro
Preliminary: To be clear, this short post is not primarily concerned with running the 32bit programs, instead specifically compiling C programs for 32bit (x86).
Compiling a C
program for a 32bit architecture in 2023?
Well, one might still want to poke at reversing smaller address-space programs,
even in 2023, and contrary to the popular belief, there still exist pieces of
software not ported to 64bit and architectures in use that are 32bit. Whatever
the motivation, the compilation process might not be as straight-forward on
Arch as one would maybe expect, so this post shows how it can be done. Unless
specified otherwise, the x86
architecture is assumed.
Example program
Just show the example program already!
Nothing fancy, just saying hi and printing the value of esp
. All that is
needed is to compile this into a 32bit binary.
/* 32ftw.c */
#include <stdio.h>
int main() {
printf("hey 32!\n");
register int e asm("esp");
printf("esp: 0x%08x\n", e);
return 0;
}
For reference, theGCC
version used was gcc (GCC) 13.1.1 20230429
.
TL;DR
To compile a 32bit C
program on
64bit-only
Arch, additional packages (on top of compilers/linkers) are required. As of
2023-06-14 these are:
core/lib32-glibc
core/libr32-gcc-libs
,
which are the GNU C library (could also use musl libc but that would probably necessitate compiler wrapping as GCC seems to prefer the GNU versions), and the 32bit version of the GCC libraries, respectively.
Installing deps and calling it a day
~ % sudo pacman -S lib32-glibc lib32-gcc-libs
resolving dependencies...
looking for conflicting packages...
Package (2) New Version Net Change
core/lib32-gcc-libs 13.1.1-1 113.12 MiB
core/lib32-glibc 2.37-3 18.06 MiB
Total Installed Size: 131.18 MiB
:: Proceed with installation? [Y/n]
The longer version
If you ever needed to compile some C
sources (such as the example listed
here) on Arch into a 32 bit binary? You might have
encountered the following:
~ % gcc -o 32ftw -m32 32ftw.c && ./32ftw
In file included from /usr/include/features.h:515,
from /usr/include/bits/libc-header-start.h:33,
from /usr/include/stdio.h:27,
from 32ftw.c:2:
/usr/include/gnu/stubs.h:7:11: fatal error: gnu/stubs-32.h: No such file or directory
7 | # include <gnu/stubs-32.h>
| ^~~~~~~~~~~~~~~~
compilation terminated.
Alright, a quick search and an answer on Arch
forums points to
a (spoiler: partial) solution: lib32-glibc
is needed, so let’s install it
~ % sudo pacman -S lib32-glibc
and try again:
~ % gcc -o 32ftw -m32 32ftw.c && ./32ftw
/usr/sbin/ld: skipping incompatible /usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/sbin/ld: skipping incompatible /usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/sbin/ld: skipping incompatible /usr/lib/libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/sbin/ld: cannot find libgcc_s.so.1: No such file or directory
/usr/sbin/ld: skipping incompatible /usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/../../../libgcc_s.so.1 when searching for libgcc_s.so.1
/usr/sbin/ld: skipping incompatible /usr/lib/libgcc_s.so.1 when searching for libgcc_s.so.1
collect2: error: ld returned 1 exit status
Oh no, it still refuses to work.
As is somewhat hinted in the linker’s error message depicted above, the
problem can be rectified by installing the GCC libraries (the 32bit version, of
course), which in Arch’s core
repository lives under the name
lib32-gcc-libs
:
~ % sudo pacman -S lib32-gcc-libs
Now the program can finally be compiled and run and we can see it’s a 32bit binary.
~ % gcc -o 32ftw -m32 32ftw.c && ./32ftw
hey 32!
esp: 0xff8d27f0
~ % file ./32ftw
32ftw: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=2ff0c8dce8f64db4960aa6aef6cd9936326e990d, for GNU/Linux 4.4.0, not stripped
~ % ldd ./32ftw
linux-gate.so.1 (0xf7f50000)
libc.so.6 => /usr/lib32/libc.so.6 (0xf7ce5000)
/lib/ld-linux.so.2 => /usr/lib/ld-linux.so.2 (0xf7f52000)
Closing words
To sum up, compiling a C
program for 32bit on contemporary Arch works fine
with just a handful of dependencies. In author’s opinion, this could be
highlighted better in the Archwiki, but perhaps the target audience is so small
that it hasn’t even been considered.
For a not-much-talking summary, check out TL;DR’s calling it a day.