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.


wanderer - https://git.dotya.ml/wanderer

archlinuxcompilation32bit

615 Words

Wed, 14 Jun 2023 10:32:52 +0000 (last modified Wed, 14 Jun 2023 14:14:25 +0200)

aa2b945 @ 14 Jun 2023