Using proprietary i386 apps on an amd64 system

Posted by dkg on Thu 14 Jun 2007 at 12:51

There's nothing like switching hardware architectures to make you realize one of the big advantages of free software: you can recompile all your free tools to use the new system. But what happens when you have a handful of non-free apps that were built for the old arch and you need to continue to be able to use them?

The Linux kernel for amd64 can actually run i386 binaries in a compatibility mode. But what if those apps depend on libraries that they expect to be provided by the system? The system libraries are now all built for amd64, so the i386 proprietary apps won't play nice with them.

Basic 32-bit library setup

For the i386 to amd64 transition, at least, you can install 32-bit libraries to be used by binaries which are running in the 32-bit compatibility mode. Debian is awesome: the really common libraries have already been packaged and organized for you, so you can just pull them in with:
apt-get install ia32-libs
If you're running a system with graphical tools (e.g. a desktop or a terminal server), you might also want to pull in the extra 32-bit GTK (GIMP ToolKit) libraries:
apt-get install ia32-libs-gtk

Filling in unusual missing libraries

Now most simple proprietary 32-bit binaries should run fine. But some more complicated ones want to rely on 32-bit libraries that haven't been nicely packaged by debian's amd64 team yet. How do you get and install those packages? There's good instructions in /usr/share/doc/ia32-libs/README.Debian:
If more libraries are needed, file wishlist severity bugs against ia32-libs
in the Debian bug tracking system at bugs.debian.org and we'll try to oblige.
For a quick fix, you can download a suitable ia32 (i386 in Debian architecture
terms) binary package, and install it on your ia64 or amd64 system using:

        dpkg -X .deb /emul/ia32-linux
        ldconfig
You can use the trusty packages.debian.org interface to find the right package and download a copy of the i386 version of the package from the mirror of your choice. Then, as root, use dpkg to extract the package as described in the snip above, and update the dynamic linker's run-time bindings with ldconfig.

It can be more complicated when you don't know what libraries are missing or needed. Sometimes, running the application will print out errors describing which libraries are needed. But you can also use /usr/bin/ldd to find out which libraries want to be dynamically linked at runtime (openssl in this example isn't a proprietary app, but i didn't have one handy; i pulled it in as an example app built for i386):

0 dkg@lemur:~$ uname -r
2.6.18-4-amd64
0 dkg@lemur:~$ file ./openssl 
./openssl: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.1, dynamically linked (uses shared libs), for GNU/Linux 2.6.1, stripped
0 dkg@lemur:~$ ldd ./openssl 
	linux-gate.so.1 =>  (0xffffe000)
	libssl.so.0.9.8 => not found
	libcrypto.so.0.9.8 => not found
	libdl.so.2 => /lib32/libdl.so.2 (0xf7f2b000)
	libz.so.1 => /usr/lib32/libz.so.1 (0xf7f16000)
	libc.so.6 => /lib32/libc.so.6 (0xf7deb000)
	/lib/ld-linux.so.2 (0xf7f38000)
0 dkg@lemur:~$ 

Finding libraries that aren't linked by ldd

If you've managed to install all the "not found" libraries from the i386 debian packages so that ldd isn't complaining, it's still possible that your proprietary binaries don't work. This is because some applications also use techniques like dlopen() to load shared libraries, instead of asking ldd to link them.

How can you figure out which libraries are needed if you don't have the source code? One way is to use strace. Do something like this as an unprivileged user:

DUMPDIR=$(mktemp -d)
strace -o $DUMPDIR/strace.out -f ./my-proprietary-app
now you can review $DUMPDIR/strace.out. Look toward the end of the file for attempts to open files with .so in their name (.so is short for shared object, which is a library):
grep open $DUMPDIR/strace.out | grep '\.so' | tail
You'll see a lot of lines like:
11829 open("/usr/lib/i486-linux-gnu/sse2/libodbc.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
11829 open("/usr/lib/i486-linux-gnu/cmov/libodbc.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
11829 open("/usr/lib/i486-linux-gnu/libodbc.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
Now you can look for a file of that name (ignore the path) in the debian i386 arch package web UI. For the example above, i would do a search for libodbc.so.1.

Open questions

package tracking?
every package extracted into the /emul/ia32-linux doesn't get tracked by the package manager. What's a good way to get dpkg (or even better, apt!) to know about and maintain the package? How do we automate security updates, for example?
package verification?
Just downloading the package from the mirror doesn't tell us that we got what we were looking for. Since etch came out, we have the luxury of apt cryptographically verifying standard packages for us. What's a simple way to verify these packages before extracting them into /emul/ia32-linux?

Other methods

Another article on this site talks about how to install a full-blown 32-bit chroot instead of going with the emulated libraries. I don't think this is necessary for most cases, though i'd be curious to hear peoples' thoughts about the relative advantages or disadvantages of each approach. Certainly, if you plan to use non-free 32-bit libraries with your free applications, a chroot might be a better way to go. But if you've just got a couple non-free applications which want to use free 32-bit libraries, you might prefer the approach i've outlined here.

This article can be found online at the Debian Administration website at the following bookmarkable URL:

This article is copyright 2007 dkg - please ask for permission to republish or translate.