1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 29 #include <stdio.h> 30 #include <strings.h> 31 #include <sys/types.h> 32 #include <dlfcn.h> 33 #include <libc_int.h> 34 #include <_rtld.h> 35 #include <_elf.h> 36 #include <msg.h> 37 #include <debug.h> 38 39 #define TLSBLOCKCNT 16 /* number of blocks of tmi_bits to allocate */ 40 /* at a time. */ 41 typedef struct { 42 uint_t *tmi_bits; 43 ulong_t tmi_lowfree; 44 ulong_t tmi_cnt; 45 } Tlsmodid; 46 47 static Tlsmodid tmid = {0, 0, 0}; 48 49 static ulong_t 50 tls_getmodid() 51 { 52 ulong_t ndx, cnt; 53 54 if (tmid.tmi_bits == 0) { 55 if ((tmid.tmi_bits = calloc(TLSBLOCKCNT, sizeof (uint_t))) == 0) 56 return ((ulong_t)-1); 57 tmid.tmi_bits[0] = 1; 58 tmid.tmi_lowfree = 1; 59 tmid.tmi_cnt = TLSBLOCKCNT; 60 return (0); 61 } 62 63 for (cnt = tmid.tmi_lowfree / (sizeof (uint_t) * 8); 64 cnt < tmid.tmi_cnt; cnt++) { 65 uint_t bits; 66 67 /* 68 * If all bits are assigned - move on. 69 */ 70 if ((tmid.tmi_bits[cnt] ^ ~((uint_t)0)) == 0) 71 continue; 72 73 for (ndx = 0, bits = 1; bits; bits = bits << 1, ndx++) { 74 if ((tmid.tmi_bits[cnt] & bits) == 0) { 75 tmid.tmi_bits[cnt] |= bits; 76 ndx = (cnt * (sizeof (uint_t)) * 8) + ndx; 77 tmid.tmi_lowfree = ndx + 1; 78 return (ndx); 79 } 80 } 81 } 82 83 /* 84 * All bits taken - must allocate a new block 85 */ 86 if ((tmid.tmi_bits = realloc(tmid.tmi_bits, 87 ((tmid.tmi_cnt * sizeof (uint_t)) + 88 (TLSBLOCKCNT * sizeof (uint_t))))) == 0) 89 return ((ulong_t)-1); 90 91 /* 92 * Clear out the tail of the new allocation. 93 */ 94 bzero(&(tmid.tmi_bits[tmid.tmi_cnt]), TLSBLOCKCNT * sizeof (uint_t)); 95 tmid.tmi_bits[tmid.tmi_cnt] = 1; 96 ndx = (tmid.tmi_cnt * sizeof (uint_t)) * 8; 97 tmid.tmi_lowfree = ndx + 1; 98 tmid.tmi_cnt += TLSBLOCKCNT; 99 100 return (ndx); 101 } 102 103 void 104 tls_freemodid(ulong_t modid) 105 { 106 ulong_t i; 107 uint_t j; 108 109 i = modid / (sizeof (uint_t) * 8); 110 /* LINTED */ 111 j = modid % (sizeof (uint_t) * 8); 112 j = ~(1 << j); 113 tmid.tmi_bits[i] &= j; 114 if (modid < tmid.tmi_lowfree) 115 tmid.tmi_lowfree = modid; 116 } 117 118 void 119 tls_modaddrem(Rt_map *lmp, uint_t flag) 120 { 121 Lm_list *lml = LIST(lmp); 122 TLS_modinfo tmi; 123 Phdr *tlsphdr; 124 void (*fptr)(TLS_modinfo *); 125 126 if (flag & TM_FLG_MODADD) { 127 fptr = (void (*)())lml->lm_lcs[CI_TLS_MODADD].lc_un.lc_func; 128 } else if (FLAGS1(lmp) & FL1_RT_TLSADD) { 129 fptr = (void (*)())lml->lm_lcs[CI_TLS_MODREM].lc_un.lc_func; 130 } else { 131 return; 132 } 133 134 tlsphdr = PTTLS(lmp); 135 136 bzero(&tmi, sizeof (tmi)); 137 tmi.tm_modname = PATHNAME(lmp); 138 tmi.tm_modid = TLSMODID(lmp); 139 tmi.tm_tlsblock = (void *)(tlsphdr->p_vaddr); 140 141 if (!(FLAGS(lmp) & FLG_RT_FIXED)) 142 tmi.tm_tlsblock = (void *)((uintptr_t)tmi.tm_tlsblock + 143 ADDR(lmp)); 144 145 tmi.tm_filesz = tlsphdr->p_filesz; 146 tmi.tm_memsz = tlsphdr->p_memsz; 147 tmi.tm_flags = 0; 148 tmi.tm_stattlsoffset = 0; 149 150 DBG_CALL(Dbg_tls_modactivity(LIST(lmp), &tmi, flag)); 151 (*fptr)(&tmi); 152 153 /* 154 * Tag that this link-map has registered its TLS, and, if this object 155 * is being removed, free up the module id. 156 */ 157 FLAGS1(lmp) |= FL1_RT_TLSADD; 158 159 if (flag & TM_FLG_MODREM) 160 tls_freemodid(TLSMODID(lmp)); 161 } 162 163 static ulong_t tls_static_size = 0; /* static TLS buffer size */ 164 static ulong_t tls_static_resv = 512; /* (extra) static TLS reservation */ 165 166 /* 167 * Track any static TLS use, retain the TLS header, and assign a TLS module 168 * identifier. 169 */ 170 int 171 tls_assign(Lm_list *lml, Rt_map *lmp, Phdr *phdr) 172 { 173 ulong_t memsz = S_ROUND(phdr->p_memsz, M_TLSSTATALIGN); 174 ulong_t filesz = phdr->p_filesz; 175 ulong_t resv = tls_static_resv; 176 177 /* 178 * If this object explicitly references static TLS, then there are some 179 * limitations. 180 */ 181 if (FLAGS1(lmp) & FL1_RT_TLSSTAT) { 182 /* 183 * Static TLS is only available to objects on the primary 184 * link-map list. 185 */ 186 if (((lml->lm_flags & LML_FLG_BASELM) == 0) || 187 ((rtld_flags2 & RT_FL2_NOPLM) != 0)) { 188 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TLS_STATBASE), 189 NAME(lmp)); 190 return (0); 191 } 192 193 /* 194 * All TLS blocks that are processed before thread 195 * initialization, are registered with libc. This 196 * initialization is carried out through a handshake with libc 197 * prior to executing any user code (ie. before the first .init 198 * sections are called). As part of this initialization, a 199 * small backup TLS reservation is added (tls_static_resv). 200 * Only explicit static TLS references that can be satisfied by 201 * this TLS backup reservation can be satisfied. 202 */ 203 if (rtld_flags2 & RT_FL2_PLMSETUP) { 204 /* 205 * Initialized static TLS can not be satisfied from the 206 * TLS backup reservation. 207 */ 208 if (filesz) { 209 eprintf(lml, ERR_FATAL, 210 MSG_INTL(MSG_TLS_STATINIT), NAME(lmp)); 211 return (0); 212 } 213 214 /* 215 * Make sure the backup reservation is sufficient. 216 */ 217 if (memsz > tls_static_resv) { 218 eprintf(lml, ERR_FATAL, 219 MSG_INTL(MSG_TLS_STATSIZE), NAME(lmp), 220 EC_XWORD(memsz), EC_XWORD(tls_static_resv)); 221 return (0); 222 } 223 224 tls_static_resv -= memsz; 225 } 226 } 227 228 /* 229 * If we haven't yet initialized threads, or this static reservation can 230 * be satisfied from the TLS backup reservation, determine the total 231 * static TLS size, and assign this object a static TLS offset. 232 */ 233 if (((rtld_flags2 & RT_FL2_PLMSETUP) == 0) || 234 (FLAGS1(lmp) & FL1_RT_TLSSTAT)) { 235 tls_static_size += memsz; 236 TLSSTATOFF(lmp) = tls_static_size; 237 } 238 239 /* 240 * Retain the PT_TLS header, obtain a new module identifier, and 241 * indicate that this link-map list contains a new TLS object. 242 */ 243 PTTLS(lmp) = phdr; 244 TLSMODID(lmp) = tls_getmodid(); 245 246 /* 247 * Now that we have a TLS module id, generate any static TLS reservation 248 * diagnostic. 249 */ 250 if (resv != tls_static_resv) 251 DBG_CALL(Dbg_tls_static_resv(lmp, memsz, tls_static_resv)); 252 253 return (++lml->lm_tls); 254 } 255 256 int 257 tls_statmod(Lm_list *lml, Rt_map *lmp) 258 { 259 uint_t tlsmodndx, tlsmodcnt = lml->lm_tls; 260 TLS_modinfo **tlsmodlist, *tlsbuflist; 261 Phdr *tlsphdr; 262 void (*fptr)(TLS_modinfo **, ulong_t); 263 264 fptr = (void (*)())lml->lm_lcs[CI_TLS_STATMOD].lc_un.lc_func; 265 266 /* 267 * Allocate a buffer to report the TLS modules, the buffer consists of: 268 * 269 * TLS_modinfo * ptrs[tlsmodcnt + 1] 270 * TLS_modinfo bufs[tlsmodcnt] 271 * 272 * The ptrs are initialized to the bufs - except the last one which 273 * null terminates the array. 274 * 275 * Note, even if no TLS has yet been observed, we still supply a 276 * TLS buffer with a single null entry. This allows us to initialize 277 * the backup TLS reservation. 278 */ 279 if ((tlsmodlist = calloc((sizeof (TLS_modinfo *) * (tlsmodcnt + 1)) + 280 (sizeof (TLS_modinfo) * tlsmodcnt), 1)) == 0) 281 return (0); 282 283 lml->lm_tls = 0; 284 285 /* 286 * If we don't have any TLS modules - report that and return. 287 */ 288 if (tlsmodcnt == 0) { 289 if (fptr) 290 (*fptr)(tlsmodlist, tls_static_resv); 291 DBG_CALL(Dbg_tls_static_block(&lml_main, 0, 0, 292 tls_static_resv)); 293 return (1); 294 } 295 296 /* 297 * Initialize the TLS buffer. 298 */ 299 tlsbuflist = (TLS_modinfo *)((uintptr_t)tlsmodlist + 300 ((tlsmodcnt + 1) * sizeof (TLS_modinfo *))); 301 302 for (tlsmodndx = 0; tlsmodndx < tlsmodcnt; tlsmodndx++) 303 tlsmodlist[tlsmodndx] = &tlsbuflist[tlsmodndx]; 304 305 /* 306 * Account for the initial dtv ptr in the TLSSIZE calculation. 307 */ 308 tlsmodndx = 0; 309 for (lmp = lml->lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) { 310 if ((FCT(lmp) != &elf_fct) || 311 (PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0)) 312 continue; 313 314 tlsphdr = PTTLS(lmp); 315 316 tlsmodlist[tlsmodndx]->tm_modname = PATHNAME(lmp); 317 tlsmodlist[tlsmodndx]->tm_modid = TLSMODID(lmp); 318 tlsmodlist[tlsmodndx]->tm_tlsblock = (void *)(tlsphdr->p_vaddr); 319 320 if (!(FLAGS(lmp) & FLG_RT_FIXED)) { 321 tlsmodlist[tlsmodndx]->tm_tlsblock = (void *) 322 ((uintptr_t)tlsmodlist[tlsmodndx]->tm_tlsblock + 323 ADDR(lmp)); 324 } 325 tlsmodlist[tlsmodndx]->tm_filesz = tlsphdr->p_filesz; 326 tlsmodlist[tlsmodndx]->tm_memsz = tlsphdr->p_memsz; 327 tlsmodlist[tlsmodndx]->tm_flags = TM_FLG_STATICTLS; 328 tlsmodlist[tlsmodndx]->tm_stattlsoffset = TLSSTATOFF(lmp); 329 tlsmodndx++; 330 } 331 332 DBG_CALL(Dbg_tls_static_block(&lml_main, (void *)tlsmodlist, 333 tls_static_size, tls_static_resv)); 334 (*fptr)(tlsmodlist, (tls_static_size + tls_static_resv)); 335 336 /* 337 * We're done with the list - clean it up. 338 */ 339 free(tlsmodlist); 340 return (1); 341 } 342