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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 #include <sys/types.h>
37 #define TLSBLOCKCNT 16 /* number of blocks of tmi_bits to allocate */
45 static Tlsmodid tmid
= {0, 0, 0};
52 if (tmid
.tmi_bits
== 0) {
54 calloc(TLSBLOCKCNT
, sizeof (uint_t
))) == NULL
)
58 tmid
.tmi_cnt
= TLSBLOCKCNT
;
62 for (cnt
= tmid
.tmi_lowfree
/ (sizeof (uint_t
) * 8);
63 cnt
< tmid
.tmi_cnt
; cnt
++) {
67 * If all bits are assigned - move on.
69 if ((tmid
.tmi_bits
[cnt
] ^ ~((uint_t
)0)) == 0)
72 for (ndx
= 0, bits
= 1; bits
; bits
= bits
<< 1, ndx
++) {
73 if ((tmid
.tmi_bits
[cnt
] & bits
) == 0) {
74 tmid
.tmi_bits
[cnt
] |= bits
;
75 ndx
= (cnt
* (sizeof (uint_t
)) * 8) + ndx
;
76 tmid
.tmi_lowfree
= ndx
+ 1;
83 * All bits taken - must allocate a new block
85 if ((tmid
.tmi_bits
= realloc(tmid
.tmi_bits
,
86 ((tmid
.tmi_cnt
* sizeof (uint_t
)) +
87 (TLSBLOCKCNT
* sizeof (uint_t
))))) == NULL
)
91 * Clear out the tail of the new allocation.
93 bzero(&(tmid
.tmi_bits
[tmid
.tmi_cnt
]), TLSBLOCKCNT
* sizeof (uint_t
));
94 tmid
.tmi_bits
[tmid
.tmi_cnt
] = 1;
95 ndx
= (tmid
.tmi_cnt
* sizeof (uint_t
)) * 8;
96 tmid
.tmi_lowfree
= ndx
+ 1;
97 tmid
.tmi_cnt
+= TLSBLOCKCNT
;
103 tls_freemodid(ulong_t modid
)
108 i
= modid
/ (sizeof (uint_t
) * 8);
110 j
= modid
% (sizeof (uint_t
) * 8);
112 tmid
.tmi_bits
[i
] &= j
;
113 if (modid
< tmid
.tmi_lowfree
)
114 tmid
.tmi_lowfree
= modid
;
118 tls_modaddrem(Rt_map
*lmp
, uint_t flag
)
120 Lm_list
*lml
= LIST(lmp
);
123 void (*fptr
)(TLS_modinfo
*);
125 if (flag
& TM_FLG_MODADD
) {
126 fptr
= (void (*)())lml
->lm_lcs
[CI_TLS_MODADD
].lc_un
.lc_func
;
127 } else if (FLAGS1(lmp
) & FL1_RT_TLSADD
) {
128 fptr
= (void (*)())lml
->lm_lcs
[CI_TLS_MODREM
].lc_un
.lc_func
;
133 tlsphdr
= PTTLS(lmp
);
135 bzero(&tmi
, sizeof (tmi
));
136 tmi
.tm_modname
= PATHNAME(lmp
);
137 tmi
.tm_modid
= TLSMODID(lmp
);
138 tmi
.tm_tlsblock
= (void *)(tlsphdr
->p_vaddr
);
140 if (!(FLAGS(lmp
) & FLG_RT_FIXED
))
141 tmi
.tm_tlsblock
= (void *)((uintptr_t)tmi
.tm_tlsblock
+
144 tmi
.tm_filesz
= tlsphdr
->p_filesz
;
145 tmi
.tm_memsz
= tlsphdr
->p_memsz
;
147 tmi
.tm_stattlsoffset
= 0;
149 DBG_CALL(Dbg_tls_modactivity(LIST(lmp
), &tmi
, flag
));
153 * Tag that this link-map has registered its TLS, and, if this object
154 * is being removed, free up the module id.
156 FLAGS1(lmp
) |= FL1_RT_TLSADD
;
158 if (flag
& TM_FLG_MODREM
)
159 tls_freemodid(TLSMODID(lmp
));
162 static ulong_t tls_static_size
= 0; /* static TLS buffer size */
163 static ulong_t tls_static_resv
= 512; /* (extra) static TLS reservation */
166 * Track any static TLS use, retain the TLS header, and assign a TLS module
170 tls_assign(Lm_list
*lml
, Rt_map
*lmp
, Phdr
*phdr
)
172 ulong_t memsz
= S_ROUND(phdr
->p_memsz
, M_TLSSTATALIGN
);
173 ulong_t filesz
= phdr
->p_filesz
;
174 ulong_t resv
= tls_static_resv
;
177 * If this object explicitly references static TLS, then there are some
180 if (FLAGS1(lmp
) & FL1_RT_TLSSTAT
) {
182 * Static TLS is only available to objects on the primary
185 if (((lml
->lm_flags
& LML_FLG_BASELM
) == 0) ||
186 ((rtld_flags2
& RT_FL2_NOPLM
) != 0)) {
187 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_TLS_STATBASE
),
193 * All TLS blocks that are processed before thread
194 * initialization, are registered with libc. This
195 * initialization is carried out through a handshake with libc
196 * prior to executing any user code (ie. before the first .init
197 * sections are called). As part of this initialization, a
198 * small backup TLS reservation is added (tls_static_resv).
199 * Only explicit static TLS references that can be satisfied by
200 * this TLS backup reservation can be satisfied.
202 if (rtld_flags2
& RT_FL2_PLMSETUP
) {
204 * Initialized static TLS can not be satisfied from the
205 * TLS backup reservation.
208 eprintf(lml
, ERR_FATAL
,
209 MSG_INTL(MSG_TLS_STATINIT
), NAME(lmp
));
214 * Make sure the backup reservation is sufficient.
216 if (memsz
> tls_static_resv
) {
217 eprintf(lml
, ERR_FATAL
,
218 MSG_INTL(MSG_TLS_STATSIZE
), NAME(lmp
),
219 EC_XWORD(memsz
), EC_XWORD(tls_static_resv
));
223 tls_static_resv
-= memsz
;
228 * If we haven't yet initialized threads, or this static reservation can
229 * be satisfied from the TLS backup reservation, determine the total
230 * static TLS size, and assign this object a static TLS offset.
232 if (((rtld_flags2
& RT_FL2_PLMSETUP
) == 0) ||
233 (FLAGS1(lmp
) & FL1_RT_TLSSTAT
)) {
234 tls_static_size
+= memsz
;
235 TLSSTATOFF(lmp
) = tls_static_size
;
239 * Retain the PT_TLS header, obtain a new module identifier, and
240 * indicate that this link-map list contains a new TLS object.
243 TLSMODID(lmp
) = tls_getmodid();
246 * Now that we have a TLS module id, generate any static TLS reservation
249 if (resv
!= tls_static_resv
)
250 DBG_CALL(Dbg_tls_static_resv(lmp
, memsz
, tls_static_resv
));
252 return (++lml
->lm_tls
);
256 tls_statmod(Lm_list
*lml
, Rt_map
*lmp
)
258 uint_t tlsmodndx
, tlsmodcnt
= lml
->lm_tls
;
259 TLS_modinfo
**tlsmodlist
, *tlsbuflist
;
261 void (*fptr
)(TLS_modinfo
**, ulong_t
);
263 fptr
= (void (*)())lml
->lm_lcs
[CI_TLS_STATMOD
].lc_un
.lc_func
;
266 * Allocate a buffer to report the TLS modules, the buffer consists of:
268 * TLS_modinfo * ptrs[tlsmodcnt + 1]
269 * TLS_modinfo bufs[tlsmodcnt]
271 * The ptrs are initialized to the bufs - except the last one which
272 * null terminates the array.
274 * Note, even if no TLS has yet been observed, we still supply a
275 * TLS buffer with a single null entry. This allows us to initialize
276 * the backup TLS reservation.
278 if ((tlsmodlist
= calloc((sizeof (TLS_modinfo
*) * (tlsmodcnt
+ 1)) +
279 (sizeof (TLS_modinfo
) * tlsmodcnt
), 1)) == NULL
)
285 * If we don't have any TLS modules - report that and return.
287 if (tlsmodcnt
== 0) {
289 (*fptr
)(tlsmodlist
, tls_static_resv
);
290 DBG_CALL(Dbg_tls_static_block(&lml_main
, 0, 0,
296 * Initialize the TLS buffer.
298 tlsbuflist
= (TLS_modinfo
*)((uintptr_t)tlsmodlist
+
299 ((tlsmodcnt
+ 1) * sizeof (TLS_modinfo
*)));
301 for (tlsmodndx
= 0; tlsmodndx
< tlsmodcnt
; tlsmodndx
++)
302 tlsmodlist
[tlsmodndx
] = &tlsbuflist
[tlsmodndx
];
305 * Account for the initial dtv ptr in the TLSSIZE calculation.
308 for (lmp
= lml
->lm_head
; lmp
; lmp
= NEXT_RT_MAP(lmp
)) {
309 if (THIS_IS_NOT_ELF(lmp
) ||
310 (PTTLS(lmp
) == 0) || (PTTLS(lmp
)->p_memsz
== 0))
313 tlsphdr
= PTTLS(lmp
);
315 tlsmodlist
[tlsmodndx
]->tm_modname
= PATHNAME(lmp
);
316 tlsmodlist
[tlsmodndx
]->tm_modid
= TLSMODID(lmp
);
317 tlsmodlist
[tlsmodndx
]->tm_tlsblock
= (void *)(tlsphdr
->p_vaddr
);
319 if (!(FLAGS(lmp
) & FLG_RT_FIXED
)) {
320 tlsmodlist
[tlsmodndx
]->tm_tlsblock
= (void *)
321 ((uintptr_t)tlsmodlist
[tlsmodndx
]->tm_tlsblock
+
324 tlsmodlist
[tlsmodndx
]->tm_filesz
= tlsphdr
->p_filesz
;
325 tlsmodlist
[tlsmodndx
]->tm_memsz
= tlsphdr
->p_memsz
;
326 tlsmodlist
[tlsmodndx
]->tm_flags
= TM_FLG_STATICTLS
;
327 tlsmodlist
[tlsmodndx
]->tm_stattlsoffset
= TLSSTATOFF(lmp
);
331 DBG_CALL(Dbg_tls_static_block(&lml_main
, (void *)tlsmodlist
,
332 tls_static_size
, tls_static_resv
));
333 (*fptr
)(tlsmodlist
, (tls_static_size
+ tls_static_resv
));
336 * We're done with the list - clean it up.