--- title: "Compiling C programs using -m32 on Arch in 2023" description: "Compiling C programs for 32bit on Arch in 2023" date: 2023-06-14T12:32:52+02:00 author: wanderer - https://git.dotya.ml/wanderer draft: false toc: true enableGitInfo: true images: tags: - archlinux - compilation - 32bit --- ## 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. ```c /* 32ftw.c */ #include int main() { printf("hey 32!\n"); register int e asm("esp"); printf("esp: 0x%08x\n", e); return 0; } ``` For reference, the`GCC` version used was `gcc (GCC) 13.1.1 20230429`. ## TL;DR To compile a 32bit `C` program on [64bit-only](https://wiki.archlinux.org/title/Frequently_asked_questions#What_architectures_does_Arch_support?) 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](https://musl.libc.org/) 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 ```sh ~ % 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](#example-program)) on Arch into a 32 bit binary? You might have encountered the following: ```sh ~ % 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 | ^~~~~~~~~~~~~~~~ compilation terminated. ``` Alright, a quick search and [an answer on Arch forums](https://bbs.archlinux.org/viewtopic.php?pid=1136063#p1136063) points to a (spoiler: *partial*) solution: `lib32-glibc` is needed, so let's install it ```sh ~ % sudo pacman -S lib32-glibc ``` and try again: ```sh ~ % 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`: ```sh ~ % sudo pacman -S lib32-gcc-libs ``` Now the program can finally be compiled and run and we can see it's a 32bit binary. ```sh ~ % 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](#installing-deps-and-calling-it-a-day).