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