2

— It's known you can run x86_32 programms with x86_64 kernel if it was compiled with support for that. But dynamic linker doesn't provide any way to define a separate set of preload libraries for 32-bit programs, so every time you run such a program, had you x86_64 preloads, you would face this error message:

ERROR: ld.so: object '… … …' from /etc/ld.so.preload cannot be preloaded (wrong ELF class: ELFCLASS64): ignored.

In case you put there the same list of x86_32-libraries to pre-load, you would get it working, but all pure x86_64 runs would start complaining as well.

The best possible way is to modify the dynamic loader to support pre-loading from separate files, obviously, but it's at least lengthy process. Can you think of some clean workaround?…

For now I'm thinking about some multi-class-pre-load.so, which could load needed files by itself, but, as I can see, there's no "multi-class" support in ELF.

poige
  • 6,231

2 Answers2

8

In your ld.so.preload, you want to specify "$LIB" in your path rather than an explicit "lib" or "lib64". Thus, on a Redhat-style distro, "/usr/alternates/$LIB/libfoo.so" becomes "/usr/alternates/lib/libfoo.so" for a 32-bit process and "/usr/alternates/lib64/libfoo.so" for a 64-bit process. On an Debian-style distro, "/usr/alternates/$LIB/libfoo.so" becomes "/usr/alternates/lib/i386-linux-gnu/libfoo.so" and "/usr/alternates/x86_64-linux-gnu/libfoo.so" respectively. Your tree then needs to be populated with libraries for both architectures.

See "rpath token expansion" in the ld.so(8) man page for more on this.

Note however, that rather than preloading a library, if you're compiling the binaries whose loading you are attempting to modify, you may find it better to modify the paths by setting DT_RUNPATHon the link line (using the same "$LIB"-style paths, thus configuring the binary to prefer your library location over the system defaults.

Alternately, as others have noted, you may edit an ELF file to set DT_RUNPATH on binaries you're not compiling.

The following works for me on an x86_64 Centos 6.5 box:

cd /tmp
mkdir lib lib64
wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.h
wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.c
gcc -m64 -shared -fPIC -ldl snoopy.c -o /tmp/lib64/snoopy.so
gcc -m32 -shared -fPIC -ldl snoopy.c -o /tmp/lib/snoopy.so
cat > true.c <<EOF
int main(void)
{ return 0; }
EOF
gcc -m64 true.c -o true64
gcc -m32 true.c -o true32
sudo bash -c "echo '/tmp/\$LIB/snoopy.so' > /etc/ld.so.preload"
strace -fo /tmp/strace64.out /tmp/true64
strace -fo /tmp/strace32.out /tmp/true32
sudo rm /etc/ld.so.preload"

In the strace output, strace64.out has:

open("/tmp/lib64/snoopy.so", O_RDONLY) = 3

while strace32.out has:

open("/tmp/lib/snoopy.so", O_RDONLY) = 3

This is with an ld.so.preload contents of:

/tmp/$LIB/snoopy.so
R Perrin
  • 3,049
  • 20
  • 11
-1

Preloading is not intended to be part of the normal operation of a system. Usually, you should actually link against the libs that you want to use.

The few people who have need to preload when running programs of multiple arches are assumed to not care about the harmless error messages.

Alternatively, as long as your programs aren't in turn starting other programs of different arches, you might be able to use better LD_PRELOAD just around the programs that have incorrect library sections.

But really, you're better off fixing the libraries as listed in the ELF file, preferably at compile stage, but there are tools to edit ELFs later.

(Side note: at first I thought your question was going to be about x64_32, which is completely different and has some interesting bugs)

o11c
  • 1,448