|
|
Message-ID: <20150412015923.GP6817@brightrain.aerifal.cx>
Date: Sat, 11 Apr 2015 21:59:23 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: Dynamic linker changes
On Sat, Apr 11, 2015 at 04:21:52PM -0400, Rich Felker wrote:
> On Wed, Apr 08, 2015 at 07:19:11PM -0400, Rich Felker wrote:
> > 3. The original plan was to have one early-ldso-relocation step and
> > avoid all possible GOT/globals use and everything after that free to
> > use arbitrary global data and symbols, with a single barrier in
> > between to prevent reordering of GOT loads before they're relocated.
> > This seems impractical since it's hard, due to issue 1, do to symbolic
> > relocations without being able to make function calls.
> >
> > Instead I'd like to treat the early-ldso-relocation process as two
> > steps. The first is generalizing and making arch-agnostic the work
> > mips, microblaze, and powerpc are doing now to get to a state where
> > all non-symbolic global accesses are safe. The second would be a
> > separate function call from the asm (or chained from the first if
> > there's an obvious way to do it) that performs symbolic relocations on
> > itself. It would end by (as proposed in the sketch before) doing a
> > symbol lookup and final call into the code that will setup the dso
> > chain, load dependencies, perform all remaining relocations, and pass
> > control to the program's entry point.
>
> I've got the first working draft of the above design, and it's three
> stages:
>
> 1. Perform relative relocations on ldso/libc itself referencing
> nothing but its arguments and the data they point to.
>
> 2. Setup a dso structure for ldso/libc and perform symbolic
> relocations on it using nothing but static functions/data from
> dynlink.c.
>
> 3. Do nearly everything the old __dynlink did, but with the ldso dso
> structure already setup and fully usable (not depending on
> -Bsymbolic-functions and arch-specific __reloc_self to make it
> almost-fully-usable like we did before).
>
> Currently, stage 1 calls into stage 2 and 3 via very primitive
> symbol-lookup code. This has some trade-offs.
>
> Pros: The dynamic linker entry point asm does not need to be aware of
> the details of the dynamic linking process. It just calls one function
> with minimal args (original SP and &_DYNAMIC) and uses the return
> value as a jump destination (along with a simple SP-fixup trick).
>
> Cons: Stage 1 is coupled with the rest of the dynamic linking process.
> This is somewhat unfortunate since the stage 1 code, minus this last
> symbol lookup step but including the entry point asm prior to calling
> stage 1, is _exactly_ what would be needed for "static PIE" Rcrt1.o.
> It could be made to work 'unmodified' for static PIE by having the
> source for Rcrt1.o provide its own definitions of the stage 2 and 3
> functions, but since stage 1 looks them up by name at runtime,
> stripping dynamic symbol names (which should in principle work for
> static PIE) would break it.
>
> I'm attaching a diff with the work so far for comments. It's
> unfinished (only i386 and mips are implemented so far; mips was chosen
> because it's the one arch that needs ugly arch-specific relocations
> and I had to check and make sure they work right in the new design)
> but seems to work.
OK, so some big ideas for resolving this:
Let's get rid of all the ldso/*/start.s files.
Instead, I want to reuse crt_arch.h, which requires making the
following changes to it:
1. Fix any existing cases where crt_arch.h uses addressing methods
that would not work prior to relocations. This is probably only
mips.
2. Add the ability for the calling file to rename the _start function
via a macro defined before including crt_arch.h.
3. Add conditional loading of &_DYNAMIC in the second arg slot before
calling __cstart.
At this point, we have minimal entry point asm that can be reused by
crt1.o, Scrt1.o, dlstart.lo, and the future rcrt1.o for static PIE.
For dlstart.c would look like this:
#ifndef START
#define START "_dl_start"
#endif
#define NEED_DYNAMIC
#include "crt_arch.h"
void __cstart(size_t *sp, size_t *dynv)
{
/* body of existing stage 1 */
}
And the future rcrt1.c would look like this:
#define START "_start"
#include "dlstart.c"
/* stage 2 and 3 functions */
where stage 2 is empty, and stage 3 looks like the __cstart in crt1.c.
Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.