fix tls offsets when p_vaddr%p_align != 0 on TLS_ABOVE_TP targets
authorSzabolcs Nagy <nsz@port70.net>
Mon, 13 May 2019 18:47:11 +0000 (18:47 +0000)
committerRich Felker <dalias@aerifal.cx>
Fri, 17 May 2019 01:48:39 +0000 (21:48 -0400)
currently the bfd linker does not seem to create tls segments where
p_vaddr%p_align != 0, but this is valid in ELF and then the runtime
computed tls offset must satisfy

  offset%p_align == (base+p_vaddr)%p_align

and in case of local exec tls (main executable) the smallest such
offset must be used (otherwise it is incompatible with the offset
computed by the static linker). the !TLS_ABOVE_TP case is handled
correctly (the offset is negative then in the formula).

the ldso code for TLS_ABOVE_TP is changed so the static tls offset
of each module satisfies the formula.

ldso/dynlink.c
src/env/__init_tls.c

index 967f1fd9342c4cafb98b31ca4a82cfdfbd48ff32..1398ff4575fd4808e98f97c43fb78f6380fccf44 100644 (file)
@@ -1125,8 +1125,8 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
                p->tls_id = ++tls_cnt;
                tls_align = MAXP2(tls_align, p->tls.align);
 #ifdef TLS_ABOVE_TP
-               p->tls.offset = tls_offset + ( (tls_align-1) &
-                       -(tls_offset + (uintptr_t)p->tls.image) );
+               p->tls.offset = tls_offset + ( (p->tls.align-1) &
+                       (-tls_offset + (uintptr_t)p->tls.image) );
                tls_offset = p->tls.offset + p->tls.size;
 #else
                tls_offset += p->tls.size + p->tls.align - 1;
@@ -1796,7 +1796,8 @@ _Noreturn void __dls3(size_t *sp)
                app.tls_id = tls_cnt = 1;
 #ifdef TLS_ABOVE_TP
                app.tls.offset = GAP_ABOVE_TP;
-               app.tls.offset += -GAP_ABOVE_TP & (app.tls.align-1);
+               app.tls.offset += (-GAP_ABOVE_TP + (uintptr_t)app.tls.image)
+                       & (app.tls.align-1);
                tls_offset = app.tls.offset + app.tls.size;
 #else
                tls_offset = app.tls.offset = app.tls.size
index 5f12500cad55129985dae6c013c9e8db04679877..772baba32d54fff8b63e69952aeec60fce48a03f 100644 (file)
@@ -115,7 +115,8 @@ static void static_init_tls(size_t *aux)
                & (main_tls.align-1);
 #ifdef TLS_ABOVE_TP
        main_tls.offset = GAP_ABOVE_TP;
-       main_tls.offset += -GAP_ABOVE_TP & (main_tls.align-1);
+       main_tls.offset += (-GAP_ABOVE_TP + (uintptr_t)main_tls.image)
+               & (main_tls.align-1);
 #else
        main_tls.offset = main_tls.size;
 #endif