From owner-p4-projects@FreeBSD.ORG Sat Apr 3 02:57:47 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 9332916A4D0; Sat, 3 Apr 2004 02:57:47 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5235B16A4CE for ; Sat, 3 Apr 2004 02:57:47 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 47A8243D31 for ; Sat, 3 Apr 2004 02:57:47 -0800 (PST) (envelope-from dfr@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i33AvlGe012472 for ; Sat, 3 Apr 2004 02:57:47 -0800 (PST) (envelope-from dfr@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i33Avknw012469 for perforce@freebsd.org; Sat, 3 Apr 2004 02:57:46 -0800 (PST) (envelope-from dfr@freebsd.org) Date: Sat, 3 Apr 2004 02:57:46 -0800 (PST) Message-Id: <200404031057.i33Avknw012469@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to dfr@freebsd.org using -f From: Doug Rabson To: Perforce Change Reviews Subject: PERFORCE change 50251 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Apr 2004 10:57:48 -0000 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 #include +#include #include #include @@ -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