move call to dynamic linker stage-3 into stage-2 function
authorRich Felker <dalias@aerifal.cx>
Mon, 25 May 2015 23:15:17 +0000 (19:15 -0400)
committerRich Felker <dalias@aerifal.cx>
Mon, 25 May 2015 23:15:17 +0000 (19:15 -0400)
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.

src/internal/dynlink.h
src/ldso/dlstart.c
src/ldso/dynlink.c

index 53661d62ffa62bd223acc9acd206827c7ac3b7c5..8621d2dddc88d7d701824321906c38b91fd94470 100644 (file)
@@ -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
index 5f84465c6182d549fec5350aba79d2edef72a91b..3aaa200fbbb5c55df7e1e5179ab1471df99c0d5e 100644 (file)
@@ -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
index 93595a0f62e58c2a7df7ddcdfa377800f0a50266..3842aeba1e7b494bed9c624fecad3c5bd74ed284 100644 (file)
@@ -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