diff options
Diffstat (limited to 'include/dlfcn.h')
-rw-r--r-- | include/dlfcn.h | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/include/dlfcn.h b/include/dlfcn.h index 2524292ebc..0dc57dbe22 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -31,20 +31,42 @@ extern char **__libc_argv attribute_hidden; /* Now define the internal interfaces. */ +/* Use RTLD_NOW here because: + 1. In pthread_cancel_init we want to use RTLD_NOW to reduce the stack usage + of future cancellation operations, particularly when the target thread + is running with a small stack. Likewise for consistency we do the same + thing in __libgcc_s_init. RTLD_NOW will rarely make a difference for + __libgcc_s_init because unwinding is already in progress, so libgcc_s.so + has already been loaded if its unwinder is used (Bug 22636). + 2. It allows us to provide robust fallback code at dlopen time for + incorrectly configured systems that mix old libnss_* modules with newly + installed libraries e.g. old libnss_nis.so.2 with new libnsl.so.1. Using + RTLD_LAZY here causes a failure at the time the symbol is called and at + that point it is much harder to safely return an error (Bug 22766). + + The use of RTLD_NOW also impacts gconv module loading, backtracing + (where the unwinder form libgcc_s.so is used), and IDNA functions + (which load libidn2), all of which load their respective DSOs on + demand, and so should not impact program startup. That is to say + that the DSOs are loaded as part of an API call and therefore we + will be calling that family of API functions shortly so RTLD_NOW or + RTLD_LAZY is not a big difference in performance, but RTLD_NOW has + better error handling semantics for the library. */ #define __libc_dlopen(name) \ - __libc_dlopen_mode (name, RTLD_LAZY | __RTLD_DLOPEN) + __libc_dlopen_mode (name, RTLD_NOW | __RTLD_DLOPEN) extern void *__libc_dlopen_mode (const char *__name, int __mode); extern void *__libc_dlsym (void *__map, const char *__name); +extern void *__libc_dlvsym (void *map, const char *name, const char *version); extern int __libc_dlclose (void *__map); libc_hidden_proto (__libc_dlopen_mode) libc_hidden_proto (__libc_dlsym) +libc_hidden_proto (__libc_dlvsym) libc_hidden_proto (__libc_dlclose) /* Locate shared object containing the given address. */ #ifdef ElfW extern int _dl_addr (const void *address, Dl_info *info, - struct link_map **mapp, const ElfW(Sym) **symbolp) - internal_function; + struct link_map **mapp, const ElfW(Sym) **symbolp); libc_hidden_proto (_dl_addr) #endif @@ -60,23 +82,21 @@ extern void _dl_close_worker (struct link_map *map, bool force) /* Look up NAME in shared object HANDLE (which may be RTLD_DEFAULT or RTLD_NEXT). WHO is the calling function, for RTLD_NEXT. Returns the symbol value, which may be NULL. */ -extern void *_dl_sym (void *handle, const char *name, void *who) - internal_function; +extern void *_dl_sym (void *handle, const char *name, void *who); /* Look up version VERSION of symbol NAME in shared object HANDLE (which may be RTLD_DEFAULT or RTLD_NEXT). WHO is the calling function, for RTLD_NEXT. Returns the symbol value, which may be NULL. */ extern void *_dl_vsym (void *handle, const char *name, const char *version, - void *who) - internal_function; + void *who); /* Helper function for <dlfcn.h> functions. Runs the OPERATE function via _dl_catch_error. Returns zero for success, nonzero for failure; and arranges for `dlerror' to return the error details. ARGS is passed as argument to OPERATE. */ extern int _dlerror_run (void (*operate) (void *), void *args) - internal_function; + attribute_hidden; #ifdef SHARED # define DL_CALLER_DECL /* Nothing */ @@ -135,6 +155,8 @@ extern void __libc_register_dl_open_hook (struct link_map *map) extern void __libc_register_dlfcn_hook (struct link_map *map) attribute_hidden; #endif -#endif +extern void __dlerror_main_freeres (void) attribute_hidden; + +#endif #endif |