For variant II static TLS, properly align tls segments. Pre-calculate
the max required alignment for the static tls segments, and honor it when carving the pieces for next module, from the static space. Use aligned allocator to get properly-aligned dynamic blocks. Reported by: dt71@gmx.com Reviewed by: kan Sponsored by: The FreeBSD Foundation MFC after: 1 week
This commit is contained in:
parent
dfe296c43a
commit
16a93df7eb
@ -231,6 +231,7 @@ char **main_argv;
|
|||||||
size_t tls_last_offset; /* Static TLS offset of last module */
|
size_t tls_last_offset; /* Static TLS offset of last module */
|
||||||
size_t tls_last_size; /* Static TLS size of last module */
|
size_t tls_last_size; /* Static TLS size of last module */
|
||||||
size_t tls_static_space; /* Static TLS space allocated */
|
size_t tls_static_space; /* Static TLS space allocated */
|
||||||
|
size_t tls_static_max_align;
|
||||||
int tls_dtv_generation = 1; /* Used to detect when dtv size changes */
|
int tls_dtv_generation = 1; /* Used to detect when dtv size changes */
|
||||||
int tls_max_index = 1; /* Largest module index allocated */
|
int tls_max_index = 1; /* Largest module index allocated */
|
||||||
|
|
||||||
@ -4281,19 +4282,22 @@ void *
|
|||||||
allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign)
|
allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign)
|
||||||
{
|
{
|
||||||
Obj_Entry *obj;
|
Obj_Entry *obj;
|
||||||
size_t size;
|
size_t size, ralign;
|
||||||
char *tls;
|
char *tls;
|
||||||
Elf_Addr *dtv, *olddtv;
|
Elf_Addr *dtv, *olddtv;
|
||||||
Elf_Addr segbase, oldsegbase, addr;
|
Elf_Addr segbase, oldsegbase, addr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
size = round(tls_static_space, tcbalign);
|
ralign = tcbalign;
|
||||||
|
if (tls_static_max_align > ralign)
|
||||||
|
ralign = tls_static_max_align;
|
||||||
|
size = round(tls_static_space, ralign) + round(tcbsize, ralign);
|
||||||
|
|
||||||
assert(tcbsize >= 2*sizeof(Elf_Addr));
|
assert(tcbsize >= 2*sizeof(Elf_Addr));
|
||||||
tls = xcalloc(1, size + tcbsize);
|
tls = malloc_aligned(size, ralign);
|
||||||
dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr));
|
dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr));
|
||||||
|
|
||||||
segbase = (Elf_Addr)(tls + size);
|
segbase = (Elf_Addr)(tls + round(tls_static_space, ralign));
|
||||||
((Elf_Addr*)segbase)[0] = segbase;
|
((Elf_Addr*)segbase)[0] = segbase;
|
||||||
((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
|
((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
|
||||||
|
|
||||||
@ -4345,8 +4349,8 @@ allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign)
|
|||||||
void
|
void
|
||||||
free_tls(void *tls, size_t tcbsize, size_t tcbalign)
|
free_tls(void *tls, size_t tcbsize, size_t tcbalign)
|
||||||
{
|
{
|
||||||
size_t size;
|
|
||||||
Elf_Addr* dtv;
|
Elf_Addr* dtv;
|
||||||
|
size_t size, ralign;
|
||||||
int dtvsize, i;
|
int dtvsize, i;
|
||||||
Elf_Addr tlsstart, tlsend;
|
Elf_Addr tlsstart, tlsend;
|
||||||
|
|
||||||
@ -4354,19 +4358,22 @@ free_tls(void *tls, size_t tcbsize, size_t tcbalign)
|
|||||||
* Figure out the size of the initial TLS block so that we can
|
* Figure out the size of the initial TLS block so that we can
|
||||||
* find stuff which ___tls_get_addr() allocated dynamically.
|
* find stuff which ___tls_get_addr() allocated dynamically.
|
||||||
*/
|
*/
|
||||||
size = round(tls_static_space, tcbalign);
|
ralign = tcbalign;
|
||||||
|
if (tls_static_max_align > ralign)
|
||||||
|
ralign = tls_static_max_align;
|
||||||
|
size = round(tls_static_space, ralign);
|
||||||
|
|
||||||
dtv = ((Elf_Addr**)tls)[1];
|
dtv = ((Elf_Addr**)tls)[1];
|
||||||
dtvsize = dtv[1];
|
dtvsize = dtv[1];
|
||||||
tlsend = (Elf_Addr) tls;
|
tlsend = (Elf_Addr) tls;
|
||||||
tlsstart = tlsend - size;
|
tlsstart = tlsend - size;
|
||||||
for (i = 0; i < dtvsize; i++) {
|
for (i = 0; i < dtvsize; i++) {
|
||||||
if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] > tlsend)) {
|
if (dtv[i + 2] != 0 && (dtv[i + 2] < tlsstart || dtv[i + 2] > tlsend)) {
|
||||||
free((void*) dtv[i+2]);
|
free_aligned(dtv[i + 2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free((void*) tlsstart);
|
free_aligned(tlsstart);
|
||||||
free((void*) dtv);
|
free((void*) dtv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4390,11 +4397,7 @@ allocate_module_tls(int index)
|
|||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
p = malloc(obj->tlssize);
|
p = malloc_aligned(obj->tlssize, obj->tlsalign);
|
||||||
if (p == NULL) {
|
|
||||||
_rtld_error("Cannot allocate TLS block for index %d", index);
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
memcpy(p, obj->tlsinit, obj->tlsinitsize);
|
memcpy(p, obj->tlsinit, obj->tlsinitsize);
|
||||||
memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
|
memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
|
||||||
|
|
||||||
@ -4426,9 +4429,11 @@ allocate_tls_offset(Obj_Entry *obj)
|
|||||||
* leave a small amount of space spare to be used for dynamically
|
* leave a small amount of space spare to be used for dynamically
|
||||||
* loading modules which use static TLS.
|
* loading modules which use static TLS.
|
||||||
*/
|
*/
|
||||||
if (tls_static_space) {
|
if (tls_static_space != 0) {
|
||||||
if (calculate_tls_end(off, obj->tlssize) > tls_static_space)
|
if (calculate_tls_end(off, obj->tlssize) > tls_static_space)
|
||||||
return false;
|
return false;
|
||||||
|
} else if (obj->tlsalign > tls_static_max_align) {
|
||||||
|
tls_static_max_align = obj->tlsalign;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_last_offset = obj->tlsoffset = off;
|
tls_last_offset = obj->tlsoffset = off;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user