xref: /illumos-gate/usr/src/cmd/sgs/rtld/common/tls.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  *	Copyright 2001-2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  *	Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <strings.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
32*7c478bd9Sstevel@tonic-gate #include <dlfcn.h>
33*7c478bd9Sstevel@tonic-gate #include <libc_int.h>
34*7c478bd9Sstevel@tonic-gate #include <_rtld.h>
35*7c478bd9Sstevel@tonic-gate #include <_elf.h>
36*7c478bd9Sstevel@tonic-gate #include <conv.h>
37*7c478bd9Sstevel@tonic-gate #include <msg.h>
38*7c478bd9Sstevel@tonic-gate #include <debug.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate static void (*	fptr_tls_modadd)(TLS_modinfo *) = 0;
42*7c478bd9Sstevel@tonic-gate static void (*	fptr_tls_modrem)(TLS_modinfo *) = 0;
43*7c478bd9Sstevel@tonic-gate static void (*	fptr_tls_statmods)(TLS_modinfo **, unsigned long) = 0;
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate static int	tlsinitialized = 0;
46*7c478bd9Sstevel@tonic-gate static unsigned long tls_static_size = 0;	/* static TLS buffer size */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #define	TLSBLOCKCNT	16	/* number of blocks of tmi_bits to allocate */
49*7c478bd9Sstevel@tonic-gate 				/* at a time. */
50*7c478bd9Sstevel@tonic-gate typedef struct {
51*7c478bd9Sstevel@tonic-gate 	uint_t	*tmi_bits;
52*7c478bd9Sstevel@tonic-gate 	ulong_t	tmi_lowfree;
53*7c478bd9Sstevel@tonic-gate 	ulong_t	tmi_cnt;
54*7c478bd9Sstevel@tonic-gate } Tlsmodid;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate static Tlsmodid	tmid = {0, 0, 0};
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate unsigned long
59*7c478bd9Sstevel@tonic-gate tls_getmodid()
60*7c478bd9Sstevel@tonic-gate {
61*7c478bd9Sstevel@tonic-gate 	ulong_t		ndx;
62*7c478bd9Sstevel@tonic-gate 	ulong_t		i;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	if (tmid.tmi_bits == 0) {
65*7c478bd9Sstevel@tonic-gate 		if ((tmid.tmi_bits =
66*7c478bd9Sstevel@tonic-gate 		    (uint_t *)calloc(TLSBLOCKCNT, sizeof (uint_t))) == 0)
67*7c478bd9Sstevel@tonic-gate 			return ((unsigned long)-1);
68*7c478bd9Sstevel@tonic-gate 		tmid.tmi_bits[0] = 1;
69*7c478bd9Sstevel@tonic-gate 		tmid.tmi_lowfree = 1;
70*7c478bd9Sstevel@tonic-gate 		tmid.tmi_cnt = TLSBLOCKCNT;
71*7c478bd9Sstevel@tonic-gate 		return (0);
72*7c478bd9Sstevel@tonic-gate 	}
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate 	for (i = tmid.tmi_lowfree / (sizeof (uint_t) * 8);
75*7c478bd9Sstevel@tonic-gate 	    i < tmid.tmi_cnt; i++) {
76*7c478bd9Sstevel@tonic-gate 		uint_t	j;
77*7c478bd9Sstevel@tonic-gate 		/*
78*7c478bd9Sstevel@tonic-gate 		 * If all bits are assigned - move on.
79*7c478bd9Sstevel@tonic-gate 		 */
80*7c478bd9Sstevel@tonic-gate 		if ((tmid.tmi_bits[i] ^ ~((uint_t)0)) == 0)
81*7c478bd9Sstevel@tonic-gate 			continue;
82*7c478bd9Sstevel@tonic-gate 		for (ndx = 0, j = 1; j; j = j << 1, ndx++) {
83*7c478bd9Sstevel@tonic-gate 			if ((tmid.tmi_bits[i] & j) == 0) {
84*7c478bd9Sstevel@tonic-gate 				tmid.tmi_bits[i] |= j;
85*7c478bd9Sstevel@tonic-gate 				ndx = (i * (sizeof (uint_t)) * 8) + ndx;
86*7c478bd9Sstevel@tonic-gate 				tmid.tmi_lowfree = ndx + 1;
87*7c478bd9Sstevel@tonic-gate 				return (ndx);
88*7c478bd9Sstevel@tonic-gate 			}
89*7c478bd9Sstevel@tonic-gate 		}
90*7c478bd9Sstevel@tonic-gate 	}
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 	/*
93*7c478bd9Sstevel@tonic-gate 	 * All bits taken - must allocate a new block
94*7c478bd9Sstevel@tonic-gate 	 */
95*7c478bd9Sstevel@tonic-gate 	if ((tmid.tmi_bits = (uint_t *)realloc(tmid.tmi_bits,
96*7c478bd9Sstevel@tonic-gate 	    ((tmid.tmi_cnt * sizeof (uint_t)) +
97*7c478bd9Sstevel@tonic-gate 	    (TLSBLOCKCNT * sizeof (uint_t))))) == 0)
98*7c478bd9Sstevel@tonic-gate 		return ((unsigned long)-1);
99*7c478bd9Sstevel@tonic-gate 	/*
100*7c478bd9Sstevel@tonic-gate 	 * clear out the tail of the new allocation
101*7c478bd9Sstevel@tonic-gate 	 */
102*7c478bd9Sstevel@tonic-gate 	bzero(&(tmid.tmi_bits[tmid.tmi_cnt]), TLSBLOCKCNT * sizeof (uint_t));
103*7c478bd9Sstevel@tonic-gate 	tmid.tmi_bits[tmid.tmi_cnt] = 1;
104*7c478bd9Sstevel@tonic-gate 	ndx = (tmid.tmi_cnt * sizeof (uint_t)) * 8;
105*7c478bd9Sstevel@tonic-gate 	tmid.tmi_lowfree = ndx + 1;
106*7c478bd9Sstevel@tonic-gate 	tmid.tmi_cnt += TLSBLOCKCNT;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	return (ndx);
109*7c478bd9Sstevel@tonic-gate }
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate void
113*7c478bd9Sstevel@tonic-gate tls_freemodid(unsigned long modid)
114*7c478bd9Sstevel@tonic-gate {
115*7c478bd9Sstevel@tonic-gate 	ulong_t	i;
116*7c478bd9Sstevel@tonic-gate 	uint_t	j;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	i = modid / (sizeof (uint_t) * 8);
119*7c478bd9Sstevel@tonic-gate 	/* LINTED */
120*7c478bd9Sstevel@tonic-gate 	j = modid % (sizeof (uint_t) * 8);
121*7c478bd9Sstevel@tonic-gate 	j = ~(1 << j);
122*7c478bd9Sstevel@tonic-gate 	tmid.tmi_bits[i] &= j;
123*7c478bd9Sstevel@tonic-gate 	if (modid < tmid.tmi_lowfree)
124*7c478bd9Sstevel@tonic-gate 		tmid.tmi_lowfree = modid;
125*7c478bd9Sstevel@tonic-gate }
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate void
129*7c478bd9Sstevel@tonic-gate tls_setroutines(Lm_list *lml, void * modadd, void * modrem, void * statmod)
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate 	/*
132*7c478bd9Sstevel@tonic-gate 	 * If a version of libc/libthread gives us only a subset
133*7c478bd9Sstevel@tonic-gate 	 * of the TLS interfaces - it's confused and we discard
134*7c478bd9Sstevel@tonic-gate 	 * the whole lot.
135*7c478bd9Sstevel@tonic-gate 	 */
136*7c478bd9Sstevel@tonic-gate 	if (!modadd || !modrem || !statmod)
137*7c478bd9Sstevel@tonic-gate 		return;
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	if ((fptr_tls_modadd == 0) || (lml->lm_flags & LML_FLG_BASELM))
140*7c478bd9Sstevel@tonic-gate 		fptr_tls_modadd = (void(*)(TLS_modinfo *)) modadd;
141*7c478bd9Sstevel@tonic-gate 	if ((fptr_tls_modrem == 0) || (lml->lm_flags & LML_FLG_BASELM))
142*7c478bd9Sstevel@tonic-gate 		fptr_tls_modrem = (void(*)(TLS_modinfo *)) modrem;
143*7c478bd9Sstevel@tonic-gate 	/*
144*7c478bd9Sstevel@tonic-gate 	 * The 'statmods' interface is only relevent for the
145*7c478bd9Sstevel@tonic-gate 	 * primary link-map - ignore all other instances.
146*7c478bd9Sstevel@tonic-gate 	 */
147*7c478bd9Sstevel@tonic-gate 	if (lml->lm_flags & LML_FLG_BASELM)
148*7c478bd9Sstevel@tonic-gate 		fptr_tls_statmods =
149*7c478bd9Sstevel@tonic-gate 			(void(*)(TLS_modinfo **, unsigned long)) statmod;
150*7c478bd9Sstevel@tonic-gate }
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate void
154*7c478bd9Sstevel@tonic-gate tls_modactivity(Rt_map * lmp, uint_t flag)
155*7c478bd9Sstevel@tonic-gate {
156*7c478bd9Sstevel@tonic-gate 	TLS_modinfo	tmi;
157*7c478bd9Sstevel@tonic-gate 	Phdr *		tlsphdr;
158*7c478bd9Sstevel@tonic-gate 	void (*		fptr)(TLS_modinfo *);
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	if (flag & TM_FLG_MODADD)
161*7c478bd9Sstevel@tonic-gate 		fptr = fptr_tls_modadd;
162*7c478bd9Sstevel@tonic-gate 	else
163*7c478bd9Sstevel@tonic-gate 		fptr = fptr_tls_modrem;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	/*
166*7c478bd9Sstevel@tonic-gate 	 * We only report TLS modactivity for the primary link-map
167*7c478bd9Sstevel@tonic-gate 	 * after all the objects have been loaded and we've reported
168*7c478bd9Sstevel@tonic-gate 	 * the STATIC tls modlist (see tls_report_modules()).
169*7c478bd9Sstevel@tonic-gate 	 */
170*7c478bd9Sstevel@tonic-gate 	if (((tlsinitialized == 0) &&
171*7c478bd9Sstevel@tonic-gate 	    (LIST(lmp)->lm_flags & LML_FLG_BASELM)) ||
172*7c478bd9Sstevel@tonic-gate 	    (fptr == 0) || (lmp == 0) || (FCT(lmp) != &elf_fct) ||
173*7c478bd9Sstevel@tonic-gate 	    (PTTLS(lmp) == 0))
174*7c478bd9Sstevel@tonic-gate 		return;
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	tlsphdr = PTTLS(lmp);
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	bzero(&tmi, sizeof (tmi));
179*7c478bd9Sstevel@tonic-gate 	tmi.tm_modname = PATHNAME(lmp);
180*7c478bd9Sstevel@tonic-gate 	tmi.tm_modid = TLSMODID(lmp);
181*7c478bd9Sstevel@tonic-gate 	tmi.tm_tlsblock = (void *)(tlsphdr->p_vaddr);
182*7c478bd9Sstevel@tonic-gate 	if (!(FLAGS(lmp) & FLG_RT_FIXED))
183*7c478bd9Sstevel@tonic-gate 		tmi.tm_tlsblock = (void *)((uintptr_t)tmi.tm_tlsblock +
184*7c478bd9Sstevel@tonic-gate 			ADDR(lmp));
185*7c478bd9Sstevel@tonic-gate 	tmi.tm_filesz = tlsphdr->p_filesz;
186*7c478bd9Sstevel@tonic-gate 	tmi.tm_memsz = tlsphdr->p_memsz;
187*7c478bd9Sstevel@tonic-gate 	tmi.tm_flags = 0;
188*7c478bd9Sstevel@tonic-gate 	tmi.tm_stattlsoffset = 0;
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	DBG_CALL(Dbg_tls_modactivity(&tmi, flag));
191*7c478bd9Sstevel@tonic-gate 	fptr(&tmi);
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	/*
194*7c478bd9Sstevel@tonic-gate 	 * Free up the moduleid
195*7c478bd9Sstevel@tonic-gate 	 */
196*7c478bd9Sstevel@tonic-gate 	if (flag & TM_FLG_MODREM)
197*7c478bd9Sstevel@tonic-gate 		tls_freemodid(TLSMODID(lmp));
198*7c478bd9Sstevel@tonic-gate }
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate void
202*7c478bd9Sstevel@tonic-gate tls_assign_soffset(Rt_map * lmp)
203*7c478bd9Sstevel@tonic-gate {
204*7c478bd9Sstevel@tonic-gate 	if (PTTLS(lmp) == 0)
205*7c478bd9Sstevel@tonic-gate 		return;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	/*
208*7c478bd9Sstevel@tonic-gate 	 * Only objects on the primary link-map list are associated
209*7c478bd9Sstevel@tonic-gate 	 * with the STATIC tls block.
210*7c478bd9Sstevel@tonic-gate 	 */
211*7c478bd9Sstevel@tonic-gate 	if (LIST(lmp)->lm_flags & LML_FLG_BASELM) {
212*7c478bd9Sstevel@tonic-gate 		tls_static_size += S_ROUND(PTTLS(lmp)->p_memsz, M_TLSSTATALIGN);
213*7c478bd9Sstevel@tonic-gate 		TLSSTATOFF(lmp) = tls_static_size;
214*7c478bd9Sstevel@tonic-gate 	}
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	/*
217*7c478bd9Sstevel@tonic-gate 	 * Everyone get's a dynamic TLS modid
218*7c478bd9Sstevel@tonic-gate 	 */
219*7c478bd9Sstevel@tonic-gate 	TLSMODID(lmp) = tls_getmodid();
220*7c478bd9Sstevel@tonic-gate }
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate int
223*7c478bd9Sstevel@tonic-gate tls_report_modules()
224*7c478bd9Sstevel@tonic-gate {
225*7c478bd9Sstevel@tonic-gate 	Rt_map *	lmp;
226*7c478bd9Sstevel@tonic-gate 	uint_t		tlsmodcnt;
227*7c478bd9Sstevel@tonic-gate 	uint_t		tlsmodndx;
228*7c478bd9Sstevel@tonic-gate 	TLS_modinfo **	tlsmodlist;
229*7c478bd9Sstevel@tonic-gate 	TLS_modinfo *	tlsbuflist;
230*7c478bd9Sstevel@tonic-gate 	Phdr *		tlsphdr;
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate 	tlsinitialized++;
233*7c478bd9Sstevel@tonic-gate 	/*
234*7c478bd9Sstevel@tonic-gate 	 * Scan through all objects to determine how many have TLS
235*7c478bd9Sstevel@tonic-gate 	 * storage.
236*7c478bd9Sstevel@tonic-gate 	 */
237*7c478bd9Sstevel@tonic-gate 	tlsmodcnt = 0;
238*7c478bd9Sstevel@tonic-gate 	for (lmp = lml_main.lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) {
239*7c478bd9Sstevel@tonic-gate 		if ((FCT(lmp) != &elf_fct) ||
240*7c478bd9Sstevel@tonic-gate 		    (PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0))
241*7c478bd9Sstevel@tonic-gate 			continue;
242*7c478bd9Sstevel@tonic-gate 		tlsmodcnt++;
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 		if (fptr_tls_statmods)
245*7c478bd9Sstevel@tonic-gate 			continue;
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 		/*
248*7c478bd9Sstevel@tonic-gate 		 * If a module has TLS - but the TLS interfaces
249*7c478bd9Sstevel@tonic-gate 		 * are not present (no libthread?). Then this is
250*7c478bd9Sstevel@tonic-gate 		 * a fatal condition.
251*7c478bd9Sstevel@tonic-gate 		 */
252*7c478bd9Sstevel@tonic-gate 		eprintf(ERR_FATAL, MSG_INTL(MSG_ERR_TLS_NOTLS),
253*7c478bd9Sstevel@tonic-gate 		    NAME(lmp));
254*7c478bd9Sstevel@tonic-gate 		return (0);
255*7c478bd9Sstevel@tonic-gate 	}
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	/*
258*7c478bd9Sstevel@tonic-gate 	 * If we don't have any TLS modules - report that and return.
259*7c478bd9Sstevel@tonic-gate 	 */
260*7c478bd9Sstevel@tonic-gate 	if (tlsmodcnt == 0) {
261*7c478bd9Sstevel@tonic-gate 		if (fptr_tls_statmods != 0)
262*7c478bd9Sstevel@tonic-gate 			fptr_tls_statmods(0, 0);
263*7c478bd9Sstevel@tonic-gate 		return (1);
264*7c478bd9Sstevel@tonic-gate 	}
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	/*
267*7c478bd9Sstevel@tonic-gate 	 * Allocate a buffer to report the TLS modules, the buffer consists of:
268*7c478bd9Sstevel@tonic-gate 	 *
269*7c478bd9Sstevel@tonic-gate 	 *	TLS_modinfo *	ptrs[tlsmodcnt + 1]
270*7c478bd9Sstevel@tonic-gate 	 *	TLS_modinfo	bufs[tlsmodcnt]
271*7c478bd9Sstevel@tonic-gate 	 *
272*7c478bd9Sstevel@tonic-gate 	 * The ptrs are initialized to the bufs - except the last
273*7c478bd9Sstevel@tonic-gate 	 * one which null terminates the array.
274*7c478bd9Sstevel@tonic-gate 	 */
275*7c478bd9Sstevel@tonic-gate 	if ((tlsmodlist = calloc((sizeof (TLS_modinfo *) * tlsmodcnt + 1) +
276*7c478bd9Sstevel@tonic-gate 	    (sizeof (TLS_modinfo) * tlsmodcnt), 1)) == 0)
277*7c478bd9Sstevel@tonic-gate 		return (0);
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	tlsbuflist = (TLS_modinfo *)((uintptr_t)tlsmodlist +
280*7c478bd9Sstevel@tonic-gate 		((tlsmodcnt + 1) * sizeof (TLS_modinfo *)));
281*7c478bd9Sstevel@tonic-gate 	for (tlsmodndx = 0; tlsmodndx < tlsmodcnt; tlsmodndx++)
282*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx] = &tlsbuflist[tlsmodndx];
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	/*
285*7c478bd9Sstevel@tonic-gate 	 * Account for the initial dtv ptr in the TLSSIZE calculation.
286*7c478bd9Sstevel@tonic-gate 	 */
287*7c478bd9Sstevel@tonic-gate 	tlsmodndx = 0;
288*7c478bd9Sstevel@tonic-gate 	for (lmp = lml_main.lm_head; lmp; lmp = (Rt_map *)NEXT(lmp)) {
289*7c478bd9Sstevel@tonic-gate 		if ((FCT(lmp) != &elf_fct) ||
290*7c478bd9Sstevel@tonic-gate 		    (PTTLS(lmp) == 0) || (PTTLS(lmp)->p_memsz == 0))
291*7c478bd9Sstevel@tonic-gate 			continue;
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 		tlsphdr = PTTLS(lmp);
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx]->tm_modname = PATHNAME(lmp);
296*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx]->tm_modid = TLSMODID(lmp);
297*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx]->tm_tlsblock =
298*7c478bd9Sstevel@tonic-gate 			(void *)(tlsphdr->p_vaddr);
299*7c478bd9Sstevel@tonic-gate 		if (!(FLAGS(lmp) & FLG_RT_FIXED))
300*7c478bd9Sstevel@tonic-gate 			tlsmodlist[tlsmodndx]->tm_tlsblock =
301*7c478bd9Sstevel@tonic-gate 				(void *)((uintptr_t)tlsmodlist[
302*7c478bd9Sstevel@tonic-gate 				tlsmodndx]->tm_tlsblock + ADDR(lmp));
303*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx]->tm_filesz = tlsphdr->p_filesz;
304*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx]->tm_memsz = tlsphdr->p_memsz;
305*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx]->tm_flags = TM_FLG_STATICTLS;
306*7c478bd9Sstevel@tonic-gate 		tlsmodlist[tlsmodndx]->tm_stattlsoffset =
307*7c478bd9Sstevel@tonic-gate 			TLSSTATOFF(lmp);
308*7c478bd9Sstevel@tonic-gate 		tlsmodndx++;
309*7c478bd9Sstevel@tonic-gate 	}
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	DBG_CALL(Dbg_tls_static_block((void *)tlsmodlist, tls_static_size));
312*7c478bd9Sstevel@tonic-gate 	fptr_tls_statmods(tlsmodlist, tls_static_size);
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 	/*
315*7c478bd9Sstevel@tonic-gate 	 * We're done with the list - clean it up.
316*7c478bd9Sstevel@tonic-gate 	 */
317*7c478bd9Sstevel@tonic-gate 	free(tlsmodlist);
318*7c478bd9Sstevel@tonic-gate 	return (1);
319*7c478bd9Sstevel@tonic-gate }
320