Date: Sat, 30 Jan 1999 16:06:04 -0700 (MST) From: Jason Gunthorpe <[EMAIL PROTECTED]>
On 30 Jan 1999, Alexandre Oliva wrote: > Obviously, this would have never been needed if old libraries had not > been replaced with (in)compatible versions, but the maintainers of > Debian have already taken this step, despite the fact that this would Look, it was not us that decided to do this. It was the upstream maintainers, other dists and a huge combination of factors. It is not in our power to choose a different direction to solve these problems, we must have libc6 xlib called libX11.so.6 and we must have libc5 called libX11.so.6 - that is what all the other dists did, that is the default and expected compilation behavoir of xlib and it is what all the new glibc binary-only programs are using (ie netscape) If you want to say that is a dumb way then fine, but you have not proposed an alternative to solving the versioning problem and you have not proposed an alternative way to handle the requirement of identical sonames and libtool continues to perpetuate this 'bad' behavoir and makes it worse by providing no way to get around it with the standard linux ld.so What you are saying, I think, is that you have two programs with A) DT_NEEDED libc.so.5, DT_NEEDED libX11.so.6 B) DT_NEEDED libc.so.6, DT_NEEDED libX11.so.6 Neither has DT_RPATH. The system has four libraries: libc.so.5 libc.so.6 libX11.so.6 with DT_NEEDED libc.so.5 libX11.so.6 with DT_NEEDED libc.so.6 You want programs A and B to both work, without modification. This was done by modifying the search algorithm used by the dynamic linker so that it chooses the version of libX11.so.6 which matches the version of libc.so.N used by the program. This was done by recording in /etc/ld.so.cache the version of libc which the shared library uses. The dynamic linker was modified to look in /etc/ld.so.cache for libraries which were not found in DT_RPATH, but to only select libraries listed in /etc/ld.so.cache which matched the version of the dynamic linker being used. Programs which are linked against different versions of libc must then use different dynamic linkers. There are in fact three different dynamic linkers which understand this ld.so.cache algorithm: the old a.out dynamic linker, the libc5 dynamic linker, and the glibc dynamic linker. I just spent some time looking at the ld.so sources. Interestingly, it seems to me that everything will work correctly in the sources I was looking at. That is because the libc5 dynamic linker on my system (RedHat 5.2) was modified to search the library cache before using the application's DT_RPATH. I think that is a hack that Debian is missing: it is the final hack to the libc5 dynamic linker to change the search path to account for the moved shared libraries even when rpath is used. I have appended the RedHat patch below. This is to ld.so-1.9.5. Of course, this will technically break the handling of DT_RPATH. However, we've already determined that DT_RPATH binaries will not work correctly anyhow, because the shared libraries were moved. So using this patch should not make us any worse off. Indeed libtool causes such a severe problem that if you take a libtool program, compile it on a libc5 Slackware and try to run it on -any- glibc system IT WILL NOT WORK. This is not quite right. As I described above, glibc and libc5 binaries use a different dynamic linker. So the behaviour of your libc5 binary depends upon the behaviour of your libc5 dynamic linker. That linker does not come from glibc. Although I can not test this, I now believe that if you take a libtool program, compile it on a libc5 Slackware and try to run it on a RedHat 5.2 system, it will work. Ian --- ld.so-1.9.5/d-link/readelflib1.c.ewt Mon Nov 17 10:04:15 1997 +++ ld.so-1.9.5/d-link/readelflib1.c Mon Nov 17 10:23:15 1997 @@ -179,38 +179,10 @@ goto goof; } - /* - * The ABI specifies that RPATH is searched before LD_*_PATH or - * the default path of /usr/lib. - * Check in rpath directories - */ - for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { - if (tpnt->libtype == elf_executable) { - pnt1 = (char *)tpnt->dynamic_info[DT_RPATH]; - if(pnt1) { - pnt1 += (unsigned int) tpnt->loadaddr + tpnt->dynamic_info[DT_STRTAB]; - while(*pnt1){ - pnt2 = mylibname; - while(*pnt1 && *pnt1 != ':') { - if (pnt2 - mylibname < 1024) - *pnt2++ = *pnt1++; - else - pnt1++; - } - if (pnt2 - mylibname >= 1024) - break; - if(pnt2[-1] != '/') *pnt2++ = '/'; - pnt = libname; - while(*pnt) *pnt2++ = *pnt++; - *pnt2++ = 0; - tpnt1 = _dl_load_elf_shared_library(mylibname, 0); - if(tpnt1) return tpnt1; - if(*pnt1 == ':') pnt1++; - } - } - } - } - + /* EWT - change things around a bit... The RPATH is almost definitely + wrong for libc 5 apps as things got moved around so much. Rather + then checking it first, we'll check it last. While this could + cause major breakages, it probably won't. */ /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ pnt1 = _dl_library_path; @@ -259,6 +231,38 @@ } } #endif + + /* + * The ABI specifies that RPATH is searched before LD_*_PATH or + * the default path of /usr/lib. + * Check in rpath directories + */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + if (tpnt->libtype == elf_executable) { + pnt1 = (char *)tpnt->dynamic_info[DT_RPATH]; + if(pnt1) { + pnt1 += (unsigned int) tpnt->loadaddr + tpnt->dynamic_info[DT_STRTAB]; + while(*pnt1){ + pnt2 = mylibname; + while(*pnt1 && *pnt1 != ':') { + if (pnt2 - mylibname < 1024) + *pnt2++ = *pnt1++; + else + pnt1++; + } + if (pnt2 - mylibname >= 1024) + break; + if(pnt2[-1] != '/') *pnt2++ = '/'; + pnt = libname; + while(*pnt) *pnt2++ = *pnt++; + *pnt2++ = 0; + tpnt1 = _dl_load_elf_shared_library(mylibname, 0); + if(tpnt1) return tpnt1; + if(*pnt1 == ':') pnt1++; + } + } + } + } /* Check in /usr/lib */ #ifdef IBCS_COMPATIBLE