2018-12-15 02:20

Linux/x32

Pro-Linux berichtet heute von Bestrebungen, die Unterstützung für das x32 ABI aus Linux zu entfernen.

Das x32 ABI ist ein Binärformat für Linux auf Intel-kompatiblen Prozessoren. Es ist als ein Versuch gestartet worden, die Vorteile von i386 und amd64 zu verbinden. x32-Programm laufen nur auf Rechnern mit dem amd64-Befehlssatz, also allen aktuellen Systemen seit ca. 2005. Sie nutzen die Vorteile der zahlreicheren und größen Prozessorregister von amd64 Systemen, verwenden jedoch eine Wortlänge von Adressen von nur 32 Bit. Damit ist der theoretisch adressierbare Speicher pro Prozess auf 4 GB begrenzt, was jedoch für viele Anwendungen ausreichend ist. Durch die kürzeren Pointer werden die Programme kleiner, bei der Ausführung passt mehr Programmcode in die CPU-Caches. Einen Vergleich von x32, i386 und amd64 gibt es auf Wikipedia.

Laut des Artikels ist jedoch fraglich, ob x32 in ausreichenden Umfang genutzt wird, um den Aufwand bei der Pflege im Mainline-Kernel zu rechtfertigen. Nur die Distributionen Debian, Gentoo und Yocto bieten einen eigenen Port mit ausschließlich x32 Paketen an. Debian/x32 ist zudem dem frühen Entwicklungsstadium nie entwachsen.

x32 Programme auf amd64 Distributionen

Jedoch können x32 Programme auch unter dem “normalen” Debian bzw Ubuntu benutzt werden. Um x32-Software ausführen zu können, muss mindestens die GNU-libc für x32 installiert sein.

# apt install libc6-x32

Zudem ist im Debian-Standardkernel der Support für x32 zwar vorhanden, muss aber mit dem Parameter syscall.x32=y eingeschaltet werden. Unter Ubuntu ist das nicht nötig, x32 ist standardmäßig aktiv.

Um auch eigene Programme für x32 (cross-)compilieren zu können, werden zudem die Header benötigt:

# apt install libc6-dev-x32

Damit kann ein C-Programm compiliert werden, z.B.:

$ gcc -mx32 -Wall -o hello hello.c

Das entstehende Programm ist ein 32-Bit Programm für amd64 (x86_64) Systeme und ist dynamisch gegen die x32-libc gelinkt. Wie man sieht, sind alle Pointer 32 Bit lang:

$ file hello
hello: ELF 32-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /libx32/ld-linux-x32.so.2, for GNU/Linux 3.4.0, [...] not stripped

$ ldd hello
linux-vdso.so.1 (0xff99a000)
libc.so.6 => /libx32/libc.so.6 (0xf77ad000)
/libx32/ld-linux-x32.so.2 (0xf7d5f000)

Go/x32

Unter Ubuntu 18.04 LTS lassen sich auch Go-Programme für x32 compilieren und ausführen. Dazu wird der GCC-Go Compiler benötigt:

# apt install gccgo-x86-64-linux-gnux32 gccgo-multilib-x86-64-linux-gnux32

Zum Compilieren des Programmes muss der passende Compiler direkt aufgerufen werden, ein -mx32 wie bei C genügt nicht.

$ x86_64-linux-gnux32-gccgo -Wall -o hello hello.go

Das Programm wird dynamisch gegen die üblichen Shared Libraries und die Go-Library von GccGo gelinkt. Letztere wird jedoch vom dynamischen Linker nicht automatisch gefunden, weil der Pfad für die Go x32 Libraries nicht in der ldconfig Konfiguration steht.

$ file hello
hello: ELF 32-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libx32/ld-linux-x32.so.2, for GNU/Linux 3.4.0, [...] with debug_info, not stripped

$ ldd hello
linux-vdso.so.1 (0xffdba000)
libgo.so.13 => not found
libgcc_s.so.1 => /usr/libx32/libgcc_s.so.1 (0xf7af9000)
libc.so.6 => /libx32/libc.so.6 (0xf7749000)
/libx32/ld-linux-x32.so.2 (0xf7d10000)

Um das Programm auszuführen, kann die benötigte Library mit LD_PRELOAD vorgeladen werden:

LD_PRELOAD=/usr/x86_64-linux-gnux32/lib/libgo.so.13.0.0 ./hello