Some libdl functions rely on return address to figure out the calling DSO and then use this information in computation (e.g. output of dlsym depends on which library called it). As reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66826 this may break under tailcall optimization i.e. in cases like return dlsym(...); Rich Felker suggested that adding new GCC attribute is a possible solution. Another option would be to hack around dlsym to prevent tailcall from happening e.g. #define dlsym(h, name) { volatile void *sym = dlsym(h, name); return (void *)sym; } Which solution is more appropriate for Glibc?
Pinged libc-alpha: https://sourceware.org/ml/libc-alpha/2017-01/msg00455.html
It is an ABI break, but I like approx: void* dlsym_internal(void* handle, const char* name, void* notail); static inline void* dlsym(void* handle, const char* name) { char notail[1]; return dlsym_internal(handle, name, notail); } Gcc should probably get an attribute. I've heard of this problem in other contexts.
The suggestion in comment 2 is a spec violation; it has a static identifier dlsym in place of the required extern one, and also breaks the identity of function pointers (different pointer per translation unit). You have to use function-like macros to do this kind of thing in a conforming way, and the macro still does not cover the case where the caller undefines the macro or directly calls the function via its address. I believe the right solution is to deprecate the old constant value of RTLD_NEXT and instead define RTLD_NEXT to expand to the address of a static anchor object inside the translation unit. The dynamic linker can then use that anchor object, rather than the return address, to identify the DSO from which it was called. This also fixes a lot of other usage patterns, e.g. where library A calls dlsym_wrapper(RTLD_NEXT, "foo") and dlsym_wrapper is defined in library B.
(In reply to Rich Felker from comment #3) > I believe the right solution is to deprecate the old constant value of > RTLD_NEXT and instead define RTLD_NEXT to expand to the address of a static > anchor object inside the translation unit. The dynamic linker can then use > that anchor object, rather than the return address, to identify the DSO from > which it was called. This also fixes a lot of other usage patterns, e.g. > where library A calls dlsym_wrapper(RTLD_NEXT, "foo") and dlsym_wrapper is > defined in library B. This also came up in the 2017 thread: https://sourceware.org/pipermail/libc-alpha/2017-January/078377.html To me it looks still the best way to solve this.