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