You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When implib is built to export wrapped symbols (-DIMPLIB_EXPORT_SHIMS), the imported library initializers may end up resolving some of the symbols to the already-available symbols provided by the wrapper and that triggers an assertion checking is_lib_loading -- we're still in the middle of calling dlopen() at that point.
One way to deal with that is to dlopen() the wrapped library with RTLD_DEEPBIND. This would tell dynamic linker to bind the symbols to the library itself and avoid the unfortunate recursion. It would bypass the implib's wrapper, but I think it's the right thing to do when we build implib with visible symbols.
We may want to make it a user-controllable option, in case someone may need to guarantee that all references to a symbol go through the wrapper, but that would have to be a trade-off as in that case they would lose the ability to import libraries that refer to themselves in their initializers.
The text was updated successfully, but these errors were encountered:
Artem-B
changed the title
Using implib from a shared library with IMPLIB_EXPORT_SHIMS triggers an assertion.
Implib IMPLIB_EXPORT_SHIMS triggers an assertion when imported DSO has initializers referring to its public symbols.
Aug 2, 2022
Yup, we ran into this during gh-15 and unfortunately I do not have a good solution for it.
One way to deal with that is to dlopen() the wrapped library with RTLD_DEEPBIND. This would tell dynamic linker to bind the symbols to the library itself and avoid the unfortunate recursion. It would bypass the implib's wrapper, but I think it's the right thing to do when we build implib with visible symbols.
Right, this is one solution. It has a disadvantage of changing the symbol resolution logic which may not be suitable for some users so I decided to not enable it by default. For now users may load library with RTLD_DEEPBIND by using --dlopen-callback.
It would be great if glibc provided us with APIs for separate library loading and ctor execution...
For completeness, the other potential solution would be to detect the is_lib_loading case and run dlopen with RTLD_NOLOAD (or locate library by hand, by searching for library via dl_iterate_phdr). The located library could then be used to call dlsym. Unfortunately it's unclear how to naturally extend this solution to --no-dlopen or --dlopen-callback cases.
For completeness, the other potential solution would be to detect the is_lib_loading case and run dlopen with RTLD_NOLOAD (or locate library by hand, by searching for library via dl_iterate_phdr). The located library could then be used to call dlsym. Unfortunately it's unclear how to naturally extend this solution to --no-dlopen or --dlopen-callback cases.
Actually it's possible to just call dlopen with default arguments (i.e. without RTLD_NOLOAD) inside the constructor and it will return the loaded library. So we can expect that in most cases just calling the load callback second time when is_lib_loading is true will return the handle.
In --no-dlopen case we could search for library via dl_iterate_phdr and then dlopen it.
This is still fragile though. In particular
load callback needs to be reentrant
the approach will not work if library is loaded by custom loader
Implib.so/arch/common/init.c.tpl
Line 60 in bbca01e
When implib is built to export wrapped symbols (-DIMPLIB_EXPORT_SHIMS), the imported library initializers may end up resolving some of the symbols to the already-available symbols provided by the wrapper and that triggers an assertion checking
is_lib_loading
-- we're still in the middle of calling dlopen() at that point.One way to deal with that is to dlopen() the wrapped library with
RTLD_DEEPBIND
. This would tell dynamic linker to bind the symbols to the library itself and avoid the unfortunate recursion. It would bypass the implib's wrapper, but I think it's the right thing to do when we build implib with visible symbols.We may want to make it a user-controllable option, in case someone may need to guarantee that all references to a symbol go through the wrapper, but that would have to be a trade-off as in that case they would lose the ability to import libraries that refer to themselves in their initializers.
The text was updated successfully, but these errors were encountered: