I am running an old version of RedHat linux (Enterprise v.3) for
backward compatiblity with some commercial tools I need to use. The
version that I have uses glibc 2.3.2 and everything works fine.
The problem I am having is that I have to use another program, that is
only supported for RedHat Linux 6.2 and 7.1. Unfortunately, these
versions use glibc 2.2.*, and not the 2.3.2 that I have at the moment.
Is there any way I can have two version of glib running on my machine
at the same time. Ideally, I would like to have my current 2.3.2
running all the programs that then when I want to run the other program
I would "switch" over to the older version. Is there someway I can do
this using either a shell script that creates and destructs symlinks as
necessary. Or is this a world of pain that I would like to stay away
from?
Thanks,
Stephen
Sure - no problem. Use LD_LIBRARY_PATH in a wrapper script. But I
think you'll find that the later glibc works fine for executables
compiled against an earlier glibc, since symbols are individually
versioned!
> running all the programs that then when I want to run the other program
> I would "switch" over to the older version. Is there someway I can do
> this using either a shell script that creates and destructs symlinks as
I don't understand why you think this should be hard, or why you think
it should be done like this! "Man ld.so", please!
> necessary. Or is this a world of pain that I would like to stay away
> from?
Peter
Thanks from the prompt reply. What you said makes sense.
I'm going to give it a shot,
Thanks,
Stephen
> Sure - no problem. Use LD_LIBRARY_PATH in a wrapper script. But I
> think you'll find that the later glibc works fine for executables
> compiled against an earlier glibc, since symbols are individually
> versioned!
Shouldn't using "LD_ASSUME_KERNEL" be the most straightforward?
[..]
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvp...@urvzvat.qr | perl -pe 'y/a-z/n-za-m/'
#bofh excuse 202: kernel panic: write-only-memory (/dev/wom0)
capacity exceeded.
>> Sure - no problem. Use LD_LIBRARY_PATH in a wrapper script. But I
>> think you'll find that the later glibc works fine for executables
>> compiled against an earlier glibc, since symbols are individually
>> versioned!
> Shouldn't using "LD_ASSUME_KERNEL" be the most straightforward?
Never heard of it (and it's not in my ld.so man page). I guess it does
something about kernel versions? Maybe I should check the info doc!
Peter
[ Using different glibc versions on the same box ]
>> Shouldn't using "LD_ASSUME_KERNEL" be the most straightforward?
> Never heard of it (and it's not in my ld.so man page). I guess it does
Although not in mine.
> something about kernel versions? Maybe I should check the info doc!
LD_ASSUME_KERNEL is iirc handled by the dynamic linker and not
hard-coded. Using 'eu-readelf' (comes with the elfutils package on
my box) is generally helpful to determine version information and
easier to use then objdump for this task. ;-)
Unsure if this feature is special to RH based distro or applies
to any, YMMV. It can be helpful for some (older) apps needing
older glibc version to let the dynamic linker know which one to
use.
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvp...@urvzvat.qr | perl -pe 'y/a-z/n-za-m/'
#bofh excuse 26: first Saturday after first full moon in Winter
> Steve <step...@gmail.com> wrote:
>> Is there any way I can have two version of glib running on my machine
>> at the same time.
Yes, but not trivially. Details here:
http://bitwagon.com/rtldi/rtldi.html
> Sure - no problem. Use LD_LIBRARY_PATH in a wrapper script.
This will not work for glibc *at all*, although it does work for
other libraries. The reason: glibc consists of many pieces, which
all must match *exactly*. One of the pieces that must match is
/lib/ld-linux.so.2. Since you can only have one version of
/lib/ld-linux.so.2, all attempts to select a different version
of libc.so.6 via LD_LIBRARY_PATH will fail with a message similar
to this:
# attempting to use newer libc.so.6 with older ld-linux.so.2
./a.out: /lib/ld-linux.so.2: version `GLIBC_2.2.3' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.5-build/libc.so.6
or this:
# attempting to use older libc.so.6 with newer ld-linux.so.2
./a.out: ./libc.so.6: version `GLIBC_2.3' not found (required by /lib/libdl.so.2)
> But I
> think you'll find that the later glibc works fine for executables
> compiled against an earlier glibc, since symbols are individually
> versioned!
Properly built executables, using documented glibc interfaces,
should work on newer versions of glibc.
However, the 3rd party app may have used undocumented interfaces
or other "internal" glibc details, and that may prevent it from
working with newer glibc.
There is also the issue of support. Assume the app crashes. OP
calls into tech support, and they say: "sorry, you are running
glibc-2.3.2, and we don't support that".
>> running all the programs that then when I want to run the other program
>> I would "switch" over to the older version. Is there someway I can do
>> this using either a shell script that creates and destructs symlinks as
Simlinks will not work either for the "version mismatch" reason
explained above.
Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
> Shouldn't using "LD_ASSUME_KERNEL" be the most straightforward?
This allows one to select from different compilations of the *same*
version of glibc (i.e. select between i386, i686 or NPTL version).
It does *not* allow one to select between multiple *versions*
of glibc. For that, you must use rtldi
(http://bitwagon.com/rtldi/rtldi.html), or binary-edit the
executable, or rebuild it with a different PT_INTERP.
> Yes, but not trivially. Details here:
It IS trivial.
> http://bitwagon.com/rtldi/rtldi.html
>> Sure - no problem. Use LD_LIBRARY_PATH in a wrapper script.
> This will not work for glibc *at all*, although it does work for
Of course it works! I do it all the time (I run glibc 2.1 and things like
skype come precompiled against glibc 2.3 or so nowadays).
> other libraries. The reason: glibc consists of many pieces, which
> all must match *exactly*. One of the pieces that must match is
Thanks, but that's making a mountain out of a molehill. What you are
saying is that libc and other libraries call other libraries, which call
other libraries, etc. And all of those must be the right ones so that
they don't call the wrong libc. Yeah. So? I put the closure of the
library's callset in the same directory and set LD_LIBRARY_PATH to it.
Here's my list for Skype:
% ll /usr/local/skype/lib/
-rwxr-xr-x 1 ptb 90248 Oct 25 09:34 ld-2.3.2.so*
lrwxrwxrwx 1 root 11 Oct 25 09:34 ld-linux.so.2 -> ld-2.3.2.so*
-rw-r--r-- 1 ptb 3552 Oct 25 09:44 libBrokenLocale-2.3.2.so
lrwxrwxrwx 1 root 24 Oct 25 09:46 libBrokenLocale.so.1 -> libBrokenLocale-2.3.2.so
-rw-r--r-- 1 ptb 9532 Oct 25 09:44 libanl-2.3.2.so
lrwxrwxrwx 1 root 15 Oct 25 09:46 libanl.so.1 -> libanl-2.3.2.so
-rwxr-xr-x 1 ptb 1244688 Oct 25 09:45 libc-2.3.2.so*
lrwxrwxrwx 1 root 13 Oct 25 09:27 libc.so.6 -> libc-2.3.2.so*
-rw-r--r-- 1 ptb 18780 Oct 25 09:45 libcrypt-2.3.2.so
lrwxrwxrwx 1 root 17 Oct 25 09:46 libcrypt.so.1 -> libcrypt-2.3.2.so
-rw-r--r-- 1 ptb 9872 Oct 25 09:45 libdl-2.3.2.so
lrwxrwxrwx 1 root 14 Oct 25 09:39 libdl.so.2 -> libdl-2.3.2.so
-rw-r--r-- 1 ptb 134496 Oct 25 09:45 libm-2.3.2.so
lrwxrwxrwx 1 root 13 Oct 25 09:27 libm.so.6 -> libm-2.3.2.so
-rw-r--r-- 1 ptb 73528 Oct 25 09:45 libnsl-2.3.2.so
lrwxrwxrwx 1 root 15 Oct 25 09:47 libnsl.so.1 -> libnsl-2.3.2.so
-rw-r--r-- 1 ptb 27304 Oct 25 09:45 libnss_compat-2.3.2.so
lrwxrwxrwx 1 root 22 Oct 25 09:47 libnss_compat.so.2 -> libnss_compat-2.3.2.so
-rw-r--r-- 1 ptb 13976 Oct 25 09:45 libnss_dns-2.3.2.so
lrwxrwxrwx 1 root 19 Oct 25 09:48 libnss_dns.so.2 ->
libnss_dns-2.3.2.so
-rw-r--r-- 1 ptb 34520 Oct 25 09:45 libnss_files-2.3.2.so
lrwxrwxrwx 1 root 21 Oct 25 09:40 libnss_files.so.2 -> libnss_files-2.3.2.so
-rw-r--r-- 1 ptb 14268 Oct 25 09:45 libnss_hesiod-2.3.2.so
lrwxrwxrwx 1 root 22 Oct 25 09:48 libnss_hesiod.so.2 -> libnss_hesiod-2.3.2.so
-rw-r--r-- 1 ptb 32480 Oct 25 09:45 libnss_nis-2.3.2.so
lrwxrwxrwx 1 root 19 Oct 25 09:49 libnss_nis.so.2 -> libnss_nis-2.3.2.so
-rw-r--r-- 1 ptb 39864 Oct 25 09:45 libnss_nisplus-2.3.2.so
lrwxrwxrwx 1 root 23 Oct 25 09:49 libnss_nisplus.so.2 -> libnss_nisplus-2.3.2.so
-rw-r--r-- 1 ptb 81127 Oct 25 09:32 libpthread-0.10.so
lrwxrwxrwx 1 root 18 Oct 25 09:33 libpthread.so.0 -> libpthread-0.10.so
-rw-r--r-- 1 ptb 64924 Oct 25 09:45 libresolv-2.3.2.so
lrwxrwxrwx 1 root 18 Oct 25 09:50 libresolv.so.2 -> libresolv-2.3.2.so
-rw-r--r-- 1 ptb 27044 Oct 25 09:45 librt-2.3.2.so
lrwxrwxrwx 1 root 14 Oct 25 09:51 librt.so.1 -> librt-2.3.2.so
-rw-r--r-- 1 ptb 7844 Oct 25 09:45 libutil-2.3.2.so
lrwxrwxrwx 1 root 16 Oct 25 09:50 libutil.so.1 -> libutil-2.3.2.so
Yeah, you also need to start the executable by calling the correct
ld-linux.so with it as target. Here's the script I use:
#! /bin/sh
SKYPEHOME=/usr/local/skype
#LD_TRACE_LOADED_OBJECTS=1
LD_BIND_NOW=1
SKYPEBIN=$SKYPEHOME/bin
SKYPELIB=$SKYPEHOME/lib
export LD_LIBRARY_PATH=$SKYPELIB
SKYPEBINARY=$SKYPEBIN/skype
SKYPELOADER=$SKYPELIB/ld-linux.so.2
exec $SKYPELOADER $SKYPEBINARY "$@"
> /lib/ld-linux.so.2. Since you can only have one version of
> /lib/ld-linux.so.2, all attempts to select a different version
Nah, you can have as many of those as you like too! See script above for what
to do.
>> But I
>> think you'll find that the later glibc works fine for executables
>> compiled against an earlier glibc, since symbols are individually
>> versioned!
> Properly built executables, using documented glibc interfaces,
> should work on newer versions of glibc.
Indeed.
> However, the 3rd party app may have used undocumented interfaces
> or other "internal" glibc details, and that may prevent it from
> working with newer glibc.
I doubt it. DOn't suspect until you have need to!
> There is also the issue of support. Assume the app crashes. OP
> calls into tech support, and they say: "sorry, you are running
> glibc-2.3.2, and we don't support that".
But he isn't. He is running whatever he sets up to run.
Peter
>> Shouldn't using "LD_ASSUME_KERNEL" be the most straightforward?
> This allows one to select from different compilations of the *same*
> version of glibc (i.e. select between i386, i686 or NPTL version).
> It does *not* allow one to select between multiple *versions*
> of glibc. For that, you must use rtldi
> (http://bitwagon.com/rtldi/rtldi.html), or binary-edit the
> executable, or rebuild it with a different PT_INTERP.
Indeed, was under the impression that it would probably because
some Oracle installation needed an older glibc and you had to set
"LD_ASSUME_KERNEL". Taking a closer look you had to execute some
script in addition which did the trick with this lines (the first
matters):
export LDEMULATION=elf_i386_glibc21
export GCC_EXEC_PREFIX=/usr/i386-glibc21-linux/lib/gcc-lib/
At least setting LDEMULATION seems to offer another possibility
for the task. ;-)
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvp...@urvzvat.qr | perl -pe 'y/a-z/n-za-m/'
#bofh excuse 83: Support staff hung over, send aspirin and
come back LATER.
I installed glibc 2.2.2 into /lib/glib2.2 and from that directory I
have executed:
./lib/ld-linux.so.2 /bin/vi
So what I'm expect to happen here is for the loader I've just installed
to load vi from my bin directory, i.e. I want my old vi program to load
using the *NEW* libc. Unfortunately, when I attempt to do this, vi
reports that it cannot load libtermcap.so.2. This suggests to me that I
need to have installed this library in my /lib/glib2.2/lib directory,
since the version in /lib has been compiled against my old version of
glibc 2.3.2
Any ideas?
> I installed glibc 2.2.2 into /lib/glib2.2 and from that directory I
> have executed:
> ./lib/ld-linux.so.2 /bin/vi
Not sufficient. Set LD_LIBRARY_PATH to /lib/glib2.2.
And carry on from there.
> using the *NEW* libc. Unfortunately, when I attempt to do this, vi
> reports that it cannot load libtermcap.so.2. This suggests to me that I
As I said.
> need to have installed this library in my /lib/glib2.2/lib directory,
Of course.
Peter
The program that I want to use has been compiled against 2.2.2. The
current version I have is 2.3.2. I have therefore installed glibc 2.2.2
to co-exist with my newer glibc version. I can run programs using the
2.2.2 version of ld-linux.so but this does not allow me to execute
programs that I already have on my system ( "/bin/vi" from my example )
because these have been compiled against the newer version of glibc.
Indeed, when I attempt to execute this program using the 2.2.2 loader
(ld-linux) it complains:
"/lib/glibc2.2/lib/libc.so.6: version `GLIBC_2.3' not found (required
by /bin/vi)"
What this is telling me is that vi has some unresolved symbols, that
would ordinarily be contained within the libc library, but since I am
using an old version of the library, these symbols do not exist.
If I run the command:
[root@localhost lib]# eu-readelf --all /bin/vi | grep "GLIBC_2.3"
13: 08049828 114 FUNC GLOBAL DEFAULT UNDEF
__ctype_tolower_loc@GLIBC_2.3 (5)
82: 08049be8 114 FUNC GLOBAL DEFAULT UNDEF
__ctype_toupper_loc@GLIBC_2.3 (5)
123: 08049e08 114 FUNC GLOBAL DEFAULT UNDEF
__ctype_b_loc@GLIBC_2.3 (5)
12: 1 *global* 5 GLIBC_2.3(libc.so.6)
82: 5 GLIBC_2.3(libc.so.6) 2 GLIBC_2.0(libc.so.6)
122: 0 *local* 5 GLIBC_2.3(libc.so.6)
0x0010: Name: GLIBC_2.3 Flags: none Version: 5
I can see that the "vi" executable requires the symbols
__ctype_to_lower_loc (etc...), from GLIBC_2.3. In addition to this I
can see that the vi requires symbols from GLIBC_[2.0, 2.3]:
eu-readelf --all /bin/vi | tail
Version needs section [ 7] '.gnu.version_r' contains 1 entry:
Addr: 0x08049330 Offset: 0x001330 Link to section: [ 5] '.dynstr'
000000: Version: 1 File: libc.so.6 Cnt: 4
0x0010: Name: GLIBC_2.3 Flags: none Version: 5
0x0020: Name: GLIBC_2.2 Flags: none Version: 4
0x0030: Name: GLIBC_2.1 Flags: none Version: 3
0x0040: Name: GLIBC_2.0 Flags: none Version: 2
Therefore, if I run my program in the manner above, the only symbols it
will require will be those from GLIB_[2.0, 2.2], and these will be
statisfied.
Is this hypothesis correct?
Thanks,
Stephen
What do you mean by that? You need to put the extra libraries in a
directory of their own and set LD_LIBRARY_PATH.
> I can run programs using the
> 2.2.2 version of ld-linux.so
Which programs? You only want to do that for 2.2.2 executables.
> but this does not allow me to execute
> programs that I already have on my system ( "/bin/vi" from my example )
It might. I don't really see why not, but perhaps it depends on the
executable and what external symbols are referenced. If it doesn't call
libdl or something like that, you may be OK.
But why on earth would you do this?
> Therefore, if I run my program in the manner above, the only symbols it
> will require will be those from GLIB_[2.0, 2.2], and these will be
> statisfied.
> Is this hypothesis correct?
Who knows. What you said was all confused! What are you trying to do?
Peter
> It IS trivial.
No, it isn't.
>
>> This will not work for glibc *at all*, although it does work for
>
> Of course it works! I do it all the time (I run glibc 2.1 and things like
> skype come precompiled against glibc 2.3 or so nowadays).
No, you don't. What you *are* doing is running your executables in
a *special* way, by running them with '/path/to/loader a.out'.
This breaks some programs outright; breaks all other programs
that want to fork()/exec() anything else, and hinders the use of gdb.
>> Since you can only have one version of
>> /lib/ld-linux.so.2, all attempts to select a different version
>
>
> Nah, you can have as many of those as you like too! See script above for what
You can't have many instances of file named '/lib/ld-linux.so.2'
(except for chroot(), of course).
You can have mane versions of the loader, but they can't be all
named /lib/ld-linux.so.2. The fact that this absolute path is
hard-coded into all dynamic executables, is what necessitates rtldi.
> At least setting LDEMULATION seems to offer another possibility
> for the task. ;-)
I've never seen LDEMULATION anywhere ...
$ cd /usr/src/redhat/SOURCES/glibc-2.3.2-200310271512
$ find . -type f | xargs grep 'LD.*EMULATION'
# no output
Aha, it is used by the ld(1) at *build* time.
The runtime loader doesn't use it.
Since the OP is not in a position to relink 3rd party executables,
I doubt LDEMULATION will do him any good.
>> At least setting LDEMULATION seems to offer another possibility
>> for the task. ;-)
> I've never seen LDEMULATION anywhere ...
> $ cd /usr/src/redhat/SOURCES/glibc-2.3.2-200310271512
> $ find . -type f | xargs grep 'LD.*EMULATION'
> # no output
> Aha, it is used by the ld(1) at *build* time.
> The runtime loader doesn't use it.
Looks like, never used it either, beside the mentioned Oracle
installation which does relink the db.
> Since the OP is not in a position to relink 3rd party executables,
> I doubt LDEMULATION will do him any good.
Rereading the OP he might want to install the various "compat-*"
rpm packages coming with his distro for backwards comparability and
see if this fixes things.
BTW
GNU grep has a "-r" option.
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvp...@urvzvat.qr | perl -pe 'y/a-z/n-za-m/'
#bofh excuse 200: The monitor needs another box of pixels.
> I am running an old version of RedHat linux (Enterprise v.3) for
> backward compatiblity with some commercial tools I need to use. The
> version that I have uses glibc 2.3.2 and everything works fine.
> The problem I am having is that I have to use another program, that is
> only supported for RedHat Linux 6.2 and 7.1. Unfortunately, these
You could try installing the various "compat-*" rpm packages coming
with your distro and test if this fixes things.
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvp...@urvzvat.qr | perl -pe 'y/a-z/n-za-m/'
#bofh excuse 362: Plasma conduit breach
I've had a look at your program, but I'm not entirely sure how it how
it is to be used. How would I invoke it to run a program...
Thanks
>> It IS trivial.
> No, it isn't.
>>> This will not work for glibc *at all*, although it does work for
>>
>> Of course it works! I do it all the time (I run glibc 2.1 and things like
>> skype come precompiled against glibc 2.3 or so nowadays).
> No, you don't. What you *are* doing is running your executables in
> a *special* way, by running them with '/path/to/loader a.out'.
Yes, I do, and yes I am. Your definition of "special way" doesn't match
mine! Using ld-linux.so as a program loader is what we all do all the
time. You get the kernel to do it, and I get my fingers to do it.
> This breaks some programs outright; breaks all other programs
It would possibly break some programs that rely on figuring out who they
are pretending to be today by looking at the name of the executable as
they are called. Tough. Renaming their executable would break them
too.
> that want to fork()/exec() anything else, and hinders the use of gdb.
Eh? No - it doesn't break fork+exec, I can assure you! As to gdb, that's
a weak a point as I've heard all week.
>>> Since you can only have one version of
>>> /lib/ld-linux.so.2, all attempts to select a different version
>>
>> Nah, you can have as many of those as you like too! See script above for what
> You can't have many instances of file named '/lib/ld-linux.so.2'
Sure you can't (unless you like playing with chroot, which I don't).
> (except for chroot(), of course).
Hic.
Peter
> I've had a look at your program,
It isn't my -- I didn't participate in its development in any way.
> but I'm not entirely sure how it how
> it is to be used. How would I invoke it to run a program...
You have to use a binary editor (e.g. emacs hexl-mode) to make
/path/to/rtldi the loader of your 3rd party binary (i.e. you
overwrite the "/lib/ld-linux.so.2" string in the executable with
"/2.2.4/rtldi\0")
>>> Of course it works! I do it all the time (I run glibc 2.1 and things like
>>> skype come precompiled against glibc 2.3 or so nowadays).
>
>> No, you don't. What you *are* doing is running your executables in
>> a *special* way, by running them with '/path/to/loader a.out'.
>
> Yes, I do, and yes I am. Your definition of "special way" doesn't match
> mine! Using ld-linux.so as a program loader is what we all do all the
> time. You get the kernel to do it, and I get my fingers to do it.
Allright, it is a question of terminology.
You said: "It is trivial to use LD_LIBRARY_PATH to select
a different version of glibc".
That isn't true. You must "in addition" run your executables with
"/path/to/loader ./a.out" instead of "./a.out". You may be in the
habit of always running them this way, but few others are probably
even aware that that's possible.
>> breaks all other programs
>> that want to fork()/exec() anything else, and hinders the use of gdb.
>
> Eh? No - it doesn't break fork+exec, I can assure you!
You can assure me all you want, but that doesn't change the facts.
Here are my facts:
$ /lib/libc.so.6 | head -1
GNU C Library stable release version 2.1.3, by Roland McGrath et al.
$ cat junk.c
int main(int argc, char *argv[])
{
if (1 < argc) {
int pid = fork();
if (0 == pid) {
execvp(argv[1], &argv[1]);
_exit(1);
} else {
int status;
wait(&status);
}
}
return 0;
}
$ gcc -g junk.c && ./a.out && echo ok && ./a.out /bin/date
ok
Tue Nov 8 20:12:00 PST 2005
Good so far. Now invoke it using an "equivalent" of your script:
$ LD_LIBRARY_PATH=/usr/src/redhat/SOURCES/glibc-2.2.4-build \
/usr/src/redhat/SOURCES/glibc-2.2.4-build/elf/ld.so ./a.out && echo ok
ok
Now let's try fork()/exec():
$ LD_LIBRARY_PATH=/usr/src/redhat/SOURCES/glibc-2.2.4-build \
/usr/src/redhat/SOURCES/glibc-2.2.4-build/elf/ld.so ./a.out /bin/date
/bin/date: /lib/ld-linux.so.2: version `GLIBC_2.2.3' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6)
/bin/date: /lib/ld-linux.so.2: version `GLIBC_2.2' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6)
Guess what? It didn't work.
If a.out was a 3rd party app, and if it attempted popen(3),
or system(3), or fork()/exec(), it would not work as expected in
the environment that your script creates either.
Now, this situation can be fixed like so:
$ /usr/src/redhat/SOURCES/glibc-2.2.4-build/elf/ld.so --library-path /usr/src/redhat/SOURCES/glibc-2.2.4-build ./a.out /bin/date
Tue Nov 8 20:21:24 PST 2005
But at that point, LD_LIBRARY_PATH is nowhere in the picture at all!
> That isn't true.
It is true ...
> You must "in addition" run your executables with
> "/path/to/loader ./a.out" instead of "./a.out".
That's part of the triviality. Is this supposed to be difficult? No,
it isn't. Is it supposed to be non-obvious? No, it isn't. Therefore it
is trivial.
From WordNet (r) 1.6 [wn]:
trivial
adj 1: (informal terms) small and of little importance; "a fiddling
sum of money"; "a footling gesture"; "our worries are
lilliputian compared with those of countries that are
at war"; "a little (or small) matter"; "a dispute over
niggling details"; "limited to petty enterprises";
"piffling efforts"; "giving a police officer a free
meal may be against the law, but it seems to be a
picayune infraction" [syn: {fiddling}, {footling}, {lilliputian},
{little}, {niggling}, {piddling}, {piffling}, {petty},
{picayune}]
2: obvious and dull; "trivial conversation"; "commonplace
prose" [syn: {banal}, {commonplace}]
3: of little substance or significance; "a few superficial
editorial changes"; "only trivial objections" [syn: {superficial}]
4: concerned with trivialities; "a trivial young woman"; "a
trivial mind"
5: not large enough to consider or notice [syn: {insignificant}]
Or rather more amusingly:
trivial /adj./ 1. Too simple to bother detailing. 2. Not
worth the speaker's time. 3. Complex, but solvable by methods so
well known that anyone not utterly {cretinous} would have
thought of them already. 4. Any problem one has already solved
(some claim that hackish `trivial' usually evaluates to `I've
seen it before'). Hackers' notions of triviality may be quite at
variance with those of non-hackers. See {nontrivial},
{uninteresting}.
The physicist Richard Feynman, who had the hacker nature to an
amazing degree (see his essay "Los Alamos From Below" in
"Surely You're Joking, Mr. Feynman!"), defined `trivial
theorem' as "one that has already been proved".
> You may be in the
> habit of always running them this way, but few others are probably
> even aware that that's possible.
That's neither here nor there. The question is whether it is difficult or
non-obvious. If it is one or the other, then it is not trivial. But I
claim that it is both easy and obvious, hence "trivial".
>> Eh? No - it doesn't break fork+exec, I can assure you!
> You can assure me all you want, but that doesn't change the facts.
> Here are my facts:
> $ /lib/libc.so.6 | head -1
> GNU C Library stable release version 2.1.3, by Roland McGrath et al.
> $ cat junk.c
> int main(int argc, char *argv[])
> {
> if (1 < argc) {
Most programs take an argument or an option.
> int pid = fork();
> if (0 == pid) {
> execvp(argv[1], &argv[1]);
> _exit(1);
> } else {
> int status;
> wait(&status);
> }
> }
> return 0;
> }
> $ gcc -g junk.c && ./a.out && echo ok && ./a.out /bin/date
> ok
> Tue Nov 8 20:12:00 PST 2005
> Good so far. Now invoke it using an "equivalent" of your script:
> $ LD_LIBRARY_PATH=/usr/src/redhat/SOURCES/glibc-2.2.4-build \
> /usr/src/redhat/SOURCES/glibc-2.2.4-build/elf/ld.so ./a.out && echo ok
> ok
> Now let's try fork()/exec():
> $ LD_LIBRARY_PATH=/usr/src/redhat/SOURCES/glibc-2.2.4-build \
> /usr/src/redhat/SOURCES/glibc-2.2.4-build/elf/ld.so ./a.out /bin/date
> /bin/date: /lib/ld-linux.so.2: version `GLIBC_2.2.3' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6)
> /bin/date: /lib/ld-linux.so.2: version `GLIBC_2.2' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6)
Interesting. Fork and exec work fine. What didn't work was the program
execed, which appears to be a 2.2.3 executable, and which still had in
its environment your value of LD_LIBRARY_PATH which pointed it at glibc
2.2.4 instead.
I misunderstood your complaint.
Try again, this time with LD_LIBRARY_PATH a colon separated sequence of
places to look.
Interesting.
> Guess what? It didn't work.
The nature of "it" is not what I understood you to mean.
> If a.out was a 3rd party app, and if it attempted popen(3),
> or system(3), or fork()/exec(), it would not work as expected in
> the environment that your script creates either.
> Now, this situation can be fixed like so:
> $ /usr/src/redhat/SOURCES/glibc-2.2.4-build/elf/ld.so --library-path /usr/src/redhat/SOURCES/glibc-2.2.4-build ./a.out /bin/date
I don't believe my ld.so takes options. At least its man page does not
say so. But I suppose that the path does not get into the environment
that way, so it would work in your instance, but NOT if the execed
program were another 2.2.4 executable.
Peter
>> You must "in addition" run your executables with
>> "/path/to/loader ./a.out" instead of "./a.out".
>
> That's part of the triviality. Is this supposed to be difficult? No,
> it isn't. Is it supposed to be non-obvious? No, it isn't. Therefore it
I don't think that's obvious.
Would you care to point me at a document that even states what is
supposed to happen when the loader is invoked that way?
>> /bin/date: /lib/ld-linux.so.2: version `GLIBC_2.2' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6)
>
> Interesting. Fork and exec work fine.
Right. It's the exec()ed program that fails.
> What didn't work was the program execed, which appears to be a
> 2.2.3 executable, and which still had in its environment your value
> of LD_LIBRARY_PATH which pointed it at glibc 2.2.4 instead.
That executable is /bin/date, and it *just* ran on that very same
glibc-2.1 system without any problems.
How could it suddenly become "a 2.2.3" executable?
> I misunderstood your complaint.
>
> Try again, this time with LD_LIBRARY_PATH a colon separated sequence of
> places to look.
That has nothing do with the problem, and it wouldn't help.
[If you still think it should help, pray tell *what* I should set
my LD_LIBRARY_PATH to.]
The problem is that LD_LIBRARY_PATH directs the a.out and
*all of its children* (including /bin/date) to use the alternative
glibc, but the "invoke loader directly" applies *only* to the a.out,
and does not apply to any of its children.
Hence they all get incorrect (version-inconsistent) execution
environment, and all fail to run.
This may be entirely *trivial*, but then *you* should have understood it :)
> The program that I want to use has been compiled against 2.2.2. The
Steve,
did you try installing the various (quite a few) "compat-*" rpm
packages coming with your distro (RHEL 3) for backwards
compatibility as I already mentioned and see if this improves
things?
[..]
--
Michael Heiming (X-PGP-Sig > GPG-Key ID: EDD27B94)
mail: echo zvp...@urvzvat.qr | perl -pe 'y/a-z/n-za-m/'
#bofh excuse 371: Incorrectly configured static routes on
the corerouters.
>>> You must "in addition" run your executables with
>>> "/path/to/loader ./a.out" instead of "./a.out".
>>
>> That's part of the triviality. Is this supposed to be difficult? No,
>> it isn't. Is it supposed to be non-obvious? No, it isn't. Therefore it
> I don't think that's obvious.
> Would you care to point me at a document that even states what is
> supposed to happen when the loader is invoked that way?
I believe "the info flie for ld[.so]" should be it. Not that I have
ever read it without shuddering, so I cannot go and check (because of my
nerves, and also because I long ago deleted it to save space, and
nerves).
It's sort of common knowledge. I think I first cottoned to it when I saw
Linus do it for some now-forgtten reason, but I should have realized
before then that the link-loader gets called by the kernel (or maybe the
elf header data, who knows!) in order to resolve linkages, and that it
probably is a C program that figures out what it should be doing via its
command line.
Plus I had to do the relink dance by hand often enough when installing a
new libc (in the days when only H.J. Lu knew the magic incantation to
compile certain bits of libc) to have learned the hard way how to get out
of various of my mess-ups. I only used the neurons I had.
>> What didn't work was the program execed, which appears to be a
>> 2.2.3 executable, and which still had in its environment your value
>> of LD_LIBRARY_PATH which pointed it at glibc 2.2.4 instead.
> That executable is /bin/date, and it *just* ran on that very same
> glibc-2.1 system without any problems.
2.1? You too (like me) run glibc 2.1? I thought I was the only human in
this part of the galaxy to still do so.
> How could it suddenly become "a 2.2.3" executable?
By being always so. Mind you, I don't see why it isn't happy with the
2.2.4 library if it was happy with the 2.1.x library.
>> Try again, this time with LD_LIBRARY_PATH a colon separated sequence of
>> places to look.
> That has nothing do with the problem, and it wouldn't help.
> [If you still think it should help, pray tell *what* I should set
> my LD_LIBRARY_PATH to.]
I was kind of planning on you including later in that path some
directory with a glibc containing a symbol that would make /bin/date
happy ever after.
> The problem is that LD_LIBRARY_PATH directs the a.out and
> *all of its children*
I don't agree with that diagnosis. It is in the environment at the time
that the process did an execv, and it stayed there. The children might or
might not get the same virus, according to a number of factors.
> (including /bin/date) to use the alternative
> glibc, but the "invoke loader directly" applies *only* to the a.out,
> and does not apply to any of its children.
I think there was a missing "should" or "ought to" there. "for reasons of
sanity". This is what I said in my snipped reply, didn't I?
> Hence they all get incorrect (version-inconsistent) execution
> environment, and all fail to run.
> This may be entirely *trivial*, but then *you* should have understood it :)
That is what I DID understand (and said I understood), and why I
suggested that you add something to the path so that more places to look
may be inherited by the poor process that does an exec in a space that
has that environment. What I don't understand is why an appropriately
versioned symbol should not be found in the existing glibc 2.2.4 if it is
in a directory later in the ld search path.
Hic.
Peter
>> Would you care to point me at a document that even states what is
>> supposed to happen when the loader is invoked that way?
>
> I believe "the info flie for ld[.so]" should be it.
The "man 8 ld.so" on RedHat 6.2 doesn't mention this, but the one
on RedHat 8.0 does ...
> It's sort of common knowledge.
Only among people who play with different glibc versions.
> I should have realized
> before then that the link-loader gets called by the kernel (or maybe the
> elf header data, who knows!) in order to resolve linkages, and that it
> probably is a C program that figures out what it should be doing via its
> command line.
It's not an "ordinary" C program by any stretch, and it
*specifically* determines that it was invoked directly (rather then
by kernel), and takes a different path through the code to handle
that special case.
Even though all other ELF platforms have ld.so equivalent, none
(AFAIK) implements that "special" handling.
> Mind you, I don't see why it isn't happy with the
> 2.2.4 library if it was happy with the 2.1.x library.
You still don't understand the problem. /bin/date is perfectly
happy with version 2.2.4 of libc.so.6
It is the libc.so.6 that is unhappy. It is unhappy about its mismatch
with /lib/ld-linux.so.2, because *that* file is the "native" system
one (i.e. it matches glibc 2.1; not 2.2.4).
>> [If you still think it should help, pray tell *what* I should set
>> my LD_LIBRARY_PATH to.]
>
> I was kind of planning on you including later in that path some
> directory with a glibc containing a symbol that would make /bin/date
> happy ever after.
It doesn't matter what I have later in that path: libc.so.6 is
searched for *once*. If the loader finds the 2.2.4 version,
no matter what other versions could be found later in that path,
/bin/date will *not* become happy.
>> The problem is that LD_LIBRARY_PATH directs the a.out and
>> *all of its children*
>
> I don't agree with that diagnosis.
Provide your own then.
> It is in the environment at the time
> that the process did an execv, and it stayed there.
Correct.
> The children might or
> might not get the same virus, according to a number of factors.
>
Huh?
>> (including /bin/date) to use the alternative
>> glibc, but the "invoke loader directly" applies *only* to the a.out,
>> and does not apply to any of its children.
>
> I think there was a missing "should" or "ought to" there. "for reasons of
> sanity". This is what I said in my snipped reply, didn't I?
I lost you here.
>
>> Hence they all get incorrect (version-inconsistent) execution
>> environment, and all fail to run.
>
>> This may be entirely *trivial*, but then *you* should have understood it :)
>
> That is what I DID understand (and said I understood), and why I
> suggested that you add something to the path so that more places to look
> may be inherited by the poor process that does an exec in a space that
> has that environment. What I don't understand is why an appropriately
> versioned symbol should not be found in the existing glibc 2.2.4 if it is
> in a directory later in the ld search path.
I believe the paragraph above demonstrates that you still don't
understand the problem; but reject my explanation of it out of sheer
"I insist this is all trivial" conviction, despite all evidence to
the contrary.
Oh well, I give up; we've argued long enough ...
> It is the libc.so.6 that is unhappy. It is unhappy about its mismatch
> with /lib/ld-linux.so.2, because *that* file is the "native" system
> one (i.e. it matches glibc 2.1; not 2.2.4).
This is confusing. As far as I recall you execed a 2.2.4 (or 2.1?)
executable from a 2.2.3 executable in a 2.1 platform. You did that
by calling the 2.2.3 executable with the 2.2.3 loader after setting
LD_LIBRARY_PATH to point to a place where all the 2.2.3 libs could be
found. Correct?
It was the final executee (or one of its libraries) that complained
about not finding its symbols, yes?
Well, the solution is to put the libraries it wants somewhere later in
the LD_LIBRARY_PATH, so that the (versioned) symbols it wants can be
found in them.
> It doesn't matter what I have later in that path: libc.so.6 is
> searched for *once*.
There would be no sense in having versioned symbols at all if that were
the case. Would there? Hmm. The way I thought versioned symbols would
work was that one could search for the symbol with the right version
in many different libraries. You SEEM to be saying that one can search for
the symbol with the right version only in ONE library.
To me that seems nuts as a design. It means that the symbol tables of
only the first library of any given (so)name is loaded. But there is
no exponential increase in complexity having multiple symbol tables -
we know that because the loader does search multiple symbol tables.
> If the loader finds the 2.2.4 version,
> no matter what other versions could be found later in that path,
> /bin/date will *not* become happy.
Then there is a bug in the loader - it can't know in what library a
symbol is to be found, so it must search all the libraries it has
for that symbol. It has no need to discard symbol tables from more
libraries of the same soname in the path especially when the others
contain more symbols.
>> I don't agree with that diagnosis.
> Provide your own then.
ld-linux has a bug, according to your description.
>> The children might or
>> might not get the same virus, according to a number of factors.
>>
> Huh?
The program doesn't have to keep the same environment for the exec, and
the children don't have to keep it either. It's even usual to drop the
whole environment.
>>> glibc, but the "invoke loader directly" applies *only* to the a.out,
>>> and does not apply to any of its children.
>>
>> I think there was a missing "should" or "ought to" there. "for reasons of
>> sanity". This is what I said in my snipped reply, didn't I?
> I lost you here.
It's a tenses thing. "Should" expresses an authoratative order. "ought"
expresses moral impulsion.
>> That is what I DID understand (and said I understood), and why I
>> suggested that you add something to the path so that more places to look
>> may be inherited by the poor process that does an exec in a space that
>> has that environment. What I don't understand is why an appropriately
>> versioned symbol should not be found in the existing glibc 2.2.4 if it is
>> in a directory later in the ld search path.
> I believe the paragraph above demonstrates that you still don't
> understand the problem; but reject my explanation of it out of sheer
I do not and have never rejected your explanation - on the contrary, I
have agreed with you throughout. I suggested a different work-around to
you based on MY understanding that versioned symbols would be searched
for in all libraries in the path, independent of soname (in the sense of
"multiple libraries with the same soname may be examined if present").
If that is not the case, feel free to correct my understanding. Your
workaround does not depend on my undestanding one way or another. It's
immune. OTOH my ld-linux.so does not take the -library_path option, or
whatever it was.
> "I insist this is all trivial" conviction, despite all evidence to
> the contrary.
It's trivial whatever the fact of the matter - it merely requires looking
at and doing the apporpriate thing about it. That requires no genius.
> Oh well, I give up; we've argued long enough ...
About nothing!
Peter
> This is confusing. As far as I recall you execed a 2.2.4 (or 2.1?)
> executable from a 2.2.3 executable in a 2.1 platform. You did that
> by calling the 2.2.3 executable with the 2.2.3 loader after setting
> LD_LIBRARY_PATH to point to a place where all the 2.2.3 libs could be
> found. Correct?
No. There are 2 executables in the picture: a.out and /bin/date.
Both are compiled and run on a glibc-2.1 (RedHat 6.2) system.
The second exe (/bin/date) is fork()ed/exec()ed by the first one.
> It was the final executee (or one of its libraries) that complained
> about not finding its symbols, yes?
Correct; except it's not the executable that doesn't find GLIBC_2.2.3
symbol; instead glibc-2.2.4-build/libc.so.6 is the "unhappy" party.
> Well, the solution is to put the libraries it wants somewhere later in
> the LD_LIBRARY_PATH, so that the (versioned) symbols it wants can be
> found in them.
No, that's not the solution.
>> It doesn't matter what I have later in that path: libc.so.6 is
>> searched for *once*.
>
> There would be no sense in having versioned symbols at all if that were
> the case.
That *is* the case. When the loader searches for 'libc.so.6' *file*,
it will stop as soon as it finds such file in its search path,
and will never search for that *file* again.
You are thinking about searching for a symbol (in which case the
loader does search multiple libraries), but that doesn't have
anything to do with the problem I described.
> The way I thought versioned symbols would
> work was that one could search for the symbol with the right version
> in many different libraries.
There are different kinds of version dependencies.
The one you are thinking of is where the exe or DSO depends (imports)
a versioned function or data symbol, e.g.
$ nm /lib/libpthread.so.0 | grep fopen
U fopen@@GLIBC_2.1
For that kind of dependency, the loader will search all globally
available DSOs for a definition of fopen() with correct version.
[Actually, it will stop if it finds fopen() with no version info
at all, but that's a minor detail.]
But the dependency that causes /bin/date not to run is of a
different kind:
$ readelf -V glibc-2.2.4-build/libc.so.6 | grep -A10 'Version needs'
Version needs section '.gnu.version_r' contains 1 entries:
Addr: 0x0000000000015b98 Offset: 0x015b98 Link to section: 4 (.dynstr)
000000: Version: 1 File: ld-linux.so.2 Cnt: 5
0x0010: Name: GLIBC_2.1.1 Flags: none Version: 17
0x0020: Name: GLIBC_2.2.3 Flags: none Version: 16
0x0030: Name: GLIBC_2.1 Flags: none Version: 15
0x0040: Name: GLIBC_2.2 Flags: none Version: 14
0x0050: Name: GLIBC_2.0 Flags: none Version: 13
The info above tells the loader: "for this libc.so.6 to be usable,
there must be ld-linux.so.2, it must provide version *definitions*
for the 5 version symbols listed". It is *that* kind of dependency
which causes the problem for /bin/date.
The reason this causes problem, is that /bin/date, having been
invoked by the kernel directly (rather then with the "/path/to/loader
/bin/date" trick), and having its PT_INTERP set to
/lib/ld-linux.so.2, is now being loaded by *that* (glibc-2.1)
version. And that version has version definitions for:
$ readelf -V /lib/ld-linux.so.2 | grep -A10 'Version definition'
Version definition section '.gnu.version_d' contains 4 entries:
Addr: 0x00000000000014a8 Offset: 0x0014a8 Link: 3 (.dynstr)
000000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: ld-linux.so.2
0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: GLIBC_2.0
0x0038: Rev: 1 Flags: none Index: 3 Cnt: 2 Name: GLIBC_2.1
0x0054: Parent 1: GLIBC_2.0
0x005c: Rev: 1 Flags: none Index: 4 Cnt: 2 Name: GLIBC_2.1.1
0x0078: Parent 1: GLIBC_2.1
Since GLIBC_2.1.1, GLIBC_2.2 and GLIBC_2.2.3 are missing from
that list, this ld-linux.so.2 is incompatible with the
glibc-2.2.4-build/libc.so.6, and therefore the loader stops as soon
as it discovers that fact.
> You SEEM to be saying that one can search for
> the symbol with the right version only in ONE library.
I hope you understand this better now.
>> If the loader finds the 2.2.4 version (of libc.so.6),
>> no matter what other versions (of libc.so.6) could be found later in that path,
>> /bin/date will *not* become happy.
>
> Then there is a bug in the loader
Nope. There is no bug: everything is functioning as designed.
>>> I don't agree with that diagnosis.
>> Provide your own then.
> ld-linux has a bug, according to your description.
No. Your mechanism of selecting alternative version of glibc
(via LD_LIBRARY_PATH) is incompatible with the way my executable
exec()s /bin/date; but that's all.
> The program doesn't have to keep the same environment for the exec, and
> the children don't have to keep it either. It's even usual to drop the
> whole environment.
It is also usual *not* to modify the environment for children.
Which brings us back to my original point: selecting different
versions of glibc via LD_LIBRARY_PATH may or may not work for a 3rd
party executable; and understanding the conditions under which it
works or doesn't work is not entirely trivial.
> The second exe (/bin/date) is fork()ed/exec()ed by the first one.
And you execed the first one with the 2.2.3 link-loader with
LD_LIBRARY_PATH set to point at 2.2.3 libraries?
> "Peter T. Breuer" <p...@oboe.it.uc3m.es> writes:
>> It was the final executee (or one of its libraries) that complained
>> about not finding its symbols, yes?
> Correct; except it's not the executable that doesn't find GLIBC_2.2.3
> symbol; instead glibc-2.2.4-build/libc.so.6 is the "unhappy" party.
Where do we get anything related to 2.2.4 from? You said we were on a 2.1
system.
>> Well, the solution is to put the libraries it wants somewhere later in
>> the LD_LIBRARY_PATH, so that the (versioned) symbols it wants can be
>> found in them.
> No, that's not the solution.
Why not ... ?
>>> It doesn't matter what I have later in that path: libc.so.6 is
>>> searched for *once*.
>>
>> There would be no sense in having versioned symbols at all if that were
>> the case.
> That *is* the case. When the loader searches for 'libc.so.6' *file*,
> it will stop as soon as it finds such file in its search path,
> and will never search for that *file* again.
If it is searching for a _symbol_ it must search for the symbol (in the
libraries matching the sonames it is linked against found in the
LD_LIBRARY_PATH). If it is searching for a library (merely in order to
satisfy a soname link dependency) then you can supply it with that
library in the LD_LIBRARY_PATH ...
> You are thinking about searching for a symbol (in which case the
> loader does search multiple libraries), but that doesn't have
> anything to do with the problem I described.
> There are different kinds of version dependencies.
> The one you are thinking of is where the exe or DSO depends (imports)
> a versioned function or data symbol, e.g.
> $ nm /lib/libpthread.so.0 | grep fopen
> U fopen@@GLIBC_2.1
> For that kind of dependency, the loader will search all globally
> available DSOs for a definition of fopen() with correct version.
> [Actually, it will stop if it finds fopen() with no version info
> at all, but that's a minor detail.]
> But the dependency that causes /bin/date not to run is of a
> different kind:
> $ readelf -V glibc-2.2.4-build/libc.so.6 | grep -A10 'Version needs'
> Version needs section '.gnu.version_r' contains 1 entries:
> Addr: 0x0000000000015b98 Offset: 0x015b98 Link to section: 4 (.dynstr)
> 000000: Version: 1 File: ld-linux.so.2 Cnt: 5
> 0x0010: Name: GLIBC_2.1.1 Flags: none Version: 17
> 0x0020: Name: GLIBC_2.2.3 Flags: none Version: 16
> 0x0030: Name: GLIBC_2.1 Flags: none Version: 15
> 0x0040: Name: GLIBC_2.2 Flags: none Version: 14
> 0x0050: Name: GLIBC_2.0 Flags: none Version: 13
> The info above tells the loader: "for this libc.so.6 to be usable,
> there must be ld-linux.so.2, it must provide version *definitions*
> for the 5 version symbols listed". It is *that* kind of dependency
> which causes the problem for /bin/date.
But what's the problem with that? You put the appropriate ld-linux.so.2
in a directory in LD_LIBRARY_PATH, no? And why is glibc 2.2.4 being used?
> The reason this causes problem, is that /bin/date, having been
> invoked by the kernel directly (rather then with the "/path/to/loader
> /bin/date" trick), and having its PT_INTERP set to
> /lib/ld-linux.so.2, is now being loaded by *that* (glibc-2.1)
A 2.1 ld-linux.so.2, I presume you mean?
> version. And that version has version definitions for:
> $ readelf -V /lib/ld-linux.so.2 | grep -A10 'Version definition'
> Version definition section '.gnu.version_d' contains 4 entries:
> Addr: 0x00000000000014a8 Offset: 0x0014a8 Link: 3 (.dynstr)
> 000000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: ld-linux.so.2
> 0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: GLIBC_2.0
> 0x0038: Rev: 1 Flags: none Index: 3 Cnt: 2 Name: GLIBC_2.1
> 0x0054: Parent 1: GLIBC_2.0
> 0x005c: Rev: 1 Flags: none Index: 4 Cnt: 2 Name: GLIBC_2.1.1
> 0x0078: Parent 1: GLIBC_2.1
> Since GLIBC_2.1.1, GLIBC_2.2 and GLIBC_2.2.3 are missing from
> that list, this ld-linux.so.2 is incompatible with the
> glibc-2.2.4-build/libc.so.6, and therefore the loader stops as soon
But it is not incompatible with the 2.1 libc that I urged you to place
later in the LD_LIBRARY_PATH. Why doesn't it go and look at that? And
what is wrong with it being happy with a 2.2.4 libc (which only contains
more Name entries than it requires?).
> as it discovers that fact.
There is no "therefore". That is a bug.
>> You SEEM to be saying that one can search for
>> the symbol with the right version only in ONE library.
> I hope you understand this better now.
>>> If the loader finds the 2.2.4 version (of libc.so.6),
>>> no matter what other versions (of libc.so.6) could be found later in that path,
>>> /bin/date will *not* become happy.
>>
>> Then there is a bug in the loader
> Nope. There is no bug: everything is functioning as designed.
Then the bug is in the design. The 2.2.4 libc says it has all the Names
required by the loader used, so it should be happy. Why should it be
future-shocked by a library that says it is backward compatible with it?
> Which brings us back to my original point: selecting different
> versions of glibc via LD_LIBRARY_PATH may or may not work for a 3rd
> party executable; and understanding the conditions under which it
> works or doesn't work is not entirely trivial.
It looks trivial to me, whatever the reason is! It seems to require no
feats of genius.
Peter
>> The second exe (/bin/date) is fork()ed/exec()ed by the first one.
>
> And you execed the first one with the 2.2.3 link-loader with
> LD_LIBRARY_PATH set to point at 2.2.3 libraries?
Correct, except for "s/2.2.3/2.2.4/g"
>> Correct; except it's not the executable that doesn't find GLIBC_2.2.3
>> symbol; instead glibc-2.2.4-build/libc.so.6 is the "unhappy" party.
>
> Where do we get anything related to 2.2.4 from?
libc.so.6 version 2.2.4 is found on LD_LIBRARY_PATH first.
[BTW, I provided complete trace of commands I used; you could just
re-read that message and anwer all of these questions yourself].
> You said we were on a 2.1 system.
Yes. Where's the contradiction in that?
>>> Well, the solution is to put the libraries it wants somewhere later in
>>> the LD_LIBRARY_PATH, so that the (versioned) symbols it wants can be
>>> found in them.
>
>> No, that's not the solution.
>
> Why not ... ?
Because (as I already explained) no matter what else I add to the
LD_LIBRARY_PATH, the "wrong" (2.2.4) version of libc.so.6 will be
found and no matter how you modify the environment, ld-2.1.3.so
and libc-2.2.4.so will not "work together".
Ok, here is the proof:
/lib/ld-linux.so.2 and /lib/libc.so.6 are from glibc-2.1.3
/usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6 and
/usr/src/redhat/SOURCES/glibc-2.2.4-build/elf/ld.so are from glibc-2.2.4
$ L224=/usr/src/redhat/SOURCES/glibc-2.2.4-build
$ LD_LIBRARY_PATH=$L224:/usr/lib:/lib $L224/elf/ld.so ./a.out && echo ok
ok
$ LD_LIBRARY_PATH=$L224:/usr/lib:/lib $L224/elf/ld.so ./a.out /bin/date
/bin/date: /lib/ld-linux.so.2: version `GLIBC_2.2.3' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6)
/bin/date: /lib/ld-linux.so.2: version `GLIBC_2.2' not found (required by /usr/src/redhat/SOURCES/glibc-2.2.4-build/libc.so.6)
See? I told you it wouldn't work, and it didn't.
> If it is searching for a library (merely in order to
> satisfy a soname link dependency) then you can supply it with that
> library in the LD_LIBRARY_PATH ...
I *did* supply it with a library. It has no trouble finding libc.so.6
The trouble is that it finds the *wrong* libc.so.6
>> It is *that* kind of dependency
>> which causes the problem for /bin/date.
>
> But what's the problem with that? You put the appropriate ld-linux.so.2
> in a directory in LD_LIBRARY_PATH, no? And why is glibc 2.2.4 being used?
It doesn't matter where I put "appropriate" ld-linux.so.2
When a.out fork()s/exec()s /bin/date, the *kernel* will look at PT_INTERP
of /bin/date, will see *absolute* path to /lib/ld-linux.so.2 (which,
on that system is part of glibc-2.1.3), and will invoke *that* loader.
>> The reason this causes problem, is that /bin/date, having been
>> invoked by the kernel directly (rather then with the "/path/to/loader
>> /bin/date" trick), and having its PT_INTERP set to
>> /lib/ld-linux.so.2, is now being loaded by *that* (glibc-2.1)
>
> A 2.1 ld-linux.so.2, I presume you mean?
Yes.
>> Since GLIBC_2.1.1, GLIBC_2.2 and GLIBC_2.2.3 are missing from
>> that list, this ld-linux.so.2 is incompatible with the
>> glibc-2.2.4-build/libc.so.6, and therefore the loader stops as soon
>
> But it is not incompatible with the 2.1 libc that I urged you to place
> later in the LD_LIBRARY_PATH. Why doesn't it go and look at that?
Because (as I explained earlier) the loader, while searching for
libc.so.6, stops *as soon* as it finds one such library.
The fact that another version of libc.so.6 is on the LD_LIBRARY_PATH
and which (if found) would have worked, doesn't do us any good.
> And
> what is wrong with it being happy with a 2.2.4 libc (which only contains
> more Name entries than it requires?).
It (the loader) is happy with the libc.so.6 (2.2.4) it found.
It's the libc.so.6 (2.2.4) that is unhappy with the loader (2.1.3).
It is unhappy because libc.so.6 and ld.so are tightly bound; they
*must* version match; they are parts of the same package, and they
know internal details of each other. They communicate via unstable
binary API. Any mismatch between them will cause hard-to-diagnose
crashes. The version info is merely a mechanism to stop with a
reasonable message before the inevitable crash, and to guarantee
both are using the same version of the API.
> There is no "therefore". That is a bug.
You could call it a bug. Glibc developers call it a feature.
>> Nope. There is no bug: everything is functioning as designed.
>
> Then the bug is in the design.
I agree: the fact that ld-linux.so.2 and libc.so.6 are in bed
together does make things more complicated then they ought to be ...
> The 2.2.4 libc says it has all the Names
> required by the loader used, so it should be happy. Why should it be
> future-shocked by a library that says it is backward compatible with it?
As explained above, it (the loader) *is* happy with the library.
But the library isn't happy with *it* :)
>> Which brings us back to my original point: selecting different
>> versions of glibc via LD_LIBRARY_PATH may or may not work for a 3rd
>> party executable; and understanding the conditions under which it
>> works or doesn't work is not entirely trivial.
>
> It looks trivial to me,
What looks trivial?
Selecting different glibc version, or understanding the reasons
why your method of doing that doesn't work for any application
doing fork()/exec()?