svn commit: r360067 - stable/12/libexec/rtld-elf
Konstantin Belousov
kib at FreeBSD.org
Sat Apr 18 03:14:17 UTC 2020
Author: kib
Date: Sat Apr 18 03:14:16 2020
New Revision: 360067
URL: https://svnweb.freebsd.org/changeset/base/360067
Log:
MFC r359634:
Make p_vaddr % p_align == p_offset % p_align for (some) TLS segments.
Modified:
stable/12/libexec/rtld-elf/map_object.c
stable/12/libexec/rtld-elf/rtld.c
stable/12/libexec/rtld-elf/rtld.h
stable/12/libexec/rtld-elf/xmalloc.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/libexec/rtld-elf/map_object.c
==============================================================================
--- stable/12/libexec/rtld-elf/map_object.c Sat Apr 18 03:09:25 2020 (r360066)
+++ stable/12/libexec/rtld-elf/map_object.c Sat Apr 18 03:14:16 2020 (r360067)
@@ -308,6 +308,7 @@ map_object(int fd, const char *path, const struct stat
obj->tlsindex = ++tls_max_index;
obj->tlssize = phtls->p_memsz;
obj->tlsalign = phtls->p_align;
+ obj->tlspoffset = phtls->p_offset;
obj->tlsinitsize = phtls->p_filesz;
obj->tlsinit = mapbase + phtls->p_vaddr;
}
Modified: stable/12/libexec/rtld-elf/rtld.c
==============================================================================
--- stable/12/libexec/rtld-elf/rtld.c Sat Apr 18 03:09:25 2020 (r360066)
+++ stable/12/libexec/rtld-elf/rtld.c Sat Apr 18 03:14:16 2020 (r360067)
@@ -1454,6 +1454,7 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t e
obj->tlsalign = ph->p_align;
obj->tlsinitsize = ph->p_filesz;
obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase);
+ obj->tlspoffset = ph->p_offset;
break;
case PT_GNU_STACK:
@@ -4821,7 +4822,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcb
Elf_Addr addr;
Elf_Addr i;
size_t extra_size, maxalign, post_size, pre_size, tls_block_size;
- size_t tls_init_align;
+ size_t tls_init_align, tls_init_offset;
if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE)
return (oldtcb);
@@ -4838,7 +4839,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcb
tls_block_size += pre_size + tls_static_space - TLS_TCB_SIZE - post_size;
/* Allocate whole TLS block */
- tls_block = malloc_aligned(tls_block_size, maxalign);
+ tls_block = malloc_aligned(tls_block_size, maxalign, 0);
tcb = (Elf_Addr **)(tls_block + pre_size + extra_size);
if (oldtcb != NULL) {
@@ -4862,15 +4863,21 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcb
for (obj = globallist_curr(objs); obj != NULL;
obj = globallist_next(obj)) {
- if (obj->tlsoffset > 0) {
- addr = (Elf_Addr)tcb + obj->tlsoffset;
- if (obj->tlsinitsize > 0)
- memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
- if (obj->tlssize > obj->tlsinitsize)
- memset((void*)(addr + obj->tlsinitsize), 0,
- obj->tlssize - obj->tlsinitsize);
- dtv[obj->tlsindex + 1] = addr;
+ if (obj->tlsoffset == 0)
+ continue;
+ tls_init_offset = obj->tlspoffset & (obj->tlsalign - 1);
+ addr = (Elf_Addr)tcb + obj->tlsoffset;
+ if (tls_init_offset > 0)
+ memset((void *)addr, 0, tls_init_offset);
+ if (obj->tlsinitsize > 0) {
+ memcpy((void *)(addr + tls_init_offset), obj->tlsinit,
+ obj->tlsinitsize);
}
+ if (obj->tlssize > obj->tlsinitsize) {
+ memset((void *)(addr + tls_init_offset + obj->tlsinitsize),
+ 0, obj->tlssize - obj->tlsinitsize - tls_init_offset);
+ }
+ dtv[obj->tlsindex + 1] = addr;
}
}
@@ -4928,7 +4935,7 @@ allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcb
size = round(tls_static_space, ralign) + round(tcbsize, ralign);
assert(tcbsize >= 2*sizeof(Elf_Addr));
- tls = malloc_aligned(size, ralign);
+ tls = malloc_aligned(size, ralign, 0 /* XXX */);
dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr));
segbase = (Elf_Addr)(tls + round(tls_static_space, ralign));
@@ -5021,25 +5028,24 @@ free_tls(void *tls, size_t tcbsize __unused, size_t t
void *
allocate_module_tls(int index)
{
- Obj_Entry* obj;
- char* p;
+ Obj_Entry *obj;
+ char *p;
- TAILQ_FOREACH(obj, &obj_list, next) {
- if (obj->marker)
- continue;
- if (obj->tlsindex == index)
- break;
- }
- if (!obj) {
- _rtld_error("Can't find module with TLS index %d", index);
- rtld_die();
- }
+ TAILQ_FOREACH(obj, &obj_list, next) {
+ if (obj->marker)
+ continue;
+ if (obj->tlsindex == index)
+ break;
+ }
+ if (obj == NULL) {
+ _rtld_error("Can't find module with TLS index %d", index);
+ rtld_die();
+ }
- p = malloc_aligned(obj->tlssize, obj->tlsalign);
- memcpy(p, obj->tlsinit, obj->tlsinitsize);
- memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
-
- return p;
+ p = malloc_aligned(obj->tlssize, obj->tlsalign, obj->tlspoffset);
+ memcpy(p, obj->tlsinit, obj->tlsinitsize);
+ memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize);
+ return (p);
}
bool
Modified: stable/12/libexec/rtld-elf/rtld.h
==============================================================================
--- stable/12/libexec/rtld-elf/rtld.h Sat Apr 18 03:09:25 2020 (r360066)
+++ stable/12/libexec/rtld-elf/rtld.h Sat Apr 18 03:14:16 2020 (r360067)
@@ -168,6 +168,7 @@ typedef struct Struct_Obj_Entry {
size_t tlssize; /* Size of TLS block for this module */
size_t tlsoffset; /* Offset of static TLS block for this module */
size_t tlsalign; /* Alignment of static TLS block */
+ size_t tlspoffset; /* p_offset of the static TLS block */
caddr_t relro_page;
size_t relro_size;
@@ -362,7 +363,7 @@ Obj_Entry *map_object(int, const char *, const struct
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);
char *xstrdup(const char *);
-void *malloc_aligned(size_t size, size_t align);
+void *malloc_aligned(size_t size, size_t align, size_t offset);
void free_aligned(void *ptr);
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
extern Elf_Sym sym_zero; /* For resolving undefined weak refs. */
Modified: stable/12/libexec/rtld-elf/xmalloc.c
==============================================================================
--- stable/12/libexec/rtld-elf/xmalloc.c Sat Apr 18 03:09:25 2020 (r360066)
+++ stable/12/libexec/rtld-elf/xmalloc.c Sat Apr 18 03:14:16 2020 (r360067)
@@ -27,6 +27,7 @@
* $FreeBSD$
*/
+#include <sys/param.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@@ -75,16 +76,21 @@ xstrdup(const char *str)
}
void *
-malloc_aligned(size_t size, size_t align)
+malloc_aligned(size_t size, size_t align, size_t offset)
{
- void *mem, *res;
+ char *mem, *res;
+ uintptr_t x;
+ offset &= align - 1;
if (align < sizeof(void *))
align = sizeof(void *);
- mem = xmalloc(size + sizeof(void *) + align - 1);
- res = (void *)round((uintptr_t)mem + sizeof(void *), align);
- *(void **)((uintptr_t)res - sizeof(void *)) = mem;
+ mem = xmalloc(size + 3 * align + offset);
+ x = roundup((uintptr_t)mem + sizeof(void *), align);
+ x += offset;
+ res = (void *)x;
+ x -= sizeof(void *);
+ memcpy((void *)x, &mem, sizeof(mem));
return (res);
}
@@ -98,6 +104,6 @@ free_aligned(void *ptr)
return;
x = (uintptr_t)ptr;
x -= sizeof(void *);
- mem = *(void **)x;
+ memcpy(&mem, (void *)x, sizeof(mem));
free(mem);
}
More information about the svn-src-stable
mailing list