Date: Thu, 22 Jul 2004 16:03:37 GMT From: Doug Rabson <dfr@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 57928 for review Message-ID: <200407221603.i6MG3bdm006681@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=57928 Change 57928 by dfr@dfr_home on 2004/07/22 16:03:00 Add some defines for non-i386 arches and flesh out the amd64 support (untested). Affected files ... .. //depot/projects/kse/libexec/rtld-elf/alpha/rtld_machdep.h#3 edit .. //depot/projects/kse/libexec/rtld-elf/amd64/reloc.c#3 edit .. //depot/projects/kse/libexec/rtld-elf/amd64/rtld_machdep.h#3 edit .. //depot/projects/kse/libexec/rtld-elf/sparc64/reloc.c#3 edit .. //depot/projects/kse/libexec/rtld-elf/sparc64/rtld_machdep.h#4 edit Differences ... ==== //depot/projects/kse/libexec/rtld-elf/alpha/rtld_machdep.h#3 (text+ko) ==== @@ -66,6 +66,7 @@ round(16, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round(prev_offset + prev_size, align) +#define calculate_tls_end(off, size) ((off) + (size)) typedef struct { unsigned long ti_module; ==== //depot/projects/kse/libexec/rtld-elf/amd64/reloc.c#3 (text+ko) ==== @@ -48,6 +48,15 @@ #include "debug.h" #include "rtld.h" +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + /* * Process the special R_X86_64_COPY relocations in the main program. These * copy data from a shared object into a region in the main program's BSS @@ -200,6 +209,108 @@ } break; + case R_X86_64_TPOFF64: + { + const Elf_Sym *def; + const Obj_Entry *defobj; + + def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, + false, cache); + if (def == NULL) + goto done; + + /* + * We lazily allocate offsets for static TLS as we + * see the first relocation that references the + * TLS block. This allows us to support (small + * amounts of) static TLS in dynamically loaded + * modules. If we run out of space, we generate an + * error. + */ + if (!defobj->tls_done) { + if (!allocate_tls_offset((Obj_Entry*) defobj)) { + _rtld_error("%s: No space available for static " + "Thread Local Storage", obj->path); + goto done; + } + } + + *where = (Elf_Addr) (def->st_value - defobj->tlsoffset); + } + break; + + case R_X86_64_TPOFF32: + { + const Elf_Sym *def; + const Obj_Entry *defobj; + + def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, + false, cache); + if (def == NULL) + goto done; + + /* + * We lazily allocate offsets for static TLS as we + * see the first relocation that references the + * TLS block. This allows us to support (small + * amounts of) static TLS in dynamically loaded + * modules. If we run out of space, we generate an + * error. + */ + if (!defobj->tls_done) { + if (!allocate_tls_offset((Obj_Entry*) defobj)) { + _rtld_error("%s: No space available for static " + "Thread Local Storage", obj->path); + goto done; + } + } + + *where32 = (Elf32_Addr) (def->st_value - defobj->tlsoffset); + } + break; + + case R_X86_64_DTPMOD64: + { + const Elf_Sym *def; + const Obj_Entry *defobj; + + def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, + false, cache); + if (def == NULL) + goto done; + + *where += (Elf_Addr) defobj->tlsindex; + } + break; + + case R_X86_64_DTPOFF64: + { + const Elf_Sym *def; + const Obj_Entry *defobj; + + def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, + false, cache); + if (def == NULL) + goto done; + + *where += (Elf_Addr) def->st_value; + } + break; + + case R_X86_64_DTPOFF32: + { + const Elf_Sym *def; + const Obj_Entry *defobj; + + def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, + false, cache); + if (def == NULL) + goto done; + + *where32 += (Elf32_Addr) def->st_value; + } + break; + case R_X86_64_RELATIVE: *where = (Elf_Addr)(obj->relocbase + rela->r_addend); break; @@ -267,24 +378,20 @@ return 0; } -void -allocate_initial_tls(Obj_Entry *list) +void * +allocate_tls(Objlist* list, size_t tcbsize, size_t tcbalign) { + Objlist_Entry *entry; Obj_Entry *obj; size_t size; char *tls; Elf_Addr *dtv; - union descriptor ldt; - Elf_Addr segbase; - int sel; + Elf_Addr segbase, addr; - size = 0; - for (obj = list; obj; obj = obj->next) { - if (obj->tlsoffset > size) - size = obj->tlsoffset; - } + size = round(tls_static_space, tcbalign); - tls = malloc(size + 2*sizeof(Elf_Addr)); + assert(tcbsize >= 2*sizeof(Elf_Addr)); + tls = malloc(size + tcbsize); dtv = malloc((tls_max_index + 2) * sizeof(Elf_Addr)); segbase = (Elf_Addr)(tls + size); @@ -293,16 +400,60 @@ 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; + STAILQ_FOREACH(entry, list, link) { + obj = entry->obj; + if (obj->tlsoffset) { + 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 + 1] = addr; + } else if (obj->tlsindex) { + dtv[obj->tlsindex + 1] = 0; + } + } + + return (void*) segbase; +} + +void +free_tls(Objlist *list, void *tls, size_t tcbsize, size_t tcbalign) +{ + size_t size; + Elf_Addr* dtv; + int dtvsize, i; + Elf_Addr tlsstart, tlsend; + + /* + * Figure out the size of the initial TLS block so that we can + * find stuff which ___tls_get_addr() allocated dynamically. + */ + size = round(tls_static_space, tcbalign); + + dtv = ((Elf_Addr**)tls)[1]; + dtvsize = dtv[1]; + tlsend = (Elf_Addr) tls; + tlsstart = tlsend - size; + for (i = 0; i < dtvsize; i++) { + if (dtv[i+2] < tlsstart || dtv[i+2] > tlsend) { + free((void*) dtv[i+2]); + } } - amd64_set_fsbase(segbase); + free((void*) tlsstart); +} + +void +allocate_initial_tls(Obj_Entry *list) +{ + /* + * Fix the size of the static TLS block by using the maximum + * offset allocated so far and adding a bit for dynamic modules to + * use. + */ + tls_static_space = tls_last_offset + 64; + amd64_set_fsbase(allocate_tls(list, 2*sizeof(Elf_Addr), 4)); } void *__tls_get_addr(tls_index *ti) ==== //depot/projects/kse/libexec/rtld-elf/amd64/rtld_machdep.h#3 (text+ko) ==== @@ -64,6 +64,7 @@ round(size, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round((prev_offset) + (size), align) +#define calculate_tls_end(off, size) (off) typedef struct { unsigned long ti_module; ==== //depot/projects/kse/libexec/rtld-elf/sparc64/reloc.c#3 (text+ko) ==== ==== //depot/projects/kse/libexec/rtld-elf/sparc64/rtld_machdep.h#4 (text+ko) ==== @@ -58,6 +58,7 @@ round(size, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ round((prev_offset) + (size), align) +#define calculate_tls_end(off, size) ((off) + (size)) typedef struct { unsigned long ti_module;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407221603.i6MG3bdm006681>