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