Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
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.