PERFORCE change 50251 for review
Doug Rabson
dfr at FreeBSD.org
Sat Apr 3 02:57:48 PST 2004
http://perforce.freebsd.org/chv.cgi?CH=50251
Change 50251 by dfr at 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
More information about the p4-projects
mailing list