1

— 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.

  • 2
    Could you please clarify how the answers you have gotten don't address your issue? I see you have offered a bounty so if you don't want it to go to waste, please elaborate. Perhaps you could give a specific example? – terdon Sep 18 '14 at 9:26
  • @terdon, specific example was already given and it's /etc/ld.so.preload – poige Sep 18 '14 at 10:49
  • 4
    Look, all I'm saying is that people seem to be having trouble understanding what you're after. You have two answers but have not explained why they don't work for you. You may think that your question is clear enough but apparently others disagree. You might get more/better answers if you elaborate and explain what is missing from those you've gotten. If you don't want to, fine, it's your question. – terdon Sep 18 '14 at 10:53
  • @Gael, some programs discard some or all environment variables then exec other programs, so /etc/ld.so.preload is the only way to enforce pre-loading. – poige Sep 18 '14 at 10:54
5
+150

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
  • Ok, here's the screen-shot which allows me calling your answer phony: goo.gl/NpgBvk – poige Sep 24 '14 at 9:49
  • Oh, yeah, there's nothing really phony in your answer, in despite it can be seemed so at the first glance. Deeper inspection has shown that on ubuntu, $LIB gets expanded into lib/x86_64-linux-gnu (sic!), that's why my check of your answer failed. Thanks for letting me (and the rest of community) know, I apologize for mistake and all the bounty is your. b – poige Sep 24 '14 at 10:13
  • I learned something today - I never noticed the lib/$ARCH path difference on Debian from Redhat. I've updated the first example to include Debian-style paths. – R Perrin Sep 24 '14 at 13:17
  • I'm glad my -150 has taught me smth as well. ) – poige Sep 24 '14 at 16:39
  • :( In Docker, $LIB expands to '' (empty string) – mcandre May 15 '15 at 20:59
-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)

  • AFAIK, there's no such thing as “x64_32”, but “x32” instead. – poige Sep 14 '14 at 5:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.