diff options
| author | Rich Felker <dalias@aerifal.cx> | 2015-05-25 19:15:17 -0400 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2015-05-25 19:15:17 -0400 | 
| commit | 768b82c6de24e480267c4c251c440edfc71800e3 (patch) | |
| tree | 9b59e909041b2ad6ca35dad514ad9fa5c5379894 | |
| parent | 967bcbf67c3ffac587de4d79abc1e5e072d83e3e (diff) | |
| download | musl-768b82c6de24e480267c4c251c440edfc71800e3.tar.gz | |
move call to dynamic linker stage-3 into stage-2 function
this move eliminates a duplicate "by-hand" symbol lookup loop from the
stage-1 code and replaces it with a call to find_sym, which can be
used once we're in stage 2. it reduces the size of the stage 1 code,
which is helpful because stage 1 will become the crt start file for
static-PIE executables, and it will allow stage 3 to access stage 2's
automatic storage, which will be important in an upcoming commit.
| -rw-r--r-- | src/internal/dynlink.h | 2 | ||||
| -rw-r--r-- | src/ldso/dlstart.c | 11 | ||||
| -rw-r--r-- | src/ldso/dynlink.c | 8 | 
3 files changed, 9 insertions, 12 deletions
| diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 53661d62..8621d2dd 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -51,7 +51,7 @@ enum {  #define AUX_CNT 32  #define DYN_CNT 32 -typedef void (*stage2_func)(unsigned char *); +typedef void (*stage2_func)(unsigned char *, size_t *);  typedef _Noreturn void (*stage3_func)(size_t *);  #endif diff --git a/src/ldso/dlstart.c b/src/ldso/dlstart.c index 5f84465c..3aaa200f 100644 --- a/src/ldso/dlstart.c +++ b/src/ldso/dlstart.c @@ -84,16 +84,7 @@ void _dlstart_c(size_t *sp, size_t *dynv)  		 && s[3]=='l' && s[4]=='s' && s[5]=='2' && !s[6])  			break;  	} -	((stage2_func)(base + syms[i].st_value))(base); - -	/* Call dynamic linker stage-3, __dls3 */ -	for (i=0; ;i++) { -		const char *s = strings + syms[i].st_name; -		if (s[0]=='_' && s[1]=='_' && s[2]=='d' -		 && s[3]=='l' && s[4]=='s' && s[5]=='3' && !s[6]) -			break; -	} -	((stage3_func)(base + syms[i].st_value))(sp); +	((stage2_func)(base + syms[i].st_value))(base, sp);  }  #endif diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 93595a0f..3842aeba 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -1116,7 +1116,7 @@ static void update_tls_size()   * linker itself, but some of the relocations performed may need to be   * replaced later due to copy relocations in the main program. */ -void __dls2(unsigned char *base) +void __dls2(unsigned char *base, size_t *sp)  {  	Ehdr *ehdr = (void *)base;  	ldso.base = base; @@ -1134,6 +1134,12 @@ void __dls2(unsigned char *base)  	ldso.relocated = 0;  	ldso.rel_update_got = 1; + +	/* Call dynamic linker stage-3, __dls3, looking it up +	 * symbolically as a barrier against moving the address +	 * load across the above relocation processing. */ +	struct symdef dls3_def = find_sym(&ldso, "__dls3", 0); +	((stage3_func)(ldso.base+dls3_def.sym->st_value))(sp);  }  /* Stage 3 of the dynamic linker is called with the dynamic linker/libc | 
