1 /* 2 * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /* 18 * Thread Information Block (TIB) and Thread Local Storage (TLS) handling 19 * (the TCB, Thread Control Block, is part of the TIB) 20 */ 21 22 #define _DYN_LOADER 23 24 #include <sys/types.h> 25 26 #include <elf.h> 27 #include <tib.h> 28 29 #include "archdep.h" 30 #include "resolve.h" 31 #include "util.h" 32 #include "syscall.h" 33 34 /* If we need the syscall, use our local syscall definition */ 35 #define __set_tcb(tcb) _dl___set_tcb(tcb) 36 37 __dso_hidden void *allocate_tib(size_t); 38 39 #define MAX(a,b) (((a)>(b))?(a):(b)) 40 41 #ifdef TIB_EXTRA_ALIGN 42 # define TIB_ALIGN MAX(__alignof__(struct tib), TIB_EXTRA_ALIGN) 43 #else 44 # define TIB_ALIGN __alignof__(struct tib) 45 #endif 46 47 48 /* size of static TLS allocation */ 49 static int static_tls_size; 50 /* alignment of static TLS allocation */ 51 static int static_tls_align; 52 /* base-offset alignment of (first) static TLS allocation */ 53 static int static_tls_align_offset; 54 55 int _dl_tib_static_done; 56 57 /* 58 * Allocate a TIB for passing to __tfork for a new thread. 'extra' 59 * is the amount of space to allocate on the side of the TIB opposite 60 * of the TLS data: before the TIB for variant 1 and after the TIB 61 * for variant 2. If non-zero, tib_thread is set to point to that area. 62 */ 63 void * 64 allocate_tib(size_t extra) 65 { 66 char *base; 67 struct tib *tib; 68 char *thread = NULL; 69 struct elf_object *obj; 70 71 #if TLS_VARIANT == 1 72 /* round up the extra size to align the TIB and TLS data after it */ 73 size_t unpad_extra = (extra <= static_tls_align_offset) ? 0 : 74 ELF_ROUND(extra - static_tls_align_offset, static_tls_align); 75 base = _dl_aligned_alloc(static_tls_align, unpad_extra + 76 static_tls_align_offset + sizeof *tib + static_tls_size); 77 if (base == NULL) 78 return NULL; 79 tib = (struct tib *)(base + unpad_extra + static_tls_align_offset); 80 if (extra) 81 thread = base; 82 #define TLS_ADDR(tibp, offset) ((char *)(tibp) + sizeof(struct tib) + (offset)) 83 84 #elif TLS_VARIANT == 2 85 /* round up the TIB size to align the extra area after it */ 86 base = _dl_aligned_alloc(static_tls_align, static_tls_size + 87 static_tls_align_offset + ELF_ROUND(sizeof *tib, TIB_EXTRA_ALIGN) + 88 extra); 89 if (base == NULL) 90 return NULL; 91 base += static_tls_align_offset; 92 tib = (struct tib *)(base + static_tls_size); 93 if (extra) 94 thread = (char *)tib + ELF_ROUND(sizeof *tib, TIB_EXTRA_ALIGN); 95 #define TLS_ADDR(tibp, offset) ((char *)(tibp) - (offset)) 96 97 #endif 98 99 for (obj = _dl_objects; obj != NULL; obj = obj->next) { 100 if (obj->tls_msize != 0) { 101 char *addr = TLS_ADDR(tib, obj->tls_offset); 102 103 _dl_memset(addr + obj->tls_fsize, 0, 104 obj->tls_msize - obj->tls_fsize); 105 if (obj->tls_static_data != NULL) 106 _dl_bcopy(obj->tls_static_data, addr, 107 obj->tls_fsize); 108 DL_DEB(("\t%s has index %u addr %p msize %u fsize %u\n", 109 obj->load_name, obj->tls_offset, 110 (void *)addr, obj->tls_msize, obj->tls_fsize)); 111 } 112 } 113 114 TIB_INIT(tib, NULL, thread); 115 116 DL_DEB(("tib new=%p\n", (void *)tib)); 117 118 return (tib); 119 } 120 __strong_alias(_dl_allocate_tib, allocate_tib); 121 122 void 123 _dl_free_tib(void *tib, size_t extra) 124 { 125 size_t tib_offset; 126 127 #if TLS_VARIANT == 1 128 tib_offset = (extra <= static_tls_align_offset) ? 0 : 129 ELF_ROUND(extra - static_tls_align_offset, static_tls_align); 130 #elif TLS_VARIANT == 2 131 tib_offset = static_tls_size; 132 #endif 133 tib_offset += static_tls_align_offset; 134 135 DL_DEB(("free tib=%p\n", (void *)tib)); 136 _dl_free((char *)tib - tib_offset); 137 } 138 139 140 /* 141 * Record what's necessary for handling TLS for an object. 142 */ 143 void 144 _dl_set_tls(elf_object_t *object, Elf_Phdr *ptls, Elf_Addr libaddr, 145 const char *libname) 146 { 147 if (ptls->p_vaddr != 0 && ptls->p_filesz != 0) 148 object->tls_static_data = (void *)(ptls->p_vaddr + libaddr); 149 object->tls_fsize = ptls->p_filesz; 150 object->tls_msize = ptls->p_memsz; 151 object->tls_align = ptls->p_align; 152 153 DL_DEB(("tls %x %x %x %x\n", 154 object->tls_static_data, object->tls_fsize, object->tls_msize, 155 object->tls_align)); 156 } 157 158 static inline Elf_Addr 159 allocate_tls_offset(Elf_Addr msize, Elf_Addr align, int for_exe) 160 { 161 Elf_Addr offset; 162 163 if (for_exe && static_tls_size != 0) 164 _dl_die("TLS allocation before executable!"); 165 166 #if TLS_VARIANT == 1 167 if (for_exe) { 168 /* 169 * Variant 1 places the data after the TIB. If the 170 * TLS alignment is larger than the TIB alignment 171 * then we may need to pad in front of the TIB to 172 * place the TLS data on the proper alignment. 173 * Example: p_align=16 sizeof(TIB)=52 align(TIB)=4 174 * - need to offset the TIB 12 bytes from the start 175 * - to place ths TLS data at offset 64 176 */ 177 static_tls_align = MAX(align, TIB_ALIGN); 178 static_tls_align_offset = 179 ELF_ROUND(sizeof(struct tib), static_tls_align) - 180 sizeof(struct tib); 181 offset = 0; 182 static_tls_size = msize; 183 } else { 184 /* 185 * If a later object increases the alignment, realign the 186 * existing sections. We push as much padding as possible 187 * to the start there it can overlap the thread structure 188 */ 189 if (static_tls_align < align) { 190 static_tls_align_offset += align - static_tls_align; 191 static_tls_align = align; 192 } 193 194 /* 195 * Round up to the required alignment, taking into account 196 * the leading padding and TIB, then allocate the space. 197 */ 198 offset = static_tls_align_offset + sizeof(struct tib) + 199 static_tls_size; 200 offset = ELF_ROUND(offset, align) - static_tls_align_offset 201 - sizeof(struct tib); 202 static_tls_size = offset + msize; 203 } 204 #elif TLS_VARIANT == 2 205 /* Realignment is automatic for variant II */ 206 if (static_tls_align < align) 207 static_tls_align = align; 208 209 /* 210 * Variant 2 places the data before the TIB so we need to round up 211 * the size to the TLS data alignment TIB's alignment. 212 * Example A: p_memsz=24 p_align=16 align(TIB)=8 213 * - need to allocate 32 bytes for TLS as compiler 214 * - will give the first TLS symbol an offset of -32 215 * Example B: p_memsz=4 p_align=4 align(TIB)=8 216 * - need to allocate 8 bytes so that the TIB is 217 * - properly aligned 218 * So: allocate the space, then round up to the alignment 219 * (these are negative offsets, so rounding up really 220 * rounds the address down) 221 */ 222 static_tls_size = ELF_ROUND(static_tls_size + msize, align); 223 offset = static_tls_size; 224 #else 225 # error "unknown TLS_VARIANT" 226 #endif 227 return offset; 228 } 229 230 /* 231 * Calculate the TLS offset for each object with static TLS. 232 */ 233 void 234 _dl_allocate_tls_offsets(void) 235 { 236 struct elf_object *obj; 237 238 static_tls_align = TIB_ALIGN; 239 for (obj = _dl_objects; obj != NULL; obj = obj->next) { 240 if (obj->tls_msize != 0) { 241 obj->tls_offset = allocate_tls_offset(obj->tls_msize, 242 obj->tls_align, obj->obj_type == OBJTYPE_EXE); 243 } 244 } 245 246 #if TLS_VARIANT == 2 247 static_tls_align_offset = ELF_ROUND(static_tls_size, static_tls_align) 248 - static_tls_size; 249 #endif 250 251 /* no more static TLS allocations after this */ 252 _dl_tib_static_done = 1; 253 254 DL_DEB(("static tls size=%x align=%x offset=%x\n", 255 static_tls_size, static_tls_align, static_tls_align_offset)); 256 } 257 258 /* 259 * Allocate the TIB + TLS for the initial thread. 260 */ 261 void 262 _dl_allocate_first_tib(void) 263 { 264 struct tib *tib; 265 266 tib = allocate_tib(0); 267 tib->tib_tid = _dl_getthrid(); 268 269 TCB_SET(TIB_TO_TCB(tib)); 270 } 271