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 2006 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 40 static void (* fptr_tls_modadd)(TLS_modinfo *) = 0; 41 static void (* fptr_tls_modrem)(TLS_modinfo *) = 0; 42 static void (* fptr_tls_statmods)(TLS_modinfo **, unsigned long) = 0; 43 44 static int tlsinitialized = 0; 45 static unsigned long tls_static_size = 0; /* static TLS buffer size */ 46 47 #define TLSBLOCKCNT 16 /* number of blocks of tmi_bits to allocate */ 48 /* at a time. */ 49 typedef struct { 50 uint_t *tmi_bits; 51 ulong_t tmi_lowfree; 52 ulong_t tmi_cnt; 53 } Tlsmodid; 54 55 static Tlsmodid tmid = {0, 0, 0}; 56 57 unsigned long 58 tls_getmodid() 59 { 60 ulong_t ndx; 61 ulong_t i; 62 63 if (tmid.tmi_bits == 0) { 64 if ((tmid.tmi_bits = 65 (uint_t *)calloc(TLSBLOCKCNT, sizeof (uint_t))) == 0) 66 return ((unsigned long)-1); 67 tmid.tmi_bits[0] = 1; 68 tmid.tmi_lowfree = 1; 69 tmid.tmi_cnt = TLSBLOCKCNT; 70 return (0); 71 } 72 73 for (i = tmid.tmi_lowfree / (sizeof (uint_t) * 8); 74 i < tmid.tmi_cnt; i++) { 75 uint_t j; 76 /* 77 * If all bits are assigned - move on. 78 */ 79 if ((tmid.tmi_bits[i] ^ ~((uint_t)0)) == 0) 80 continue; 81 for (ndx = 0, j = 1; j; j = j << 1, ndx++) { 82 if ((tmid.tmi_bits[i] & j) == 0) { 83 tmid.tmi_bits[i] |= j; 84 ndx = (i * (sizeof (uint_t)) * 8) + ndx; 85 tmid.tmi_lowfree = ndx + 1; 86 return (ndx); 87 } 88 } 89 } 90 91 /* 92 * All bits taken - must allocate a new block 93 */ 94 if ((tmid.tmi_bits = (uint_t *)realloc(tmid.tmi_bits, 95 ((tmid.tmi_cnt * sizeof (uint_t)) + 96 (TLSBLOCKCNT * sizeof (uint_t))))) == 0) 97 return ((unsigned long)-1); 98 /* 99 * clear out the tail of the new allocation 100 */ 101 bzero(&(tmid.tmi_bits[tmid.tmi_cnt]), TLSBLOCKCNT * sizeof (uint_t)); 102 tmid.tmi_bits[tmid.tmi_cnt] = 1; 103 ndx = (tmid.tmi_cnt * sizeof (uint_t)) * 8; 104 tmid.tmi_lowfree = ndx + 1; 105 tmid.tmi_cnt += TLSBLOCKCNT; 106 107 return (ndx); 108 } 109 110 111 void 112 tls_freemodid(unsigned long modid) 113 { 114 ulong_t i; 115 uint_t j; 116 117 i = modid / (sizeof (uint_t) * 8); 118 /* LINTED */ 119 j = modid % (sizeof (uint_t) * 8); 120 j = ~(1 << j); 121 tmid.tmi_bits[i] &= j; 122 if (modid < tmid.tmi_lowfree) 123 tmid.tmi_lowfree = modid; 124 } 125 126 127 void 128 tls_setroutines(Lm_list *lml, void * modadd, void * modrem, void * statmod) 129 { 130 /* 131 * If a version of libc/libthread gives us only a subset 132 * of the TLS interfaces - it's confused and we discard 133 * the whole lot. 134 */ 135 if (!modadd || !modrem || !statmod) 136 return; 137 138 if ((fptr_tls_modadd == 0) || (lml->lm_flags & LML_FLG_BASELM)) 139 fptr_tls_modadd = (void(*)(TLS_modinfo *)) modadd; 140 if ((fptr_tls_modrem == 0) || (lml->lm_flags & LML_FLG_BASELM)) 141 fptr_tls_modrem = (void(*)(TLS_modinfo *)) modrem; 142 /* 143 * The 'statmods' interface is only relevent for the 144 * primary link-map - ignore all other instances. 145 */ 146 if (lml->lm_flags & LML_FLG_BASELM) 147 fptr_tls_statmods = 148 (void(*)(TLS_modinfo **, unsigned long)) statmod; 149 } 150 151 152 void 153 tls_modactivity(Rt_map * lmp, uint_t flag) 154 { 155 TLS_modinfo tmi; 156 Phdr * tlsphdr; 157 void (* fptr)(TLS_modinfo *); 158 159 if (flag & TM_FLG_MODADD) 160 fptr = fptr_tls_modadd; 161 else 162 fptr = fptr_tls_modrem; 163 164 /* 165 * We only report TLS modactivity for the primary link-map 166 * after all the objects have been loaded and we've reported 167 * the STATIC tls modlist (see tls_report_modules()). 168 */ 169 if (((tlsinitialized == 0) && 170 (LIST(lmp)->lm_flags & LML_FLG_BASELM)) || 171 (fptr == 0) || (lmp == 0) || (FCT(lmp) != &elf_fct) || 172 (PTTLS(lmp) == 0)) 173 return; 174 175 tlsphdr = PTTLS(lmp); 176 177 bzero(&tmi, sizeof (tmi)); 178 tmi.tm_modname = PATHNAME(lmp); 179 tmi.tm_modid = TLSMODID(lmp); 180 tmi.tm_tlsblock = (void *)(tlsphdr->p_vaddr); 181 if (!(FLAGS(lmp) & FLG_RT_FIXED)) 182 tmi.tm_tlsblock = (void *)((uintptr_t)tmi.tm_tlsblock + 183 ADDR(lmp)); 184 tmi.tm_filesz = tlsphdr->p_filesz; 185 tmi.tm_memsz = tlsphdr->p_memsz; 186 tmi.tm_flags = 0; 187 tmi.tm_stattlsoffset = 0; 188 189 DBG_CALL(Dbg_tls_modactivity(LIST(lmp), &tmi, flag)); 190 fptr(&tmi); 191 192 /* 193 * Free up the moduleid 194 */ 195 if (flag & TM_FLG_MODREM) 196 tls_freemodid(TLSMODID(lmp)); 197 } 198 199 200 void 201 tls_assign_soffset(Rt_map * lmp) 202 { 203 if (PTTLS(lmp) == 0) 204 return; 205 206 /* 207 * Only objects on the primary link-map list are associated 208 * with the STATIC tls block. 209 */ 210 if (LIST(lmp)->lm_flags & LML_FLG_BASELM) { 211 tls_static_size += S_ROUND(PTTLS(lmp)->p_memsz, M_TLSSTATALIGN); 212 TLSSTATOFF(lmp) = tls_static_size; 213 } 214 215 /* 216 * Everyone get's a dynamic TLS modid 217 */ 218 TLSMODID(lmp) = tls_getmodid(); 219 } 220 221 int 222 tls_report_modules() 223 { 224 Rt_map *lmp; 225 uint_t tlsmodcnt, tlsmodndx; 226 TLS_modinfo **tlsmodlist; 227 TLS_modinfo *tlsbuflist; 228 Phdr *tlsphdr; 229 230 tlsinitialized++; 231 /* 232 * Scan through all objects to determine how many have TLS storage. 233 */ 234 tlsmodcnt = 0; 235 for (lmp = lml_main.lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) { 236 if ((FCT(lmp) != &elf_fct) || 237 (PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0)) 238 continue; 239 tlsmodcnt++; 240 241 if (fptr_tls_statmods) 242 continue; 243 244 /* 245 * If a module has TLS - but the TLS interfaces are not present 246 * (no libthread?). Then this is a fatal condition. 247 */ 248 eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_ERR_TLS_NOTLS), 249 NAME(lmp)); 250 return (0); 251 } 252 253 /* 254 * If we don't have any TLS modules - report that and return. 255 */ 256 if (tlsmodcnt == 0) { 257 if (fptr_tls_statmods != 0) 258 fptr_tls_statmods(0, 0); 259 return (1); 260 } 261 262 /* 263 * Allocate a buffer to report the TLS modules, the buffer consists of: 264 * 265 * TLS_modinfo * ptrs[tlsmodcnt + 1] 266 * TLS_modinfo bufs[tlsmodcnt] 267 * 268 * The ptrs are initialized to the bufs - except the last 269 * one which null terminates the array. 270 */ 271 if ((tlsmodlist = calloc((sizeof (TLS_modinfo *) * tlsmodcnt + 1) + 272 (sizeof (TLS_modinfo) * tlsmodcnt), 1)) == 0) 273 return (0); 274 275 tlsbuflist = (TLS_modinfo *)((uintptr_t)tlsmodlist + 276 ((tlsmodcnt + 1) * sizeof (TLS_modinfo *))); 277 for (tlsmodndx = 0; tlsmodndx < tlsmodcnt; tlsmodndx++) 278 tlsmodlist[tlsmodndx] = &tlsbuflist[tlsmodndx]; 279 280 /* 281 * Account for the initial dtv ptr in the TLSSIZE calculation. 282 */ 283 tlsmodndx = 0; 284 for (lmp = lml_main.lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) { 285 if ((FCT(lmp) != &elf_fct) || 286 (PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0)) 287 continue; 288 289 tlsphdr = PTTLS(lmp); 290 291 tlsmodlist[tlsmodndx]->tm_modname = PATHNAME(lmp); 292 tlsmodlist[tlsmodndx]->tm_modid = TLSMODID(lmp); 293 tlsmodlist[tlsmodndx]->tm_tlsblock = 294 (void *)(tlsphdr->p_vaddr); 295 if (!(FLAGS(lmp) & FLG_RT_FIXED)) 296 tlsmodlist[tlsmodndx]->tm_tlsblock = 297 (void *)((uintptr_t)tlsmodlist[ 298 tlsmodndx]->tm_tlsblock + ADDR(lmp)); 299 tlsmodlist[tlsmodndx]->tm_filesz = tlsphdr->p_filesz; 300 tlsmodlist[tlsmodndx]->tm_memsz = tlsphdr->p_memsz; 301 tlsmodlist[tlsmodndx]->tm_flags = TM_FLG_STATICTLS; 302 tlsmodlist[tlsmodndx]->tm_stattlsoffset = 303 TLSSTATOFF(lmp); 304 tlsmodndx++; 305 } 306 307 DBG_CALL(Dbg_tls_static_block(&lml_main, (void *)tlsmodlist, 308 tls_static_size)); 309 fptr_tls_statmods(tlsmodlist, tls_static_size); 310 311 /* 312 * We're done with the list - clean it up. 313 */ 314 free(tlsmodlist); 315 return (1); 316 } 317