This is the mail archive of the
mailing list for the glibc project.
Re: [PATCH] Support -z initfirst for multiple shared libraries
- From: d wk <dwksrc at gmail dot com>
- To: "Carlos O'Donell" <carlos at redhat dot com>
- Cc: libc-alpha at sourceware dot org
- Date: Thu, 28 Apr 2016 14:47:35 -0400
- Subject: Re: [PATCH] Support -z initfirst for multiple shared libraries
- Authentication-results: sourceware.org; auth=none
- References: <CAPESumqMqVem6VvaKXf_ko1zpM9_wOXixp1O7WGtS0RnvhMSpg at mail dot gmail dot com> <57221A3C dot 905 at redhat dot com>
On Thu, Apr 28, 2016 at 10:12 AM, Carlos O'Donell <firstname.lastname@example.org> wrote:
> On 04/26/2016 04:58 PM, d wk wrote:
>> In a project of mine, I needed to run some code before any constructors
>> from any system libraries (such as libc or libpthread). The linker/loader
>> -z initfirst feature is perfect for this, but it only supports one shared
>> library. Unfortunately libpthread also uses this feature (I assume the
>> feature exists because pthread needed it), so my project was incompatible
>> with libpthread.
>> So, I wrote a small patch which changes the single dl_initfirst variable
>> into a linked list. This patch does not change the size of any data
>> structures (it's ABI compatible), just turns dl_initfirst into a list. The
>> list is not freed (the allocator wouldn't free it anyway), and insertion
>> into the list is quadratic, but I expect there will never be more than
>> a handful of initfirst libraries!
>> This patch records initfirst libraries in load order, so LD_PRELOAD
>> libraries will have their constructors called before libpthread. If the
>> opposite behaviour is desired, the LD_PRELOAD'd library can always declare
>> a dependency on libpthread. Normally LD_PRELOAD constructors are run last,
>> which is very inconvenient when trying to inject new functionality, and
>> I expect anyone using -z initfirst with LD_PRELOAD to really want to run
>> first. The patch is written against latest glibc 2.23 (I also tested on
>> glibc 2.21, and it's not quite compatible with 2.17 since the other data
>> structures changed).
>> I was not the first person to run into this problem,
>> someone wanted the same thing on stack overflow two years
>> ago. You can see my answer there with a complete test case.
>> Hope you will accept this patch. Comments welcome. Thanks,
> (1) High level review: I like the idea.
> At a high level I like the idea.
> We have one open bug for this here:
> Bug 14379 - shared object constructors are called in the wrong order
> It is true that LD_PRELOAD'd libraries are loaded last, but only because
> of a quirk in the processing mechanics. The library is first in the scope
> search order (so the symbols interpose) which means it's initialized last,
> and finalized first after the application.
> To be honest I think this is a bug and LD_PRELOAD'd libraries should be
> initialized and finalized based on their dependencies.
I would be a little wary of changing existing LD_PRELOAD constructor
ordering behaviour. It might break some existing programs (certainly
it would break the system I created). The problem is that LD_PRELOAD is
often used for debugging, profiling, and overriding things; sometimes this
means you need to run very early, and sometimes this means you need to run
very late. As it happens, I needed both, hence this initfirst patch. If
LD_PRELOAD is changed as you suggest, even if this patch is accepted,
there will be no way to "run late" anymore.
I agree that the overall initfirst, LD_PRELOAD, etc scheme could use some
adjustments; I was proposing this patch as a straightforward fix that
could be incorporated without breaking anything (because only libpthread is
using this feature right now). It would be helpful for me and potentially
other tool builders. I'm happy to help design larger-scale changes too.
> (2) DF_1_INITFIRST
> Implementing DF_1_INITFIRST is going to be complicated. It is complicated
> by the fact that dlopen could result in N libraries being loaded, and if
> M of those is DF_1_INITFIRST, then M must be initialized first. This
> is my interpretation of the Solaris implementation and the reason for
> the wording "at the same time."
> I can't look at your patch to review this though (copyright issues).
> (3) Finalization of DF_1_INITFIRST and initfirst libraries.
> Ignore DF_1_INITFIRST.
> Finalization for initfirst libraries has to happen after the
> finalization of all other libraries. This makes the behaviour
> deterministic and symmetric.
Not currently implemented, as I said, and it's orthogonal to the problem
of supporting multiple libraries -- but I agree that this should be done.
> (4) Copyright status?
> Please clarify your copyright status with the project:
> I don't see your name on the copyright assignment documents
> from the FSF.
> The easiest form is:
> It assigns all current and future contributions to glibc to the FSF and
> allows us to accept them immediately.
I sent the form in, hopefully it'll be processed soon. I am a researcher
and there are unlikely to be any issues in this regard.