Re: dlopen()ing shared libraries considered harmful (was Re: Depends/Recommends from libraries)
- Date: Wed, 29 Mar 2017 20:00:54 +0200
- From: Jens Reyer <jre.winesim@xxxxxxxxx>
- Subject: Re: dlopen()ing shared libraries considered harmful (was Re: Depends/Recommends from libraries)
On 03/26/2017 09:37 AM, Florian Weimer wrote:
> * Guillem Jover:
>>> dlopen()ing dependencies in the way that is most commonly implemented,
>>> with dlopen("libimobiledevice.so.6") and dlsym(handle, "idevice_new")
>>> or similar, has some practical problems for Debian:
>>> * The libraries used aren't visible to dpkg-shlibdeps. The maintainer has
>>> to know what dlopen() calls the code will make, and either hard-code an
>>> appropriate Depends (or in this case Recommends), or link a dummy
>>> executable against the same things that are dlopen()ed (as is done
>>> in packages like wine and openal-soft) and use that for dpkg-shlibdeps.
>>> Either way, they have to remember to update it for every new upstream
>>> release. This is the sort of tedious-but-subtle work that we automate
>>> because otherwise it will inevitably be incorrect after a few releases.
>>> * The exact symbols used aren't visible to dpkg-shlibdeps. The maintainer
>>> has to hard-code a version number that has all the required symbols.
>>> Again, this is the sort of thing that we automate because it will
>>> inevitably go wrong if done manually.
>> * Because the shared library SONAME is hard-coded in both code and
>> packaging metadata, whenever there's a transition with a SOVERSION
>> bump that could have been handled with a simple mass binNMU, instead
>> it requires manual intervention to patch those, while making sure it
>> still works due to the points above.
At least for Wine the SONAME of dlopen'ed libraries is not hardcoded,
but computed during configure. We then grep these SONAMEs and build a
helper elf binary to compute the needed dependencies with dpkg-shlibdeps.
So this solution is fully automatic both upstream and in the packaging,
therefore it allows for binNMUs.
Building the helper binary could even be omitted if someone implements
this in dpkg-shlibdeps (see #596715 "dpkg-shlibdeps: Please allow to
manually add library dependencies via shlibdeps").
> * For regular dynamic linking, the static linker (ld) puts the default
> symbol version seen in the linked DSO into the object which refers
> to that DSO, so that each symbol refers to a fixed symbol version.
> This symbol version matches the header file contents of the library
> at the time, and is consistent with the link. With dlopen/dlsym,
> this step does not happen, and dlsym will pick the newest (*) symbol
> version. This version might not match what was in the header files
> at compilation time. (Theoretically, it would be possible to
> determine the applicable symbol version at compile time and use
> dlvsym, but no one does that.)
> (*) Not quite because we have a bug:
>>> The pedantically correct way to have weak library dependencies is this
>>> multi-level chain of linking, analogous to what is documented for APIs
>>> that wrap dlopen() such as libltdl and GLib's GModule:
>>> - eventual API user, e.g. /usr/bin/gnome-software
>>> - a plugin intended to be dlopen()ed, e.g. libgs_plugin_flatpak-user.so
>>> has DT_NEEDED on:
>>> - libflatpak0
>> I don't think this is pedantical at all, it's IMO the only sane and
>> correct way to handle this.
> Right, this way also allows the static linker to do its job and fix
> the symbol version.