Translation(s): none


X32 is an ABI for amd64/x86_64 CPUs using 32-bit pointers. The idea is to combine the larger register set of x86_64 with the smaller memory and cache footprint resulting from 32-bit pointers.

Getting Started

Before you can run X32 binaries, you will need to install a kernel with the appropriate support. This means a kernel of version 3.4.0 or later, configured with CONFIG_X86_X32=y. Currently, none of the kernel packages in the Debian archive have this support (see #708070). If you want to use a prebuilt kernel, you can download packages from http://87.98.215.228/debian/byhand/l/linux.

Once you're running a kernel with X32 support, you can create a chroot to start experimenting with:

apt-get install debian-ports-archive-keyring
debootstrap --arch=x32 --keyring=/usr/share/keyrings/debian-ports-archive-keyring.gpg unstable /path/to/chroot http://ftp.debian-ports.org/debian

The old multistrap way:

cat > x32-multistrap.conf << EOF
[General]
arch=x32
directory=x32-chroot
# same as --tidy-up option if set to true
cleanup=false
# same as --no-auth option if set to true
# keyring packages listed in each debootstrap will
# still be installed.
noauth=false
# extract all downloaded archives (default is true)
unpack=true
# the order of sections is not important.
# the debootstrap option determines which repository
# is used to calculate the list of Priority: required packages.
debootstrap=Base Base-unreleased
aptsources=Base Base-unreleased


[Base]
packages=apt build-essential fakeroot
source=http://ftp.debian-ports.org/debian
keyring=debian-ports-archive-keyring
suite=sid
omitdebsrc=true

[Base-unreleased]
packages=
source=http://ftp.debian-ports.org/debian
suite=unreleased
omitdebsrc=true
EOF

multistrap -f ~/x32-multistrap.conf -d /root/x32-chroot/
(unset LANG LC_ALL; export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true; \
chroot /root/x32-chroot/ /var/lib/dpkg/info/dash.preinst && \
chroot /root/x32-chroot/ dpkg --configure -a && \
chroot /root/x32-chroot/ /bin/bash -c 'dpkg -i /var/cache/apt/archives/*.deb')

Common Issues

Outdated gnulib

This typically manifests with an error like this:

gcc -std=gnu99  -I.   -D_FORTIFY_SOURCE=2  -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wall -c -o fseterr.o fseterr.c
In file included from fseterr.h:20:0,
                 from fseterr.c:20:
./stdio.h:496:1: error: 'gets' undeclared here (not in a function)
make[5]: *** [fseterr.o] Error 1
make[5]: Leaving directory `/tmp/buildd/bison-2.5.dfsg/lib'
make[4]: *** [all-recursive] Error 1
make[4]: Leaving directory `/tmp/buildd/bison-2.5.dfsg/lib'
make[3]: *** [all] Error 2
make[3]: Leaving directory `/tmp/buildd/bison-2.5.dfsg/lib'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/tmp/buildd/bison-2.5.dfsg'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/tmp/buildd/bison-2.5.dfsg'
make: *** [debian/stamp-makefile-build] Error 2
dpkg-buildpackage: error: debian/rules build gave error exit status 2

This happens because the X32 port is using eglibc 2.16, which no longer declares a prototype for gets() by default. The fix is either to update from gnulib git (note that the stable release currently in sid doesn't have the required fix) -- or as a temporary measure, to edit stdio.in.h to look something like:

...
/* It is very rare that the developer ever has full control of stdin,
   so any use of gets warrants an unconditional warning.  Assume it is
   always declared, since it is required by C89.  */
#undef gets
#if 0
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
#endif
...

Outdated libtool

This typically manifests with an error like:

/bin/bash ../libtool  --tag=CC   --mode=link gcc  -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnux32/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnux32/glib-2.0/include   -pthread -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnux32/glib-2.0/include -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnux32/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12     -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wall -g -version-info 100:6:100 -export-dynamic -export-symbols-regex "^unique.*" -rpath /usr/lib -no-undefined -Wl,-z,relro -Wl,-z,defs -Wl,-O1 -Wl,--as-needed -o libunique-1.0.la -rpath /usr/lib uniqueapp.lo uniquebackend.lo uniquemessage.lo    uniqueenumtypes.lo  uniquemarshal.lo ../unique/bacon/libunique-bacon.la ../unique/dbus/libunique-dbus.la -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lglib-2.0   -lX11   -ldbus-glib-1 -ldbus-1 -lgobject-2.0 -lglib-2.0   
../libtool: line 7510: test: : integer expression expected
../libtool: line 7510: test: : integer expression expected
../libtool: line 7615: test: : integer expression expected
../libtool: line 7687: test: : integer expression expected
../libtool: line 7687: test: : integer expression expected
../libtool: line 7687: test: : integer expression expected
../libtool: line 7687: test: : integer expression expected
libtool: link: /usr/bin/ld -m elf_i386 -r -o .libs/libunique-1.0.la-1.o .libs/uniqueapp.o 
/usr/bin/ld: Relocatable linking with relocations from format elf32-x86-64 (.libs/uniqueapp.o) to format elf32-i386 (.libs/libunique-1.0.la-1.o) is not supported
make[5]: *** [libunique-1.0.la] Error 1
make[5]: Leaving directory `/tmp/buildd/libunique-1.1.6/unique'
make[4]: *** [all-recursive] Error 1
make[4]: Leaving directory `/tmp/buildd/libunique-1.1.6/unique'
make[3]: *** [all] Error 2
make[3]: Leaving directory `/tmp/buildd/libunique-1.1.6/unique'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/tmp/buildd/libunique-1.1.6'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/tmp/buildd/libunique-1.1.6'
make: *** [debian/stamp-makefile-build] Error 2
dpkg-buildpackage: error: debian/rules build gave error exit status 2

Note the "-m elf_i386", which should be "-m elf32_x86_64" on X32. The fix is to re-libtoolize with libtool version at least 2.4.2-1.2 from sid. If you prefer to use something like dh_autoreconf to do this at build time, so much the better.

Use of sysctl(2)

The error message from this typically looks something like:

gcc -o jemalloc.o -c  -DOSTYPE=\"Linux3\" -DOSARCH=Linux  -I../../../memory/jemalloc -I. -I../../dist/include -I../../dist/include/nsprpub  -I/usr/include/nspr -I/usr/include/nss      -fPIC -D_FORTIFY_SOURCE=2 -Wall -W -Wno-unused -Wpointer-arith -Wdeclaration-after-statement -Wcast-align -W -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -fno-strict-aliasing -pthread -ffunction-sections -fdata-sections -pipe  -DNDEBUG -DTRIMMED -g -Os -freorder-blocks  -fomit-frame-pointer  -D_FORTIFY_SOURCE=2 -include ../../mozilla-config.h -DMOZILLA_CLIENT -MD -MF .deps/jemalloc.pp /tmp/buildd/iceweasel-10.0.11esr/memory/jemalloc/jemalloc.c
In file included from /usr/include/x86_64-linux-gnux32/sys/sysctl.h:79:0,
                 from /tmp/buildd/iceweasel-10.0.11esr/memory/jemalloc/jemalloc.c:327:
/usr/include/x86_64-linux-gnux32/bits/sysctl.h:19:3: error: #error "sysctl system call is unsupported in x32 kernel"

The sysctl(2) interface is unmaintained and deprecated even on architectures where it's currently provided, so it's better to update the code to read or write from the corresponding /proc/sys/kernel/* file directly.

amd64 assembly

If your code uses inline assembly based on #ifdef __x86_64__ or #ifdef __amd64__, etc., these conditions will also be triggered on X32 builds. Some of the time this will work properly; however, if some of the inputs or outputs of the assembly fragment are of pointer or long types, you might get operand size mismatches like this:

/tmp/buildd/php5-5.4.4/ext/standard/math.c: Assembler messages:
/tmp/buildd/php5-5.4.4/ext/standard/math.c:628: Error: incorrect register `%esi' used with `q' suffix
/tmp/buildd/php5-5.4.4/ext/standard/math.c:629: Error: incorrect register `%edx' used with `q' suffix
/tmp/buildd/php5-5.4.4/ext/standard/math.c:632: Error: incorrect register `%edx' used with `q' suffix
/tmp/buildd/php5-5.4.4/ext/standard/math.c:633: Error: incorrect register `%esi' used with `q' suffix
make[1]: *** [ext/standard/math.lo] Error 1

Depending on the situation, you might be able to get by with just removing explicit "q" suffixes from the opcodes and letting the GNU assembler infer the correct size suffix. Otherwise, you can distinguish between regular amd64 and X32 by testing if __ILP32__ is defined. (Note that it's recommended to use __ILP32__ rather than __LP64__ as the discriminator, as __ILP32__ is specified by the X32 ABI, while __LP64__ is not specified by the AMD64 ABI.)

Bug Reports

I am currently using the usertag user debian-x32@lists.debian.org for all X32-related bug reports. (I've requested such a mailing list, but it hasn't been created yet.) Some of the tags I'm currently using, or may use in the near future, include:

See also

http://sites.google.com/site/x32abi/


DanielSchepler