Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Apr 2020 03:14:16 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r360067 - stable/12/libexec/rtld-elf
Message-ID:  <202004180314.03I3EGLS065134@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004180314.03I3EGLS065134>