Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Apr 2004 02:57:46 -0800 (PST)
From:      Doug Rabson <dfr@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 50251 for review
Message-ID:  <200404031057.i33Avknw012469@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=50251

Change 50251 by dfr@dfr_home on 2004/04/03 02:57:19

	Start on TLS support for non-i386 arches. Probably doesn't compile,
	certainly doesn't work (missing support for arch-specific TLS
	relocs).

Affected files ...

.. //depot/projects/kse/libexec/rtld-elf/alpha/reloc.c#2 edit
.. //depot/projects/kse/libexec/rtld-elf/alpha/rtld_machdep.h#2 edit
.. //depot/projects/kse/libexec/rtld-elf/amd64/reloc.c#2 edit
.. //depot/projects/kse/libexec/rtld-elf/amd64/rtld_machdep.h#2 edit
.. //depot/projects/kse/libexec/rtld-elf/i386/rtld_machdep.h#4 edit
.. //depot/projects/kse/libexec/rtld-elf/ia64/reloc.c#2 edit
.. //depot/projects/kse/libexec/rtld-elf/ia64/rtld_machdep.h#2 edit
.. //depot/projects/kse/libexec/rtld-elf/map_object.c#3 edit
.. //depot/projects/kse/libexec/rtld-elf/rtld.c#4 edit
.. //depot/projects/kse/libexec/rtld-elf/rtld.h#3 edit
.. //depot/projects/kse/libexec/rtld-elf/sparc64/reloc.c#2 edit
.. //depot/projects/kse/libexec/rtld-elf/sparc64/rtld_machdep.h#2 edit

Differences ...

==== //depot/projects/kse/libexec/rtld-elf/alpha/reloc.c#2 (text+ko) ====

@@ -505,3 +505,46 @@
 		obj->pltgot[3] = (Elf_Addr) obj;
 	}
 }
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+    Obj_Entry *obj;
+    size_t size;
+    char *tls;
+    Elf_Addr *dtv;
+    union descriptor ldt;
+    Elf_Addr segbase;
+    int sel;
+
+    size = 0;
+    for (obj = list; obj; obj = obj->next) {
+        if (obj->tlsoffset + obj->tlssize > size)
+            size = obj->tlsoffset + obj->tlssize;
+    }
+
+    tls = malloc(size);
+    dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr));
+
+    *(Elf_Addr**) tls = dtv;
+
+    dtv[0] = tls_dtv_generation;
+    dtv[1] = tls_max_index;
+    for (obj = list; obj; obj = obj->next) {
+	Elf_Addr addr = tls + obj->tlsoffset;
+	memset((void*) (addr + obj->tlsinitsize),
+	       0, obj->tlssize - obj->tlsinitsize);
+        if (obj->tlsinit)
+	    memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
+	dtv[obj->tlsindex] = addr;
+    }
+
+    alpha_pal_wrunique((u_int64_t) tls);
+}
+
+void *__tls_get_addr(tls_index* ti)
+{
+    Elf_Addr** tp = (Elf_Addr**) alpha_pal_rdunique();
+
+    return tls_get_addr_common(&tp[0], ti->ti_module, ti->ti_offset);
+}

==== //depot/projects/kse/libexec/rtld-elf/alpha/rtld_machdep.h#2 (text+ko) ====

@@ -60,4 +60,18 @@
 /* Lazy binding entry point, called via PLT. */
 void _rtld_bind_start_old(void);
 
+#define round(size, align) \
+	(((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+	round(16, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+	round(prev_offset + prev_size, align)
+
+typedef struct {
+    unsigned long ti_module;
+    unsigned long ti_offset;
+} tls_index;
+
+extern void *__tls_get_addr(tls_index *ti);
+
 #endif

==== //depot/projects/kse/libexec/rtld-elf/amd64/reloc.c#2 (text+ko) ====

@@ -33,6 +33,7 @@
 
 #include <sys/param.h>
 #include <sys/mman.h>
+#include <sys/sysarch.h>
 
 #include <dlfcn.h>
 #include <err.h>
@@ -265,3 +266,52 @@
     obj->jmpslots_done = true;
     return 0;
 }
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+    Obj_Entry *obj;
+    size_t size;
+    char *tls;
+    Elf_Addr *dtv;
+    union descriptor ldt;
+    Elf_Addr segbase;
+    int sel;
+
+    size = 0;
+    for (obj = list; obj; obj = obj->next) {
+        if (obj->tlsoffset > size)
+            size = obj->tlsoffset;
+    }
+
+    tls = malloc(size + 2*sizeof(Elf_Addr));
+    dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr));
+
+    segbase = (Elf_Addr)(tls + size);
+    ((Elf_Addr*)segbase)[0] = segbase;
+    ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
+
+    dtv[0] = tls_dtv_generation;
+    dtv[1] = tls_max_index;
+    for (obj = list; obj; obj = obj->next) {
+	Elf_Addr addr = segbase - obj->tlsoffset;
+	memset((void*) (addr + obj->tlsinitsize),
+	       0, obj->tlssize - obj->tlsinitsize);
+        if (obj->tlsinit)
+	    memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
+	dtv[obj->tlsindex] = addr;
+    }
+
+    amd64_set_fsbase(segbase);
+}
+
+void *__tls_get_addr(tls_index *ti)
+{
+    Elf_Addr** segbase;
+    Elf_Addr* dtv;
+
+    __asm __volatile("movl %%fs:0, %0" : "=r" (segbase));
+    dtv = segbase[1];
+
+    return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
+}

==== //depot/projects/kse/libexec/rtld-elf/amd64/rtld_machdep.h#2 (text+ko) ====

@@ -58,4 +58,18 @@
 #define call_initfini_pointer(obj, target) \
 	(((InitFunc)(target))())
 
+#define round(size, align) \
+	(((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+	round(size, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+	round((prev_offset) + (size), align)
+
+typedef struct {
+    unsigned long ti_module;
+    unsigned long ti_offset;
+} tls_index;
+
+extern void *__tls_get_addr(tls_index *ti);
+
 #endif

==== //depot/projects/kse/libexec/rtld-elf/i386/rtld_machdep.h#4 (text+ko) ====

@@ -58,9 +58,12 @@
 #define call_initfini_pointer(obj, target) \
 	(((InitFunc)(target))())
 
-#define calculate_tls_offset(prev_offset, size, align) \
-	(((prev_offset) + (size) + ((align) - 1)) \
-	    & ~((align) - 1))
+#define round(size, align) \
+	(((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+	round(size, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+	round((prev_offset) + (size), align)
 
 typedef struct {
     unsigned long ti_module;

==== //depot/projects/kse/libexec/rtld-elf/ia64/reloc.c#2 (text+ko) ====

@@ -535,3 +535,47 @@
 	pltres[1] = FPTR_TARGET(_rtld_bind_start);
 	pltres[2] = FPTR_GP(_rtld_bind_start);
 }
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+    register struct Elf_Addr** tp __asm__("r13");
+    Obj_Entry *obj;
+    size_t size;
+    char *tls;
+    Elf_Addr *dtv;
+    union descriptor ldt;
+    Elf_Addr segbase;
+    int sel;
+
+    size = 0;
+    for (obj = list; obj; obj = obj->next) {
+        if (obj->tlsoffset + obj->tlssize > size)
+            size = obj->tlsoffset + obj->tlssize;
+    }
+
+    tls = malloc(size);
+    dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr));
+
+    *(Elf_Addr**) tls = dtv;
+
+    dtv[0] = tls_dtv_generation;
+    dtv[1] = tls_max_index;
+    for (obj = list; obj; obj = obj->next) {
+	Elf_Addr addr = tls + obj->tlsoffset;
+	memset((void*) (addr + obj->tlsinitsize),
+	       0, obj->tlssize - obj->tlsinitsize);
+        if (obj->tlsinit)
+	    memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
+	dtv[obj->tlsindex] = addr;
+    }
+
+    tp = (Elf_Addr**) tls;
+}
+
+void *__tls_get_addr(unsigned int module, unsigned int offset)
+{
+    register struct Elf_Addr** tp __asm__("r13");
+
+    return tls_get_addr_common(&tp[0], module, offset);
+}

==== //depot/projects/kse/libexec/rtld-elf/ia64/rtld_machdep.h#2 (text+ko) ====

@@ -55,4 +55,13 @@
 void *make_function_pointer(const Elf_Sym *, const struct Struct_Obj_Entry *);
 void call_initfini_pointer(const struct Struct_Obj_Entry *, Elf_Addr);
 
+#define round(size, align) \
+	(((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+	round(16, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+	round(prev_offset + prev_size, align)
+
+extern void *__tls_get_addr(unsigned long module, unsigned long offset);
+
 #endif

==== //depot/projects/kse/libexec/rtld-elf/map_object.c#3 (text+ko) ====

@@ -239,9 +239,16 @@
 	obj->tlssize = phtls->p_memsz;
 	obj->tlsinitsize = phtls->p_filesz;
 	obj->tlsinit = mapbase + phtls->p_vaddr;
-	obj->tlsoffset = calculate_tls_offset(tls_last_offset,
-					      phtls->p_memsz, phtls->p_align);
+	if (obj->tlsindex == 1)
+	    obj->tlsoffset = calculate_first_tls_offset(phtls->p_memsz,
+							phtls->p_align);
+	else
+	    obj->tlsoffset = calculate_tls_offset(tls_last_offset,
+						  tls_last_size,
+						  phtls->p_memsz,
+						  phtls->p_align);
 	tls_last_offset = obj->tlsoffset;
+	tls_last_size = obj->tlssize;
     }
     return obj;
 }

==== //depot/projects/kse/libexec/rtld-elf/rtld.c#4 (text+ko) ====

@@ -195,6 +195,7 @@
  * Globals to control TLS allocation.
  */
 size_t tls_last_offset;		/* TLS offset of last module */
+size_t tls_last_size;		/* TLS size of last module */
 int tls_dtv_generation = 1;	/* Used to detect when dtv size changes  */
 int tls_max_index = 1;		/* Largest module index allocated */
 
@@ -401,10 +402,8 @@
     lockdflt_init();
 
     /* setup TLS for main thread */
-    dbg("initializing initial thread local storage (size %d)",
-	tls_last_offset);
+    dbg("initializing initial thread local storage");
     allocate_initial_tls(obj_list);
-    dbg("foo");
 
     /* Make a list of init functions to call. */
     objlist_init(&initlist);
@@ -745,9 +744,10 @@
 
 	case PT_TLS:
 	    obj->tlsindex = 1;
-	    obj->tlsoffset = calculate_tls_offset(0, ph->p_memsz,
-						  ph->p_align);
+	    obj->tlsoffset = calculate_first_tls_offset(ph->p_memsz,
+							ph->p_align);
 	    tls_last_offset = obj->tlsoffset;
+	    tls_last_size = obj->tlssize;
 	    obj->tlssize = ph->p_memsz;
 	    obj->tlsinitsize = ph->p_filesz;
 	    obj->tlsinit = (void*) ph->p_vaddr;

==== //depot/projects/kse/libexec/rtld-elf/rtld.h#3 (text+ko) ====

@@ -64,6 +64,7 @@
 #define true	1
 
 extern size_t tls_last_offset;
+extern size_t tls_last_size;
 extern int tls_dtv_generation;
 extern int tls_max_index;
 

==== //depot/projects/kse/libexec/rtld-elf/sparc64/reloc.c#2 (text+ko) ====

@@ -717,3 +717,49 @@
 	pltgot[7] = MOV_g1_o0;
 	flush(pltgot, 28);
 }
+
+void
+allocate_initial_tls(Obj_Entry *list)
+{
+    register struct Elf_Addr tp __asm__("%g7");
+    Obj_Entry *obj;
+    size_t size;
+    char *tls;
+    Elf_Addr *dtv;
+    union descriptor ldt;
+    Elf_Addr segbase;
+    int sel;
+
+    size = 0;
+    for (obj = list; obj; obj = obj->next) {
+        if (obj->tlsoffset > size)
+            size = obj->tlsoffset;
+    }
+
+    tls = malloc(size + 2*sizeof(Elf_Addr));
+    dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr));
+
+    segbase = (Elf_Addr)(tls + size);
+    ((Elf_Addr*)segbase)[0] = segbase;
+    ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
+
+    dtv[0] = tls_dtv_generation;
+    dtv[1] = tls_max_index;
+    for (obj = list; obj; obj = obj->next) {
+	Elf_Addr addr = segbase - obj->tlsoffset;
+	memset((void*) (addr + obj->tlsinitsize),
+	       0, obj->tlssize - obj->tlsinitsize);
+        if (obj->tlsinit)
+	    memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize);
+	dtv[obj->tlsindex] = addr;
+    }
+
+    tp = segbase;
+}
+
+void *__tls_get_addr(tls_index *ti)
+{
+    register struct Elf_Addr** tp __asm__("%g7");
+
+    return tls_get_addr_common(&tp[0], ti->ti_module, ti->ti_offset);
+}

==== //depot/projects/kse/libexec/rtld-elf/sparc64/rtld_machdep.h#2 (text+ko) ====

@@ -50,4 +50,18 @@
 #define call_initfini_pointer(obj, target) \
 	(((InitFunc)(target))())
 
+#define round(size, align) \
+	(((size) + (align) - 1) & ~((align) - 1))
+#define calculate_first_tls_offset(size, align) \
+	round(size, align)
+#define calculate_tls_offset(prev_offset, prev_size, size, align) \
+	round((prev_offset) + (size), align)
+
+typedef struct {
+    unsigned long ti_module;
+    unsigned long ti_offset;
+} tls_index;
+
+extern void *__tls_get_addr(tls_index *ti);
+
 #endif



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