ldso: RTLD_LAZY is broken :(

Carmelo AMOROSO carmelo.amoroso at st.com
Fri Sep 2 04:11:26 UTC 2011


On 02/09/2011 0.45, William Pitcock wrote:
> hi,
> 
> consider the following code, call it loader.c:
> 
> petrie:~/weak$ cat loader.c
> #include <stdio.h>
> #include <stdlib.h>
> #include <dlfcn.h>
> 
> int main(int argc, const char *argv[]) {
>         /* make gcc -pedantic happy.  --nenolod */
>         union {
>                 void *addr;
>                 void (*func)(void);
>         } dlcompat_runner_f;
>         void *dlptr;
> 
>         dlptr = dlopen("./test-attribute-weak.so", RTLD_GLOBAL |
>         RTLD_LAZY); if (dlptr == NULL)
>         {
>                 printf("error: %s\n", dlerror());
>                 return EXIT_FAILURE;
>         }
> 
>         dlcompat_runner_f.addr = dlsym(dlptr, "runner");
>         dlcompat_runner_f.func();
> 
>         dlclose(dlptr);
> 
>         return EXIT_SUCCESS;
> }
> 
> compile it like so:
> 
> petrie:~/weak$ gcc -o loader loader.c -ldl
> 
> now, consider the test-attribute-weak sources:
> 
> petrie:~/weak$ cat test-attribute-weak.c
> #include <stdio.h>
> 
> void strong_symbol(void) {
>         printf("this is a strongly-linked symbol\n");
> }
> 
> void weak_symbol(void) __attribute__((weak));
> void undef_symbol(void);
> 
> void runner(void) {
>         strong_symbol();
> 
>         if (weak_symbol != NULL)
>                 weak_symbol();
>         else
>                 printf("weak_symbol() couldn't be resolved\n");
> 
>         undef_symbol();
> }
> 
> compile it like so:
> 
> petrie:~/weak$ gcc -fPIC -shared -o test-attribute-weak.so
> test-attribute-weak.c
> 
> now run:
> 
> petrie:~/weak$ ./loader
> 
> /home/nenolod/weak/loader: symbol 'undef_symbol': can't resolve symbol
> error: (null)
> 
> this is wrong.  since it's RTLD_LAZY, we shouldn't care about
> undef_symbol until we actually try to use it.
> 
> this is what happens on a libc6 system (Debian EGLIBC-based):
> 
> nenolod at carpathia:~/weak$ ./loader
> this is a strongly-linked symbol
> weak_symbol() couldn't be resolved
> ./loader: symbol lookup error: ./test-attribute-weak.so: undefined
> symbol: undef_symbol
> 
> the behaviour is similar on freebsd and solaris.
> 
> when running ./loader with LD_DEBUG=all, we get:
> 
> 
> do_dlopen():365: Trying to dlopen './test-attribute-weak.so', RTLD_GLOBAL:1 RTLD_NOW:0
> _dl_load_shared_library:219:    find library='test-attribute-weak.so'; searching
> _dl_load_shared_library:225:    trying file='./test-attribute-weak.so'
> _dl_load_elf_shared_library:898: 
>         file='./test-attribute-weak.so';  generating link map
> _dl_load_elf_shared_library:899:                dynamic: 0x7fe20569d770  base: 0x7fe20549d000
> _dl_load_elf_shared_library:901:                  entry: 0x7fe20549d524  phdr: 0x7fe20549d040  phnum: 0x5
> 
> do_dlopen():399: Looking for needed libraries
> do_dlopen():416: Trying to load 'libc.so.0.9.32', needed by './test-attribute-weak.so'
> _dl_load_shared_library:219:    find library='libc.so.0.9.32'; searching
> _dl_load_shared_library:281:    searching cache='/etc/ld.so.cache'
> do_dlopen():416: Trying to load 'ld64-uClibc.so.0.9.32', needed by '/lib/libc.so.0.9.32'
> _dl_load_shared_library:219:    find library='ld64-uClibc.so.0.9.32'; searching
> _dl_load_shared_library:281:    searching cache='/etc/ld.so.cache'
> 
> INIT/FINI order and dependencies:
> lib: ./test-attribute-weak.so has deps:
>  /lib/libc.so.0.9.32 
> lib: /lib/libc.so.0.9.32 has deps:
>  /lib/ld64-uClibc.so.0.9.32 
> lib: /lib/ld64-uClibc.so.0.9.32 has deps:
> 
> do_dlopen():501: Beginning dlopen relocation fixups
> _dl_fixup:923: relocation processing: ./test-attribute-weak.so
> 
> __cxa_finalize
>         value=0x0       size=0x0        info=0x22       other=0x0       shndx=0x0
>         R_X86_64_GLOB_DAT       offset=0x2008e0 addend=0x0
>         patched: 0x0 ==> 0x7fe2056e419c @ 0x7fe20569d8e0
> 
> weak_symbol
>         value=0x0       size=0x0        info=0x20       other=0x0       shndx=0x0
>         R_X86_64_GLOB_DAT       offset=0x2008e8 addend=0x0
>         patched: 0x0 ==> 0x0 @ 0x7fe20569d8e8
> 
> _Jv_RegisterClasses
>         value=0x0       size=0x0        info=0x20       other=0x0       shndx=0x0
>         R_X86_64_GLOB_DAT       offset=0x2008f0 addend=0x0
>         patched: 0x0 ==> 0x0 @ 0x7fe20569d8f0
> 
> undef_symbol
>         value=0x0       size=0x0        info=0x10       other=0x0       shndx=0x0
>         R_X86_64_JUMP_SLOT      offset=0x200910 addend=0x0
> 
> /home/nenolod/weak/loader: symbol 'undef_symbol': can't resolve symbol
> do_dlclose():765: ./test-attribute-weak.so: usage count: 1
> do_dlclose():792: unmapping: ./test-attribute-weak.so
> do_dlclose():919: removing loaded_modules: ./test-attribute-weak.so
> do_dlclose():937: removing symbol_tables: ./test-attribute-weak.so
> error: (null)
> _dl_fini:265: 
> calling FINI: /lib/libdl.so.0.9.32
> 
> is there some reason why the behaviour is this way?  i couldn't imagine
> that being the case as it's not posixly-correct.
> 
> william

interesting... let me see deeply.

thanks,
carmelo

> _______________________________________________
> uClibc mailing list
> uClibc at uclibc.org
> http://lists.busybox.net/mailman/listinfo/uclibc
> 



More information about the uClibc mailing list