158 lines
5.1 KiB
Markdown
158 lines
5.1 KiB
Markdown
---
|
|
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 <stdio.h>
|
|
|
|
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 <gnu/stubs-32.h>
|
|
| ^~~~~~~~~~~~~~~~
|
|
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).
|