github.com/afumu/libc@v0.0.6/musl/src/env/__init_tls.c (about) 1 #define SYSCALL_NO_TLS 1 2 #include <elf.h> 3 #include <limits.h> 4 #include <sys/mman.h> 5 #include <string.h> 6 #include <stddef.h> 7 #include "pthread_impl.h" 8 #include "libc.h" 9 #include "atomic.h" 10 #include "syscall.h" 11 12 volatile int __thread_list_lock; 13 14 int __init_tp(void *p) 15 { 16 pthread_t td = p; 17 td->self = td; 18 int r = __set_thread_area(TP_ADJ(p)); 19 if (r < 0) return -1; 20 if (!r) libc.can_do_threads = 1; 21 td->detach_state = DT_JOINABLE; 22 td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock); 23 td->locale = &libc.global_locale; 24 td->robust_list.head = &td->robust_list.head; 25 td->sysinfo = __sysinfo; 26 td->next = td->prev = td; 27 return 0; 28 } 29 30 static struct builtin_tls { 31 char c; 32 struct pthread pt; 33 void *space[16]; 34 } builtin_tls[1]; 35 #define MIN_TLS_ALIGN offsetof(struct builtin_tls, pt) 36 37 static struct tls_module main_tls; 38 39 void *__copy_tls(unsigned char *mem) 40 { 41 pthread_t td; 42 struct tls_module *p; 43 size_t i; 44 uintptr_t *dtv; 45 46 #ifdef TLS_ABOVE_TP 47 dtv = (uintptr_t*)(mem + libc.tls_size) - (libc.tls_cnt + 1); 48 49 mem += -((uintptr_t)mem + sizeof(struct pthread)) & (libc.tls_align-1); 50 td = (pthread_t)mem; 51 mem += sizeof(struct pthread); 52 53 for (i=1, p=libc.tls_head; p; i++, p=p->next) { 54 dtv[i] = (uintptr_t)(mem + p->offset) + DTP_OFFSET; 55 memcpy(mem + p->offset, p->image, p->len); 56 } 57 #else 58 dtv = (uintptr_t *)mem; 59 60 mem += libc.tls_size - sizeof(struct pthread); 61 mem -= (uintptr_t)mem & (libc.tls_align-1); 62 td = (pthread_t)mem; 63 64 for (i=1, p=libc.tls_head; p; i++, p=p->next) { 65 dtv[i] = (uintptr_t)(mem - p->offset) + DTP_OFFSET; 66 memcpy(mem - p->offset, p->image, p->len); 67 } 68 #endif 69 dtv[0] = libc.tls_cnt; 70 td->dtv = td->dtv_copy = dtv; 71 return td; 72 } 73 74 #if ULONG_MAX == 0xffffffff 75 typedef Elf32_Phdr Phdr; 76 #else 77 typedef Elf64_Phdr Phdr; 78 #endif 79 80 extern weak hidden const size_t _DYNAMIC[]; 81 82 static void static_init_tls(size_t *aux) 83 { 84 unsigned char *p; 85 size_t n; 86 Phdr *phdr, *tls_phdr=0; 87 size_t base = 0; 88 void *mem; 89 90 for (p=(void *)aux[AT_PHDR],n=aux[AT_PHNUM]; n; n--,p+=aux[AT_PHENT]) { 91 phdr = (void *)p; 92 if (phdr->p_type == PT_PHDR) 93 base = aux[AT_PHDR] - phdr->p_vaddr; 94 if (phdr->p_type == PT_DYNAMIC && _DYNAMIC) 95 base = (size_t)_DYNAMIC - phdr->p_vaddr; 96 if (phdr->p_type == PT_TLS) 97 tls_phdr = phdr; 98 if (phdr->p_type == PT_GNU_STACK && 99 phdr->p_memsz > __default_stacksize) 100 __default_stacksize = 101 phdr->p_memsz < DEFAULT_STACK_MAX ? 102 phdr->p_memsz : DEFAULT_STACK_MAX; 103 } 104 105 if (tls_phdr) { 106 main_tls.image = (void *)(base + tls_phdr->p_vaddr); 107 main_tls.len = tls_phdr->p_filesz; 108 main_tls.size = tls_phdr->p_memsz; 109 main_tls.align = tls_phdr->p_align; 110 libc.tls_cnt = 1; 111 libc.tls_head = &main_tls; 112 } 113 114 main_tls.size += (-main_tls.size - (uintptr_t)main_tls.image) 115 & (main_tls.align-1); 116 #ifdef TLS_ABOVE_TP 117 main_tls.offset = GAP_ABOVE_TP; 118 main_tls.offset += (-GAP_ABOVE_TP + (uintptr_t)main_tls.image) 119 & (main_tls.align-1); 120 #else 121 main_tls.offset = main_tls.size; 122 #endif 123 if (main_tls.align < MIN_TLS_ALIGN) main_tls.align = MIN_TLS_ALIGN; 124 125 libc.tls_align = main_tls.align; 126 libc.tls_size = 2*sizeof(void *) + sizeof(struct pthread) 127 #ifdef TLS_ABOVE_TP 128 + main_tls.offset 129 #endif 130 + main_tls.size + main_tls.align 131 + MIN_TLS_ALIGN-1 & -MIN_TLS_ALIGN; 132 133 if (libc.tls_size > sizeof builtin_tls) { 134 #ifndef SYS_mmap2 135 #define SYS_mmap2 SYS_mmap 136 #endif 137 mem = (void *)__syscall( 138 SYS_mmap2, 139 0, libc.tls_size, PROT_READ|PROT_WRITE, 140 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 141 /* -4095...-1 cast to void * will crash on dereference anyway, 142 * so don't bloat the init code checking for error codes and 143 * explicitly calling a_crash(). */ 144 } else { 145 mem = builtin_tls; 146 } 147 148 /* Failure to initialize thread pointer is always fatal. */ 149 if (__init_tp(__copy_tls(mem)) < 0) 150 a_crash(); 151 } 152 153 weak_alias(static_init_tls, __init_tls);