kdeinit problem: LD_BIND_NOW cached by glibc
Karl Vogel
karl.vogel at telenet.be
Mon Nov 22 23:52:43 CET 2004
While looking at the glibc source I noticed that it caches the
LD_BIND_NOW variable, which means that unsetting it after program start,
will not change anything for dlopen()'s done by the program.
This would also mean that the kdeinit hack in KDE will always do a
complete bind of the symbols when loading the libkdeinit_appname.so
module.
Time for a test...
----- te.c ---
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char *argv[])
{
void *handle;
int i;
unsetenv("LD_BIND_NOW");
for(i= 0; i<100;i++) {
handle= dlopen(argv[1], RTLD_LAZY);
if (handle == NULL)
perror(dlerror());
dlclose(handle);
}
return 0;
}
-----
$ time ./te /usr/lib/libkdeinit_konsole.so
real 0m0.227s
user 0m0.171s
sys 0m0.009s
$ export LD_BIND_NOW=1
$ time ./te /usr/lib/libkdeinit_konsole.so
real 0m18.408s
user 0m17.922s
sys 0m0.413s
I also verified this with libltdl and got the same results. This clearly
shows that unsetenv("LD_BIND_NOW") has no effect on the dlopen.
This is with glibc 2.3.3 (glibc-2.3.3-74) on Fedora Core 3.
The glibc files in question:
elf/rtld.c :
static void
process_envvars (enum mode *modep)
{
....
case 8:
/* Do we bind early? */
if (memcmp (envline, "BIND_NOW", 8) == 0)
{
GLRO(dl_lazy) = envline[9] == '\0';
break;
}
elf/dl-open.c :
/* Only do lazy relocation if `LD_BIND_NOW' is not set. */
lazy = (mode & RTLD_BINDING_MASK) == RTLD_LAZY && GLRO(dl_lazy);
Maybe somebody can verify the test program on SuSE and/or other
distros/glibc's.
Working around this for kdeinit is possible, but will be hackish.
More information about the Kde-optimize
mailing list