xref: /titanic_52/usr/src/cmd/sgs/libld/common/sections.c (revision d9c5840bd764434fd93f85a52eb4cbc24bff03da)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21fb1354edSrie 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
257c478bd9Sstevel@tonic-gate  *
26bf994817SAli Bahrami  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Module sections. Initialize special sections
317c478bd9Sstevel@tonic-gate  */
32ba2be530Sab196087 
33ba2be530Sab196087 #define	ELF_TARGET_AMD64
34ba2be530Sab196087 
357c478bd9Sstevel@tonic-gate #include	<string.h>
367c478bd9Sstevel@tonic-gate #include	<strings.h>
377c478bd9Sstevel@tonic-gate #include	<stdio.h>
387c478bd9Sstevel@tonic-gate #include	<link.h>
395aefb655Srie #include	<debug.h>
407c478bd9Sstevel@tonic-gate #include	"msg.h"
417c478bd9Sstevel@tonic-gate #include	"_libld.h"
427c478bd9Sstevel@tonic-gate 
43a194faf8Srie inline static void
4460758829Srie remove_local(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
4560758829Srie {
4660758829Srie 	Sym	*sym = sdp->sd_sym;
4760758829Srie 	uchar_t	type = ELF_ST_TYPE(sym->st_info);
4860758829Srie 	/* LINTED - only used for assert() */
4960758829Srie 	int	err;
5060758829Srie 
5144bac77bSrie 	if ((ofl->ofl_flags & FLG_OF_REDLSYM) == 0) {
5260758829Srie 		ofl->ofl_locscnt--;
53a194faf8Srie 
5460758829Srie 		err = st_delstring(ofl->ofl_strtab, sdp->sd_name);
5560758829Srie 		assert(err != -1);
5660758829Srie 
5760758829Srie 		if (allow_ldynsym && ldynsym_symtype[type]) {
5860758829Srie 			ofl->ofl_dynlocscnt--;
59a194faf8Srie 
6060758829Srie 			err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
6160758829Srie 			assert(err != -1);
6260758829Srie 			/* Remove from sort section? */
6360758829Srie 			DYNSORT_COUNT(sdp, sym, type, --);
6460758829Srie 		}
6560758829Srie 	}
6660758829Srie 	sdp->sd_flags |= FLG_SY_ISDISC;
6760758829Srie }
6860758829Srie 
69a194faf8Srie inline static void
7060758829Srie remove_scoped(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
7160758829Srie {
7260758829Srie 	Sym	*sym = sdp->sd_sym;
7360758829Srie 	uchar_t	type = ELF_ST_TYPE(sym->st_info);
7460758829Srie 	/* LINTED - only used for assert() */
7560758829Srie 	int	err;
7660758829Srie 
7760758829Srie 	ofl->ofl_scopecnt--;
7860758829Srie 	ofl->ofl_elimcnt++;
7960758829Srie 
8060758829Srie 	err = st_delstring(ofl->ofl_strtab, sdp->sd_name);
8160758829Srie 	assert(err != -1);
8260758829Srie 
8360758829Srie 	if (allow_ldynsym && ldynsym_symtype[type]) {
8460758829Srie 		ofl->ofl_dynscopecnt--;
85a194faf8Srie 
8660758829Srie 		err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
8760758829Srie 		assert(err != -1);
8860758829Srie 		/* Remove from sort section? */
8960758829Srie 		DYNSORT_COUNT(sdp, sym, type, --);
9060758829Srie 	}
91635216b6SRod Evans 	sdp->sd_flags |= FLG_SY_ELIM;
9260758829Srie }
9360758829Srie 
94a194faf8Srie inline static void
95a194faf8Srie ignore_sym(Ofl_desc *ofl, Ifl_desc *ifl, Sym_desc *sdp, int allow_ldynsym)
96a194faf8Srie {
97a194faf8Srie 	Os_desc	*osp;
98a194faf8Srie 	Is_desc	*isp = sdp->sd_isc;
99a194faf8Srie 	uchar_t	bind = ELF_ST_BIND(sdp->sd_sym->st_info);
100a194faf8Srie 
101a194faf8Srie 	if (bind == STB_LOCAL) {
102a194faf8Srie 		uchar_t	type = ELF_ST_TYPE(sdp->sd_sym->st_info);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 		/*
105a194faf8Srie 		 * Skip section symbols, these were never collected in the
106a194faf8Srie 		 * first place.
107a194faf8Srie 		 */
108a194faf8Srie 		if (type == STT_SECTION)
109a194faf8Srie 			return;
110a194faf8Srie 
111a194faf8Srie 		/*
112a194faf8Srie 		 * Determine if the whole file is being removed.  Remove any
113a194faf8Srie 		 * file symbol, and any symbol that is not associated with a
114a194faf8Srie 		 * section, provided the symbol has not been identified as
115a194faf8Srie 		 * (update) required.
116a194faf8Srie 		 */
117a194faf8Srie 		if (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) &&
118a194faf8Srie 		    ((type == STT_FILE) || ((isp == NULL) &&
119a194faf8Srie 		    ((sdp->sd_flags & FLG_SY_UPREQD) == 0)))) {
120a194faf8Srie 			DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
121a194faf8Srie 			if (ifl->ifl_flags & FLG_IF_IGNORE)
122a194faf8Srie 				remove_local(ofl, sdp, allow_ldynsym);
123a194faf8Srie 			return;
124a194faf8Srie 		}
125a194faf8Srie 
126a194faf8Srie 	} else {
127a194faf8Srie 		/*
128a194faf8Srie 		 * Global symbols can only be eliminated when the interfaces of
129a194faf8Srie 		 * an object have been defined via versioning/scoping.
130a194faf8Srie 		 */
13108278a5eSRod Evans 		if (!SYM_IS_HIDDEN(sdp))
132a194faf8Srie 			return;
133a194faf8Srie 
134a194faf8Srie 		/*
135a194faf8Srie 		 * Remove any unreferenced symbols that are not associated with
136a194faf8Srie 		 * a section.
137a194faf8Srie 		 */
138a194faf8Srie 		if ((isp == NULL) && ((sdp->sd_flags & FLG_SY_UPREQD) == 0)) {
139a194faf8Srie 			DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
140a194faf8Srie 			if (ifl->ifl_flags & FLG_IF_IGNORE)
141a194faf8Srie 				remove_scoped(ofl, sdp, allow_ldynsym);
142a194faf8Srie 			return;
143a194faf8Srie 		}
144a194faf8Srie 	}
145a194faf8Srie 
146a194faf8Srie 	/*
147a194faf8Srie 	 * Do not discard any symbols that are associated with non-allocable
148a194faf8Srie 	 * segments.
149a194faf8Srie 	 */
150a194faf8Srie 	if (isp && ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
151a194faf8Srie 	    ((osp = isp->is_osdesc) != 0) &&
152a194faf8Srie 	    (osp->os_sgdesc->sg_phdr.p_type == PT_LOAD)) {
153a194faf8Srie 		DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
154a194faf8Srie 		if (ifl->ifl_flags & FLG_IF_IGNORE) {
155a194faf8Srie 			if (bind == STB_LOCAL)
156a194faf8Srie 				remove_local(ofl, sdp, allow_ldynsym);
157a194faf8Srie 			else
158a194faf8Srie 				remove_scoped(ofl, sdp, allow_ldynsym);
159a194faf8Srie 		}
160a194faf8Srie 	}
161a194faf8Srie }
162a194faf8Srie 
163*d9c5840bSRichard Lowe static Boolean
164*d9c5840bSRichard Lowe isdesc_discarded(Is_desc *isp)
165*d9c5840bSRichard Lowe {
166*d9c5840bSRichard Lowe 	Ifl_desc	*ifl = isp->is_file;
167*d9c5840bSRichard Lowe 	Os_desc		*osp = isp->is_osdesc;
168*d9c5840bSRichard Lowe 	Word		ptype = osp->os_sgdesc->sg_phdr.p_type;
169*d9c5840bSRichard Lowe 
170*d9c5840bSRichard Lowe 	if (isp->is_flags & FLG_IS_DISCARD)
171*d9c5840bSRichard Lowe 		return (TRUE);
172*d9c5840bSRichard Lowe 
173*d9c5840bSRichard Lowe 	/*
174*d9c5840bSRichard Lowe 	 * If the file is discarded, it will take
175*d9c5840bSRichard Lowe 	 * the section with it.
176*d9c5840bSRichard Lowe 	 */
177*d9c5840bSRichard Lowe 	if (ifl &&
178*d9c5840bSRichard Lowe 	    (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) ||
179*d9c5840bSRichard Lowe 	    ((ptype == PT_LOAD) &&
180*d9c5840bSRichard Lowe 	    ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
181*d9c5840bSRichard Lowe 	    (isp->is_shdr->sh_size > 0))) &&
182*d9c5840bSRichard Lowe 	    (ifl->ifl_flags & FLG_IF_IGNORE))
183*d9c5840bSRichard Lowe 		return (TRUE);
184*d9c5840bSRichard Lowe 
185*d9c5840bSRichard Lowe 	return (FALSE);
186*d9c5840bSRichard Lowe }
187*d9c5840bSRichard Lowe 
188a194faf8Srie /*
189e64d0ff9SAli Bahrami  * There are situations where we may count output sections (ofl_shdrcnt)
190e64d0ff9SAli Bahrami  * that are subsequently eliminated from the output object. Whether or
191e64d0ff9SAli Bahrami  * not this happens cannot be known until all input has been seen and
192e64d0ff9SAli Bahrami  * section elimination code has run. However, the situations where this
193e64d0ff9SAli Bahrami  * outcome is possible are known, and are flagged by setting FLG_OF_ADJOSCNT.
194e64d0ff9SAli Bahrami  *
195e64d0ff9SAli Bahrami  * If FLG_OF_ADJOSCNT is set, this routine makes a pass over the output
196e64d0ff9SAli Bahrami  * sections. If an unused output section is encountered, we decrement
197e64d0ff9SAli Bahrami  * ofl->ofl_shdrcnt and remove the section name from the .shstrtab string
198e64d0ff9SAli Bahrami  * table (ofl->ofl_shdrsttab).
199e64d0ff9SAli Bahrami  *
200e64d0ff9SAli Bahrami  * This code must be kept in sync with the similar code
201e64d0ff9SAli Bahrami  * found in outfile.c:ld_create_outfile().
202e64d0ff9SAli Bahrami  */
203e64d0ff9SAli Bahrami static void
204e64d0ff9SAli Bahrami adjust_os_count(Ofl_desc *ofl)
205e64d0ff9SAli Bahrami {
206e64d0ff9SAli Bahrami 	Sg_desc		*sgp;
207e64d0ff9SAli Bahrami 	Is_desc		*isp;
208e64d0ff9SAli Bahrami 	Os_desc		*osp;
209e64d0ff9SAli Bahrami 	Aliste		idx1;
210e64d0ff9SAli Bahrami 
211e64d0ff9SAli Bahrami 	if ((ofl->ofl_flags & FLG_OF_ADJOSCNT) == 0)
212e64d0ff9SAli Bahrami 		return;
213e64d0ff9SAli Bahrami 
214e64d0ff9SAli Bahrami 	/*
215e64d0ff9SAli Bahrami 	 * For each output section, look at the input sections to find at least
216e64d0ff9SAli Bahrami 	 * one input section that has not been eliminated. If none are found,
217e64d0ff9SAli Bahrami 	 * the -z ignore processing above has eliminated that output section.
218e64d0ff9SAli Bahrami 	 */
219e64d0ff9SAli Bahrami 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
220e64d0ff9SAli Bahrami 		Aliste	idx2;
221e64d0ff9SAli Bahrami 
222e64d0ff9SAli Bahrami 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
223e64d0ff9SAli Bahrami 			Aliste	idx3;
224e64d0ff9SAli Bahrami 			int	keep = 0, os_isdescs_idx;
225e64d0ff9SAli Bahrami 
226e64d0ff9SAli Bahrami 			OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx3, isp) {
227e64d0ff9SAli Bahrami 				/*
228e64d0ff9SAli Bahrami 				 * We have found a kept input section,
229e64d0ff9SAli Bahrami 				 * so the output section will be created.
230e64d0ff9SAli Bahrami 				 */
231*d9c5840bSRichard Lowe 				if (!isdesc_discarded(isp)) {
232e64d0ff9SAli Bahrami 					keep = 1;
233e64d0ff9SAli Bahrami 					break;
234e64d0ff9SAli Bahrami 				}
235*d9c5840bSRichard Lowe 			}
236e64d0ff9SAli Bahrami 			/*
237e64d0ff9SAli Bahrami 			 * If no section of this name was kept, decrement
238e64d0ff9SAli Bahrami 			 * the count and remove the name from .shstrtab.
239e64d0ff9SAli Bahrami 			 */
240e64d0ff9SAli Bahrami 			if (keep == 0) {
241e64d0ff9SAli Bahrami 				/* LINTED - only used for assert() */
242e64d0ff9SAli Bahrami 				int err;
243e64d0ff9SAli Bahrami 
244e64d0ff9SAli Bahrami 				ofl->ofl_shdrcnt--;
245e64d0ff9SAli Bahrami 				err = st_delstring(ofl->ofl_shdrsttab,
246e64d0ff9SAli Bahrami 				    osp->os_name);
247e64d0ff9SAli Bahrami 				assert(err != -1);
248e64d0ff9SAli Bahrami 			}
249e64d0ff9SAli Bahrami 		}
250e64d0ff9SAli Bahrami 	}
251e64d0ff9SAli Bahrami }
252e64d0ff9SAli Bahrami 
253e64d0ff9SAli Bahrami /*
254a194faf8Srie  * If -zignore has been in effect, scan all input files to determine if the
255a194faf8Srie  * file, or sections from the file, have been referenced.  If not, the file or
2561da7e599SAli Bahrami  * some of the files sections can be discarded. If sections are to be
2571da7e599SAli Bahrami  * discarded, rescan the output relocations and the symbol table and remove
2581da7e599SAli Bahrami  * the relocations and symbol entries that are no longer required.
2597c478bd9Sstevel@tonic-gate  *
2607c478bd9Sstevel@tonic-gate  * Note:  It's possible that a section which is being discarded has contributed
2617c478bd9Sstevel@tonic-gate  *	  to the GOT table or the PLT table.  However, we can't at this point
2627c478bd9Sstevel@tonic-gate  *	  eliminate the corresponding entries.  This is because there could well
2637c478bd9Sstevel@tonic-gate  *	  be other sections referencing those same entries, but we don't have
2647c478bd9Sstevel@tonic-gate  *	  the infrastructure to determine this.  So, keep the PLT and GOT
2657c478bd9Sstevel@tonic-gate  *	  entries in the table in case someone wants them.
2667c478bd9Sstevel@tonic-gate  * Note:  The section to be affected needs to be allocatable.
2677c478bd9Sstevel@tonic-gate  *	  So even if -zignore is in effect, if the section is not allocatable,
2687c478bd9Sstevel@tonic-gate  *	  we do not eliminate it.
2697c478bd9Sstevel@tonic-gate  */
2705aefb655Srie static uintptr_t
2717c478bd9Sstevel@tonic-gate ignore_section_processing(Ofl_desc *ofl)
2727c478bd9Sstevel@tonic-gate {
2731da7e599SAli Bahrami 	Sg_desc		*sgp;
2741da7e599SAli Bahrami 	Is_desc		*isp;
2751da7e599SAli Bahrami 	Os_desc		*osp;
2767c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
277bf994817SAli Bahrami 	Rel_cachebuf	*rcbp;
278bf994817SAli Bahrami 	Rel_desc	*rsp;
279a194faf8Srie 	int		allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
28057ef7aa9SRod Evans 	Aliste		idx1;
2817c478bd9Sstevel@tonic-gate 
28257ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_objs, idx1, ifl)) {
2837c478bd9Sstevel@tonic-gate 		uint_t	num, discard;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 		/*
2867c478bd9Sstevel@tonic-gate 		 * Diagnose (-D unused) a completely unreferenced file.
2877c478bd9Sstevel@tonic-gate 		 */
2887c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_flags & FLG_IF_FILEREF) == 0)
2895aefb655Srie 			DBG_CALL(Dbg_unused_file(ofl->ofl_lml,
2905aefb655Srie 			    ifl->ifl_name, 0, 0));
291fb1354edSrie 		if (((ofl->ofl_flags1 & FLG_OF1_IGNPRC) == 0) ||
292fb1354edSrie 		    ((ifl->ifl_flags & FLG_IF_IGNORE) == 0))
2937c478bd9Sstevel@tonic-gate 			continue;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		/*
296fb1354edSrie 		 * Before scanning the whole symbol table to determine if
297fb1354edSrie 		 * symbols should be discard - quickly (relatively) scan the
298fb1354edSrie 		 * sections to determine if any are to be discarded.
2997c478bd9Sstevel@tonic-gate 		 */
300fb1354edSrie 		discard = 0;
301fb1354edSrie 		if (ifl->ifl_flags & FLG_IF_FILEREF) {
302fb1354edSrie 			for (num = 1; num < ifl->ifl_shnum; num++) {
3031da7e599SAli Bahrami 				if (((isp = ifl->ifl_isdesc[num]) != NULL) &&
3047c478bd9Sstevel@tonic-gate 				    ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
3051da7e599SAli Bahrami 				    ((osp = isp->is_osdesc) != NULL) &&
3061da7e599SAli Bahrami 				    ((sgp = osp->os_sgdesc) != NULL) &&
307fb1354edSrie 				    (sgp->sg_phdr.p_type == PT_LOAD)) {
3087c478bd9Sstevel@tonic-gate 					discard++;
3097c478bd9Sstevel@tonic-gate 					break;
3107c478bd9Sstevel@tonic-gate 				}
3117c478bd9Sstevel@tonic-gate 			}
312fb1354edSrie 		}
313fb1354edSrie 
3147c478bd9Sstevel@tonic-gate 		/*
3157c478bd9Sstevel@tonic-gate 		 * No sections are to be 'ignored'
3167c478bd9Sstevel@tonic-gate 		 */
317fb1354edSrie 		if ((discard == 0) && (ifl->ifl_flags & FLG_IF_FILEREF))
3187c478bd9Sstevel@tonic-gate 			continue;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 		/*
321fb1354edSrie 		 * We know that we have discarded sections.  Scan the symbol
322fb1354edSrie 		 * table for this file to determine if symbols need to be
323fb1354edSrie 		 * discarded that are associated with the 'ignored' sections.
3247c478bd9Sstevel@tonic-gate 		 */
3257c478bd9Sstevel@tonic-gate 		for (num = 1; num < ifl->ifl_symscnt; num++) {
3267c478bd9Sstevel@tonic-gate 			Sym_desc	*sdp;
3277c478bd9Sstevel@tonic-gate 
328a194faf8Srie 			/*
329a194faf8Srie 			 * If the symbol definition has been resolved to another
330a194faf8Srie 			 * file, or the symbol has already been discarded or
331a194faf8Srie 			 * eliminated, skip it.
332a194faf8Srie 			 */
3337c478bd9Sstevel@tonic-gate 			sdp = ifl->ifl_oldndx[num];
334a194faf8Srie 			if ((sdp->sd_file != ifl) ||
335635216b6SRod Evans 			    (sdp->sd_flags &
336635216b6SRod Evans 			    (FLG_SY_ISDISC | FLG_SY_INVALID | FLG_SY_ELIM)))
3377c478bd9Sstevel@tonic-gate 				continue;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 			/*
340a194faf8Srie 			 * Complete the investigation of the symbol.
3417c478bd9Sstevel@tonic-gate 			 */
342a194faf8Srie 			ignore_sym(ofl, ifl, sdp, allow_ldynsym);
343a194faf8Srie 		}
3447c478bd9Sstevel@tonic-gate 	}
3457c478bd9Sstevel@tonic-gate 
346fb1354edSrie 	/*
347a194faf8Srie 	 * If we were only here to solicit debugging diagnostics, we're done.
348fb1354edSrie 	 */
349fb1354edSrie 	if ((ofl->ofl_flags1 & FLG_OF1_IGNPRC) == 0)
350fb1354edSrie 		return (1);
351fb1354edSrie 
3527c478bd9Sstevel@tonic-gate 	/*
353fb1354edSrie 	 * Scan all output relocations searching for those against discarded or
354fb1354edSrie 	 * ignored sections.  If one is found, decrement the total outrel count.
3557c478bd9Sstevel@tonic-gate 	 */
356bf994817SAli Bahrami 	REL_CACHE_TRAVERSE(&ofl->ofl_outrels, idx1, rcbp, rsp) {
357a194faf8Srie 		Is_desc		*isc = rsp->rel_isdesc;
3587c478bd9Sstevel@tonic-gate 		uint_t		flags, entsize;
3597c478bd9Sstevel@tonic-gate 		Shdr		*shdr;
3607c478bd9Sstevel@tonic-gate 
361bf994817SAli Bahrami 		if ((isc == NULL) || ((isc->is_flags & (FLG_IS_SECTREF))) ||
36257ef7aa9SRod Evans 		    ((ifl = isc->is_file) == NULL) ||
3637c478bd9Sstevel@tonic-gate 		    ((ifl->ifl_flags & FLG_IF_IGNORE) == 0) ||
36457ef7aa9SRod Evans 		    ((shdr = isc->is_shdr) == NULL) ||
3657c478bd9Sstevel@tonic-gate 		    ((shdr->sh_flags & SHF_ALLOC) == 0))
3667c478bd9Sstevel@tonic-gate 			continue;
3677c478bd9Sstevel@tonic-gate 
368a194faf8Srie 		flags = rsp->rel_flags;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		if (flags & (FLG_REL_GOT | FLG_REL_BSS |
3717c478bd9Sstevel@tonic-gate 		    FLG_REL_NOINFO | FLG_REL_PLT))
3727c478bd9Sstevel@tonic-gate 			continue;
3737c478bd9Sstevel@tonic-gate 
374bf994817SAli Bahrami 		osp = RELAUX_GET_OSDESC(rsp);
3757c478bd9Sstevel@tonic-gate 
376a194faf8Srie 		if (rsp->rel_flags & FLG_REL_RELA)
3777c478bd9Sstevel@tonic-gate 			entsize = sizeof (Rela);
3787c478bd9Sstevel@tonic-gate 		else
3797c478bd9Sstevel@tonic-gate 			entsize = sizeof (Rel);
3807c478bd9Sstevel@tonic-gate 
381a194faf8Srie 		assert(osp->os_szoutrels > 0);
382a194faf8Srie 		osp->os_szoutrels -= entsize;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		if (!(flags & FLG_REL_PLT))
3857c478bd9Sstevel@tonic-gate 			ofl->ofl_reloccntsub++;
3867c478bd9Sstevel@tonic-gate 
387ba2be530Sab196087 		if (rsp->rel_rtype == ld_targ.t_m.m_r_relative)
3887c478bd9Sstevel@tonic-gate 			ofl->ofl_relocrelcnt--;
3897c478bd9Sstevel@tonic-gate 	}
3901da7e599SAli Bahrami 
3911da7e599SAli Bahrami 	/*
392e64d0ff9SAli Bahrami 	 * As a result of our work here, the number of output sections may
393e64d0ff9SAli Bahrami 	 * have decreased. Trigger a call to adjust_os_count().
3941da7e599SAli Bahrami 	 */
395e64d0ff9SAli Bahrami 	ofl->ofl_flags |= FLG_OF_ADJOSCNT;
3961da7e599SAli Bahrami 
3977c478bd9Sstevel@tonic-gate 	return (1);
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate /*
4019039eeafSab196087  * Allocate Elf_Data, Shdr, and Is_desc structures for a new
4029039eeafSab196087  * section.
4039039eeafSab196087  *
4049039eeafSab196087  * entry:
4059039eeafSab196087  *	ofl - Output file descriptor
4069039eeafSab196087  *	shtype - SHT_ type code for section.
4079039eeafSab196087  *	shname - String giving the name for the new section.
4089039eeafSab196087  *	entcnt - # of items contained in the data part of the new section.
4099039eeafSab196087  *		This value is multiplied against the known element size
4109039eeafSab196087  *		for the section type to determine the size of the data
4119039eeafSab196087  *		area for the section. It is only meaningful in cases where
4129039eeafSab196087  *		the section type has a non-zero element size. In other cases,
4139039eeafSab196087  *		the caller must set the size fields in the *ret_data and
4149039eeafSab196087  *		*ret_shdr structs manually.
4159039eeafSab196087  *	ret_isec, ret_shdr, ret_data - Address of pointers to
4169039eeafSab196087  *		receive address of newly allocated structs.
4179039eeafSab196087  *
4189039eeafSab196087  * exit:
4199039eeafSab196087  *	On error, returns S_ERROR. On success, returns (1), and the
4209039eeafSab196087  *	ret_ pointers have been updated to point at the new structures,
421cce0e03bSab196087  *	which have been filled in. To finish the task, the caller must
4229039eeafSab196087  *	update any fields within the supplied descriptors that differ
4239039eeafSab196087  *	from its needs, and then call ld_place_section().
4249039eeafSab196087  */
4259039eeafSab196087 static uintptr_t
4269039eeafSab196087 new_section(Ofl_desc *ofl, Word shtype, const char *shname, Xword entcnt,
4279039eeafSab196087 	Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
4289039eeafSab196087 {
4299039eeafSab196087 	typedef struct sec_info {
4309039eeafSab196087 		Word d_type;
4319039eeafSab196087 		Word align;	/* Used in both data and section header */
4329039eeafSab196087 		Word sh_flags;
4339039eeafSab196087 		Word sh_entsize;
4349039eeafSab196087 	} SEC_INFO_T;
4359039eeafSab196087 
4369039eeafSab196087 	const SEC_INFO_T	*sec_info;
4379039eeafSab196087 
4389039eeafSab196087 	Shdr		*shdr;
4399039eeafSab196087 	Elf_Data	*data;
4409039eeafSab196087 	Is_desc		*isec;
4419039eeafSab196087 	size_t		size;
4429039eeafSab196087 
4439039eeafSab196087 	/*
4449039eeafSab196087 	 * For each type of section, we have a distinct set of
4459039eeafSab196087 	 * SEC_INFO_T values. This macro defines a static structure
4469039eeafSab196087 	 * containing those values and generates code to set the sec_info
4479039eeafSab196087 	 * pointer to refer to it. The pointer in sec_info remains valid
4489039eeafSab196087 	 * outside of the declaration scope because the info_s struct is static.
449ba2be530Sab196087 	 *
450ba2be530Sab196087 	 * We can't determine the value of M_WORD_ALIGN at compile time, so
451ba2be530Sab196087 	 * a different variant is used for those cases.
4529039eeafSab196087 	 */
4539039eeafSab196087 #define	SET_SEC_INFO(d_type, d_align, sh_flags, sh_entsize) \
4549039eeafSab196087 	{ \
4559039eeafSab196087 		static const SEC_INFO_T info_s = { d_type, d_align, sh_flags, \
4569039eeafSab196087 		    sh_entsize}; \
4579039eeafSab196087 		sec_info = &info_s; \
4589039eeafSab196087 	}
459ba2be530Sab196087 #define	SET_SEC_INFO_WORD_ALIGN(d_type, sh_flags, sh_entsize) \
460ba2be530Sab196087 	{ \
461ba2be530Sab196087 		static SEC_INFO_T info_s = { d_type, 0, sh_flags, \
462ba2be530Sab196087 		    sh_entsize}; \
463ba2be530Sab196087 		info_s.align = ld_targ.t_m.m_word_align; \
464ba2be530Sab196087 		sec_info = &info_s; \
465ba2be530Sab196087 	}
4669039eeafSab196087 
4679039eeafSab196087 	switch (shtype) {
4689039eeafSab196087 	case SHT_PROGBITS:
4699039eeafSab196087 		/*
4709039eeafSab196087 		 * SHT_PROGBITS sections contain are used for many
4719039eeafSab196087 		 * different sections. Alignments and flags differ.
4729039eeafSab196087 		 * Some have a standard entsize, and others don't.
4739039eeafSab196087 		 * We set some defaults here, but there is no expectation
4749039eeafSab196087 		 * that they are correct or complete for any specific
4759039eeafSab196087 		 * purpose. The caller must provide the correct values.
4769039eeafSab196087 		 */
477ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0)
4789039eeafSab196087 		break;
4799039eeafSab196087 
4809039eeafSab196087 	case SHT_SYMTAB:
481ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, 0, sizeof (Sym))
4829039eeafSab196087 		break;
4839039eeafSab196087 
4849039eeafSab196087 	case SHT_DYNSYM:
4854f680cc6SAli Bahrami 		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, SHF_ALLOC, sizeof (Sym))
4864f680cc6SAli Bahrami 		break;
4874f680cc6SAli Bahrami 
4889039eeafSab196087 	case SHT_SUNW_LDYNSYM:
4894f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
490ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, SHF_ALLOC, sizeof (Sym))
4919039eeafSab196087 		break;
4929039eeafSab196087 
4939039eeafSab196087 	case SHT_STRTAB:
4949039eeafSab196087 		/*
4959039eeafSab196087 		 * A string table may or may not be allocable, depending
4969039eeafSab196087 		 * on context, so we leave that flag unset and leave it to
4979039eeafSab196087 		 * the caller to add it if necessary.
4989039eeafSab196087 		 *
4999039eeafSab196087 		 * String tables do not have a standard entsize, so
5009039eeafSab196087 		 * we set it to 0.
5019039eeafSab196087 		 */
5029039eeafSab196087 		SET_SEC_INFO(ELF_T_BYTE, 1, SHF_STRINGS, 0)
5039039eeafSab196087 		break;
5049039eeafSab196087 
5059039eeafSab196087 	case SHT_RELA:
5069039eeafSab196087 		/*
5079039eeafSab196087 		 * Relocations with an addend (Everything except 32-bit X86).
5089039eeafSab196087 		 * The caller is expected to set all section header flags.
5099039eeafSab196087 		 */
510ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_RELA, 0, sizeof (Rela))
5119039eeafSab196087 		break;
5129039eeafSab196087 
5139039eeafSab196087 	case SHT_REL:
5149039eeafSab196087 		/*
5159039eeafSab196087 		 * Relocations without an addend (32-bit X86 only).
5169039eeafSab196087 		 * The caller is expected to set all section header flags.
5179039eeafSab196087 		 */
518ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_REL, 0, sizeof (Rel))
5199039eeafSab196087 		break;
5209039eeafSab196087 
5219039eeafSab196087 	case SHT_HASH:
5224f680cc6SAli Bahrami 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, sizeof (Word))
5234f680cc6SAli Bahrami 		break;
5244f680cc6SAli Bahrami 
525d579eb63Sab196087 	case SHT_SUNW_symsort:
526d579eb63Sab196087 	case SHT_SUNW_tlssort:
5274f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
528ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, sizeof (Word))
5299039eeafSab196087 		break;
5309039eeafSab196087 
5319039eeafSab196087 	case SHT_DYNAMIC:
5329039eeafSab196087 		/*
53394c044f4SRod Evans 		 * A dynamic section may or may not be allocable, and may or
53494c044f4SRod Evans 		 * may not be writable, depending on context, so we leave the
53594c044f4SRod Evans 		 * flags unset and leave it to the caller to add them if
53694c044f4SRod Evans 		 * necessary.
5379039eeafSab196087 		 */
53894c044f4SRod Evans 		SET_SEC_INFO_WORD_ALIGN(ELF_T_DYN, 0, sizeof (Dyn))
5399039eeafSab196087 		break;
5409039eeafSab196087 
5419039eeafSab196087 	case SHT_NOBITS:
5429039eeafSab196087 		/*
5439039eeafSab196087 		 * SHT_NOBITS is used for BSS-type sections. The size and
5449039eeafSab196087 		 * alignment depend on the specific use and must be adjusted
5459039eeafSab196087 		 * by the caller.
5469039eeafSab196087 		 */
5479039eeafSab196087 		SET_SEC_INFO(ELF_T_BYTE, 0, SHF_ALLOC | SHF_WRITE, 0)
5489039eeafSab196087 		break;
5499039eeafSab196087 
5509039eeafSab196087 	case SHT_INIT_ARRAY:
5519039eeafSab196087 	case SHT_FINI_ARRAY:
5529039eeafSab196087 	case SHT_PREINIT_ARRAY:
5539039eeafSab196087 		SET_SEC_INFO(ELF_T_ADDR, sizeof (Addr), SHF_ALLOC | SHF_WRITE,
5549039eeafSab196087 		    sizeof (Addr))
5559039eeafSab196087 		break;
5569039eeafSab196087 
5579039eeafSab196087 	case SHT_SYMTAB_SHNDX:
5589039eeafSab196087 		/*
5599039eeafSab196087 		 * Note that these sections are created to be associated
5609039eeafSab196087 		 * with both symtab and dynsym symbol tables. However, they
5619039eeafSab196087 		 * are non-allocable in all cases, because the runtime
5629039eeafSab196087 		 * linker has no need for this information. It is purely
5639039eeafSab196087 		 * informational, used by elfdump(1), debuggers, etc.
5649039eeafSab196087 		 */
565ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, 0, sizeof (Word));
5669039eeafSab196087 		break;
5679039eeafSab196087 
5689039eeafSab196087 	case SHT_SUNW_cap:
5694f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
570ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_CAP, SHF_ALLOC, sizeof (Cap));
5719039eeafSab196087 		break;
5729039eeafSab196087 
57308278a5eSRod Evans 	case SHT_SUNW_capchain:
57408278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_OSABI;
57508278a5eSRod Evans 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC,
57608278a5eSRod Evans 		    sizeof (Capchain));
57708278a5eSRod Evans 		break;
57808278a5eSRod Evans 
57908278a5eSRod Evans 	case SHT_SUNW_capinfo:
58008278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_OSABI;
58108278a5eSRod Evans #if	_ELF64
58208278a5eSRod Evans 		SET_SEC_INFO(ELF_T_XWORD, sizeof (Xword), SHF_ALLOC,
58308278a5eSRod Evans 		    sizeof (Capinfo));
58408278a5eSRod Evans #else
58508278a5eSRod Evans 		SET_SEC_INFO(ELF_T_WORD, sizeof (Word), SHF_ALLOC,
58608278a5eSRod Evans 		    sizeof (Capinfo));
58708278a5eSRod Evans #endif
58808278a5eSRod Evans 		break;
58908278a5eSRod Evans 
5909039eeafSab196087 	case SHT_SUNW_move:
5914f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
5929039eeafSab196087 		SET_SEC_INFO(ELF_T_BYTE, sizeof (Lword),
5939039eeafSab196087 		    SHF_ALLOC | SHF_WRITE, sizeof (Move));
5949039eeafSab196087 		break;
5959039eeafSab196087 
5969039eeafSab196087 	case SHT_SUNW_syminfo:
5974f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
5989039eeafSab196087 		/*
5999039eeafSab196087 		 * The sh_info field of the SHT_*_syminfo section points
6009039eeafSab196087 		 * to the header index of the associated .dynamic section,
6019039eeafSab196087 		 * so we also set SHF_INFO_LINK.
6029039eeafSab196087 		 */
603ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE,
6049039eeafSab196087 		    SHF_ALLOC | SHF_INFO_LINK, sizeof (Syminfo));
6059039eeafSab196087 		break;
6069039eeafSab196087 
6079039eeafSab196087 	case SHT_SUNW_verneed:
6089039eeafSab196087 	case SHT_SUNW_verdef:
6094f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
6109039eeafSab196087 		/*
6119039eeafSab196087 		 * The info for verneed and versym happen to be the same.
6129039eeafSab196087 		 * The entries in these sections are not of uniform size,
6139039eeafSab196087 		 * so we set the entsize to 0.
6149039eeafSab196087 		 */
615ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0);
6169039eeafSab196087 		break;
6179039eeafSab196087 
6189039eeafSab196087 	case SHT_SUNW_versym:
6194f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
620ba2be530Sab196087 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC,
6219039eeafSab196087 		    sizeof (Versym));
6229039eeafSab196087 		break;
6239039eeafSab196087 
6249039eeafSab196087 	default:
6259039eeafSab196087 		/* Should not happen: fcn called with unknown section type */
6269039eeafSab196087 		assert(0);
6279039eeafSab196087 		return (S_ERROR);
6289039eeafSab196087 	}
6299039eeafSab196087 #undef	SET_SEC_INFO
630ba2be530Sab196087 #undef	SET_SEC_INFO_WORD_ALIGN
6319039eeafSab196087 
6329039eeafSab196087 	size = entcnt * sec_info->sh_entsize;
6339039eeafSab196087 
6349039eeafSab196087 	/*
6359039eeafSab196087 	 * Allocate and initialize the Elf_Data structure.
6369039eeafSab196087 	 */
63757ef7aa9SRod Evans 	if ((data = libld_calloc(sizeof (Elf_Data), 1)) == NULL)
6389039eeafSab196087 		return (S_ERROR);
6399039eeafSab196087 	data->d_type = sec_info->d_type;
6409039eeafSab196087 	data->d_size = size;
6419039eeafSab196087 	data->d_align = sec_info->align;
6429039eeafSab196087 	data->d_version = ofl->ofl_dehdr->e_version;
6439039eeafSab196087 
6449039eeafSab196087 	/*
6459039eeafSab196087 	 * Allocate and initialize the Shdr structure.
6469039eeafSab196087 	 */
64757ef7aa9SRod Evans 	if ((shdr = libld_calloc(sizeof (Shdr), 1)) == NULL)
6489039eeafSab196087 		return (S_ERROR);
6499039eeafSab196087 	shdr->sh_type = shtype;
6509039eeafSab196087 	shdr->sh_size = size;
6519039eeafSab196087 	shdr->sh_flags = sec_info->sh_flags;
6529039eeafSab196087 	shdr->sh_addralign = sec_info->align;
6539039eeafSab196087 	shdr->sh_entsize = sec_info->sh_entsize;
6549039eeafSab196087 
6559039eeafSab196087 	/*
6569039eeafSab196087 	 * Allocate and initialize the Is_desc structure.
6579039eeafSab196087 	 */
65857ef7aa9SRod Evans 	if ((isec = libld_calloc(1, sizeof (Is_desc))) == NULL)
6599039eeafSab196087 		return (S_ERROR);
6609039eeafSab196087 	isec->is_name = shname;
6619039eeafSab196087 	isec->is_shdr = shdr;
6629039eeafSab196087 	isec->is_indata = data;
6639039eeafSab196087 
6649039eeafSab196087 
6659039eeafSab196087 	*ret_isec = isec;
6669039eeafSab196087 	*ret_shdr = shdr;
6679039eeafSab196087 	*ret_data = data;
6689039eeafSab196087 	return (1);
6699039eeafSab196087 }
6709039eeafSab196087 
6719039eeafSab196087 /*
672cce0e03bSab196087  * Use an existing input section as a template to create a new
673cce0e03bSab196087  * input section with the same values as the original, other than
674cce0e03bSab196087  * the size of the data area which is supplied by the caller.
675cce0e03bSab196087  *
676cce0e03bSab196087  * entry:
677cce0e03bSab196087  *	ofl - Output file descriptor
678cce0e03bSab196087  *	ifl - Input file section to use as a template
679cce0e03bSab196087  *	size - Size of data area for new section
680cce0e03bSab196087  *	ret_isec, ret_shdr, ret_data - Address of pointers to
681cce0e03bSab196087  *		receive address of newly allocated structs.
682cce0e03bSab196087  *
683cce0e03bSab196087  * exit:
684cce0e03bSab196087  *	On error, returns S_ERROR. On success, returns (1), and the
685cce0e03bSab196087  *	ret_ pointers have been updated to point at the new structures,
686cce0e03bSab196087  *	which have been filled in. To finish the task, the caller must
687cce0e03bSab196087  *	update any fields within the supplied descriptors that differ
688cce0e03bSab196087  *	from its needs, and then call ld_place_section().
689cce0e03bSab196087  */
690cce0e03bSab196087 static uintptr_t
691cce0e03bSab196087 new_section_from_template(Ofl_desc *ofl, Is_desc *tmpl_isp, size_t size,
692cce0e03bSab196087 	Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
693cce0e03bSab196087 {
694cce0e03bSab196087 	Shdr		*shdr;
695cce0e03bSab196087 	Elf_Data	*data;
696cce0e03bSab196087 	Is_desc		*isec;
697cce0e03bSab196087 
698cce0e03bSab196087 	/*
699cce0e03bSab196087 	 * Allocate and initialize the Elf_Data structure.
700cce0e03bSab196087 	 */
70157ef7aa9SRod Evans 	if ((data = libld_calloc(sizeof (Elf_Data), 1)) == NULL)
702cce0e03bSab196087 		return (S_ERROR);
703cce0e03bSab196087 	data->d_type = tmpl_isp->is_indata->d_type;
704cce0e03bSab196087 	data->d_size = size;
705cce0e03bSab196087 	data->d_align = tmpl_isp->is_shdr->sh_addralign;
706cce0e03bSab196087 	data->d_version = ofl->ofl_dehdr->e_version;
707cce0e03bSab196087 
708cce0e03bSab196087 	/*
709cce0e03bSab196087 	 * Allocate and initialize the Shdr structure.
710cce0e03bSab196087 	 */
71157ef7aa9SRod Evans 	if ((shdr = libld_malloc(sizeof (Shdr))) == NULL)
712cce0e03bSab196087 		return (S_ERROR);
713cce0e03bSab196087 	*shdr = *tmpl_isp->is_shdr;
714cce0e03bSab196087 	shdr->sh_addr = 0;
715cce0e03bSab196087 	shdr->sh_offset = 0;
716cce0e03bSab196087 	shdr->sh_size = size;
717cce0e03bSab196087 
718cce0e03bSab196087 	/*
719cce0e03bSab196087 	 * Allocate and initialize the Is_desc structure.
720cce0e03bSab196087 	 */
72157ef7aa9SRod Evans 	if ((isec = libld_calloc(1, sizeof (Is_desc))) == NULL)
722cce0e03bSab196087 		return (S_ERROR);
723cce0e03bSab196087 	isec->is_name = tmpl_isp->is_name;
724cce0e03bSab196087 	isec->is_shdr = shdr;
725cce0e03bSab196087 	isec->is_indata = data;
726cce0e03bSab196087 
727cce0e03bSab196087 
728cce0e03bSab196087 	*ret_isec = isec;
729cce0e03bSab196087 	*ret_shdr = shdr;
730cce0e03bSab196087 	*ret_data = data;
731cce0e03bSab196087 	return (1);
732cce0e03bSab196087 }
733cce0e03bSab196087 
734cce0e03bSab196087 /*
7357c478bd9Sstevel@tonic-gate  * Build a .bss section for allocation of tentative definitions.  Any `static'
7367c478bd9Sstevel@tonic-gate  * .bss definitions would have been associated to their own .bss sections and
7377c478bd9Sstevel@tonic-gate  * thus collected from the input files.  `global' .bss definitions are tagged
7387c478bd9Sstevel@tonic-gate  * as COMMON and do not cause any associated .bss section elements to be
7397c478bd9Sstevel@tonic-gate  * generated.  Here we add up all these COMMON symbols and generate the .bss
7407c478bd9Sstevel@tonic-gate  * section required to represent them.
7417c478bd9Sstevel@tonic-gate  */
7427c478bd9Sstevel@tonic-gate uintptr_t
74357ef7aa9SRod Evans ld_make_bss(Ofl_desc *ofl, Xword size, Xword align, uint_t ident)
7447c478bd9Sstevel@tonic-gate {
7457c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
7467c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
7477c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
7487c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
7497c478bd9Sstevel@tonic-gate 	Xword		rsize = (Xword)ofl->ofl_relocbsssz;
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	/*
7529039eeafSab196087 	 * Allocate header structs. We will set the name ourselves below,
7539039eeafSab196087 	 * and there is no entcnt for a BSS. So, the shname and entcnt
7549039eeafSab196087 	 * arguments are 0.
7557c478bd9Sstevel@tonic-gate 	 */
7569039eeafSab196087 	if (new_section(ofl, SHT_NOBITS, NULL, 0,
7579039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
7587c478bd9Sstevel@tonic-gate 		return (S_ERROR);
7599039eeafSab196087 
7607c478bd9Sstevel@tonic-gate 	data->d_size = (size_t)size;
7617c478bd9Sstevel@tonic-gate 	data->d_align = (size_t)align;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	shdr->sh_size = size;
7647c478bd9Sstevel@tonic-gate 	shdr->sh_addralign = align;
7657c478bd9Sstevel@tonic-gate 
76657ef7aa9SRod Evans 	if (ident == ld_targ.t_id.id_tlsbss) {
7677c478bd9Sstevel@tonic-gate 		isec->is_name = MSG_ORIG(MSG_SCN_TBSS);
7687c478bd9Sstevel@tonic-gate 		ofl->ofl_istlsbss = isec;
76954d82594Sseizo 		shdr->sh_flags |= SHF_TLS;
7700bc07c75Srie 
77157ef7aa9SRod Evans 	} else if (ident == ld_targ.t_id.id_bss) {
7727c478bd9Sstevel@tonic-gate 		isec->is_name = MSG_ORIG(MSG_SCN_BSS);
7737c478bd9Sstevel@tonic-gate 		ofl->ofl_isbss = isec;
77454d82594Sseizo 
775ba2be530Sab196087 #if	defined(_ELF64)
77657ef7aa9SRod Evans 	} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
77757ef7aa9SRod Evans 	    (ident == ld_targ.t_id.id_lbss)) {
77854d82594Sseizo 		isec->is_name = MSG_ORIG(MSG_SCN_LBSS);
77954d82594Sseizo 		ofl->ofl_islbss = isec;
78054d82594Sseizo 		shdr->sh_flags |= SHF_AMD64_LARGE;
78154d82594Sseizo #endif
7827c478bd9Sstevel@tonic-gate 	}
78354d82594Sseizo 
7847c478bd9Sstevel@tonic-gate 	/*
78557ef7aa9SRod Evans 	 * Retain this .*bss input section as this will be where global symbol
78657ef7aa9SRod Evans 	 * references are added.
7877c478bd9Sstevel@tonic-gate 	 */
78869112eddSAli Bahrami 	if ((osp = ld_place_section(ofl, isec, NULL, ident, NULL)) ==
7891dd9d86fSAli Bahrami 	    (Os_desc *)S_ERROR)
7907c478bd9Sstevel@tonic-gate 		return (S_ERROR);
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 	/*
79357ef7aa9SRod Evans 	 * If relocations exist against a .*bss section, a section symbol must
79457ef7aa9SRod Evans 	 * be created for the section in the .dynsym symbol table.
7957c478bd9Sstevel@tonic-gate 	 */
7967c478bd9Sstevel@tonic-gate 	if (!(osp->os_flags & FLG_OS_OUTREL)) {
7971d9df23bSab196087 		ofl_flag_t	flagtotest;
79857ef7aa9SRod Evans 
79957ef7aa9SRod Evans 		if (ident == ld_targ.t_id.id_tlsbss)
8007c478bd9Sstevel@tonic-gate 			flagtotest = FLG_OF1_TLSOREL;
8017c478bd9Sstevel@tonic-gate 		else
8027c478bd9Sstevel@tonic-gate 			flagtotest = FLG_OF1_BSSOREL;
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 		if (ofl->ofl_flags1 & flagtotest) {
8057c478bd9Sstevel@tonic-gate 			ofl->ofl_dynshdrcnt++;
8067c478bd9Sstevel@tonic-gate 			osp->os_flags |= FLG_OS_OUTREL;
8077c478bd9Sstevel@tonic-gate 		}
8087c478bd9Sstevel@tonic-gate 	}
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	osp->os_szoutrels = rsize;
8117c478bd9Sstevel@tonic-gate 	return (1);
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate /*
8157c478bd9Sstevel@tonic-gate  * Build a SHT_{INIT|FINI|PREINIT}ARRAY section (specified via
81657ef7aa9SRod Evans  * ld -z *array=name).
8177c478bd9Sstevel@tonic-gate  */
8185aefb655Srie static uintptr_t
81957ef7aa9SRod Evans make_array(Ofl_desc *ofl, Word shtype, const char *sectname, APlist *alp)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate 	uint_t		entcount;
82257ef7aa9SRod Evans 	Aliste		idx;
8237c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
8247c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
8257c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
8267c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
8277c478bd9Sstevel@tonic-gate 	Rel_desc	reld;
8287c478bd9Sstevel@tonic-gate 	Rela		reloc;
8297c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
83002ca3e02Srie 	uintptr_t	ret = 1;
8317c478bd9Sstevel@tonic-gate 
83257ef7aa9SRod Evans 	if (alp == NULL)
8337c478bd9Sstevel@tonic-gate 		return (1);
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	entcount = 0;
83657ef7aa9SRod Evans 	for (APLIST_TRAVERSE(alp, idx, sdp))
8377c478bd9Sstevel@tonic-gate 		entcount++;
8387c478bd9Sstevel@tonic-gate 
8399039eeafSab196087 	if (new_section(ofl, shtype, sectname, entcount, &isec, &shdr, &data) ==
8409039eeafSab196087 	    S_ERROR)
8417c478bd9Sstevel@tonic-gate 		return (S_ERROR);
8427c478bd9Sstevel@tonic-gate 
84357ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(sizeof (Addr), entcount)) == NULL)
8447c478bd9Sstevel@tonic-gate 		return (S_ERROR);
8457c478bd9Sstevel@tonic-gate 
84669112eddSAli Bahrami 	if (ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_array, NULL) ==
847ba2be530Sab196087 	    (Os_desc *)S_ERROR)
8487c478bd9Sstevel@tonic-gate 		return (S_ERROR);
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	osp = isec->is_osdesc;
8517c478bd9Sstevel@tonic-gate 
8520e233487SRod Evans 	if ((ofl->ofl_osinitarray == NULL) && (shtype == SHT_INIT_ARRAY))
8537c478bd9Sstevel@tonic-gate 		ofl->ofl_osinitarray = osp;
8540e233487SRod Evans 	if ((ofl->ofl_ospreinitarray == NULL) && (shtype == SHT_PREINIT_ARRAY))
8557c478bd9Sstevel@tonic-gate 		ofl->ofl_ospreinitarray = osp;
8560e233487SRod Evans 	else if ((ofl->ofl_osfiniarray == NULL) && (shtype == SHT_FINI_ARRAY))
8577c478bd9Sstevel@tonic-gate 		ofl->ofl_osfiniarray = osp;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	/*
8607c478bd9Sstevel@tonic-gate 	 * Create relocations against this section to initialize it to the
8617c478bd9Sstevel@tonic-gate 	 * function addresses.
8627c478bd9Sstevel@tonic-gate 	 */
8637c478bd9Sstevel@tonic-gate 	reld.rel_isdesc = isec;
864bf994817SAli Bahrami 	reld.rel_aux = NULL;
8657c478bd9Sstevel@tonic-gate 	reld.rel_flags = FLG_REL_LOAD;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	/*
8687c478bd9Sstevel@tonic-gate 	 * Fabricate the relocation information (as if a relocation record had
8697c478bd9Sstevel@tonic-gate 	 * been input - see init_rel()).
8707c478bd9Sstevel@tonic-gate 	 */
871ba2be530Sab196087 	reld.rel_rtype = ld_targ.t_m.m_r_arrayaddr;
8727c478bd9Sstevel@tonic-gate 	reld.rel_roffset = 0;
8737c478bd9Sstevel@tonic-gate 	reld.rel_raddend = 0;
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	/*
8767c478bd9Sstevel@tonic-gate 	 * Create a minimal relocation record to satisfy process_sym_reloc()
8777c478bd9Sstevel@tonic-gate 	 * debugging requirements.
8787c478bd9Sstevel@tonic-gate 	 */
8797c478bd9Sstevel@tonic-gate 	reloc.r_offset = 0;
880ba2be530Sab196087 	reloc.r_info = ELF_R_INFO(0, ld_targ.t_m.m_r_arrayaddr);
8817c478bd9Sstevel@tonic-gate 	reloc.r_addend = 0;
8827c478bd9Sstevel@tonic-gate 
883ba2be530Sab196087 	DBG_CALL(Dbg_reloc_generate(ofl->ofl_lml, osp,
884ba2be530Sab196087 	    ld_targ.t_m.m_rel_sht_type));
88557ef7aa9SRod Evans 	for (APLIST_TRAVERSE(alp, idx, sdp)) {
8867c478bd9Sstevel@tonic-gate 		reld.rel_sym = sdp;
8877c478bd9Sstevel@tonic-gate 
8885aefb655Srie 		if (ld_process_sym_reloc(ofl, &reld, (Rel *)&reloc, isec,
889e23c41c9SAli Bahrami 		    MSG_INTL(MSG_STR_COMMAND), 0) == S_ERROR) {
89002ca3e02Srie 			ret = S_ERROR;
89102ca3e02Srie 			continue;
89202ca3e02Srie 		}
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 		reld.rel_roffset += (Xword)sizeof (Addr);
8957c478bd9Sstevel@tonic-gate 		reloc.r_offset = reld.rel_roffset;
8967c478bd9Sstevel@tonic-gate 	}
8977c478bd9Sstevel@tonic-gate 
89802ca3e02Srie 	return (ret);
8997c478bd9Sstevel@tonic-gate }
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate /*
9027c478bd9Sstevel@tonic-gate  * Build a comment section (-Qy option).
9037c478bd9Sstevel@tonic-gate  */
9045aefb655Srie static uintptr_t
9057c478bd9Sstevel@tonic-gate make_comment(Ofl_desc *ofl)
9067c478bd9Sstevel@tonic-gate {
9077c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
9087c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
9097c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
9107c478bd9Sstevel@tonic-gate 
9119039eeafSab196087 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_COMMENT), 0,
9129039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
9137c478bd9Sstevel@tonic-gate 		return (S_ERROR);
9149039eeafSab196087 
9157c478bd9Sstevel@tonic-gate 	data->d_buf = (void *)ofl->ofl_sgsid;
9167c478bd9Sstevel@tonic-gate 	data->d_size = strlen(ofl->ofl_sgsid) + 1;
9177c478bd9Sstevel@tonic-gate 	data->d_align = 1;
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)data->d_size;
9209039eeafSab196087 	shdr->sh_flags = 0;
9217c478bd9Sstevel@tonic-gate 	shdr->sh_addralign = 1;
9227c478bd9Sstevel@tonic-gate 
92369112eddSAli Bahrami 	return ((uintptr_t)ld_place_section(ofl, isec, NULL,
9241dd9d86fSAli Bahrami 	    ld_targ.t_id.id_note, NULL));
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate /*
9287c478bd9Sstevel@tonic-gate  * Make the dynamic section.  Calculate the size of any strings referenced
9297c478bd9Sstevel@tonic-gate  * within this structure, they will be added to the global string table
9307c478bd9Sstevel@tonic-gate  * (.dynstr).  This routine should be called before make_dynstr().
9311d9df23bSab196087  *
9321d9df23bSab196087  * This routine must be maintained in parallel with update_odynamic()
9331d9df23bSab196087  * in update.c
9347c478bd9Sstevel@tonic-gate  */
9355aefb655Srie static uintptr_t
9367c478bd9Sstevel@tonic-gate make_dynamic(Ofl_desc *ofl)
9377c478bd9Sstevel@tonic-gate {
9387c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
9397c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
9407c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
9417c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
9427c478bd9Sstevel@tonic-gate 	size_t		cnt = 0;
94357ef7aa9SRod Evans 	Aliste		idx;
9447c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
9457c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
9467c478bd9Sstevel@tonic-gate 	size_t		size;
947635216b6SRod Evans 	Str_tbl		*strtbl;
9481d9df23bSab196087 	ofl_flag_t	flags = ofl->ofl_flags;
9491d9df23bSab196087 	int		not_relobj = !(flags & FLG_OF_RELOBJ);
9507c478bd9Sstevel@tonic-gate 	int		unused = 0;
9517c478bd9Sstevel@tonic-gate 
9521d9df23bSab196087 	/*
953635216b6SRod Evans 	 * Select the required string table.
954635216b6SRod Evans 	 */
955635216b6SRod Evans 	if (OFL_IS_STATIC_OBJ(ofl))
956635216b6SRod Evans 		strtbl = ofl->ofl_strtab;
957635216b6SRod Evans 	else
958635216b6SRod Evans 		strtbl = ofl->ofl_dynstrtab;
959635216b6SRod Evans 
960635216b6SRod Evans 	/*
9611d9df23bSab196087 	 * Only a limited subset of DT_ entries apply to relocatable
9621d9df23bSab196087 	 * objects. See the comment at the head of update_odynamic() in
9631d9df23bSab196087 	 * update.c for details.
9641d9df23bSab196087 	 */
9659039eeafSab196087 	if (new_section(ofl, SHT_DYNAMIC, MSG_ORIG(MSG_SCN_DYNAMIC), 0,
9669039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
9677c478bd9Sstevel@tonic-gate 		return (S_ERROR);
9689039eeafSab196087 
96994c044f4SRod Evans 	/*
97094c044f4SRod Evans 	 * new_section() does not set SHF_ALLOC.  If we're building anything
97194c044f4SRod Evans 	 * besides a relocatable object, then the .dynamic section should
97294c044f4SRod Evans 	 * reside in allocatable memory.
97394c044f4SRod Evans 	 */
9741d9df23bSab196087 	if (not_relobj)
9757c478bd9Sstevel@tonic-gate 		shdr->sh_flags |= SHF_ALLOC;
9767c478bd9Sstevel@tonic-gate 
97794c044f4SRod Evans 	/*
97894c044f4SRod Evans 	 * new_section() does not set SHF_WRITE.  If we're building an object
97994c044f4SRod Evans 	 * that specifies an interpretor, then a DT_DEBUG entry is created,
98094c044f4SRod Evans 	 * which is initialized to the applications link-map list at runtime.
98194c044f4SRod Evans 	 */
98294c044f4SRod Evans 	if (ofl->ofl_osinterp)
98394c044f4SRod Evans 		shdr->sh_flags |= SHF_WRITE;
98494c044f4SRod Evans 
985ba2be530Sab196087 	osp = ofl->ofl_osdynamic =
98669112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynamic, NULL);
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 	/*
9897c478bd9Sstevel@tonic-gate 	 * Reserve entries for any needed dependencies.
9907c478bd9Sstevel@tonic-gate 	 */
99157ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_sos, idx, ifl)) {
9927c478bd9Sstevel@tonic-gate 		if (!(ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR)))
9937c478bd9Sstevel@tonic-gate 			continue;
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 		/*
996fb1354edSrie 		 * If this dependency didn't satisfy any symbol references,
9977c478bd9Sstevel@tonic-gate 		 * generate a debugging diagnostic (ld(1) -Dunused can be used
9987c478bd9Sstevel@tonic-gate 		 * to display these).  If this is a standard needed dependency,
9997c478bd9Sstevel@tonic-gate 		 * and -z ignore is in effect, drop the dependency.  Explicitly
10007c478bd9Sstevel@tonic-gate 		 * defined dependencies (i.e., -N dep) don't get dropped, and
10017c478bd9Sstevel@tonic-gate 		 * are flagged as being required to simplify update_odynamic()
10027c478bd9Sstevel@tonic-gate 		 * processing.
10037c478bd9Sstevel@tonic-gate 		 */
1004fb1354edSrie 		if ((ifl->ifl_flags & FLG_IF_NEEDSTR) ||
1005fb1354edSrie 		    ((ifl->ifl_flags & FLG_IF_DEPREQD) == 0)) {
10067c478bd9Sstevel@tonic-gate 			if (unused++ == 0)
10075aefb655Srie 				DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
10085aefb655Srie 			DBG_CALL(Dbg_unused_file(ofl->ofl_lml, ifl->ifl_soname,
1009fb1354edSrie 			    (ifl->ifl_flags & FLG_IF_NEEDSTR), 0));
10107c478bd9Sstevel@tonic-gate 
10111007fd6fSAli Bahrami 			/*
10121007fd6fSAli Bahrami 			 * Guidance: Remove unused dependency.
10131007fd6fSAli Bahrami 			 *
10141007fd6fSAli Bahrami 			 * If -z ignore is in effect, this warning is not
10151007fd6fSAli Bahrami 			 * needed because we will quietly remove the unused
10161007fd6fSAli Bahrami 			 * dependency.
10171007fd6fSAli Bahrami 			 */
10181007fd6fSAli Bahrami 			if (OFL_GUIDANCE(ofl, FLG_OFG_NO_UNUSED) &&
10191007fd6fSAli Bahrami 			    ((ifl->ifl_flags & FLG_IF_IGNORE) == 0))
10201007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_GUIDANCE,
10211007fd6fSAli Bahrami 				    MSG_INTL(MSG_GUIDE_UNUSED),
10221007fd6fSAli Bahrami 				    ifl->ifl_soname);
10231007fd6fSAli Bahrami 
10247c478bd9Sstevel@tonic-gate 			if (ifl->ifl_flags & FLG_IF_NEEDSTR)
10257c478bd9Sstevel@tonic-gate 				ifl->ifl_flags |= FLG_IF_DEPREQD;
10267c478bd9Sstevel@tonic-gate 			else if (ifl->ifl_flags & FLG_IF_IGNORE)
10277c478bd9Sstevel@tonic-gate 				continue;
10287c478bd9Sstevel@tonic-gate 		}
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 		/*
1031f441771bSRod Evans 		 * If this object requires a DT_POSFLAG_1 entry, reserve it.
10327c478bd9Sstevel@tonic-gate 		 */
1033f441771bSRod Evans 		if ((ifl->ifl_flags & MSK_IF_POSFLAG1) && not_relobj)
10347c478bd9Sstevel@tonic-gate 			cnt++;
10357c478bd9Sstevel@tonic-gate 
1036635216b6SRod Evans 		if (st_insert(strtbl, ifl->ifl_soname) == -1)
10377c478bd9Sstevel@tonic-gate 			return (S_ERROR);
10387c478bd9Sstevel@tonic-gate 		cnt++;
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 		/*
10417c478bd9Sstevel@tonic-gate 		 * If the needed entry contains the $ORIGIN token make sure
10427c478bd9Sstevel@tonic-gate 		 * the associated DT_1_FLAGS entry is created.
10437c478bd9Sstevel@tonic-gate 		 */
10447c478bd9Sstevel@tonic-gate 		if (strstr(ifl->ifl_soname, MSG_ORIG(MSG_STR_ORIGIN))) {
10457c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
10467c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags |= DF_ORIGIN;
10477c478bd9Sstevel@tonic-gate 		}
10487c478bd9Sstevel@tonic-gate 	}
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate 	if (unused)
10515aefb655Srie 		DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
10527c478bd9Sstevel@tonic-gate 
10531d9df23bSab196087 	if (not_relobj) {
10547c478bd9Sstevel@tonic-gate 		/*
10557c478bd9Sstevel@tonic-gate 		 * Reserve entries for any per-symbol auxiliary/filter strings.
10567c478bd9Sstevel@tonic-gate 		 */
1057cce0e03bSab196087 		cnt += alist_nitems(ofl->ofl_dtsfltrs);
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 		/*
10601d9df23bSab196087 		 * Reserve entries for _init() and _fini() section addresses.
10617c478bd9Sstevel@tonic-gate 		 */
10625aefb655Srie 		if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U),
1063635216b6SRod Evans 		    SYM_NOHASH, NULL, ofl)) != NULL) &&
10641d9df23bSab196087 		    (sdp->sd_ref == REF_REL_NEED) &&
10655b59e4caSab196087 		    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
10667c478bd9Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_UPREQD;
10677c478bd9Sstevel@tonic-gate 			cnt++;
10687c478bd9Sstevel@tonic-gate 		}
10695aefb655Srie 		if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U),
1070635216b6SRod Evans 		    SYM_NOHASH, NULL, ofl)) != NULL) &&
10711d9df23bSab196087 		    (sdp->sd_ref == REF_REL_NEED) &&
10725b59e4caSab196087 		    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
10737c478bd9Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_UPREQD;
10747c478bd9Sstevel@tonic-gate 			cnt++;
10757c478bd9Sstevel@tonic-gate 		}
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 		/*
10781d9df23bSab196087 		 * Reserve entries for any soname, filter name (shared libs
10791d9df23bSab196087 		 * only), run-path pointers, cache names and audit requirements.
10807c478bd9Sstevel@tonic-gate 		 */
10817c478bd9Sstevel@tonic-gate 		if (ofl->ofl_soname) {
10827c478bd9Sstevel@tonic-gate 			cnt++;
1083635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_soname) == -1)
10847c478bd9Sstevel@tonic-gate 				return (S_ERROR);
10857c478bd9Sstevel@tonic-gate 		}
10867c478bd9Sstevel@tonic-gate 		if (ofl->ofl_filtees) {
10877c478bd9Sstevel@tonic-gate 			cnt++;
1088635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_filtees) == -1)
10897c478bd9Sstevel@tonic-gate 				return (S_ERROR);
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 			/*
10921d9df23bSab196087 			 * If the filtees entry contains the $ORIGIN token
10931d9df23bSab196087 			 * make sure the associated DT_1_FLAGS entry is created.
10947c478bd9Sstevel@tonic-gate 			 */
10951d9df23bSab196087 			if (strstr(ofl->ofl_filtees,
10961d9df23bSab196087 			    MSG_ORIG(MSG_STR_ORIGIN))) {
10977c478bd9Sstevel@tonic-gate 				ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
10987c478bd9Sstevel@tonic-gate 				ofl->ofl_dtflags |= DF_ORIGIN;
10997c478bd9Sstevel@tonic-gate 			}
11007c478bd9Sstevel@tonic-gate 		}
11011d9df23bSab196087 	}
11021d9df23bSab196087 
11037c478bd9Sstevel@tonic-gate 	if (ofl->ofl_rpath) {
11047c478bd9Sstevel@tonic-gate 		cnt += 2;	/* DT_RPATH & DT_RUNPATH */
1105635216b6SRod Evans 		if (st_insert(strtbl, ofl->ofl_rpath) == -1)
11067c478bd9Sstevel@tonic-gate 			return (S_ERROR);
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 		/*
11097c478bd9Sstevel@tonic-gate 		 * If the rpath entry contains the $ORIGIN token make sure
11107c478bd9Sstevel@tonic-gate 		 * the associated DT_1_FLAGS entry is created.
11117c478bd9Sstevel@tonic-gate 		 */
11127c478bd9Sstevel@tonic-gate 		if (strstr(ofl->ofl_rpath, MSG_ORIG(MSG_STR_ORIGIN))) {
11137c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
11147c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags |= DF_ORIGIN;
11157c478bd9Sstevel@tonic-gate 		}
11167c478bd9Sstevel@tonic-gate 	}
11171d9df23bSab196087 
11181d9df23bSab196087 	if (not_relobj) {
111957ef7aa9SRod Evans 		Aliste	idx;
112094c044f4SRod Evans 		Sg_desc	*sgp;
112157ef7aa9SRod Evans 
11227c478bd9Sstevel@tonic-gate 		if (ofl->ofl_config) {
11237c478bd9Sstevel@tonic-gate 			cnt++;
1124635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_config) == -1)
11257c478bd9Sstevel@tonic-gate 				return (S_ERROR);
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 			/*
11281d9df23bSab196087 			 * If the config entry contains the $ORIGIN token
11291d9df23bSab196087 			 * make sure the associated DT_1_FLAGS entry is created.
11307c478bd9Sstevel@tonic-gate 			 */
11317c478bd9Sstevel@tonic-gate 			if (strstr(ofl->ofl_config, MSG_ORIG(MSG_STR_ORIGIN))) {
11327c478bd9Sstevel@tonic-gate 				ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
11337c478bd9Sstevel@tonic-gate 				ofl->ofl_dtflags |= DF_ORIGIN;
11347c478bd9Sstevel@tonic-gate 			}
11357c478bd9Sstevel@tonic-gate 		}
11367c478bd9Sstevel@tonic-gate 		if (ofl->ofl_depaudit) {
11377c478bd9Sstevel@tonic-gate 			cnt++;
1138635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_depaudit) == -1)
11397c478bd9Sstevel@tonic-gate 				return (S_ERROR);
11407c478bd9Sstevel@tonic-gate 		}
11417c478bd9Sstevel@tonic-gate 		if (ofl->ofl_audit) {
11427c478bd9Sstevel@tonic-gate 			cnt++;
1143635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_audit) == -1)
11447c478bd9Sstevel@tonic-gate 				return (S_ERROR);
11457c478bd9Sstevel@tonic-gate 		}
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate 		/*
114894c044f4SRod Evans 		 * Reserve entries for the DT_HASH, DT_STRTAB, DT_STRSZ,
114994c044f4SRod Evans 		 * DT_SYMTAB, DT_SYMENT, and DT_CHECKSUM.
11507c478bd9Sstevel@tonic-gate 		 */
11517c478bd9Sstevel@tonic-gate 		cnt += 6;
11527c478bd9Sstevel@tonic-gate 
11539039eeafSab196087 		/*
11549039eeafSab196087 		 * If we are including local functions at the head of
11559039eeafSab196087 		 * the dynsym, then also reserve entries for DT_SUNW_SYMTAB
11569039eeafSab196087 		 * and DT_SUNW_SYMSZ.
11579039eeafSab196087 		 */
1158d579eb63Sab196087 		if (OFL_ALLOW_LDYNSYM(ofl))
11599039eeafSab196087 			cnt += 2;
11609039eeafSab196087 
1161d579eb63Sab196087 		if ((ofl->ofl_dynsymsortcnt > 0) ||
1162d579eb63Sab196087 		    (ofl->ofl_dyntlssortcnt > 0))
1163d579eb63Sab196087 			cnt++;		/* DT_SUNW_SORTENT */
1164d579eb63Sab196087 
1165d579eb63Sab196087 		if (ofl->ofl_dynsymsortcnt > 0)
1166d579eb63Sab196087 			cnt += 2;	/* DT_SUNW_[SYMSORT|SYMSORTSZ] */
1167d579eb63Sab196087 
1168d579eb63Sab196087 		if (ofl->ofl_dyntlssortcnt > 0)
1169d579eb63Sab196087 			cnt += 2;	/* DT_SUNW_[TLSSORT|TLSSORTSZ] */
1170d579eb63Sab196087 
11717c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) ==
11727c478bd9Sstevel@tonic-gate 		    FLG_OF_VERDEF)
11737c478bd9Sstevel@tonic-gate 			cnt += 2;		/* DT_VERDEF & DT_VERDEFNUM */
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) ==
11767c478bd9Sstevel@tonic-gate 		    FLG_OF_VERNEED)
11777c478bd9Sstevel@tonic-gate 			cnt += 2;		/* DT_VERNEED & DT_VERNEEDNUM */
11787c478bd9Sstevel@tonic-gate 
11791d9df23bSab196087 		if ((flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt)
118094c044f4SRod Evans 			cnt++;			/* DT_RELACOUNT */
11817c478bd9Sstevel@tonic-gate 
118294c044f4SRod Evans 		if (flags & FLG_OF_TEXTREL)	/* DT_TEXTREL */
11837c478bd9Sstevel@tonic-gate 			cnt++;
11847c478bd9Sstevel@tonic-gate 
118594c044f4SRod Evans 		if (ofl->ofl_osfiniarray)	/* DT_FINI_ARRAY */
118694c044f4SRod Evans 			cnt += 2;		/*    DT_FINI_ARRAYSZ */
11877c478bd9Sstevel@tonic-gate 
118894c044f4SRod Evans 		if (ofl->ofl_osinitarray)	/* DT_INIT_ARRAY */
118994c044f4SRod Evans 			cnt += 2;		/*    DT_INIT_ARRAYSZ */
11907c478bd9Sstevel@tonic-gate 
119194c044f4SRod Evans 		if (ofl->ofl_ospreinitarray)	/* DT_PREINIT_ARRAY & */
119294c044f4SRod Evans 			cnt += 2;		/*    DT_PREINIT_ARRAYSZ */
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate 		/*
119594c044f4SRod Evans 		 * If we have plt's reserve a DT_PLTRELSZ, DT_PLTREL and
119694c044f4SRod Evans 		 * DT_JMPREL.
11977c478bd9Sstevel@tonic-gate 		 */
11987c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltcnt)
11997c478bd9Sstevel@tonic-gate 			cnt += 3;
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 		/*
120294c044f4SRod Evans 		 * If plt padding is needed (Sparcv9).
12037c478bd9Sstevel@tonic-gate 		 */
12047c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltpad)
12057c478bd9Sstevel@tonic-gate 			cnt += 2;		/* DT_PLTPAD & DT_PLTPADSZ */
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 		/*
120894c044f4SRod Evans 		 * If we have any relocations reserve a DT_REL, DT_RELSZ and
120994c044f4SRod Evans 		 * DT_RELENT entry.
12107c478bd9Sstevel@tonic-gate 		 */
12117c478bd9Sstevel@tonic-gate 		if (ofl->ofl_relocsz)
12127c478bd9Sstevel@tonic-gate 			cnt += 3;
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 		/*
121594c044f4SRod Evans 		 * If a syminfo section is required create DT_SYMINFO,
121694c044f4SRod Evans 		 * DT_SYMINSZ, and DT_SYMINENT entries.
12177c478bd9Sstevel@tonic-gate 		 */
12181d9df23bSab196087 		if (flags & FLG_OF_SYMINFO)
12197c478bd9Sstevel@tonic-gate 			cnt += 3;
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 		/*
12227c478bd9Sstevel@tonic-gate 		 * If there are any partially initialized sections allocate
122394c044f4SRod Evans 		 * DT_MOVETAB, DT_MOVESZ and DT_MOVEENT.
12247c478bd9Sstevel@tonic-gate 		 */
12257c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osmove)
12267c478bd9Sstevel@tonic-gate 			cnt += 3;
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate 		/*
12299039eeafSab196087 		 * Allocate one DT_REGISTER entry for every register symbol.
12307c478bd9Sstevel@tonic-gate 		 */
12317c478bd9Sstevel@tonic-gate 		cnt += ofl->ofl_regsymcnt;
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 		/*
12347c478bd9Sstevel@tonic-gate 		 * Reserve a entry for each '-zrtldinfo=...' specified
12357c478bd9Sstevel@tonic-gate 		 * on the command line.
12367c478bd9Sstevel@tonic-gate 		 */
123757ef7aa9SRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_rtldinfo, idx, sdp))
12387c478bd9Sstevel@tonic-gate 			cnt++;
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 		/*
124194c044f4SRod Evans 		 * The following entry should only be placed in a segment that
124294c044f4SRod Evans 		 * is writable.
12437c478bd9Sstevel@tonic-gate 		 */
124494c044f4SRod Evans 		if (((sgp = osp->os_sgdesc) != NULL) &&
124594c044f4SRod Evans 		    (sgp->sg_phdr.p_flags & PF_W) && ofl->ofl_osinterp)
124694c044f4SRod Evans 			cnt++;		/* DT_DEBUG */
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 		/*
124908278a5eSRod Evans 		 * Capabilities require a .dynamic entry for the .SUNW_cap
125008278a5eSRod Evans 		 * section.
12517c478bd9Sstevel@tonic-gate 		 */
12527c478bd9Sstevel@tonic-gate 		if (ofl->ofl_oscap)
125394c044f4SRod Evans 			cnt++;			/* DT_SUNW_CAP */
12547c478bd9Sstevel@tonic-gate 
125508278a5eSRod Evans 		/*
125608278a5eSRod Evans 		 * Symbol capabilities require a .dynamic entry for the
125708278a5eSRod Evans 		 * .SUNW_capinfo section.
125808278a5eSRod Evans 		 */
125908278a5eSRod Evans 		if (ofl->ofl_oscapinfo)
126094c044f4SRod Evans 			cnt++;			/* DT_SUNW_CAPINFO */
126108278a5eSRod Evans 
126208278a5eSRod Evans 		/*
126308278a5eSRod Evans 		 * Capabilities chain information requires a .SUNW_capchain
126494c044f4SRod Evans 		 * entry (DT_SUNW_CAPCHAIN), entry size (DT_SUNW_CAPCHAINENT),
126594c044f4SRod Evans 		 * and total size (DT_SUNW_CAPCHAINSZ).
126608278a5eSRod Evans 		 */
126708278a5eSRod Evans 		if (ofl->ofl_oscapchain)
126894c044f4SRod Evans 			cnt += 3;
126908278a5eSRod Evans 
12707c478bd9Sstevel@tonic-gate 		if (flags & FLG_OF_SYMBOLIC)
127194c044f4SRod Evans 			cnt++;			/* DT_SYMBOLIC */
12721d9df23bSab196087 	}
12737c478bd9Sstevel@tonic-gate 
12747c478bd9Sstevel@tonic-gate 	/*
12755aefb655Srie 	 * Account for Architecture dependent .dynamic entries, and defaults.
12767c478bd9Sstevel@tonic-gate 	 */
1277ba2be530Sab196087 	(*ld_targ.t_mr.mr_mach_make_dynamic)(ofl, &cnt);
12787c478bd9Sstevel@tonic-gate 
12793244bcaaSab196087 	/*
12803244bcaaSab196087 	 * DT_FLAGS, DT_FLAGS_1, DT_SUNW_STRPAD, and DT_NULL. Also,
12813244bcaaSab196087 	 * allow room for the unused extra DT_NULLs. These are included
12823244bcaaSab196087 	 * to allow an ELF editor room to add items later.
12833244bcaaSab196087 	 */
12843244bcaaSab196087 	cnt += 4 + DYNAMIC_EXTRA_ELTS;
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 	/*
1287ba2be530Sab196087 	 * DT_SUNW_LDMACH. Used to hold the ELF machine code of the
1288ba2be530Sab196087 	 * linker that produced the output object. This information
1289ba2be530Sab196087 	 * allows us to determine whether a given object was linked
1290ba2be530Sab196087 	 * natively, or by a linker running on a different type of
1291ba2be530Sab196087 	 * system. This information can be valuable if one suspects
1292ba2be530Sab196087 	 * that a problem might be due to alignment or byte order issues.
1293ba2be530Sab196087 	 */
1294ba2be530Sab196087 	cnt++;
1295ba2be530Sab196087 
1296ba2be530Sab196087 	/*
12977c478bd9Sstevel@tonic-gate 	 * Determine the size of the section from the number of entries.
12987c478bd9Sstevel@tonic-gate 	 */
12997c478bd9Sstevel@tonic-gate 	size = cnt * (size_t)shdr->sh_entsize;
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
13027c478bd9Sstevel@tonic-gate 	data->d_size = size;
13037c478bd9Sstevel@tonic-gate 
13044f680cc6SAli Bahrami 	/*
13054f680cc6SAli Bahrami 	 * There are several tags that are specific to the Solaris osabi
13064f680cc6SAli Bahrami 	 * range which we unconditionally put into any dynamic section
13074f680cc6SAli Bahrami 	 * we create (e.g. DT_SUNW_STRPAD or DT_SUNW_LDMACH). As such,
13084f680cc6SAli Bahrami 	 * any Solaris object with a dynamic section should be tagged as
13094f680cc6SAli Bahrami 	 * ELFOSABI_SOLARIS.
13104f680cc6SAli Bahrami 	 */
13114f680cc6SAli Bahrami 	ofl->ofl_flags |= FLG_OF_OSABI;
13124f680cc6SAli Bahrami 
13137c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osdynamic);
13147c478bd9Sstevel@tonic-gate }
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate /*
13177c478bd9Sstevel@tonic-gate  * Build the GOT section and its associated relocation entries.
13187c478bd9Sstevel@tonic-gate  */
13197c478bd9Sstevel@tonic-gate uintptr_t
13205aefb655Srie ld_make_got(Ofl_desc *ofl)
13217c478bd9Sstevel@tonic-gate {
13227c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
1323ba2be530Sab196087 	Shdr	*shdr;
13247c478bd9Sstevel@tonic-gate 	Is_desc	*isec;
1325ba2be530Sab196087 	size_t	size = (size_t)ofl->ofl_gotcnt * ld_targ.t_m.m_got_entsize;
13267c478bd9Sstevel@tonic-gate 	size_t	rsize = (size_t)ofl->ofl_relocgotsz;
13277c478bd9Sstevel@tonic-gate 
13289039eeafSab196087 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_GOT), 0,
13299039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
13307c478bd9Sstevel@tonic-gate 		return (S_ERROR);
13319039eeafSab196087 
13327c478bd9Sstevel@tonic-gate 	data->d_size = size;
13337c478bd9Sstevel@tonic-gate 
13349039eeafSab196087 	shdr->sh_flags |= SHF_WRITE;
13357c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
1336ba2be530Sab196087 	shdr->sh_entsize = ld_targ.t_m.m_got_entsize;
13377c478bd9Sstevel@tonic-gate 
133869112eddSAli Bahrami 	ofl->ofl_osgot = ld_place_section(ofl, isec, NULL,
133969112eddSAli Bahrami 	    ld_targ.t_id.id_got, NULL);
1340ba2be530Sab196087 	if (ofl->ofl_osgot == (Os_desc *)S_ERROR)
13417c478bd9Sstevel@tonic-gate 		return (S_ERROR);
13427c478bd9Sstevel@tonic-gate 
13437c478bd9Sstevel@tonic-gate 	ofl->ofl_osgot->os_szoutrels = (Xword)rsize;
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 	return (1);
13467c478bd9Sstevel@tonic-gate }
13477c478bd9Sstevel@tonic-gate 
13487c478bd9Sstevel@tonic-gate /*
134970d3e49eSrie  * Build an interpreter section.
13507c478bd9Sstevel@tonic-gate  */
13515aefb655Srie static uintptr_t
13527c478bd9Sstevel@tonic-gate make_interp(Ofl_desc *ofl)
13537c478bd9Sstevel@tonic-gate {
13547c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
13557c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
13567c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
13577c478bd9Sstevel@tonic-gate 	const char	*iname = ofl->ofl_interp;
13587c478bd9Sstevel@tonic-gate 	size_t		size;
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 	/*
136170d3e49eSrie 	 * If -z nointerp is in effect, don't create an interpreter section.
136270d3e49eSrie 	 */
136370d3e49eSrie 	if (ofl->ofl_flags1 & FLG_OF1_NOINTRP)
136470d3e49eSrie 		return (1);
136570d3e49eSrie 
136670d3e49eSrie 	/*
136794c044f4SRod Evans 	 * An .interp section is always created for a dynamic executable.
136894c044f4SRod Evans 	 * A user can define the interpreter to use.  This definition overrides
136994c044f4SRod Evans 	 * the default that would be recorded in an executable, and triggers
137094c044f4SRod Evans 	 * the creation of an .interp section in any other object.  Presumably
137194c044f4SRod Evans 	 * the user knows what they are doing.  Refer to the generic ELF ABI
137294c044f4SRod Evans 	 * section 5-4, and the ld(1) -I option.
13737c478bd9Sstevel@tonic-gate 	 */
13747c478bd9Sstevel@tonic-gate 	if (((ofl->ofl_flags & (FLG_OF_DYNAMIC | FLG_OF_EXEC |
13757c478bd9Sstevel@tonic-gate 	    FLG_OF_RELOBJ)) != (FLG_OF_DYNAMIC | FLG_OF_EXEC)) && !iname)
13767c478bd9Sstevel@tonic-gate 		return (1);
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate 	/*
137994c044f4SRod Evans 	 * In the case of a dynamic executable, supply a default interpreter
138094c044f4SRod Evans 	 * if the user has not specified their own.
13817c478bd9Sstevel@tonic-gate 	 */
1382ba2be530Sab196087 	if (iname == NULL)
1383ba2be530Sab196087 		iname = ofl->ofl_interp = ld_targ.t_m.m_def_interp;
13847c478bd9Sstevel@tonic-gate 
13857c478bd9Sstevel@tonic-gate 	size = strlen(iname) + 1;
13867c478bd9Sstevel@tonic-gate 
13879039eeafSab196087 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_INTERP), 0,
13889039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
13897c478bd9Sstevel@tonic-gate 		return (S_ERROR);
13909039eeafSab196087 
13917c478bd9Sstevel@tonic-gate 	data->d_size = size;
13927c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
13939039eeafSab196087 	data->d_align = shdr->sh_addralign = 1;
13947c478bd9Sstevel@tonic-gate 
1395ba2be530Sab196087 	ofl->ofl_osinterp =
139669112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_interp, NULL);
13977c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osinterp);
13987c478bd9Sstevel@tonic-gate }
13997c478bd9Sstevel@tonic-gate 
14007c478bd9Sstevel@tonic-gate /*
140108278a5eSRod Evans  * Common function used to build the SHT_SUNW_versym section, SHT_SUNW_syminfo
140208278a5eSRod Evans  * section, and SHT_SUNW_capinfo section.  Each of these sections provide
140308278a5eSRod Evans  * additional symbol information, and their size parallels the associated
140408278a5eSRod Evans  * symbol table.
140569112eddSAli Bahrami  */
140608278a5eSRod Evans static Os_desc *
140708278a5eSRod Evans make_sym_sec(Ofl_desc *ofl, const char *sectname, Word stype, int ident)
14087c478bd9Sstevel@tonic-gate {
14097c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
14107c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
14117c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate 	/*
141408278a5eSRod Evans 	 * We don't know the size of this section yet, so set it to 0.  The
141508278a5eSRod Evans 	 * size gets filled in after the associated symbol table is sized.
14167c478bd9Sstevel@tonic-gate 	 */
141708278a5eSRod Evans 	if (new_section(ofl, stype, sectname, 0, &isec, &shdr, &data) ==
141808278a5eSRod Evans 	    S_ERROR)
141908278a5eSRod Evans 		return ((Os_desc *)S_ERROR);
14207c478bd9Sstevel@tonic-gate 
142108278a5eSRod Evans 	return (ld_place_section(ofl, isec, NULL, ident, NULL));
142269112eddSAli Bahrami }
142369112eddSAli Bahrami 
142408278a5eSRod Evans /*
142508278a5eSRod Evans  * Determine whether a symbol capability is redundant because the object
142608278a5eSRod Evans  * capabilities are more restrictive.
142708278a5eSRod Evans  */
142808278a5eSRod Evans inline static int
142908278a5eSRod Evans is_cap_redundant(Objcapset *ocapset, Objcapset *scapset)
143008278a5eSRod Evans {
143108278a5eSRod Evans 	Alist		*oalp, *salp;
143208278a5eSRod Evans 	elfcap_mask_t	omsk, smsk;
143369112eddSAli Bahrami 
143408278a5eSRod Evans 	/*
143508278a5eSRod Evans 	 * Inspect any platform capabilities.  If the object defines platform
143608278a5eSRod Evans 	 * capabilities, then the object will only be loaded for those
143708278a5eSRod Evans 	 * platforms.  A symbol capability set that doesn't define the same
143808278a5eSRod Evans 	 * platforms is redundant, and a symbol capability that does not provide
143908278a5eSRod Evans 	 * at least one platform name that matches a platform name in the object
144008278a5eSRod Evans 	 * capabilities will never execute (as the object wouldn't have been
144108278a5eSRod Evans 	 * loaded).
144208278a5eSRod Evans 	 */
144308278a5eSRod Evans 	oalp = ocapset->oc_plat.cl_val;
144408278a5eSRod Evans 	salp = scapset->oc_plat.cl_val;
144508278a5eSRod Evans 	if (oalp && ((salp == NULL) || cap_names_match(oalp, salp)))
144608278a5eSRod Evans 		return (1);
144708278a5eSRod Evans 
144808278a5eSRod Evans 	/*
144908278a5eSRod Evans 	 * If the symbol capability set defines platforms, and the object
145008278a5eSRod Evans 	 * doesn't, then the symbol set is more restrictive.
145108278a5eSRod Evans 	 */
145208278a5eSRod Evans 	if (salp && (oalp == NULL))
145308278a5eSRod Evans 		return (0);
145408278a5eSRod Evans 
145508278a5eSRod Evans 	/*
145608278a5eSRod Evans 	 * Next, inspect any machine name capabilities.  If the object defines
145708278a5eSRod Evans 	 * machine name capabilities, then the object will only be loaded for
145808278a5eSRod Evans 	 * those machines.  A symbol capability set that doesn't define the same
145908278a5eSRod Evans 	 * machine names is redundant, and a symbol capability that does not
146008278a5eSRod Evans 	 * provide at least one machine name that matches a machine name in the
146108278a5eSRod Evans 	 * object capabilities will never execute (as the object wouldn't have
146208278a5eSRod Evans 	 * been loaded).
146308278a5eSRod Evans 	 */
146408278a5eSRod Evans 	oalp = ocapset->oc_plat.cl_val;
146508278a5eSRod Evans 	salp = scapset->oc_plat.cl_val;
146608278a5eSRod Evans 	if (oalp && ((salp == NULL) || cap_names_match(oalp, salp)))
146708278a5eSRod Evans 		return (1);
146808278a5eSRod Evans 
146908278a5eSRod Evans 	/*
147008278a5eSRod Evans 	 * If the symbol capability set defines machine names, and the object
147108278a5eSRod Evans 	 * doesn't, then the symbol set is more restrictive.
147208278a5eSRod Evans 	 */
147308278a5eSRod Evans 	if (salp && (oalp == NULL))
147408278a5eSRod Evans 		return (0);
147508278a5eSRod Evans 
147608278a5eSRod Evans 	/*
147708278a5eSRod Evans 	 * Next, inspect any hardware capabilities.  If the objects hardware
147808278a5eSRod Evans 	 * capabilities are greater than or equal to that of the symbols
147908278a5eSRod Evans 	 * capabilities, then the symbol capability set is redundant.  If the
148008278a5eSRod Evans 	 * symbols hardware capabilities are greater that the objects, then the
148108278a5eSRod Evans 	 * symbol set is more restrictive.
148208278a5eSRod Evans 	 *
148308278a5eSRod Evans 	 * Note that this is a somewhat arbitrary definition, as each capability
148408278a5eSRod Evans 	 * bit is independent of the others, and some of the higher order bits
148508278a5eSRod Evans 	 * could be considered to be less important than lower ones.  However,
148608278a5eSRod Evans 	 * this is the only reasonable non-subjective definition.
148708278a5eSRod Evans 	 */
148808278a5eSRod Evans 	omsk = ocapset->oc_hw_2.cm_val;
148908278a5eSRod Evans 	smsk = scapset->oc_hw_2.cm_val;
149008278a5eSRod Evans 	if ((omsk > smsk) || (omsk && (omsk == smsk)))
149108278a5eSRod Evans 		return (1);
149208278a5eSRod Evans 	if (omsk < smsk)
149308278a5eSRod Evans 		return (0);
149408278a5eSRod Evans 
149508278a5eSRod Evans 	/*
149608278a5eSRod Evans 	 * Finally, inspect the remaining hardware capabilities.
149708278a5eSRod Evans 	 */
149808278a5eSRod Evans 	omsk = ocapset->oc_hw_1.cm_val;
149908278a5eSRod Evans 	smsk = scapset->oc_hw_1.cm_val;
150008278a5eSRod Evans 	if ((omsk > smsk) || (omsk && (omsk == smsk)))
150108278a5eSRod Evans 		return (1);
150208278a5eSRod Evans 
150308278a5eSRod Evans 	return (0);
150408278a5eSRod Evans }
150508278a5eSRod Evans 
150608278a5eSRod Evans /*
150708278a5eSRod Evans  * Capabilities values might have been assigned excluded values.  These
150808278a5eSRod Evans  * excluded values should be removed before calculating any capabilities
150908278a5eSRod Evans  * sections size.
151008278a5eSRod Evans  */
151108278a5eSRod Evans static void
151208278a5eSRod Evans capmask_value(Lm_list *lml, Word type, Capmask *capmask, int *title)
151308278a5eSRod Evans {
151408278a5eSRod Evans 	/*
151508278a5eSRod Evans 	 * First determine whether any bits should be excluded.
151608278a5eSRod Evans 	 */
151708278a5eSRod Evans 	if ((capmask->cm_val & capmask->cm_exc) == 0)
151808278a5eSRod Evans 		return;
151908278a5eSRod Evans 
152008278a5eSRod Evans 	DBG_CALL(Dbg_cap_post_title(lml, title));
152108278a5eSRod Evans 
152208278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_CURRENT, type,
152308278a5eSRod Evans 	    capmask->cm_val, ld_targ.t_m.m_mach));
152408278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_EXCLUDE, type,
152508278a5eSRod Evans 	    capmask->cm_exc, ld_targ.t_m.m_mach));
152608278a5eSRod Evans 
152708278a5eSRod Evans 	capmask->cm_val &= ~capmask->cm_exc;
152808278a5eSRod Evans 
152908278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_RESOLVED, type,
153008278a5eSRod Evans 	    capmask->cm_val, ld_targ.t_m.m_mach));
153108278a5eSRod Evans }
153208278a5eSRod Evans 
153308278a5eSRod Evans static void
153408278a5eSRod Evans capstr_value(Lm_list *lml, Word type, Caplist *caplist, int *title)
153508278a5eSRod Evans {
153608278a5eSRod Evans 	Aliste	idx1, idx2;
153708278a5eSRod Evans 	char	*estr;
153808278a5eSRod Evans 	Capstr	*capstr;
153908278a5eSRod Evans 	Boolean	found = FALSE;
154008278a5eSRod Evans 
154108278a5eSRod Evans 	/*
154208278a5eSRod Evans 	 * First determine whether any strings should be excluded.
154308278a5eSRod Evans 	 */
154408278a5eSRod Evans 	for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) {
154508278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
154608278a5eSRod Evans 			if (strcmp(estr, capstr->cs_str) == 0) {
154708278a5eSRod Evans 				found = TRUE;
154808278a5eSRod Evans 				break;
154908278a5eSRod Evans 			}
155008278a5eSRod Evans 		}
155108278a5eSRod Evans 	}
155208278a5eSRod Evans 
155308278a5eSRod Evans 	if (found == FALSE)
155408278a5eSRod Evans 		return;
155508278a5eSRod Evans 
155608278a5eSRod Evans 	/*
155708278a5eSRod Evans 	 * Traverse the current strings, then delete the excluded strings,
155808278a5eSRod Evans 	 * and finally display the resolved strings.
155908278a5eSRod Evans 	 */
156008278a5eSRod Evans 	if (DBG_ENABLED) {
156108278a5eSRod Evans 		Dbg_cap_post_title(lml, title);
156208278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
156308278a5eSRod Evans 			Dbg_cap_ptr_entry(lml, DBG_STATE_CURRENT, type,
156408278a5eSRod Evans 			    capstr->cs_str);
156508278a5eSRod Evans 		}
156608278a5eSRod Evans 	}
156708278a5eSRod Evans 	for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) {
156808278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
156908278a5eSRod Evans 			if (strcmp(estr, capstr->cs_str) == 0) {
157008278a5eSRod Evans 				DBG_CALL(Dbg_cap_ptr_entry(lml,
157108278a5eSRod Evans 				    DBG_STATE_EXCLUDE, type, capstr->cs_str));
157208278a5eSRod Evans 				alist_delete(caplist->cl_val, &idx2);
157308278a5eSRod Evans 				break;
157408278a5eSRod Evans 			}
157508278a5eSRod Evans 		}
157608278a5eSRod Evans 	}
157708278a5eSRod Evans 	if (DBG_ENABLED) {
157808278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
157908278a5eSRod Evans 			Dbg_cap_ptr_entry(lml, DBG_STATE_RESOLVED, type,
158008278a5eSRod Evans 			    capstr->cs_str);
158108278a5eSRod Evans 		}
158208278a5eSRod Evans 	}
158308278a5eSRod Evans }
158408278a5eSRod Evans 
158508278a5eSRod Evans /*
158608278a5eSRod Evans  * Build a capabilities section.
158708278a5eSRod Evans  */
158808278a5eSRod Evans #define	CAP_UPDATE(cap, capndx, tag, val)	\
158908278a5eSRod Evans 	cap->c_tag = tag; \
159008278a5eSRod Evans 	cap->c_un.c_val = val; \
159108278a5eSRod Evans 	cap++, capndx++;
159208278a5eSRod Evans 
159308278a5eSRod Evans static uintptr_t
159408278a5eSRod Evans make_cap(Ofl_desc *ofl, Word shtype, const char *shname, int ident)
159508278a5eSRod Evans {
159608278a5eSRod Evans 	Shdr		*shdr;
159708278a5eSRod Evans 	Elf_Data	*data;
159808278a5eSRod Evans 	Is_desc		*isec;
159908278a5eSRod Evans 	Cap		*cap;
160008278a5eSRod Evans 	size_t		size = 0;
160108278a5eSRod Evans 	Word		capndx = 0;
160208278a5eSRod Evans 	Str_tbl		*strtbl;
160308278a5eSRod Evans 	Objcapset	*ocapset = &ofl->ofl_ocapset;
160408278a5eSRod Evans 	Aliste		idx1;
160508278a5eSRod Evans 	Capstr		*capstr;
160608278a5eSRod Evans 	int		title = 0;
160708278a5eSRod Evans 
160808278a5eSRod Evans 	/*
160908278a5eSRod Evans 	 * Determine which string table to use for any CA_SUNW_MACH,
161008278a5eSRod Evans 	 * CA_SUNW_PLAT, or CA_SUNW_ID strings.
161108278a5eSRod Evans 	 */
161208278a5eSRod Evans 	if (OFL_IS_STATIC_OBJ(ofl))
161308278a5eSRod Evans 		strtbl = ofl->ofl_strtab;
161408278a5eSRod Evans 	else
161508278a5eSRod Evans 		strtbl = ofl->ofl_dynstrtab;
161608278a5eSRod Evans 
161708278a5eSRod Evans 	/*
1618d47ecb8cSRod Evans 	 * If symbol capabilities have been requested, but none have been
1619d47ecb8cSRod Evans 	 * created, warn the user.  This scenario can occur if none of the
1620d47ecb8cSRod Evans 	 * input relocatable objects defined any object capabilities.
1621d47ecb8cSRod Evans 	 */
16221007fd6fSAli Bahrami 	if ((ofl->ofl_flags & FLG_OF_OTOSCAP) && (ofl->ofl_capsymcnt == 0))
16231007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_CAP_NOSYMSFOUND));
1624d47ecb8cSRod Evans 
1625d47ecb8cSRod Evans 	/*
162608278a5eSRod Evans 	 * If symbol capabilities have been collected, but no symbols are left
162708278a5eSRod Evans 	 * referencing these capabilities, promote the capability groups back
162808278a5eSRod Evans 	 * to an object capability definition.
162908278a5eSRod Evans 	 */
163008278a5eSRod Evans 	if ((ofl->ofl_flags & FLG_OF_OTOSCAP) && ofl->ofl_capsymcnt &&
163108278a5eSRod Evans 	    (ofl->ofl_capfamilies == NULL)) {
16321007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_CAP_NOSYMSFOUND));
163308278a5eSRod Evans 		ld_cap_move_symtoobj(ofl);
163408278a5eSRod Evans 		ofl->ofl_capsymcnt = 0;
163508278a5eSRod Evans 		ofl->ofl_capgroups = NULL;
1636f441771bSRod Evans 		ofl->ofl_flags &= ~FLG_OF_OTOSCAP;
163708278a5eSRod Evans 	}
163808278a5eSRod Evans 
163908278a5eSRod Evans 	/*
164008278a5eSRod Evans 	 * Remove any excluded capabilities.
164108278a5eSRod Evans 	 */
164208278a5eSRod Evans 	capstr_value(ofl->ofl_lml, CA_SUNW_PLAT, &ocapset->oc_plat, &title);
164308278a5eSRod Evans 	capstr_value(ofl->ofl_lml, CA_SUNW_MACH, &ocapset->oc_mach, &title);
164408278a5eSRod Evans 	capmask_value(ofl->ofl_lml, CA_SUNW_HW_2, &ocapset->oc_hw_2, &title);
164508278a5eSRod Evans 	capmask_value(ofl->ofl_lml, CA_SUNW_HW_1, &ocapset->oc_hw_1, &title);
164608278a5eSRod Evans 	capmask_value(ofl->ofl_lml, CA_SUNW_SF_1, &ocapset->oc_sf_1, &title);
164708278a5eSRod Evans 
164808278a5eSRod Evans 	/*
164908278a5eSRod Evans 	 * Determine how many entries are required for any object capabilities.
165008278a5eSRod Evans 	 */
165108278a5eSRod Evans 	size += alist_nitems(ocapset->oc_plat.cl_val);
165208278a5eSRod Evans 	size += alist_nitems(ocapset->oc_mach.cl_val);
165308278a5eSRod Evans 	if (ocapset->oc_hw_2.cm_val)
165408278a5eSRod Evans 		size++;
165508278a5eSRod Evans 	if (ocapset->oc_hw_1.cm_val)
165608278a5eSRod Evans 		size++;
165708278a5eSRod Evans 	if (ocapset->oc_sf_1.cm_val)
165808278a5eSRod Evans 		size++;
165908278a5eSRod Evans 
166008278a5eSRod Evans 	/*
166108278a5eSRod Evans 	 * Only identify a capabilities group if the group has content.  If a
166208278a5eSRod Evans 	 * capabilities identifier exists, and no other capabilities have been
166308278a5eSRod Evans 	 * supplied, remove the identifier.  This scenario could exist if a
166408278a5eSRod Evans 	 * user mistakenly defined a lone identifier, or if an identified group
166508278a5eSRod Evans 	 * was overridden so as to clear the existing capabilities and the
166608278a5eSRod Evans 	 * identifier was not also cleared.
166708278a5eSRod Evans 	 */
166808278a5eSRod Evans 	if (ocapset->oc_id.cs_str) {
166908278a5eSRod Evans 		if (size)
167008278a5eSRod Evans 			size++;
167108278a5eSRod Evans 		else
167208278a5eSRod Evans 			ocapset->oc_id.cs_str = NULL;
167308278a5eSRod Evans 	}
167408278a5eSRod Evans 	if (size)
167508278a5eSRod Evans 		size++;			/* Add CA_SUNW_NULL */
167608278a5eSRod Evans 
167708278a5eSRod Evans 	/*
167808278a5eSRod Evans 	 * Determine how many entries are required for any symbol capabilities.
167908278a5eSRod Evans 	 */
168008278a5eSRod Evans 	if (ofl->ofl_capsymcnt) {
168108278a5eSRod Evans 		/*
168208278a5eSRod Evans 		 * If there are no object capabilities, a CA_SUNW_NULL entry
168308278a5eSRod Evans 		 * is required before any symbol capabilities.
168408278a5eSRod Evans 		 */
168508278a5eSRod Evans 		if (size == 0)
168608278a5eSRod Evans 			size++;
168708278a5eSRod Evans 		size += ofl->ofl_capsymcnt;
168808278a5eSRod Evans 	}
168908278a5eSRod Evans 
169008278a5eSRod Evans 	if (size == 0)
169108278a5eSRod Evans 		return (NULL);
169208278a5eSRod Evans 
169308278a5eSRod Evans 	if (new_section(ofl, shtype, shname, size, &isec,
169408278a5eSRod Evans 	    &shdr, &data) == S_ERROR)
16957c478bd9Sstevel@tonic-gate 		return (S_ERROR);
16967c478bd9Sstevel@tonic-gate 
169757ef7aa9SRod Evans 	if ((data->d_buf = libld_malloc(shdr->sh_size)) == NULL)
16987c478bd9Sstevel@tonic-gate 		return (S_ERROR);
16997c478bd9Sstevel@tonic-gate 
17007c478bd9Sstevel@tonic-gate 	cap = (Cap *)data->d_buf;
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate 	/*
170308278a5eSRod Evans 	 * Fill in any object capabilities.  If there is an identifier, then the
170408278a5eSRod Evans 	 * identifier comes first.  The remaining items follow in precedence
170508278a5eSRod Evans 	 * order, although the order isn't important for runtime verification.
17067c478bd9Sstevel@tonic-gate 	 */
170708278a5eSRod Evans 	if (ocapset->oc_id.cs_str) {
170808278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_CAPSTRS;
170908278a5eSRod Evans 		if (st_insert(strtbl, ocapset->oc_id.cs_str) == -1)
171008278a5eSRod Evans 			return (S_ERROR);
171108278a5eSRod Evans 		ocapset->oc_id.cs_ndx = capndx;
171208278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0);
17137c478bd9Sstevel@tonic-gate 	}
171408278a5eSRod Evans 	if (ocapset->oc_plat.cl_val) {
171508278a5eSRod Evans 		ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS);
171608278a5eSRod Evans 
171708278a5eSRod Evans 		/*
171808278a5eSRod Evans 		 * Insert any platform name strings in the appropriate string
171908278a5eSRod Evans 		 * table.  The capability value can't be filled in yet, as the
172008278a5eSRod Evans 		 * final offset of the strings isn't known until later.
172108278a5eSRod Evans 		 */
172208278a5eSRod Evans 		for (ALIST_TRAVERSE(ocapset->oc_plat.cl_val, idx1, capstr)) {
172308278a5eSRod Evans 			if (st_insert(strtbl, capstr->cs_str) == -1)
172408278a5eSRod Evans 				return (S_ERROR);
172508278a5eSRod Evans 			capstr->cs_ndx = capndx;
172608278a5eSRod Evans 			CAP_UPDATE(cap, capndx, CA_SUNW_PLAT, 0);
172708278a5eSRod Evans 		}
172808278a5eSRod Evans 	}
172908278a5eSRod Evans 	if (ocapset->oc_mach.cl_val) {
173008278a5eSRod Evans 		ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS);
173108278a5eSRod Evans 
173208278a5eSRod Evans 		/*
173308278a5eSRod Evans 		 * Insert the machine name strings in the appropriate string
173408278a5eSRod Evans 		 * table.  The capability value can't be filled in yet, as the
173508278a5eSRod Evans 		 * final offset of the strings isn't known until later.
173608278a5eSRod Evans 		 */
173708278a5eSRod Evans 		for (ALIST_TRAVERSE(ocapset->oc_mach.cl_val, idx1, capstr)) {
173808278a5eSRod Evans 			if (st_insert(strtbl, capstr->cs_str) == -1)
173908278a5eSRod Evans 				return (S_ERROR);
174008278a5eSRod Evans 			capstr->cs_ndx = capndx;
174108278a5eSRod Evans 			CAP_UPDATE(cap, capndx, CA_SUNW_MACH, 0);
174208278a5eSRod Evans 		}
174308278a5eSRod Evans 	}
174408278a5eSRod Evans 	if (ocapset->oc_hw_2.cm_val) {
174508278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_PTCAP;
174608278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_HW_2, ocapset->oc_hw_2.cm_val);
174708278a5eSRod Evans 	}
174808278a5eSRod Evans 	if (ocapset->oc_hw_1.cm_val) {
174908278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_PTCAP;
175008278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_HW_1, ocapset->oc_hw_1.cm_val);
175108278a5eSRod Evans 	}
175208278a5eSRod Evans 	if (ocapset->oc_sf_1.cm_val) {
175308278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_PTCAP;
175408278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_SF_1, ocapset->oc_sf_1.cm_val);
175508278a5eSRod Evans 	}
175608278a5eSRod Evans 	CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0);
175708278a5eSRod Evans 
175808278a5eSRod Evans 	/*
175908278a5eSRod Evans 	 * Fill in any symbol capabilities.
176008278a5eSRod Evans 	 */
176108278a5eSRod Evans 	if (ofl->ofl_capgroups) {
176208278a5eSRod Evans 		Cap_group	*cgp;
176308278a5eSRod Evans 
176408278a5eSRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) {
176508278a5eSRod Evans 			Objcapset	*scapset = &cgp->cg_set;
176608278a5eSRod Evans 			Aliste		idx2;
176708278a5eSRod Evans 			Is_desc		*isp;
176808278a5eSRod Evans 
176908278a5eSRod Evans 			cgp->cg_ndx = capndx;
177008278a5eSRod Evans 
177108278a5eSRod Evans 			if (scapset->oc_id.cs_str) {
177208278a5eSRod Evans 				ofl->ofl_flags |= FLG_OF_CAPSTRS;
177308278a5eSRod Evans 				/*
177408278a5eSRod Evans 				 * Insert the identifier string in the
177508278a5eSRod Evans 				 * appropriate string table.  The capability
177608278a5eSRod Evans 				 * value can't be filled in yet, as the final
177708278a5eSRod Evans 				 * offset of the string isn't known until later.
177808278a5eSRod Evans 				 */
177908278a5eSRod Evans 				if (st_insert(strtbl,
178008278a5eSRod Evans 				    scapset->oc_id.cs_str) == -1)
178108278a5eSRod Evans 					return (S_ERROR);
178208278a5eSRod Evans 				scapset->oc_id.cs_ndx = capndx;
178308278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0);
178408278a5eSRod Evans 			}
178508278a5eSRod Evans 
178608278a5eSRod Evans 			if (scapset->oc_plat.cl_val) {
178708278a5eSRod Evans 				ofl->ofl_flags |= FLG_OF_CAPSTRS;
178808278a5eSRod Evans 
178908278a5eSRod Evans 				/*
179008278a5eSRod Evans 				 * Insert the platform name string in the
179108278a5eSRod Evans 				 * appropriate string table.  The capability
179208278a5eSRod Evans 				 * value can't be filled in yet, as the final
179308278a5eSRod Evans 				 * offset of the string isn't known until later.
179408278a5eSRod Evans 				 */
179508278a5eSRod Evans 				for (ALIST_TRAVERSE(scapset->oc_plat.cl_val,
179608278a5eSRod Evans 				    idx2, capstr)) {
179708278a5eSRod Evans 					if (st_insert(strtbl,
179808278a5eSRod Evans 					    capstr->cs_str) == -1)
179908278a5eSRod Evans 						return (S_ERROR);
180008278a5eSRod Evans 					capstr->cs_ndx = capndx;
180108278a5eSRod Evans 					CAP_UPDATE(cap, capndx,
180208278a5eSRod Evans 					    CA_SUNW_PLAT, 0);
180308278a5eSRod Evans 				}
180408278a5eSRod Evans 			}
180508278a5eSRod Evans 			if (scapset->oc_mach.cl_val) {
180608278a5eSRod Evans 				ofl->ofl_flags |= FLG_OF_CAPSTRS;
180708278a5eSRod Evans 
180808278a5eSRod Evans 				/*
180908278a5eSRod Evans 				 * Insert the machine name string in the
181008278a5eSRod Evans 				 * appropriate string table.  The capability
181108278a5eSRod Evans 				 * value can't be filled in yet, as the final
181208278a5eSRod Evans 				 * offset of the string isn't known until later.
181308278a5eSRod Evans 				 */
181408278a5eSRod Evans 				for (ALIST_TRAVERSE(scapset->oc_mach.cl_val,
181508278a5eSRod Evans 				    idx2, capstr)) {
181608278a5eSRod Evans 					if (st_insert(strtbl,
181708278a5eSRod Evans 					    capstr->cs_str) == -1)
181808278a5eSRod Evans 						return (S_ERROR);
181908278a5eSRod Evans 					capstr->cs_ndx = capndx;
182008278a5eSRod Evans 					CAP_UPDATE(cap, capndx,
182108278a5eSRod Evans 					    CA_SUNW_MACH, 0);
182208278a5eSRod Evans 				}
182308278a5eSRod Evans 			}
182408278a5eSRod Evans 			if (scapset->oc_hw_2.cm_val) {
182508278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_HW_2,
182608278a5eSRod Evans 				    scapset->oc_hw_2.cm_val);
182708278a5eSRod Evans 			}
182808278a5eSRod Evans 			if (scapset->oc_hw_1.cm_val) {
182908278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_HW_1,
183008278a5eSRod Evans 				    scapset->oc_hw_1.cm_val);
183108278a5eSRod Evans 			}
183208278a5eSRod Evans 			if (scapset->oc_sf_1.cm_val) {
183308278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_SF_1,
183408278a5eSRod Evans 				    scapset->oc_sf_1.cm_val);
183508278a5eSRod Evans 			}
183608278a5eSRod Evans 			CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0);
183708278a5eSRod Evans 
183808278a5eSRod Evans 			/*
183908278a5eSRod Evans 			 * If any object capabilities are available, determine
184008278a5eSRod Evans 			 * whether these symbol capabilities are less
184108278a5eSRod Evans 			 * restrictive, and hence redundant.
184208278a5eSRod Evans 			 */
184308278a5eSRod Evans 			if (((ofl->ofl_flags & FLG_OF_PTCAP) == 0) ||
184408278a5eSRod Evans 			    (is_cap_redundant(ocapset, scapset) == 0))
184508278a5eSRod Evans 				continue;
184608278a5eSRod Evans 
184708278a5eSRod Evans 			/*
184808278a5eSRod Evans 			 * Indicate any files that provide redundant symbol
184908278a5eSRod Evans 			 * capabilities.
185008278a5eSRod Evans 			 */
185108278a5eSRod Evans 			for (APLIST_TRAVERSE(cgp->cg_secs, idx2, isp)) {
18521007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
185308278a5eSRod Evans 				    MSG_INTL(MSG_CAP_REDUNDANT),
185408278a5eSRod Evans 				    isp->is_file->ifl_name,
185508278a5eSRod Evans 				    EC_WORD(isp->is_scnndx), isp->is_name);
185608278a5eSRod Evans 			}
185708278a5eSRod Evans 		}
185808278a5eSRod Evans 	}
185908278a5eSRod Evans 
186008278a5eSRod Evans 	/*
186108278a5eSRod Evans 	 * If capabilities strings are required, the sh_info field of the
186208278a5eSRod Evans 	 * section header will be set to the associated string table.
186308278a5eSRod Evans 	 */
186408278a5eSRod Evans 	if (ofl->ofl_flags & FLG_OF_CAPSTRS)
186508278a5eSRod Evans 		shdr->sh_flags |= SHF_INFO_LINK;
186608278a5eSRod Evans 
186708278a5eSRod Evans 	/*
186808278a5eSRod Evans 	 * Place these capabilities in the output file.
186908278a5eSRod Evans 	 */
187008278a5eSRod Evans 	if ((ofl->ofl_oscap = ld_place_section(ofl, isec,
187108278a5eSRod Evans 	    NULL, ident, NULL)) == (Os_desc *)S_ERROR)
187208278a5eSRod Evans 		return (S_ERROR);
187308278a5eSRod Evans 
187408278a5eSRod Evans 	/*
187508278a5eSRod Evans 	 * If symbol capabilities are required, then a .SUNW_capinfo section is
187608278a5eSRod Evans 	 * also created.  This table will eventually be sized to match the
187708278a5eSRod Evans 	 * associated symbol table.
187808278a5eSRod Evans 	 */
187908278a5eSRod Evans 	if (ofl->ofl_capfamilies) {
188008278a5eSRod Evans 		if ((ofl->ofl_oscapinfo = make_sym_sec(ofl,
188108278a5eSRod Evans 		    MSG_ORIG(MSG_SCN_SUNWCAPINFO), SHT_SUNW_capinfo,
188208278a5eSRod Evans 		    ld_targ.t_id.id_capinfo)) == (Os_desc *)S_ERROR)
188308278a5eSRod Evans 			return (S_ERROR);
188408278a5eSRod Evans 
188508278a5eSRod Evans 		/*
188608278a5eSRod Evans 		 * If we're generating a dynamic object, capabilities family
188708278a5eSRod Evans 		 * members are maintained in a .SUNW_capchain section.
188808278a5eSRod Evans 		 */
188908278a5eSRod Evans 		if (ofl->ofl_capchaincnt &&
189008278a5eSRod Evans 		    ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) {
189108278a5eSRod Evans 			if (new_section(ofl, SHT_SUNW_capchain,
189208278a5eSRod Evans 			    MSG_ORIG(MSG_SCN_SUNWCAPCHAIN),
189308278a5eSRod Evans 			    ofl->ofl_capchaincnt, &isec, &shdr,
189408278a5eSRod Evans 			    &data) == S_ERROR)
189508278a5eSRod Evans 				return (S_ERROR);
189608278a5eSRod Evans 
189708278a5eSRod Evans 			ofl->ofl_oscapchain = ld_place_section(ofl, isec,
189808278a5eSRod Evans 			    NULL, ld_targ.t_id.id_capchain, NULL);
189908278a5eSRod Evans 			if (ofl->ofl_oscapchain == (Os_desc *)S_ERROR)
190008278a5eSRod Evans 				return (S_ERROR);
190108278a5eSRod Evans 
190208278a5eSRod Evans 		}
190308278a5eSRod Evans 	}
190408278a5eSRod Evans 	return (1);
190508278a5eSRod Evans }
190608278a5eSRod Evans #undef	CAP_UPDATE
19077c478bd9Sstevel@tonic-gate 
19087c478bd9Sstevel@tonic-gate /*
19097c478bd9Sstevel@tonic-gate  * Build the PLT section and its associated relocation entries.
19107c478bd9Sstevel@tonic-gate  */
19115aefb655Srie static uintptr_t
19127c478bd9Sstevel@tonic-gate make_plt(Ofl_desc *ofl)
19137c478bd9Sstevel@tonic-gate {
19147c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
19157c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
19167c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
1917ba2be530Sab196087 	size_t		size = ld_targ.t_m.m_plt_reservsz +
191860758829Srie 	    (((size_t)ofl->ofl_pltcnt + (size_t)ofl->ofl_pltpad) *
1919ba2be530Sab196087 	    ld_targ.t_m.m_plt_entsize);
19207c478bd9Sstevel@tonic-gate 	size_t		rsize = (size_t)ofl->ofl_relocpltsz;
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate 	/*
1923ba2be530Sab196087 	 * On sparc, account for the NOP at the end of the plt.
19247c478bd9Sstevel@tonic-gate 	 */
1925ba2be530Sab196087 	if (ld_targ.t_m.m_mach == LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
19267c478bd9Sstevel@tonic-gate 		size += sizeof (Word);
19277c478bd9Sstevel@tonic-gate 
19289039eeafSab196087 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_PLT), 0,
19299039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
19307c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19319039eeafSab196087 
19327c478bd9Sstevel@tonic-gate 	data->d_size = size;
1933ba2be530Sab196087 	data->d_align = ld_targ.t_m.m_plt_align;
19347c478bd9Sstevel@tonic-gate 
1935ba2be530Sab196087 	shdr->sh_flags = ld_targ.t_m.m_plt_shf_flags;
19367c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
1937ba2be530Sab196087 	shdr->sh_addralign = ld_targ.t_m.m_plt_align;
1938ba2be530Sab196087 	shdr->sh_entsize = ld_targ.t_m.m_plt_entsize;
19397c478bd9Sstevel@tonic-gate 
194069112eddSAli Bahrami 	ofl->ofl_osplt = ld_place_section(ofl, isec, NULL,
194169112eddSAli Bahrami 	    ld_targ.t_id.id_plt, NULL);
1942ba2be530Sab196087 	if (ofl->ofl_osplt == (Os_desc *)S_ERROR)
19437c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19447c478bd9Sstevel@tonic-gate 
19457c478bd9Sstevel@tonic-gate 	ofl->ofl_osplt->os_szoutrels = (Xword)rsize;
19467c478bd9Sstevel@tonic-gate 
19477c478bd9Sstevel@tonic-gate 	return (1);
19487c478bd9Sstevel@tonic-gate }
19497c478bd9Sstevel@tonic-gate 
19507c478bd9Sstevel@tonic-gate /*
19517c478bd9Sstevel@tonic-gate  * Make the hash table.  Only built for dynamic executables and shared
19527c478bd9Sstevel@tonic-gate  * libraries, and provides hashed lookup into the global symbol table
19537c478bd9Sstevel@tonic-gate  * (.dynsym) for the run-time linker to resolve symbol lookups.
19547c478bd9Sstevel@tonic-gate  */
19555aefb655Srie static uintptr_t
19567c478bd9Sstevel@tonic-gate make_hash(Ofl_desc *ofl)
19577c478bd9Sstevel@tonic-gate {
19587c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
19597c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
19607c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
19617c478bd9Sstevel@tonic-gate 	size_t		size;
19627c478bd9Sstevel@tonic-gate 	Word		nsyms = ofl->ofl_globcnt;
19637c478bd9Sstevel@tonic-gate 	size_t		cnt;
19647c478bd9Sstevel@tonic-gate 
19657c478bd9Sstevel@tonic-gate 	/*
19669039eeafSab196087 	 * Allocate section header structures. We set entcnt to 0
19679039eeafSab196087 	 * because it's going to change after we place this section.
19687c478bd9Sstevel@tonic-gate 	 */
19699039eeafSab196087 	if (new_section(ofl, SHT_HASH, MSG_ORIG(MSG_SCN_HASH), 0,
19709039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
19717c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate 	/*
19747c478bd9Sstevel@tonic-gate 	 * Place the section first since it will affect the local symbol
19757c478bd9Sstevel@tonic-gate 	 * count.
19767c478bd9Sstevel@tonic-gate 	 */
19771dd9d86fSAli Bahrami 	ofl->ofl_oshash =
197869112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_hash, NULL);
1979ba2be530Sab196087 	if (ofl->ofl_oshash == (Os_desc *)S_ERROR)
19807c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate 	/*
19837c478bd9Sstevel@tonic-gate 	 * Calculate the number of output hash buckets.
19847c478bd9Sstevel@tonic-gate 	 */
19857c478bd9Sstevel@tonic-gate 	ofl->ofl_hashbkts = findprime(nsyms);
19867c478bd9Sstevel@tonic-gate 
19877c478bd9Sstevel@tonic-gate 	/*
19887c478bd9Sstevel@tonic-gate 	 * The size of the hash table is determined by
19897c478bd9Sstevel@tonic-gate 	 *
19907c478bd9Sstevel@tonic-gate 	 *	i.	the initial nbucket and nchain entries (2)
19917c478bd9Sstevel@tonic-gate 	 *	ii.	the number of buckets (calculated above)
19927c478bd9Sstevel@tonic-gate 	 *	iii.	the number of chains (this is based on the number of
1993635216b6SRod Evans 	 *		symbols in the .dynsym array).
19947c478bd9Sstevel@tonic-gate 	 */
1995635216b6SRod Evans 	cnt = 2 + ofl->ofl_hashbkts + DYNSYM_ALL_CNT(ofl);
19967c478bd9Sstevel@tonic-gate 	size = cnt * shdr->sh_entsize;
19977c478bd9Sstevel@tonic-gate 
19987c478bd9Sstevel@tonic-gate 	/*
19997c478bd9Sstevel@tonic-gate 	 * Finalize the section header and data buffer initialization.
20007c478bd9Sstevel@tonic-gate 	 */
200157ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(size, 1)) == NULL)
20027c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20037c478bd9Sstevel@tonic-gate 	data->d_size = size;
20047c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
20057c478bd9Sstevel@tonic-gate 
20067c478bd9Sstevel@tonic-gate 	return (1);
20077c478bd9Sstevel@tonic-gate }
20087c478bd9Sstevel@tonic-gate 
20097c478bd9Sstevel@tonic-gate /*
20107c478bd9Sstevel@tonic-gate  * Generate the standard symbol table.  Contains all locals and globals,
20117c478bd9Sstevel@tonic-gate  * and resides in a non-allocatable section (ie. it can be stripped).
20127c478bd9Sstevel@tonic-gate  */
20135aefb655Srie static uintptr_t
20147c478bd9Sstevel@tonic-gate make_symtab(Ofl_desc *ofl)
20157c478bd9Sstevel@tonic-gate {
20167c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
20177c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
20187c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
20197c478bd9Sstevel@tonic-gate 	Is_desc		*xisec = 0;
20207c478bd9Sstevel@tonic-gate 	size_t		size;
20217c478bd9Sstevel@tonic-gate 	Word		symcnt;
20227c478bd9Sstevel@tonic-gate 
20237c478bd9Sstevel@tonic-gate 	/*
20249039eeafSab196087 	 * Create the section headers. Note that we supply an ent_cnt
20259039eeafSab196087 	 * of 0. We won't know the count until the section has been placed.
20267c478bd9Sstevel@tonic-gate 	 */
20279039eeafSab196087 	if (new_section(ofl, SHT_SYMTAB, MSG_ORIG(MSG_SCN_SYMTAB), 0,
20289039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
20297c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20307c478bd9Sstevel@tonic-gate 
20317c478bd9Sstevel@tonic-gate 	/*
20327c478bd9Sstevel@tonic-gate 	 * Place the section first since it will affect the local symbol
20337c478bd9Sstevel@tonic-gate 	 * count.
20347c478bd9Sstevel@tonic-gate 	 */
203569112eddSAli Bahrami 	if ((ofl->ofl_ossymtab = ld_place_section(ofl, isec, NULL,
2036635216b6SRod Evans 	    ld_targ.t_id.id_symtab, NULL)) == (Os_desc *)S_ERROR)
20377c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20387c478bd9Sstevel@tonic-gate 
20397c478bd9Sstevel@tonic-gate 	/*
20407c478bd9Sstevel@tonic-gate 	 * At this point we've created all but the 'shstrtab' section.
20417c478bd9Sstevel@tonic-gate 	 * Determine if we have to use 'Extended Sections'.  If so - then
20427c478bd9Sstevel@tonic-gate 	 * also create a SHT_SYMTAB_SHNDX section.
20437c478bd9Sstevel@tonic-gate 	 */
20447c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_shdrcnt + 1) >= SHN_LORESERVE) {
20457c478bd9Sstevel@tonic-gate 		Shdr		*xshdr;
20467c478bd9Sstevel@tonic-gate 		Elf_Data	*xdata;
20477c478bd9Sstevel@tonic-gate 
20489039eeafSab196087 		if (new_section(ofl, SHT_SYMTAB_SHNDX,
20499039eeafSab196087 		    MSG_ORIG(MSG_SCN_SYMTAB_SHNDX), 0, &xisec,
20509039eeafSab196087 		    &xshdr, &xdata) == S_ERROR)
20517c478bd9Sstevel@tonic-gate 			return (S_ERROR);
20529039eeafSab196087 
205369112eddSAli Bahrami 		if ((ofl->ofl_ossymshndx = ld_place_section(ofl, xisec, NULL,
20541dd9d86fSAli Bahrami 		    ld_targ.t_id.id_symtab_ndx, NULL)) == (Os_desc *)S_ERROR)
20557c478bd9Sstevel@tonic-gate 			return (S_ERROR);
20567c478bd9Sstevel@tonic-gate 	}
20570e233487SRod Evans 
20587c478bd9Sstevel@tonic-gate 	/*
20597c478bd9Sstevel@tonic-gate 	 * Calculated number of symbols, which need to be augmented by
2060635216b6SRod Evans 	 * the (yet to be created) .shstrtab entry.
20617c478bd9Sstevel@tonic-gate 	 */
2062635216b6SRod Evans 	symcnt = (size_t)(1 + SYMTAB_ALL_CNT(ofl));
20637c478bd9Sstevel@tonic-gate 	size = symcnt * shdr->sh_entsize;
20647c478bd9Sstevel@tonic-gate 
20657c478bd9Sstevel@tonic-gate 	/*
20667c478bd9Sstevel@tonic-gate 	 * Finalize the section header and data buffer initialization.
20677c478bd9Sstevel@tonic-gate 	 */
20687c478bd9Sstevel@tonic-gate 	data->d_size = size;
20697c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
20707c478bd9Sstevel@tonic-gate 
20717c478bd9Sstevel@tonic-gate 	/*
20727c478bd9Sstevel@tonic-gate 	 * If we created a SHT_SYMTAB_SHNDX - then set it's sizes too.
20737c478bd9Sstevel@tonic-gate 	 */
20747c478bd9Sstevel@tonic-gate 	if (xisec) {
20757c478bd9Sstevel@tonic-gate 		size_t	xsize = symcnt * sizeof (Word);
20767c478bd9Sstevel@tonic-gate 
20777c478bd9Sstevel@tonic-gate 		xisec->is_indata->d_size = xsize;
20787c478bd9Sstevel@tonic-gate 		xisec->is_shdr->sh_size = (Xword)xsize;
20797c478bd9Sstevel@tonic-gate 	}
20807c478bd9Sstevel@tonic-gate 
20817c478bd9Sstevel@tonic-gate 	return (1);
20827c478bd9Sstevel@tonic-gate }
20837c478bd9Sstevel@tonic-gate 
20847c478bd9Sstevel@tonic-gate /*
2085d579eb63Sab196087  * Build a dynamic symbol table. These tables reside in the text
2086d579eb63Sab196087  * segment of a dynamic executable or shared library.
2087d579eb63Sab196087  *
2088d579eb63Sab196087  *	.SUNW_ldynsym contains local function symbols
2089d579eb63Sab196087  *	.dynsym contains only globals symbols
2090d579eb63Sab196087  *
2091d579eb63Sab196087  * The two tables are created adjacent to each other, with .SUNW_ldynsym
2092d579eb63Sab196087  * coming first.
20937c478bd9Sstevel@tonic-gate  */
20945aefb655Srie static uintptr_t
20957c478bd9Sstevel@tonic-gate make_dynsym(Ofl_desc *ofl)
20967c478bd9Sstevel@tonic-gate {
20979039eeafSab196087 	Shdr		*shdr, *lshdr;
20989039eeafSab196087 	Elf_Data	*data, *ldata;
20999039eeafSab196087 	Is_desc		*isec, *lisec;
21007c478bd9Sstevel@tonic-gate 	size_t		size;
21017c478bd9Sstevel@tonic-gate 	Xword		cnt;
2102d579eb63Sab196087 	int		allow_ldynsym;
21039039eeafSab196087 
2104d579eb63Sab196087 	/*
2105d579eb63Sab196087 	 * Unless explicitly disabled, always produce a .SUNW_ldynsym section
2106d579eb63Sab196087 	 * when it is allowed by the file type, even if the resulting
2107d579eb63Sab196087 	 * table only ends up with a single STT_FILE in it. There are
2108d579eb63Sab196087 	 * two reasons: (1) It causes the generation of the DT_SUNW_SYMTAB
2109d579eb63Sab196087 	 * entry in the .dynamic section, which is something we would
2110d579eb63Sab196087 	 * like to encourage, and (2) Without it, we cannot generate
2111d579eb63Sab196087 	 * the associated .SUNW_dyn[sym|tls]sort sections, which are of
2112d579eb63Sab196087 	 * value to DTrace.
2113d579eb63Sab196087 	 *
2114d579eb63Sab196087 	 * In practice, it is extremely rare for an object not to have
2115d579eb63Sab196087 	 * local symbols for .SUNW_ldynsym, so 99% of the time, we'd be
2116d579eb63Sab196087 	 * doing it anyway.
2117d579eb63Sab196087 	 */
2118d579eb63Sab196087 	allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
21197c478bd9Sstevel@tonic-gate 
21207c478bd9Sstevel@tonic-gate 	/*
21219039eeafSab196087 	 * Create the section headers. Note that we supply an ent_cnt
21229039eeafSab196087 	 * of 0. We won't know the count until the section has been placed.
21237c478bd9Sstevel@tonic-gate 	 */
2124d579eb63Sab196087 	if (allow_ldynsym && new_section(ofl, SHT_SUNW_LDYNSYM,
21259039eeafSab196087 	    MSG_ORIG(MSG_SCN_LDYNSYM), 0, &lisec, &lshdr, &ldata) == S_ERROR)
21267c478bd9Sstevel@tonic-gate 		return (S_ERROR);
21279039eeafSab196087 
21289039eeafSab196087 	if (new_section(ofl, SHT_DYNSYM, MSG_ORIG(MSG_SCN_DYNSYM), 0,
21299039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
21309039eeafSab196087 		return (S_ERROR);
21317c478bd9Sstevel@tonic-gate 
21327c478bd9Sstevel@tonic-gate 	/*
21339039eeafSab196087 	 * Place the section(s) first since it will affect the local symbol
21347c478bd9Sstevel@tonic-gate 	 * count.
21357c478bd9Sstevel@tonic-gate 	 */
2136d579eb63Sab196087 	if (allow_ldynsym &&
213769112eddSAli Bahrami 	    ((ofl->ofl_osldynsym = ld_place_section(ofl, lisec, NULL,
21381dd9d86fSAli Bahrami 	    ld_targ.t_id.id_ldynsym, NULL)) == (Os_desc *)S_ERROR))
21399039eeafSab196087 		return (S_ERROR);
2140ba2be530Sab196087 	ofl->ofl_osdynsym =
214169112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynsym, NULL);
2142ba2be530Sab196087 	if (ofl->ofl_osdynsym == (Os_desc *)S_ERROR)
21437c478bd9Sstevel@tonic-gate 		return (S_ERROR);
21447c478bd9Sstevel@tonic-gate 
2145635216b6SRod Evans 	cnt = DYNSYM_ALL_CNT(ofl);
21467c478bd9Sstevel@tonic-gate 	size = (size_t)cnt * shdr->sh_entsize;
21477c478bd9Sstevel@tonic-gate 
21487c478bd9Sstevel@tonic-gate 	/*
21497c478bd9Sstevel@tonic-gate 	 * Finalize the section header and data buffer initialization.
21507c478bd9Sstevel@tonic-gate 	 */
21517c478bd9Sstevel@tonic-gate 	data->d_size = size;
21527c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
21537c478bd9Sstevel@tonic-gate 
21549039eeafSab196087 	/*
21559039eeafSab196087 	 * An ldynsym contains local function symbols. It is not
21569039eeafSab196087 	 * used for linking, but if present, serves to allow better
21579039eeafSab196087 	 * stack traces to be generated in contexts where the symtab
21589039eeafSab196087 	 * is not available. (dladdr(), or stripped executable/library files).
21599039eeafSab196087 	 */
2160d579eb63Sab196087 	if (allow_ldynsym) {
21619039eeafSab196087 		cnt = 1 + ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt;
21629039eeafSab196087 		size = (size_t)cnt * shdr->sh_entsize;
21639039eeafSab196087 
21649039eeafSab196087 		ldata->d_size = size;
21659039eeafSab196087 		lshdr->sh_size = (Xword)size;
21669039eeafSab196087 	}
21679039eeafSab196087 
21687c478bd9Sstevel@tonic-gate 	return (1);
21697c478bd9Sstevel@tonic-gate }
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate /*
2172d579eb63Sab196087  * Build .SUNW_dynsymsort and/or .SUNW_dyntlssort sections. These are
2173d579eb63Sab196087  * index sections for the .SUNW_ldynsym/.dynsym pair that present data
2174d579eb63Sab196087  * and function symbols sorted by address.
2175d579eb63Sab196087  */
2176d579eb63Sab196087 static uintptr_t
2177d579eb63Sab196087 make_dynsort(Ofl_desc *ofl)
2178d579eb63Sab196087 {
2179d579eb63Sab196087 	Shdr		*shdr;
2180d579eb63Sab196087 	Elf_Data	*data;
2181d579eb63Sab196087 	Is_desc		*isec;
2182d579eb63Sab196087 
2183d579eb63Sab196087 	/* Only do it if the .SUNW_ldynsym section is present */
2184d579eb63Sab196087 	if (!OFL_ALLOW_LDYNSYM(ofl))
2185d579eb63Sab196087 		return (1);
2186d579eb63Sab196087 
2187d579eb63Sab196087 	/* .SUNW_dynsymsort */
2188d579eb63Sab196087 	if (ofl->ofl_dynsymsortcnt > 0) {
2189d579eb63Sab196087 		if (new_section(ofl, SHT_SUNW_symsort,
2190d579eb63Sab196087 		    MSG_ORIG(MSG_SCN_DYNSYMSORT), ofl->ofl_dynsymsortcnt,
2191d579eb63Sab196087 		    &isec, &shdr, &data) == S_ERROR)
2192d579eb63Sab196087 		return (S_ERROR);
2193d579eb63Sab196087 
219469112eddSAli Bahrami 		if ((ofl->ofl_osdynsymsort = ld_place_section(ofl, isec, NULL,
21951dd9d86fSAli Bahrami 		    ld_targ.t_id.id_dynsort, NULL)) == (Os_desc *)S_ERROR)
2196d579eb63Sab196087 			return (S_ERROR);
2197d579eb63Sab196087 	}
2198d579eb63Sab196087 
2199d579eb63Sab196087 	/* .SUNW_dyntlssort */
2200d579eb63Sab196087 	if (ofl->ofl_dyntlssortcnt > 0) {
2201d579eb63Sab196087 		if (new_section(ofl, SHT_SUNW_tlssort,
2202d579eb63Sab196087 		    MSG_ORIG(MSG_SCN_DYNTLSSORT),
2203d579eb63Sab196087 		    ofl->ofl_dyntlssortcnt, &isec, &shdr, &data) == S_ERROR)
2204d579eb63Sab196087 		return (S_ERROR);
2205d579eb63Sab196087 
220669112eddSAli Bahrami 		if ((ofl->ofl_osdyntlssort = ld_place_section(ofl, isec, NULL,
22071dd9d86fSAli Bahrami 		    ld_targ.t_id.id_dynsort, NULL)) == (Os_desc *)S_ERROR)
2208d579eb63Sab196087 			return (S_ERROR);
2209d579eb63Sab196087 	}
2210d579eb63Sab196087 
2211d579eb63Sab196087 	return (1);
2212d579eb63Sab196087 }
2213d579eb63Sab196087 
2214d579eb63Sab196087 /*
22159039eeafSab196087  * Helper routine for make_dynsym_shndx. Builds a
2216d579eb63Sab196087  * a SHT_SYMTAB_SHNDX for .dynsym or .SUNW_ldynsym, without knowing
22179039eeafSab196087  * which one it is.
22187c478bd9Sstevel@tonic-gate  */
22195aefb655Srie static uintptr_t
22209039eeafSab196087 make_dyn_shndx(Ofl_desc *ofl, const char *shname, Os_desc *symtab,
22219039eeafSab196087     Os_desc **ret_os)
22227c478bd9Sstevel@tonic-gate {
22237c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
22247c478bd9Sstevel@tonic-gate 	Is_desc		*dynsymisp;
22257c478bd9Sstevel@tonic-gate 	Shdr		*shdr, *dynshdr;
22267c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
22277c478bd9Sstevel@tonic-gate 
22281dd9d86fSAli Bahrami 	dynsymisp = ld_os_first_isdesc(symtab);
22299039eeafSab196087 	dynshdr = dynsymisp->is_shdr;
22307c478bd9Sstevel@tonic-gate 
22319039eeafSab196087 	if (new_section(ofl, SHT_SYMTAB_SHNDX, shname,
22329039eeafSab196087 	    (dynshdr->sh_size / dynshdr->sh_entsize),
22339039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
22347c478bd9Sstevel@tonic-gate 		return (S_ERROR);
22357c478bd9Sstevel@tonic-gate 
223669112eddSAli Bahrami 	if ((*ret_os = ld_place_section(ofl, isec, NULL,
22371dd9d86fSAli Bahrami 	    ld_targ.t_id.id_dynsym_ndx, NULL)) == (Os_desc *)S_ERROR)
22387c478bd9Sstevel@tonic-gate 		return (S_ERROR);
22397c478bd9Sstevel@tonic-gate 
22409039eeafSab196087 	assert(*ret_os);
22419039eeafSab196087 
22429039eeafSab196087 	return (1);
22439039eeafSab196087 }
22449039eeafSab196087 
22459039eeafSab196087 /*
22469039eeafSab196087  * Build a SHT_SYMTAB_SHNDX for the .dynsym, and .SUNW_ldynsym
22479039eeafSab196087  */
22489039eeafSab196087 static uintptr_t
22499039eeafSab196087 make_dynsym_shndx(Ofl_desc *ofl)
22509039eeafSab196087 {
22519039eeafSab196087 	/*
2252d579eb63Sab196087 	 * If there is a .SUNW_ldynsym, generate a section for its extended
22539039eeafSab196087 	 * index section as well.
22549039eeafSab196087 	 */
2255d579eb63Sab196087 	if (OFL_ALLOW_LDYNSYM(ofl)) {
22569039eeafSab196087 		if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_LDYNSYM_SHNDX),
22579039eeafSab196087 		    ofl->ofl_osldynsym, &ofl->ofl_osldynshndx) == S_ERROR)
22589039eeafSab196087 			return (S_ERROR);
22599039eeafSab196087 	}
22609039eeafSab196087 
22619039eeafSab196087 	/* The Generate a section for the dynsym */
22629039eeafSab196087 	if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_DYNSYM_SHNDX),
22639039eeafSab196087 	    ofl->ofl_osdynsym, &ofl->ofl_osdynshndx) == S_ERROR)
22649039eeafSab196087 		return (S_ERROR);
22657c478bd9Sstevel@tonic-gate 
22667c478bd9Sstevel@tonic-gate 	return (1);
22677c478bd9Sstevel@tonic-gate }
22687c478bd9Sstevel@tonic-gate 
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate /*
22717c478bd9Sstevel@tonic-gate  * Build a string table for the section headers.
22727c478bd9Sstevel@tonic-gate  */
22735aefb655Srie static uintptr_t
22747c478bd9Sstevel@tonic-gate make_shstrtab(Ofl_desc *ofl)
22757c478bd9Sstevel@tonic-gate {
22767c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
22777c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
22787c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
22797c478bd9Sstevel@tonic-gate 	size_t		size;
22807c478bd9Sstevel@tonic-gate 
22819039eeafSab196087 	if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_SHSTRTAB),
22829039eeafSab196087 	    0, &isec, &shdr, &data) == S_ERROR)
22837c478bd9Sstevel@tonic-gate 		return (S_ERROR);
22847c478bd9Sstevel@tonic-gate 
22857c478bd9Sstevel@tonic-gate 	/*
22867c478bd9Sstevel@tonic-gate 	 * Place the section first, as it may effect the number of section
22877c478bd9Sstevel@tonic-gate 	 * headers to account for.
22887c478bd9Sstevel@tonic-gate 	 */
2289ba2be530Sab196087 	ofl->ofl_osshstrtab =
229069112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_note, NULL);
2291ba2be530Sab196087 	if (ofl->ofl_osshstrtab == (Os_desc *)S_ERROR)
22927c478bd9Sstevel@tonic-gate 		return (S_ERROR);
22937c478bd9Sstevel@tonic-gate 
22947c478bd9Sstevel@tonic-gate 	size = st_getstrtab_sz(ofl->ofl_shdrsttab);
22957c478bd9Sstevel@tonic-gate 	assert(size > 0);
22967c478bd9Sstevel@tonic-gate 
22977c478bd9Sstevel@tonic-gate 	data->d_size = size;
22987c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
22997c478bd9Sstevel@tonic-gate 
23007c478bd9Sstevel@tonic-gate 	return (1);
23017c478bd9Sstevel@tonic-gate }
23027c478bd9Sstevel@tonic-gate 
23037c478bd9Sstevel@tonic-gate /*
23047c478bd9Sstevel@tonic-gate  * Build a string section for the standard symbol table.
23057c478bd9Sstevel@tonic-gate  */
23065aefb655Srie static uintptr_t
23077c478bd9Sstevel@tonic-gate make_strtab(Ofl_desc *ofl)
23087c478bd9Sstevel@tonic-gate {
23097c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
23107c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
23117c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
23127c478bd9Sstevel@tonic-gate 	size_t		size;
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 	/*
23157c478bd9Sstevel@tonic-gate 	 * This string table consists of all the global and local symbols.
23167c478bd9Sstevel@tonic-gate 	 * Account for null bytes at end of the file name and the beginning
23177c478bd9Sstevel@tonic-gate 	 * of section.
23187c478bd9Sstevel@tonic-gate 	 */
23197c478bd9Sstevel@tonic-gate 	if (st_insert(ofl->ofl_strtab, ofl->ofl_name) == -1)
23207c478bd9Sstevel@tonic-gate 		return (S_ERROR);
23217c478bd9Sstevel@tonic-gate 
23227c478bd9Sstevel@tonic-gate 	size = st_getstrtab_sz(ofl->ofl_strtab);
23237c478bd9Sstevel@tonic-gate 	assert(size > 0);
23247c478bd9Sstevel@tonic-gate 
23259039eeafSab196087 	if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_STRTAB),
23269039eeafSab196087 	    0, &isec, &shdr, &data) == S_ERROR)
23277c478bd9Sstevel@tonic-gate 		return (S_ERROR);
23289039eeafSab196087 
23299039eeafSab196087 	/* Set the size of the data area */
23307c478bd9Sstevel@tonic-gate 	data->d_size = size;
23317c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
23327c478bd9Sstevel@tonic-gate 
2333ba2be530Sab196087 	ofl->ofl_osstrtab =
233469112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_strtab, NULL);
23357c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osstrtab);
23367c478bd9Sstevel@tonic-gate }
23377c478bd9Sstevel@tonic-gate 
23387c478bd9Sstevel@tonic-gate /*
23397c478bd9Sstevel@tonic-gate  * Build a string table for the dynamic symbol table.
23407c478bd9Sstevel@tonic-gate  */
23415aefb655Srie static uintptr_t
23427c478bd9Sstevel@tonic-gate make_dynstr(Ofl_desc *ofl)
23437c478bd9Sstevel@tonic-gate {
23447c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
23457c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
23467c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
23477c478bd9Sstevel@tonic-gate 	size_t		size;
23487c478bd9Sstevel@tonic-gate 
23497c478bd9Sstevel@tonic-gate 	/*
2350d579eb63Sab196087 	 * If producing a .SUNW_ldynsym, account for the initial STT_FILE
2351d579eb63Sab196087 	 * symbol that precedes the scope reduced global symbols.
23529039eeafSab196087 	 */
2353d579eb63Sab196087 	if (OFL_ALLOW_LDYNSYM(ofl)) {
23549039eeafSab196087 		if (st_insert(ofl->ofl_dynstrtab, ofl->ofl_name) == -1)
23559039eeafSab196087 			return (S_ERROR);
23569039eeafSab196087 		ofl->ofl_dynscopecnt++;
23579039eeafSab196087 	}
23589039eeafSab196087 
23599039eeafSab196087 	/*
23607c478bd9Sstevel@tonic-gate 	 * Account for any local, named register symbols.  These locals are
23617c478bd9Sstevel@tonic-gate 	 * required for reference from DT_REGISTER .dynamic entries.
23627c478bd9Sstevel@tonic-gate 	 */
23637c478bd9Sstevel@tonic-gate 	if (ofl->ofl_regsyms) {
23647c478bd9Sstevel@tonic-gate 		int	ndx;
23657c478bd9Sstevel@tonic-gate 
23667c478bd9Sstevel@tonic-gate 		for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
23677c478bd9Sstevel@tonic-gate 			Sym_desc	*sdp;
23687c478bd9Sstevel@tonic-gate 
236957ef7aa9SRod Evans 			if ((sdp = ofl->ofl_regsyms[ndx]) == NULL)
23707c478bd9Sstevel@tonic-gate 				continue;
23717c478bd9Sstevel@tonic-gate 
237208278a5eSRod Evans 			if (!SYM_IS_HIDDEN(sdp) &&
23737c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(sdp->sd_sym->st_info) != STB_LOCAL))
23747c478bd9Sstevel@tonic-gate 				continue;
23757c478bd9Sstevel@tonic-gate 
237657ef7aa9SRod Evans 			if (sdp->sd_sym->st_name == NULL)
23777c478bd9Sstevel@tonic-gate 				continue;
23787c478bd9Sstevel@tonic-gate 
23797c478bd9Sstevel@tonic-gate 			if (st_insert(ofl->ofl_dynstrtab, sdp->sd_name) == -1)
23807c478bd9Sstevel@tonic-gate 				return (S_ERROR);
23817c478bd9Sstevel@tonic-gate 		}
23827c478bd9Sstevel@tonic-gate 	}
23837c478bd9Sstevel@tonic-gate 
23847c478bd9Sstevel@tonic-gate 	/*
23857c478bd9Sstevel@tonic-gate 	 * Reserve entries for any per-symbol auxiliary/filter strings.
23867c478bd9Sstevel@tonic-gate 	 */
2387cce0e03bSab196087 	if (ofl->ofl_dtsfltrs != NULL) {
23887c478bd9Sstevel@tonic-gate 		Dfltr_desc	*dftp;
2389cce0e03bSab196087 		Aliste		idx;
23907c478bd9Sstevel@tonic-gate 
2391cce0e03bSab196087 		for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, idx, dftp))
23927c478bd9Sstevel@tonic-gate 			if (st_insert(ofl->ofl_dynstrtab, dftp->dft_str) == -1)
23937c478bd9Sstevel@tonic-gate 				return (S_ERROR);
23947c478bd9Sstevel@tonic-gate 	}
23957c478bd9Sstevel@tonic-gate 
23967c478bd9Sstevel@tonic-gate 	size = st_getstrtab_sz(ofl->ofl_dynstrtab);
23977c478bd9Sstevel@tonic-gate 	assert(size > 0);
23987c478bd9Sstevel@tonic-gate 
23999039eeafSab196087 	if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_DYNSTR),
24009039eeafSab196087 	    0, &isec, &shdr, &data) == S_ERROR)
24017c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24027c478bd9Sstevel@tonic-gate 
24039039eeafSab196087 	/* Make it allocable if necessary */
24047c478bd9Sstevel@tonic-gate 	if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
24059039eeafSab196087 		shdr->sh_flags |= SHF_ALLOC;
24067c478bd9Sstevel@tonic-gate 
24079039eeafSab196087 	/* Set the size of the data area */
24083244bcaaSab196087 	data->d_size = size + DYNSTR_EXTRA_PAD;
24093244bcaaSab196087 
24107c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
24117c478bd9Sstevel@tonic-gate 
2412ba2be530Sab196087 	ofl->ofl_osdynstr =
241369112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynstr, NULL);
24147c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osdynstr);
24157c478bd9Sstevel@tonic-gate }
24167c478bd9Sstevel@tonic-gate 
24177c478bd9Sstevel@tonic-gate /*
24187c478bd9Sstevel@tonic-gate  * Generate an output relocation section which will contain the relocation
24197c478bd9Sstevel@tonic-gate  * information to be applied to the `osp' section.
24207c478bd9Sstevel@tonic-gate  *
24217c478bd9Sstevel@tonic-gate  * If (osp == NULL) then we are creating the coalesced relocation section
24227c478bd9Sstevel@tonic-gate  * for an executable and/or a shared object.
24237c478bd9Sstevel@tonic-gate  */
24245aefb655Srie static uintptr_t
24257c478bd9Sstevel@tonic-gate make_reloc(Ofl_desc *ofl, Os_desc *osp)
24267c478bd9Sstevel@tonic-gate {
24277c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
24287c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
24297c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
24307c478bd9Sstevel@tonic-gate 	size_t		size;
24317c478bd9Sstevel@tonic-gate 	Xword		sh_flags;
24327c478bd9Sstevel@tonic-gate 	char 		*sectname;
24337c478bd9Sstevel@tonic-gate 	Os_desc		*rosp;
24347c478bd9Sstevel@tonic-gate 	Word		relsize;
24357c478bd9Sstevel@tonic-gate 	const char	*rel_prefix;
24367c478bd9Sstevel@tonic-gate 
24377c478bd9Sstevel@tonic-gate 	/* LINTED */
2438ba2be530Sab196087 	if (ld_targ.t_m.m_rel_sht_type == SHT_REL) {
24397c478bd9Sstevel@tonic-gate 		/* REL */
24407c478bd9Sstevel@tonic-gate 		relsize = sizeof (Rel);
24417c478bd9Sstevel@tonic-gate 		rel_prefix = MSG_ORIG(MSG_SCN_REL);
24427c478bd9Sstevel@tonic-gate 	} else {
24437c478bd9Sstevel@tonic-gate 		/* RELA */
24447c478bd9Sstevel@tonic-gate 		relsize = sizeof (Rela);
24457c478bd9Sstevel@tonic-gate 		rel_prefix = MSG_ORIG(MSG_SCN_RELA);
24467c478bd9Sstevel@tonic-gate 	}
24477c478bd9Sstevel@tonic-gate 
24487c478bd9Sstevel@tonic-gate 	if (osp) {
24497c478bd9Sstevel@tonic-gate 		size = osp->os_szoutrels;
24507c478bd9Sstevel@tonic-gate 		sh_flags = osp->os_shdr->sh_flags;
24517c478bd9Sstevel@tonic-gate 		if ((sectname = libld_malloc(strlen(rel_prefix) +
24527c478bd9Sstevel@tonic-gate 		    strlen(osp->os_name) + 1)) == 0)
24537c478bd9Sstevel@tonic-gate 			return (S_ERROR);
24547c478bd9Sstevel@tonic-gate 		(void) strcpy(sectname, rel_prefix);
24557c478bd9Sstevel@tonic-gate 		(void) strcat(sectname, osp->os_name);
2456e38a713aSrie 	} else if (ofl->ofl_flags & FLG_OF_COMREL) {
24577c478bd9Sstevel@tonic-gate 		size = (ofl->ofl_reloccnt - ofl->ofl_reloccntsub) * relsize;
24587c478bd9Sstevel@tonic-gate 		sh_flags = SHF_ALLOC;
24597c478bd9Sstevel@tonic-gate 		sectname = (char *)MSG_ORIG(MSG_SCN_SUNWRELOC);
24607c478bd9Sstevel@tonic-gate 	} else {
24617c478bd9Sstevel@tonic-gate 		size = ofl->ofl_relocrelsz;
24627c478bd9Sstevel@tonic-gate 		sh_flags = SHF_ALLOC;
24637c478bd9Sstevel@tonic-gate 		sectname = (char *)rel_prefix;
24647c478bd9Sstevel@tonic-gate 	}
24657c478bd9Sstevel@tonic-gate 
24667c478bd9Sstevel@tonic-gate 	/*
24677c478bd9Sstevel@tonic-gate 	 * Keep track of total size of 'output relocations' (to be stored
24687c478bd9Sstevel@tonic-gate 	 * in .dynamic)
24697c478bd9Sstevel@tonic-gate 	 */
24707c478bd9Sstevel@tonic-gate 	/* LINTED */
24717c478bd9Sstevel@tonic-gate 	ofl->ofl_relocsz += (Xword)size;
24727c478bd9Sstevel@tonic-gate 
2473ba2be530Sab196087 	if (new_section(ofl, ld_targ.t_m.m_rel_sht_type, sectname, 0, &isec,
2474ba2be530Sab196087 	    &shdr, &data) == S_ERROR)
24757c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24769039eeafSab196087 
24777c478bd9Sstevel@tonic-gate 	data->d_size = size;
24787c478bd9Sstevel@tonic-gate 
24797c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
24809039eeafSab196087 	if (OFL_ALLOW_DYNSYM(ofl) && (sh_flags & SHF_ALLOC))
24817c478bd9Sstevel@tonic-gate 		shdr->sh_flags = SHF_ALLOC;
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate 	if (osp) {
24847c478bd9Sstevel@tonic-gate 		/*
24857c478bd9Sstevel@tonic-gate 		 * The sh_info field of the SHT_REL* sections points to the
24867c478bd9Sstevel@tonic-gate 		 * section the relocations are to be applied to.
24877c478bd9Sstevel@tonic-gate 		 */
24887c478bd9Sstevel@tonic-gate 		shdr->sh_flags |= SHF_INFO_LINK;
24897c478bd9Sstevel@tonic-gate 	}
24907c478bd9Sstevel@tonic-gate 
249169112eddSAli Bahrami 	rosp = ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_rel, NULL);
2492ba2be530Sab196087 	if (rosp == (Os_desc *)S_ERROR)
24937c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24947c478bd9Sstevel@tonic-gate 
24956b3ba5bdSAli Bahrami 	/*
24966b3ba5bdSAli Bahrami 	 * Associate this relocation section to the section its going to
24976b3ba5bdSAli Bahrami 	 * relocate.
24986b3ba5bdSAli Bahrami 	 */
24997c478bd9Sstevel@tonic-gate 	if (osp) {
25006b3ba5bdSAli Bahrami 		Aliste	idx;
25017c478bd9Sstevel@tonic-gate 		Is_desc	*risp;
25020bc07c75Srie 
25037c478bd9Sstevel@tonic-gate 		/*
25047c478bd9Sstevel@tonic-gate 		 * This is used primarily so that we can update
25057c478bd9Sstevel@tonic-gate 		 * SHT_GROUP[sect_no] entries to point to the
25067c478bd9Sstevel@tonic-gate 		 * created output relocation sections.
25077c478bd9Sstevel@tonic-gate 		 */
25086b3ba5bdSAli Bahrami 		for (APLIST_TRAVERSE(osp->os_relisdescs, idx, risp)) {
25097c478bd9Sstevel@tonic-gate 			risp->is_osdesc = rosp;
25100bc07c75Srie 
25117c478bd9Sstevel@tonic-gate 			/*
25120bc07c75Srie 			 * If the input relocation section had the SHF_GROUP
25137010c12aSrie 			 * flag set - propagate it to the output relocation
25140bc07c75Srie 			 * section.
25157c478bd9Sstevel@tonic-gate 			 */
25167c478bd9Sstevel@tonic-gate 			if (risp->is_shdr->sh_flags & SHF_GROUP) {
25177c478bd9Sstevel@tonic-gate 				rosp->os_shdr->sh_flags |= SHF_GROUP;
25187c478bd9Sstevel@tonic-gate 				break;
25197c478bd9Sstevel@tonic-gate 			}
25207c478bd9Sstevel@tonic-gate 		}
25217c478bd9Sstevel@tonic-gate 		osp->os_relosdesc = rosp;
25227c478bd9Sstevel@tonic-gate 	} else
25237c478bd9Sstevel@tonic-gate 		ofl->ofl_osrel = rosp;
25247c478bd9Sstevel@tonic-gate 
25257c478bd9Sstevel@tonic-gate 	/*
25267c478bd9Sstevel@tonic-gate 	 * If this is the first relocation section we've encountered save it
25277c478bd9Sstevel@tonic-gate 	 * so that the .dynamic entry can be initialized accordingly.
25287c478bd9Sstevel@tonic-gate 	 */
25297c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osrelhead == (Os_desc *)0)
25307c478bd9Sstevel@tonic-gate 		ofl->ofl_osrelhead = rosp;
25317c478bd9Sstevel@tonic-gate 
25327c478bd9Sstevel@tonic-gate 	return (1);
25337c478bd9Sstevel@tonic-gate }
25347c478bd9Sstevel@tonic-gate 
25357c478bd9Sstevel@tonic-gate /*
25367c478bd9Sstevel@tonic-gate  * Generate version needed section.
25377c478bd9Sstevel@tonic-gate  */
25385aefb655Srie static uintptr_t
25397c478bd9Sstevel@tonic-gate make_verneed(Ofl_desc *ofl)
25407c478bd9Sstevel@tonic-gate {
25417c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
25427c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
25437c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
25447c478bd9Sstevel@tonic-gate 
25457c478bd9Sstevel@tonic-gate 	/*
25469039eeafSab196087 	 * verneed sections do not have a constant element size, so the
25479039eeafSab196087 	 * value of ent_cnt specified here (0) is meaningless.
25487c478bd9Sstevel@tonic-gate 	 */
25499039eeafSab196087 	if (new_section(ofl, SHT_SUNW_verneed, MSG_ORIG(MSG_SCN_SUNWVERSION),
25509039eeafSab196087 	    0, &isec, &shdr, &data) == S_ERROR)
25517c478bd9Sstevel@tonic-gate 		return (S_ERROR);
25527c478bd9Sstevel@tonic-gate 
25539039eeafSab196087 	/* During version processing we calculated the total size. */
25549039eeafSab196087 	data->d_size = ofl->ofl_verneedsz;
25559039eeafSab196087 	shdr->sh_size = (Xword)ofl->ofl_verneedsz;
25567c478bd9Sstevel@tonic-gate 
2557ba2be530Sab196087 	ofl->ofl_osverneed =
255869112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_version, NULL);
25597c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osverneed);
25607c478bd9Sstevel@tonic-gate }
25617c478bd9Sstevel@tonic-gate 
25627c478bd9Sstevel@tonic-gate /*
25637c478bd9Sstevel@tonic-gate  * Generate a version definition section.
25647c478bd9Sstevel@tonic-gate  *
25657c478bd9Sstevel@tonic-gate  *  o	the SHT_SUNW_verdef section defines the versions that exist within this
25667c478bd9Sstevel@tonic-gate  *	image.
25677c478bd9Sstevel@tonic-gate  */
25685aefb655Srie static uintptr_t
25697c478bd9Sstevel@tonic-gate make_verdef(Ofl_desc *ofl)
25707c478bd9Sstevel@tonic-gate {
25717c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
25727c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
25737c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
25747c478bd9Sstevel@tonic-gate 	Ver_desc	*vdp;
2575635216b6SRod Evans 	Str_tbl		*strtab;
25767c478bd9Sstevel@tonic-gate 
25777c478bd9Sstevel@tonic-gate 	/*
25787c478bd9Sstevel@tonic-gate 	 * Reserve a string table entry for the base version dependency (other
25797c478bd9Sstevel@tonic-gate 	 * dependencies have symbol representations, which will already be
25807c478bd9Sstevel@tonic-gate 	 * accounted for during symbol processing).
25817c478bd9Sstevel@tonic-gate 	 */
258257ef7aa9SRod Evans 	vdp = (Ver_desc *)ofl->ofl_verdesc->apl_data[0];
25837c478bd9Sstevel@tonic-gate 
2584635216b6SRod Evans 	if (OFL_IS_STATIC_OBJ(ofl))
2585635216b6SRod Evans 		strtab = ofl->ofl_strtab;
2586635216b6SRod Evans 	else
2587635216b6SRod Evans 		strtab = ofl->ofl_dynstrtab;
2588635216b6SRod Evans 
2589635216b6SRod Evans 	if (st_insert(strtab, vdp->vd_name) == -1)
25907c478bd9Sstevel@tonic-gate 		return (S_ERROR);
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 	/*
25939039eeafSab196087 	 * verdef sections do not have a constant element size, so the
25949039eeafSab196087 	 * value of ent_cnt specified here (0) is meaningless.
25957c478bd9Sstevel@tonic-gate 	 */
25969039eeafSab196087 	if (new_section(ofl, SHT_SUNW_verdef, MSG_ORIG(MSG_SCN_SUNWVERSION),
25979039eeafSab196087 	    0, &isec, &shdr, &data) == S_ERROR)
25987c478bd9Sstevel@tonic-gate 		return (S_ERROR);
25997c478bd9Sstevel@tonic-gate 
26009039eeafSab196087 	/* During version processing we calculated the total size. */
26019039eeafSab196087 	data->d_size = ofl->ofl_verdefsz;
26029039eeafSab196087 	shdr->sh_size = (Xword)ofl->ofl_verdefsz;
26037c478bd9Sstevel@tonic-gate 
2604ba2be530Sab196087 	ofl->ofl_osverdef =
260569112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_version, NULL);
26067c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osverdef);
26077c478bd9Sstevel@tonic-gate }
26087c478bd9Sstevel@tonic-gate 
26097c478bd9Sstevel@tonic-gate /*
26107c478bd9Sstevel@tonic-gate  * This routine is called when -z nopartial is in effect.
26117c478bd9Sstevel@tonic-gate  */
26127c478bd9Sstevel@tonic-gate uintptr_t
261335450702SAli Bahrami ld_make_parexpn_data(Ofl_desc *ofl, size_t size, Xword align)
26147c478bd9Sstevel@tonic-gate {
26157c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
26167c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
26177c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
26187c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
26197c478bd9Sstevel@tonic-gate 
262035450702SAli Bahrami 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_DATA), 0,
26219039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
26227c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26239039eeafSab196087 
26249039eeafSab196087 	shdr->sh_flags |= SHF_WRITE;
26257c478bd9Sstevel@tonic-gate 	data->d_size = size;
26269039eeafSab196087 	shdr->sh_size = (Xword)size;
26279039eeafSab196087 	if (align != 0) {
26289039eeafSab196087 		data->d_align = align;
26299039eeafSab196087 		shdr->sh_addralign = align;
26309039eeafSab196087 	}
26319039eeafSab196087 
263257ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(size, 1)) == NULL)
26337c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26347c478bd9Sstevel@tonic-gate 
26357c478bd9Sstevel@tonic-gate 	/*
263635450702SAli Bahrami 	 * Retain handle to this .data input section. Variables using move
263735450702SAli Bahrami 	 * sections (partial initialization) will be redirected here when
263835450702SAli Bahrami 	 * such global references are added and '-z nopartial' is in effect.
26397c478bd9Sstevel@tonic-gate 	 */
264035450702SAli Bahrami 	ofl->ofl_isparexpn = isec;
264169112eddSAli Bahrami 	osp = ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_data, NULL);
2642ba2be530Sab196087 	if (osp == (Os_desc *)S_ERROR)
26437c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26447c478bd9Sstevel@tonic-gate 
26457c478bd9Sstevel@tonic-gate 	if (!(osp->os_flags & FLG_OS_OUTREL)) {
26467c478bd9Sstevel@tonic-gate 		ofl->ofl_dynshdrcnt++;
26477c478bd9Sstevel@tonic-gate 		osp->os_flags |= FLG_OS_OUTREL;
26487c478bd9Sstevel@tonic-gate 	}
26497c478bd9Sstevel@tonic-gate 	return (1);
26507c478bd9Sstevel@tonic-gate }
26517c478bd9Sstevel@tonic-gate 
26527c478bd9Sstevel@tonic-gate /*
26537c478bd9Sstevel@tonic-gate  * Make .sunwmove section
26547c478bd9Sstevel@tonic-gate  */
26557c478bd9Sstevel@tonic-gate uintptr_t
26565aefb655Srie ld_make_sunwmove(Ofl_desc *ofl, int mv_nums)
26577c478bd9Sstevel@tonic-gate {
26587c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
26597c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
26607c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
266157ef7aa9SRod Evans 	Aliste		idx;
266257ef7aa9SRod Evans 	Sym_desc	*sdp;
26637c478bd9Sstevel@tonic-gate 	int 		cnt = 1;
26647c478bd9Sstevel@tonic-gate 
26657c478bd9Sstevel@tonic-gate 
26669039eeafSab196087 	if (new_section(ofl, SHT_SUNW_move, MSG_ORIG(MSG_SCN_SUNWMOVE),
26679039eeafSab196087 	    mv_nums, &isec, &shdr, &data) == S_ERROR)
26687c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26697c478bd9Sstevel@tonic-gate 
267057ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(data->d_size, 1)) == NULL)
26717c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26727c478bd9Sstevel@tonic-gate 
26737c478bd9Sstevel@tonic-gate 	/*
26747c478bd9Sstevel@tonic-gate 	 * Copy move entries
26757c478bd9Sstevel@tonic-gate 	 */
267657ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_parsyms, idx, sdp)) {
267757ef7aa9SRod Evans 		Aliste		idx2;
267857ef7aa9SRod Evans 		Mv_desc		*mdp;
26797c478bd9Sstevel@tonic-gate 
268057ef7aa9SRod Evans 		if (sdp->sd_flags & FLG_SY_PAREXPN)
26817c478bd9Sstevel@tonic-gate 			continue;
268257ef7aa9SRod Evans 
268357ef7aa9SRod Evans 		for (ALIST_TRAVERSE(sdp->sd_move, idx2, mdp))
268457ef7aa9SRod Evans 			mdp->md_oidx = cnt++;
26857c478bd9Sstevel@tonic-gate 	}
268657ef7aa9SRod Evans 
268769112eddSAli Bahrami 	if ((ofl->ofl_osmove = ld_place_section(ofl, isec, NULL, 0, NULL)) ==
26887c478bd9Sstevel@tonic-gate 	    (Os_desc *)S_ERROR)
26897c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26907c478bd9Sstevel@tonic-gate 
26917c478bd9Sstevel@tonic-gate 	return (1);
26927c478bd9Sstevel@tonic-gate }
26937c478bd9Sstevel@tonic-gate 
26947c478bd9Sstevel@tonic-gate /*
2695cce0e03bSab196087  * Given a relocation descriptor that references a string table
2696cce0e03bSab196087  * input section, locate the string referenced and return a pointer
2697cce0e03bSab196087  * to it.
2698cce0e03bSab196087  */
2699cce0e03bSab196087 static const char *
2700cce0e03bSab196087 strmerge_get_reloc_str(Ofl_desc *ofl, Rel_desc *rsp)
2701cce0e03bSab196087 {
2702cce0e03bSab196087 	Sym_desc *sdp = rsp->rel_sym;
2703cce0e03bSab196087 	Xword	 str_off;
2704cce0e03bSab196087 
2705cce0e03bSab196087 	/*
2706cce0e03bSab196087 	 * In the case of an STT_SECTION symbol, the addend of the
2707cce0e03bSab196087 	 * relocation gives the offset into the string section. For
2708cce0e03bSab196087 	 * other symbol types, the symbol value is the offset.
2709cce0e03bSab196087 	 */
2710cce0e03bSab196087 
2711cce0e03bSab196087 	if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_SECTION) {
2712cce0e03bSab196087 		str_off = sdp->sd_sym->st_value;
2713cce0e03bSab196087 	} else if ((rsp->rel_flags & FLG_REL_RELA) == FLG_REL_RELA) {
2714cce0e03bSab196087 		/*
2715cce0e03bSab196087 		 * For SHT_RELA, the addend value is found in the
2716cce0e03bSab196087 		 * rel_raddend field of the relocation.
2717cce0e03bSab196087 		 */
2718cce0e03bSab196087 		str_off = rsp->rel_raddend;
2719cce0e03bSab196087 	} else {	/* REL and STT_SECTION */
2720cce0e03bSab196087 		/*
2721cce0e03bSab196087 		 * For SHT_REL, the "addend" is not part of the relocation
2722cce0e03bSab196087 		 * record. Instead, it is found at the relocation target
2723cce0e03bSab196087 		 * address.
2724cce0e03bSab196087 		 */
2725cce0e03bSab196087 		uchar_t *addr = (uchar_t *)((uintptr_t)rsp->rel_roffset +
2726cce0e03bSab196087 		    (uintptr_t)rsp->rel_isdesc->is_indata->d_buf);
2727cce0e03bSab196087 
2728cce0e03bSab196087 		if (ld_reloc_targval_get(ofl, rsp, addr, &str_off) == 0)
2729cce0e03bSab196087 			return (0);
2730cce0e03bSab196087 	}
2731cce0e03bSab196087 
2732cce0e03bSab196087 	return (str_off + (char *)sdp->sd_isc->is_indata->d_buf);
2733cce0e03bSab196087 }
2734cce0e03bSab196087 
2735cce0e03bSab196087 /*
2736cce0e03bSab196087  * First pass over the relocation records for string table merging.
2737cce0e03bSab196087  * Build lists of relocations and symbols that will need modification,
2738cce0e03bSab196087  * and insert the strings they reference into the mstrtab string table.
2739cce0e03bSab196087  *
2740cce0e03bSab196087  * entry:
2741cce0e03bSab196087  *	ofl, osp - As passed to ld_make_strmerge().
2742cce0e03bSab196087  *	mstrtab - String table to receive input strings. This table
2743cce0e03bSab196087  *		must be in its first (initialization) pass and not
2744cce0e03bSab196087  *		yet cooked (st_getstrtab_sz() not yet called).
274557ef7aa9SRod Evans  *	rel_alpp - APlist to receive pointer to any relocation
2746cce0e03bSab196087  *		descriptors with STT_SECTION symbols that reference
2747cce0e03bSab196087  *		one of the input sections being merged.
274857ef7aa9SRod Evans  *	sym_alpp - APlist to receive pointer to any symbols that reference
2749cce0e03bSab196087  *		one of the input sections being merged.
2750bf994817SAli Bahrami  *	rcp - Pointer to cache of relocation descriptors to examine.
2751bf994817SAli Bahrami  *		Either &ofl->ofl_actrels (active relocations)
2752cce0e03bSab196087  *		or &ofl->ofl_outrels (output relocations).
2753cce0e03bSab196087  *
2754cce0e03bSab196087  * exit:
275557ef7aa9SRod Evans  *	On success, rel_alpp and sym_alpp are updated, and
275608278a5eSRod Evans  *	any strings in the mergeable input sections referenced by
2757cce0e03bSab196087  *	a relocation has been entered into mstrtab. True (1) is returned.
2758cce0e03bSab196087  *
2759cce0e03bSab196087  *	On failure, False (0) is returned.
2760cce0e03bSab196087  */
2761cce0e03bSab196087 static int
2762cce0e03bSab196087 strmerge_pass1(Ofl_desc *ofl, Os_desc *osp, Str_tbl *mstrtab,
2763bf994817SAli Bahrami     APlist **rel_alpp, APlist **sym_alpp, Rel_cache *rcp)
2764cce0e03bSab196087 {
276557ef7aa9SRod Evans 	Aliste		idx;
2766bf994817SAli Bahrami 	Rel_cachebuf	*rcbp;
2767cce0e03bSab196087 	Sym_desc	*sdp;
2768cce0e03bSab196087 	Sym_desc	*last_sdp = NULL;
2769cce0e03bSab196087 	Rel_desc	*rsp;
2770cce0e03bSab196087 	const char	*name;
2771cce0e03bSab196087 
2772bf994817SAli Bahrami 	REL_CACHE_TRAVERSE(rcp, idx, rcbp, rsp) {
2773cce0e03bSab196087 		sdp = rsp->rel_sym;
2774bf994817SAli Bahrami 		if ((sdp->sd_isc == NULL) || ((sdp->sd_isc->is_flags &
2775bf994817SAli Bahrami 		    (FLG_IS_DISCARD | FLG_IS_INSTRMRG)) != FLG_IS_INSTRMRG) ||
2776cce0e03bSab196087 		    (sdp->sd_isc->is_osdesc != osp))
2777cce0e03bSab196087 			continue;
2778cce0e03bSab196087 
2779cce0e03bSab196087 		/*
2780bf994817SAli Bahrami 		 * Remember symbol for use in the third pass. There is no
2781bf994817SAli Bahrami 		 * reason to save a given symbol more than once, so we take
2782bf994817SAli Bahrami 		 * advantage of the fact that relocations to a given symbol
2783bf994817SAli Bahrami 		 * tend to cluster in the list. If this is the same symbol
2784bf994817SAli Bahrami 		 * we saved last time, don't bother.
2785cce0e03bSab196087 		 */
2786cce0e03bSab196087 		if (last_sdp != sdp) {
2787bf994817SAli Bahrami 			if (aplist_append(sym_alpp, sdp, AL_CNT_STRMRGSYM) ==
2788bf994817SAli Bahrami 			    NULL)
2789cce0e03bSab196087 				return (0);
2790cce0e03bSab196087 			last_sdp = sdp;
2791cce0e03bSab196087 		}
2792cce0e03bSab196087 
2793cce0e03bSab196087 		/* Enter the string into our new string table */
2794cce0e03bSab196087 		name = strmerge_get_reloc_str(ofl, rsp);
2795cce0e03bSab196087 		if (st_insert(mstrtab, name) == -1)
2796cce0e03bSab196087 			return (0);
2797cce0e03bSab196087 
2798cce0e03bSab196087 		/*
2799bf994817SAli Bahrami 		 * If this is an STT_SECTION symbol, then the second pass
2800bf994817SAli Bahrami 		 * will need to modify this relocation, so hang on to it.
2801cce0e03bSab196087 		 */
2802bf994817SAli Bahrami 		if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) &&
2803bf994817SAli Bahrami 		    (aplist_append(rel_alpp, rsp, AL_CNT_STRMRGREL) == NULL))
2804cce0e03bSab196087 			return (0);
2805cce0e03bSab196087 	}
2806cce0e03bSab196087 
2807cce0e03bSab196087 	return (1);
2808cce0e03bSab196087 }
2809cce0e03bSab196087 
2810cce0e03bSab196087 /*
2811cce0e03bSab196087  * If the output section has any SHF_MERGE|SHF_STRINGS input sections,
2812cce0e03bSab196087  * replace them with a single merged/compressed input section.
2813cce0e03bSab196087  *
2814cce0e03bSab196087  * entry:
2815cce0e03bSab196087  *	ofl - Output file descriptor
2816cce0e03bSab196087  *	osp - Output section descriptor
281757ef7aa9SRod Evans  *	rel_alpp, sym_alpp, - Address of 2 APlists, to be used
2818cce0e03bSab196087  *		for internal processing. On the initial call to
2819cce0e03bSab196087  *		ld_make_strmerge, these list pointers must be NULL.
2820cce0e03bSab196087  *		The caller is encouraged to pass the same lists back for
2821cce0e03bSab196087  *		successive calls to this function without freeing
2822cce0e03bSab196087  *		them in between calls. This causes a single pair of
2823cce0e03bSab196087  *		memory allocations to be reused multiple times.
2824cce0e03bSab196087  *
2825cce0e03bSab196087  * exit:
2826cce0e03bSab196087  *	If section merging is possible, it is done. If no errors are
2827cce0e03bSab196087  *	encountered, True (1) is returned. On error, S_ERROR.
2828cce0e03bSab196087  *
282957ef7aa9SRod Evans  *	The contents of rel_alpp and sym_alpp on exit are
2830cce0e03bSab196087  *	undefined. The caller can free them, or pass them back to a subsequent
2831cce0e03bSab196087  *	call to this routine, but should not examine their contents.
2832cce0e03bSab196087  */
2833cce0e03bSab196087 static uintptr_t
283457ef7aa9SRod Evans ld_make_strmerge(Ofl_desc *ofl, Os_desc *osp, APlist **rel_alpp,
283557ef7aa9SRod Evans     APlist **sym_alpp)
2836cce0e03bSab196087 {
2837cce0e03bSab196087 	Str_tbl		*mstrtab;	/* string table for string merge secs */
2838cce0e03bSab196087 	Is_desc		*mstrsec;	/* Generated string merge section */
2839cce0e03bSab196087 	Is_desc		*isp;
2840cce0e03bSab196087 	Shdr		*mstr_shdr;
2841cce0e03bSab196087 	Elf_Data	*mstr_data;
2842cce0e03bSab196087 	Sym_desc	*sdp;
2843cce0e03bSab196087 	Rel_desc	*rsp;
2844cce0e03bSab196087 	Aliste		idx;
2845cce0e03bSab196087 	size_t		data_size;
2846cce0e03bSab196087 	int		st_setstring_status;
2847cce0e03bSab196087 	size_t		stoff;
2848cce0e03bSab196087 
2849cce0e03bSab196087 	/* If string table compression is disabled, there's nothing to do */
2850cce0e03bSab196087 	if ((ofl->ofl_flags1 & FLG_OF1_NCSTTAB) != 0)
2851cce0e03bSab196087 		return (1);
2852cce0e03bSab196087 
2853cce0e03bSab196087 	/*
2854cce0e03bSab196087 	 * Pass over the mergeable input sections, and if they haven't
2855cce0e03bSab196087 	 * all been discarded, create a string table.
2856cce0e03bSab196087 	 */
2857cce0e03bSab196087 	mstrtab = NULL;
2858cce0e03bSab196087 	for (APLIST_TRAVERSE(osp->os_mstrisdescs, idx, isp)) {
2859*d9c5840bSRichard Lowe 		if (isdesc_discarded(isp))
2860*d9c5840bSRichard Lowe 			continue;
2861*d9c5840bSRichard Lowe 
2862*d9c5840bSRichard Lowe 		/*
2863*d9c5840bSRichard Lowe 		 * Input sections of 0 size are dubiously valid since they do
2864*d9c5840bSRichard Lowe 		 * not even contain the NUL string.  Ignore them.
2865*d9c5840bSRichard Lowe 		 */
2866*d9c5840bSRichard Lowe 		if (isp->is_shdr->sh_size == 0)
2867cce0e03bSab196087 			continue;
2868cce0e03bSab196087 
2869cce0e03bSab196087 		/*
2870cce0e03bSab196087 		 * We have at least one non-discarded section.
2871cce0e03bSab196087 		 * Create a string table descriptor.
2872cce0e03bSab196087 		 */
2873cce0e03bSab196087 		if ((mstrtab = st_new(FLG_STNEW_COMPRESS)) == NULL)
2874cce0e03bSab196087 			return (S_ERROR);
2875cce0e03bSab196087 		break;
2876cce0e03bSab196087 	}
2877cce0e03bSab196087 
2878cce0e03bSab196087 	/* If no string table was created, we have no mergeable sections */
2879cce0e03bSab196087 	if (mstrtab == NULL)
2880cce0e03bSab196087 		return (1);
2881cce0e03bSab196087 
2882cce0e03bSab196087 	/*
2883cce0e03bSab196087 	 * This routine has to make 3 passes:
2884cce0e03bSab196087 	 *
2885cce0e03bSab196087 	 *	1) Examine all relocations, insert strings from relocations
288608278a5eSRod Evans 	 *		to the mergeable input sections into the string table.
2887cce0e03bSab196087 	 *	2) Modify the relocation values to be correct for the
2888cce0e03bSab196087 	 *		new merged section.
2889cce0e03bSab196087 	 *	3) Modify the symbols used by the relocations to reference
2890cce0e03bSab196087 	 *		the new section.
2891cce0e03bSab196087 	 *
2892cce0e03bSab196087 	 * These passes cannot be combined:
2893cce0e03bSab196087 	 *	- The string table code works in two passes, and all
2894cce0e03bSab196087 	 *		strings have to be loaded in pass one before the
2895cce0e03bSab196087 	 *		offset of any strings can be determined.
2896cce0e03bSab196087 	 *	- Multiple relocations reference a single symbol, so the
2897cce0e03bSab196087 	 *		symbol cannot be modified until all relocations are
2898cce0e03bSab196087 	 *		fixed.
2899cce0e03bSab196087 	 *
2900cce0e03bSab196087 	 * The number of relocations related to section merging is usually
2901cce0e03bSab196087 	 * a mere fraction of the overall active and output relocation lists,
2902cce0e03bSab196087 	 * and the number of symbols is usually a fraction of the number
2903cce0e03bSab196087 	 * of related relocations. We therefore build APlists for the
2904cce0e03bSab196087 	 * relocations and symbols in the first pass, and then use those
2905cce0e03bSab196087 	 * lists to accelerate the operation of pass 2 and 3.
2906cce0e03bSab196087 	 *
2907cce0e03bSab196087 	 * Reinitialize the lists to a completely empty state.
2908cce0e03bSab196087 	 */
290957ef7aa9SRod Evans 	aplist_reset(*rel_alpp);
291057ef7aa9SRod Evans 	aplist_reset(*sym_alpp);
2911cce0e03bSab196087 
2912cce0e03bSab196087 	/*
2913cce0e03bSab196087 	 * Pass 1:
2914cce0e03bSab196087 	 *
2915cce0e03bSab196087 	 * Every relocation related to this output section (and the input
2916cce0e03bSab196087 	 * sections that make it up) is found in either the active, or the
2917cce0e03bSab196087 	 * output relocation list, depending on whether the relocation is to
2918cce0e03bSab196087 	 * be processed by this invocation of the linker, or inserted into the
2919cce0e03bSab196087 	 * output object.
2920cce0e03bSab196087 	 *
2921cce0e03bSab196087 	 * Build lists of relocations and symbols that will need modification,
2922cce0e03bSab196087 	 * and insert the strings they reference into the mstrtab string table.
2923cce0e03bSab196087 	 */
292457ef7aa9SRod Evans 	if (strmerge_pass1(ofl, osp, mstrtab, rel_alpp, sym_alpp,
2925bf994817SAli Bahrami 	    &ofl->ofl_actrels) == 0)
2926cce0e03bSab196087 		goto return_s_error;
292757ef7aa9SRod Evans 	if (strmerge_pass1(ofl, osp, mstrtab, rel_alpp, sym_alpp,
2928bf994817SAli Bahrami 	    &ofl->ofl_outrels) == 0)
2929cce0e03bSab196087 		goto return_s_error;
2930cce0e03bSab196087 
2931cce0e03bSab196087 	/*
2932cce0e03bSab196087 	 * Get the size of the new input section. Requesting the
2933cce0e03bSab196087 	 * string table size "cooks" the table, and finalizes its contents.
2934cce0e03bSab196087 	 */
2935cce0e03bSab196087 	data_size = st_getstrtab_sz(mstrtab);
2936cce0e03bSab196087 
2937cce0e03bSab196087 	/* Create a new input section to hold the merged strings */
2938cce0e03bSab196087 	if (new_section_from_template(ofl, isp, data_size,
2939cce0e03bSab196087 	    &mstrsec, &mstr_shdr, &mstr_data) == S_ERROR)
2940cce0e03bSab196087 		goto return_s_error;
2941cce0e03bSab196087 	mstrsec->is_flags |= FLG_IS_GNSTRMRG;
2942cce0e03bSab196087 
2943cce0e03bSab196087 	/*
2944cce0e03bSab196087 	 * Allocate a data buffer for the new input section.
2945cce0e03bSab196087 	 * Then, associate the buffer with the string table descriptor.
2946cce0e03bSab196087 	 */
294757ef7aa9SRod Evans 	if ((mstr_data->d_buf = libld_malloc(data_size)) == NULL)
2948cce0e03bSab196087 		goto return_s_error;
2949cce0e03bSab196087 	if (st_setstrbuf(mstrtab, mstr_data->d_buf, data_size) == -1)
2950cce0e03bSab196087 		goto return_s_error;
2951cce0e03bSab196087 
2952cce0e03bSab196087 	/* Add the new section to the output image */
295369112eddSAli Bahrami 	if (ld_place_section(ofl, mstrsec, NULL, osp->os_identndx, NULL) ==
2954cce0e03bSab196087 	    (Os_desc *)S_ERROR)
2955cce0e03bSab196087 		goto return_s_error;
2956cce0e03bSab196087 
2957cce0e03bSab196087 	/*
2958cce0e03bSab196087 	 * Pass 2:
2959cce0e03bSab196087 	 *
2960cce0e03bSab196087 	 * Revisit the relocation descriptors with STT_SECTION symbols
2961cce0e03bSab196087 	 * that were saved by the first pass. Update each relocation
2962cce0e03bSab196087 	 * record so that the offset it contains is for the new section
2963cce0e03bSab196087 	 * instead of the original.
2964cce0e03bSab196087 	 */
296557ef7aa9SRod Evans 	for (APLIST_TRAVERSE(*rel_alpp, idx, rsp)) {
2966cce0e03bSab196087 		const char	*name;
2967cce0e03bSab196087 
2968cce0e03bSab196087 		/* Put the string into the merged string table */
2969cce0e03bSab196087 		name = strmerge_get_reloc_str(ofl, rsp);
2970cce0e03bSab196087 		st_setstring_status = st_setstring(mstrtab, name, &stoff);
2971cce0e03bSab196087 		if (st_setstring_status == -1) {
2972cce0e03bSab196087 			/*
2973cce0e03bSab196087 			 * A failure to insert at this point means that
2974cce0e03bSab196087 			 * something is corrupt. This isn't a resource issue.
2975cce0e03bSab196087 			 */
2976cce0e03bSab196087 			assert(st_setstring_status != -1);
2977cce0e03bSab196087 			goto return_s_error;
2978cce0e03bSab196087 		}
2979cce0e03bSab196087 
2980cce0e03bSab196087 		/*
2981cce0e03bSab196087 		 * Alter the relocation to access the string at the
2982cce0e03bSab196087 		 * new offset in our new string table.
2983cce0e03bSab196087 		 *
2984cce0e03bSab196087 		 * For SHT_RELA platforms, it suffices to simply
2985cce0e03bSab196087 		 * update the rel_raddend field of the relocation.
2986cce0e03bSab196087 		 *
2987cce0e03bSab196087 		 * For SHT_REL platforms, the new "addend" value
2988cce0e03bSab196087 		 * needs to be written at the address being relocated.
2989cce0e03bSab196087 		 * However, we can't alter the input sections which
2990cce0e03bSab196087 		 * are mapped readonly, and the output image has not
2991cce0e03bSab196087 		 * been created yet. So, we defer this operation,
2992cce0e03bSab196087 		 * using the rel_raddend field of the relocation
2993cce0e03bSab196087 		 * which is normally 0 on a REL platform, to pass the
2994cce0e03bSab196087 		 * new "addend" value to ld_perform_outreloc() or
2995cce0e03bSab196087 		 * ld_do_activerelocs(). The FLG_REL_NADDEND flag
2996cce0e03bSab196087 		 * tells them that this is the case.
2997cce0e03bSab196087 		 */
2998cce0e03bSab196087 		if ((rsp->rel_flags & FLG_REL_RELA) == 0)   /* REL */
2999cce0e03bSab196087 			rsp->rel_flags |= FLG_REL_NADDEND;
3000cce0e03bSab196087 		rsp->rel_raddend = (Sxword)stoff;
3001cce0e03bSab196087 
3002cce0e03bSab196087 		/*
3003bf994817SAli Bahrami 		 * Generate a symbol name string for STT_SECTION symbols
3004bf994817SAli Bahrami 		 * that might reference our merged section. This shows up
3005bf994817SAli Bahrami 		 * in debug output and helps show how the relocation has
3006bf994817SAli Bahrami 		 * changed from its original input section to our merged one.
3007cce0e03bSab196087 		 */
3008bf994817SAli Bahrami 		if (ld_stt_section_sym_name(mstrsec) == NULL)
3009cce0e03bSab196087 			goto return_s_error;
3010cce0e03bSab196087 	}
3011cce0e03bSab196087 
3012cce0e03bSab196087 	/*
3013cce0e03bSab196087 	 * Pass 3:
3014cce0e03bSab196087 	 *
3015cce0e03bSab196087 	 * Modify the symbols referenced by the relocation descriptors
3016cce0e03bSab196087 	 * so that they reference the new input section containing the
3017cce0e03bSab196087 	 * merged strings instead of the original input sections.
3018cce0e03bSab196087 	 */
301957ef7aa9SRod Evans 	for (APLIST_TRAVERSE(*sym_alpp, idx, sdp)) {
3020cce0e03bSab196087 		/*
3021cce0e03bSab196087 		 * If we've already processed this symbol, don't do it
3022cce0e03bSab196087 		 * twice. strmerge_pass1() uses a heuristic (relocations to
3023cce0e03bSab196087 		 * the same symbol clump together) to avoid inserting a
3024cce0e03bSab196087 		 * given symbol more than once, but repeat symbols in
3025cce0e03bSab196087 		 * the list can occur.
3026cce0e03bSab196087 		 */
3027cce0e03bSab196087 		if ((sdp->sd_isc->is_flags & FLG_IS_INSTRMRG) == 0)
3028cce0e03bSab196087 			continue;
3029cce0e03bSab196087 
3030cce0e03bSab196087 		if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_SECTION) {
3031cce0e03bSab196087 			/*
3032cce0e03bSab196087 			 * This is not an STT_SECTION symbol, so its
3033cce0e03bSab196087 			 * value is the offset of the string within the
3034cce0e03bSab196087 			 * input section. Update the address to reflect
3035cce0e03bSab196087 			 * the address in our new merged section.
3036cce0e03bSab196087 			 */
3037cce0e03bSab196087 			const char *name = sdp->sd_sym->st_value +
3038cce0e03bSab196087 			    (char *)sdp->sd_isc->is_indata->d_buf;
3039cce0e03bSab196087 
3040cce0e03bSab196087 			st_setstring_status =
3041cce0e03bSab196087 			    st_setstring(mstrtab, name, &stoff);
3042cce0e03bSab196087 			if (st_setstring_status == -1) {
3043cce0e03bSab196087 				/*
3044cce0e03bSab196087 				 * A failure to insert at this point means
3045cce0e03bSab196087 				 * something is corrupt. This isn't a
3046cce0e03bSab196087 				 * resource issue.
3047cce0e03bSab196087 				 */
3048cce0e03bSab196087 				assert(st_setstring_status != -1);
3049cce0e03bSab196087 				goto return_s_error;
3050cce0e03bSab196087 			}
3051cce0e03bSab196087 
3052cce0e03bSab196087 			if (ld_sym_copy(sdp) == S_ERROR)
3053cce0e03bSab196087 				goto return_s_error;
3054cce0e03bSab196087 			sdp->sd_sym->st_value = (Word)stoff;
3055cce0e03bSab196087 		}
3056cce0e03bSab196087 
3057cce0e03bSab196087 		/* Redirect the symbol to our new merged section */
3058cce0e03bSab196087 		sdp->sd_isc = mstrsec;
3059cce0e03bSab196087 	}
3060cce0e03bSab196087 
3061cce0e03bSab196087 	/*
3062cce0e03bSab196087 	 * There are no references left to the original input string sections.
3063cce0e03bSab196087 	 * Mark them as discarded so they don't go into the output image.
3064cce0e03bSab196087 	 * At the same time, add up the sizes of the replaced sections.
3065cce0e03bSab196087 	 */
3066cce0e03bSab196087 	data_size = 0;
3067cce0e03bSab196087 	for (APLIST_TRAVERSE(osp->os_mstrisdescs, idx, isp)) {
3068cce0e03bSab196087 		if (isp->is_flags & (FLG_IS_DISCARD | FLG_IS_GNSTRMRG))
3069cce0e03bSab196087 			continue;
3070cce0e03bSab196087 
3071cce0e03bSab196087 		data_size += isp->is_indata->d_size;
3072cce0e03bSab196087 
3073cce0e03bSab196087 		isp->is_flags |= FLG_IS_DISCARD;
3074cce0e03bSab196087 		DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, isp, mstrsec));
3075cce0e03bSab196087 	}
3076cce0e03bSab196087 
3077cce0e03bSab196087 	/* Report how much space we saved in the output section */
307869112eddSAli Bahrami 	DBG_CALL(Dbg_sec_genstr_compress(ofl->ofl_lml, osp->os_name, data_size,
307969112eddSAli Bahrami 	    mstr_data->d_size));
3080cce0e03bSab196087 
3081cce0e03bSab196087 	st_destroy(mstrtab);
3082cce0e03bSab196087 	return (1);
3083cce0e03bSab196087 
3084cce0e03bSab196087 return_s_error:
3085cce0e03bSab196087 	st_destroy(mstrtab);
3086cce0e03bSab196087 	return (S_ERROR);
3087cce0e03bSab196087 }
3088cce0e03bSab196087 
3089635216b6SRod Evans /*
3090635216b6SRod Evans  * Update a data buffers size.  A number of sections have to be created, and
3091635216b6SRod Evans  * the sections header contributes to the size of the eventual section.  Thus,
3092635216b6SRod Evans  * a section may be created, and once all associated sections have been created,
3093635216b6SRod Evans  * we return to establish the required section size.
3094635216b6SRod Evans  */
3095635216b6SRod Evans inline static void
3096635216b6SRod Evans update_data_size(Os_desc *osp, ulong_t cnt)
3097635216b6SRod Evans {
3098635216b6SRod Evans 	Is_desc		*isec = ld_os_first_isdesc(osp);
3099635216b6SRod Evans 	Elf_Data	*data = isec->is_indata;
3100635216b6SRod Evans 	Shdr		*shdr = osp->os_shdr;
3101635216b6SRod Evans 	size_t		size = cnt * shdr->sh_entsize;
3102635216b6SRod Evans 
3103635216b6SRod Evans 	shdr->sh_size = (Xword)size;
3104635216b6SRod Evans 	data->d_size = size;
3105635216b6SRod Evans }
3106cce0e03bSab196087 
3107cce0e03bSab196087 /*
31087c478bd9Sstevel@tonic-gate  * The following sections are built after all input file processing and symbol
31097c478bd9Sstevel@tonic-gate  * validation has been carried out.  The order is important (because the
31107c478bd9Sstevel@tonic-gate  * addition of a section adds a new symbol there is a chicken and egg problem
31117c478bd9Sstevel@tonic-gate  * of maintaining the appropriate counts).  By maintaining a known order the
31127c478bd9Sstevel@tonic-gate  * individual routines can compensate for later, known, additions.
31137c478bd9Sstevel@tonic-gate  */
31147c478bd9Sstevel@tonic-gate uintptr_t
31155aefb655Srie ld_make_sections(Ofl_desc *ofl)
31167c478bd9Sstevel@tonic-gate {
31171d9df23bSab196087 	ofl_flag_t	flags = ofl->ofl_flags;
31187c478bd9Sstevel@tonic-gate 	Sg_desc		*sgp;
31197c478bd9Sstevel@tonic-gate 
31207c478bd9Sstevel@tonic-gate 	/*
31217c478bd9Sstevel@tonic-gate 	 * Generate any special sections.
31227c478bd9Sstevel@tonic-gate 	 */
31237c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_ADDVERS)
31247c478bd9Sstevel@tonic-gate 		if (make_comment(ofl) == S_ERROR)
31257c478bd9Sstevel@tonic-gate 			return (S_ERROR);
31267c478bd9Sstevel@tonic-gate 
31277c478bd9Sstevel@tonic-gate 	if (make_interp(ofl) == S_ERROR)
31287c478bd9Sstevel@tonic-gate 		return (S_ERROR);
31297c478bd9Sstevel@tonic-gate 
313008278a5eSRod Evans 	/*
313108278a5eSRod Evans 	 * Create a capabilities section if required.
313208278a5eSRod Evans 	 */
313308278a5eSRod Evans 	if (make_cap(ofl, SHT_SUNW_cap, MSG_ORIG(MSG_SCN_SUNWCAP),
313408278a5eSRod Evans 	    ld_targ.t_id.id_cap) == S_ERROR)
31357c478bd9Sstevel@tonic-gate 		return (S_ERROR);
31367c478bd9Sstevel@tonic-gate 
313708278a5eSRod Evans 	/*
313808278a5eSRod Evans 	 * Create any init/fini array sections.
313908278a5eSRod Evans 	 */
31407c478bd9Sstevel@tonic-gate 	if (make_array(ofl, SHT_INIT_ARRAY, MSG_ORIG(MSG_SCN_INITARRAY),
314157ef7aa9SRod Evans 	    ofl->ofl_initarray) == S_ERROR)
31427c478bd9Sstevel@tonic-gate 		return (S_ERROR);
31437c478bd9Sstevel@tonic-gate 
31447c478bd9Sstevel@tonic-gate 	if (make_array(ofl, SHT_FINI_ARRAY, MSG_ORIG(MSG_SCN_FINIARRAY),
314557ef7aa9SRod Evans 	    ofl->ofl_finiarray) == S_ERROR)
31467c478bd9Sstevel@tonic-gate 		return (S_ERROR);
31477c478bd9Sstevel@tonic-gate 
31487c478bd9Sstevel@tonic-gate 	if (make_array(ofl, SHT_PREINIT_ARRAY, MSG_ORIG(MSG_SCN_PREINITARRAY),
314957ef7aa9SRod Evans 	    ofl->ofl_preiarray) == S_ERROR)
31507c478bd9Sstevel@tonic-gate 		return (S_ERROR);
31517c478bd9Sstevel@tonic-gate 
31527c478bd9Sstevel@tonic-gate 	/*
31537c478bd9Sstevel@tonic-gate 	 * Make the .plt section.  This occurs after any other relocation
31547c478bd9Sstevel@tonic-gate 	 * sections are generated (see reloc_init()) to ensure that the
31557c478bd9Sstevel@tonic-gate 	 * associated relocation section is after all the other relocation
31567c478bd9Sstevel@tonic-gate 	 * sections.
31577c478bd9Sstevel@tonic-gate 	 */
31587c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_pltcnt) || (ofl->ofl_pltpad))
31597c478bd9Sstevel@tonic-gate 		if (make_plt(ofl) == S_ERROR)
31607c478bd9Sstevel@tonic-gate 			return (S_ERROR);
31617c478bd9Sstevel@tonic-gate 
3162fb1354edSrie 	/*
3163fb1354edSrie 	 * Determine whether any sections or files are not referenced.  Under
3164fb1354edSrie 	 * -Dunused a diagnostic for any unused components is generated, under
3165fb1354edSrie 	 * -zignore the component is removed from the final output.
3166fb1354edSrie 	 */
31675aefb655Srie 	if (DBG_ENABLED || (ofl->ofl_flags1 & FLG_OF1_IGNPRC)) {
31687c478bd9Sstevel@tonic-gate 		if (ignore_section_processing(ofl) == S_ERROR)
31697c478bd9Sstevel@tonic-gate 			return (S_ERROR);
31707c478bd9Sstevel@tonic-gate 	}
31717c478bd9Sstevel@tonic-gate 
31727c478bd9Sstevel@tonic-gate 	/*
3173e64d0ff9SAli Bahrami 	 * If we have detected a situation in which previously placed
3174e64d0ff9SAli Bahrami 	 * output sections may have been discarded, perform the necessary
3175e64d0ff9SAli Bahrami 	 * readjustment.
3176e64d0ff9SAli Bahrami 	 */
3177e64d0ff9SAli Bahrami 	if (ofl->ofl_flags & FLG_OF_ADJOSCNT)
3178e64d0ff9SAli Bahrami 		adjust_os_count(ofl);
3179e64d0ff9SAli Bahrami 
3180e64d0ff9SAli Bahrami 	/*
3181cce0e03bSab196087 	 * Do any of the output sections contain input sections that
3182cce0e03bSab196087 	 * are candidates for string table merging? For each such case,
3183cce0e03bSab196087 	 * we create a replacement section, insert it, and discard the
3184cce0e03bSab196087 	 * originals.
3185cce0e03bSab196087 	 *
318657ef7aa9SRod Evans 	 * rel_alpp and sym_alpp are used by ld_make_strmerge()
3187cce0e03bSab196087 	 * for its internal processing. We are responsible for the
3188cce0e03bSab196087 	 * initialization and cleanup, and ld_make_strmerge() handles the rest.
318957ef7aa9SRod Evans 	 * This allows us to reuse a single pair of memory buffers, allocated
319057ef7aa9SRod Evans 	 * for this processing, for all the output sections.
3191cce0e03bSab196087 	 */
3192cce0e03bSab196087 	if ((ofl->ofl_flags1 & FLG_OF1_NCSTTAB) == 0) {
3193cce0e03bSab196087 		int	error_seen = 0;
319457ef7aa9SRod Evans 		APlist	*rel_alpp = NULL;
319557ef7aa9SRod Evans 		APlist	*sym_alpp = NULL;
319657ef7aa9SRod Evans 		Aliste	idx1;
3197cce0e03bSab196087 
319857ef7aa9SRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
3199cce0e03bSab196087 			Os_desc	*osp;
320057ef7aa9SRod Evans 			Aliste	idx2;
3201cce0e03bSab196087 
320257ef7aa9SRod Evans 			for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp))
3203cce0e03bSab196087 				if ((osp->os_mstrisdescs != NULL) &&
3204cce0e03bSab196087 				    (ld_make_strmerge(ofl, osp,
320557ef7aa9SRod Evans 				    &rel_alpp, &sym_alpp) ==
3206cce0e03bSab196087 				    S_ERROR)) {
3207cce0e03bSab196087 					error_seen = 1;
3208cce0e03bSab196087 					break;
3209cce0e03bSab196087 				}
3210cce0e03bSab196087 		}
321157ef7aa9SRod Evans 		if (rel_alpp != NULL)
321269112eddSAli Bahrami 			libld_free(rel_alpp);
321357ef7aa9SRod Evans 		if (sym_alpp != NULL)
321469112eddSAli Bahrami 			libld_free(sym_alpp);
3215cce0e03bSab196087 		if (error_seen != 0)
3216cce0e03bSab196087 			return (S_ERROR);
3217cce0e03bSab196087 	}
3218cce0e03bSab196087 
3219cce0e03bSab196087 	/*
32207c478bd9Sstevel@tonic-gate 	 * Add any necessary versioning information.
32217c478bd9Sstevel@tonic-gate 	 */
3222090a8d9eSAli Bahrami 	if (!(flags & FLG_OF_NOVERSEC)) {
3223090a8d9eSAli Bahrami 		if ((flags & FLG_OF_VERNEED) &&
3224090a8d9eSAli Bahrami 		    (make_verneed(ofl) == S_ERROR))
32257c478bd9Sstevel@tonic-gate 			return (S_ERROR);
3226090a8d9eSAli Bahrami 		if ((flags & FLG_OF_VERDEF) &&
3227090a8d9eSAli Bahrami 		    (make_verdef(ofl) == S_ERROR))
32287c478bd9Sstevel@tonic-gate 			return (S_ERROR);
3229090a8d9eSAli Bahrami 		if ((flags & (FLG_OF_VERNEED | FLG_OF_VERDEF)) &&
3230090a8d9eSAli Bahrami 		    ((ofl->ofl_osversym = make_sym_sec(ofl,
32319039eeafSab196087 		    MSG_ORIG(MSG_SCN_SUNWVERSYM), SHT_SUNW_versym,
3232090a8d9eSAli Bahrami 		    ld_targ.t_id.id_version)) == (Os_desc*)S_ERROR))
32337c478bd9Sstevel@tonic-gate 			return (S_ERROR);
32347c478bd9Sstevel@tonic-gate 	}
32357c478bd9Sstevel@tonic-gate 
32367c478bd9Sstevel@tonic-gate 	/*
32379039eeafSab196087 	 * Create a syminfo section if necessary.
32387c478bd9Sstevel@tonic-gate 	 */
32391d9df23bSab196087 	if (flags & FLG_OF_SYMINFO) {
32407c478bd9Sstevel@tonic-gate 		if ((ofl->ofl_ossyminfo = make_sym_sec(ofl,
32419039eeafSab196087 		    MSG_ORIG(MSG_SCN_SUNWSYMINFO), SHT_SUNW_syminfo,
3242ba2be530Sab196087 		    ld_targ.t_id.id_syminfo)) == (Os_desc *)S_ERROR)
32437c478bd9Sstevel@tonic-gate 			return (S_ERROR);
32447c478bd9Sstevel@tonic-gate 	}
32457c478bd9Sstevel@tonic-gate 
32461d9df23bSab196087 	if (flags & FLG_OF_COMREL) {
32477c478bd9Sstevel@tonic-gate 		/*
32487c478bd9Sstevel@tonic-gate 		 * If -zcombreloc is enabled then all relocations (except for
32497c478bd9Sstevel@tonic-gate 		 * the PLT's) are coalesced into a single relocation section.
32507c478bd9Sstevel@tonic-gate 		 */
32517c478bd9Sstevel@tonic-gate 		if (ofl->ofl_reloccnt) {
32527c478bd9Sstevel@tonic-gate 			if (make_reloc(ofl, NULL) == S_ERROR)
32537c478bd9Sstevel@tonic-gate 				return (S_ERROR);
32547c478bd9Sstevel@tonic-gate 		}
32557c478bd9Sstevel@tonic-gate 	} else {
325657ef7aa9SRod Evans 		Aliste	idx1;
325757ef7aa9SRod Evans 
32587c478bd9Sstevel@tonic-gate 		/*
32590bc07c75Srie 		 * Create the required output relocation sections.  Note, new
32600bc07c75Srie 		 * sections may be added to the section list that is being
32610bc07c75Srie 		 * traversed.  These insertions can move the elements of the
32620bc07c75Srie 		 * Alist such that a section descriptor is re-read.  Recursion
32630bc07c75Srie 		 * is prevented by maintaining a previous section pointer and
32640bc07c75Srie 		 * insuring that this pointer isn't re-examined.
32657c478bd9Sstevel@tonic-gate 		 */
326657ef7aa9SRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
3267cce0e03bSab196087 			Os_desc	*osp, *posp = 0;
326857ef7aa9SRod Evans 			Aliste	idx2;
32697c478bd9Sstevel@tonic-gate 
327057ef7aa9SRod Evans 			for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
32710bc07c75Srie 				if ((osp != posp) && osp->os_szoutrels &&
32727c478bd9Sstevel@tonic-gate 				    (osp != ofl->ofl_osplt)) {
32737c478bd9Sstevel@tonic-gate 					if (make_reloc(ofl, osp) == S_ERROR)
32747c478bd9Sstevel@tonic-gate 						return (S_ERROR);
32757c478bd9Sstevel@tonic-gate 				}
32760bc07c75Srie 				posp = osp;
32777c478bd9Sstevel@tonic-gate 			}
32787c478bd9Sstevel@tonic-gate 		}
32797c478bd9Sstevel@tonic-gate 
32807c478bd9Sstevel@tonic-gate 		/*
32817c478bd9Sstevel@tonic-gate 		 * If we're not building a combined relocation section, then
32827c478bd9Sstevel@tonic-gate 		 * build a .rel[a] section as required.
32837c478bd9Sstevel@tonic-gate 		 */
32847c478bd9Sstevel@tonic-gate 		if (ofl->ofl_relocrelsz) {
32857c478bd9Sstevel@tonic-gate 			if (make_reloc(ofl, NULL) == S_ERROR)
32867c478bd9Sstevel@tonic-gate 				return (S_ERROR);
32877c478bd9Sstevel@tonic-gate 		}
32887c478bd9Sstevel@tonic-gate 	}
32897c478bd9Sstevel@tonic-gate 
32907c478bd9Sstevel@tonic-gate 	/*
32917c478bd9Sstevel@tonic-gate 	 * The PLT relocations are always in their own section, and we try to
32927c478bd9Sstevel@tonic-gate 	 * keep them at the end of the PLT table.  We do this to keep the hot
32937c478bd9Sstevel@tonic-gate 	 * "data" PLT's at the head of the table nearer the .dynsym & .hash.
32947c478bd9Sstevel@tonic-gate 	 */
32957c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osplt && ofl->ofl_relocpltsz) {
32967c478bd9Sstevel@tonic-gate 		if (make_reloc(ofl, ofl->ofl_osplt) == S_ERROR)
32977c478bd9Sstevel@tonic-gate 			return (S_ERROR);
32987c478bd9Sstevel@tonic-gate 	}
32997c478bd9Sstevel@tonic-gate 
33007c478bd9Sstevel@tonic-gate 	/*
33017c478bd9Sstevel@tonic-gate 	 * Finally build the symbol and section header sections.
33027c478bd9Sstevel@tonic-gate 	 */
33037c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_DYNAMIC) {
33047c478bd9Sstevel@tonic-gate 		if (make_dynamic(ofl) == S_ERROR)
33057c478bd9Sstevel@tonic-gate 			return (S_ERROR);
3306635216b6SRod Evans 
33077c478bd9Sstevel@tonic-gate 		/*
3308635216b6SRod Evans 		 * A number of sections aren't necessary within a relocatable
3309635216b6SRod Evans 		 * object, even if -dy has been used.
33107c478bd9Sstevel@tonic-gate 		 */
33117c478bd9Sstevel@tonic-gate 		if (!(flags & FLG_OF_RELOBJ)) {
33127c478bd9Sstevel@tonic-gate 			if (make_hash(ofl) == S_ERROR)
33137c478bd9Sstevel@tonic-gate 				return (S_ERROR);
3314635216b6SRod Evans 			if (make_dynstr(ofl) == S_ERROR)
3315635216b6SRod Evans 				return (S_ERROR);
33167c478bd9Sstevel@tonic-gate 			if (make_dynsym(ofl) == S_ERROR)
33177c478bd9Sstevel@tonic-gate 				return (S_ERROR);
33187e16fca0SAli Bahrami 			if (ld_unwind_make_hdr(ofl) == S_ERROR)
33197c478bd9Sstevel@tonic-gate 				return (S_ERROR);
3320d579eb63Sab196087 			if (make_dynsort(ofl) == S_ERROR)
3321d579eb63Sab196087 				return (S_ERROR);
33227c478bd9Sstevel@tonic-gate 		}
33237c478bd9Sstevel@tonic-gate 	}
33247c478bd9Sstevel@tonic-gate 
33257c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) ||
33267c478bd9Sstevel@tonic-gate 	    ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) {
33277c478bd9Sstevel@tonic-gate 		/*
33287c478bd9Sstevel@tonic-gate 		 * Do we need to make a SHT_SYMTAB_SHNDX section
33297c478bd9Sstevel@tonic-gate 		 * for the dynsym.  If so - do it now.
33307c478bd9Sstevel@tonic-gate 		 */
33317c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynsym &&
33327c478bd9Sstevel@tonic-gate 		    ((ofl->ofl_shdrcnt + 3) >= SHN_LORESERVE)) {
33337c478bd9Sstevel@tonic-gate 			if (make_dynsym_shndx(ofl) == S_ERROR)
33347c478bd9Sstevel@tonic-gate 				return (S_ERROR);
33357c478bd9Sstevel@tonic-gate 		}
33367c478bd9Sstevel@tonic-gate 
33377c478bd9Sstevel@tonic-gate 		if (make_strtab(ofl) == S_ERROR)
33387c478bd9Sstevel@tonic-gate 			return (S_ERROR);
33397c478bd9Sstevel@tonic-gate 		if (make_symtab(ofl) == S_ERROR)
33407c478bd9Sstevel@tonic-gate 			return (S_ERROR);
33417c478bd9Sstevel@tonic-gate 	} else {
33427c478bd9Sstevel@tonic-gate 		/*
33437c478bd9Sstevel@tonic-gate 		 * Do we need to make a SHT_SYMTAB_SHNDX section
33447c478bd9Sstevel@tonic-gate 		 * for the dynsym.  If so - do it now.
33457c478bd9Sstevel@tonic-gate 		 */
33467c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynsym &&
33477c478bd9Sstevel@tonic-gate 		    ((ofl->ofl_shdrcnt + 1) >= SHN_LORESERVE)) {
33487c478bd9Sstevel@tonic-gate 			if (make_dynsym_shndx(ofl) == S_ERROR)
33497c478bd9Sstevel@tonic-gate 				return (S_ERROR);
33507c478bd9Sstevel@tonic-gate 		}
33517c478bd9Sstevel@tonic-gate 	}
33527c478bd9Sstevel@tonic-gate 
33537c478bd9Sstevel@tonic-gate 	if (make_shstrtab(ofl) == S_ERROR)
33547c478bd9Sstevel@tonic-gate 		return (S_ERROR);
33557c478bd9Sstevel@tonic-gate 
33567c478bd9Sstevel@tonic-gate 	/*
3357635216b6SRod Evans 	 * Now that we've created all output sections, adjust the size of the
3358635216b6SRod Evans 	 * SHT_SUNW_versym and SHT_SUNW_syminfo section, which are dependent on
3359635216b6SRod Evans 	 * the associated symbol table sizes.
33607c478bd9Sstevel@tonic-gate 	 */
33617c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osversym || ofl->ofl_ossyminfo) {
33627c478bd9Sstevel@tonic-gate 		ulong_t		cnt;
3363635216b6SRod Evans 		Is_desc		*isp;
336460758829Srie 		Os_desc		*osp;
33657c478bd9Sstevel@tonic-gate 
3366635216b6SRod Evans 		if (OFL_IS_STATIC_OBJ(ofl))
336760758829Srie 			osp = ofl->ofl_ossymtab;
3368635216b6SRod Evans 		else
336960758829Srie 			osp = ofl->ofl_osdynsym;
33707c478bd9Sstevel@tonic-gate 
3371635216b6SRod Evans 		isp = ld_os_first_isdesc(osp);
3372635216b6SRod Evans 		cnt = (isp->is_shdr->sh_size / isp->is_shdr->sh_entsize);
3373635216b6SRod Evans 
3374635216b6SRod Evans 		if (ofl->ofl_osversym)
3375635216b6SRod Evans 			update_data_size(ofl->ofl_osversym, cnt);
3376635216b6SRod Evans 
3377635216b6SRod Evans 		if (ofl->ofl_ossyminfo)
3378635216b6SRod Evans 			update_data_size(ofl->ofl_ossyminfo, cnt);
33797c478bd9Sstevel@tonic-gate 	}
33807c478bd9Sstevel@tonic-gate 
338108278a5eSRod Evans 	/*
338208278a5eSRod Evans 	 * Now that we've created all output sections, adjust the size of the
338308278a5eSRod Evans 	 * SHT_SUNW_capinfo, which is dependent on the associated symbol table
338408278a5eSRod Evans 	 * size.
338508278a5eSRod Evans 	 */
338608278a5eSRod Evans 	if (ofl->ofl_oscapinfo) {
338708278a5eSRod Evans 		ulong_t	cnt;
338808278a5eSRod Evans 
338908278a5eSRod Evans 		/*
339008278a5eSRod Evans 		 * Symbol capabilities symbols are placed directly after the
339108278a5eSRod Evans 		 * STT_FILE symbol, section symbols, and any register symbols.
339208278a5eSRod Evans 		 * Effectively these are the first of any series of demoted
339308278a5eSRod Evans 		 * (scoped) symbols.
339408278a5eSRod Evans 		 */
339508278a5eSRod Evans 		if (OFL_IS_STATIC_OBJ(ofl))
339608278a5eSRod Evans 			cnt = SYMTAB_ALL_CNT(ofl);
339708278a5eSRod Evans 		else
339808278a5eSRod Evans 			cnt = DYNSYM_ALL_CNT(ofl);
339908278a5eSRod Evans 
340008278a5eSRod Evans 		update_data_size(ofl->ofl_oscapinfo, cnt);
340108278a5eSRod Evans 	}
34027c478bd9Sstevel@tonic-gate 	return (1);
34037c478bd9Sstevel@tonic-gate }
3404c1c6f601Srie 
3405c1c6f601Srie /*
3406c1c6f601Srie  * Build an additional data section - used to back OBJT symbol definitions
3407c1c6f601Srie  * added with a mapfile.
3408c1c6f601Srie  */
3409c1c6f601Srie Is_desc *
3410c1c6f601Srie ld_make_data(Ofl_desc *ofl, size_t size)
3411c1c6f601Srie {
3412c1c6f601Srie 	Shdr		*shdr;
3413c1c6f601Srie 	Elf_Data	*data;
3414c1c6f601Srie 	Is_desc		*isec;
3415c1c6f601Srie 
34169039eeafSab196087 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_DATA), 0,
34179039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
3418c1c6f601Srie 		return ((Is_desc *)S_ERROR);
34199039eeafSab196087 
3420c1c6f601Srie 	data->d_size = size;
3421c1c6f601Srie 	shdr->sh_size = (Xword)size;
34229039eeafSab196087 	shdr->sh_flags |= SHF_WRITE;
3423c1c6f601Srie 
342457ef7aa9SRod Evans 	if (aplist_append(&ofl->ofl_mapdata, isec, AL_CNT_OFL_MAPSECS) == NULL)
3425c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3426c1c6f601Srie 
3427c1c6f601Srie 	return (isec);
3428c1c6f601Srie }
3429c1c6f601Srie 
3430c1c6f601Srie /*
3431c1c6f601Srie  * Build an additional text section - used to back FUNC symbol definitions
3432c1c6f601Srie  * added with a mapfile.
3433c1c6f601Srie  */
3434c1c6f601Srie Is_desc *
3435c1c6f601Srie ld_make_text(Ofl_desc *ofl, size_t size)
3436c1c6f601Srie {
3437c1c6f601Srie 	Shdr		*shdr;
3438c1c6f601Srie 	Elf_Data	*data;
3439c1c6f601Srie 	Is_desc		*isec;
3440c1c6f601Srie 
3441c1c6f601Srie 	/*
3442c1c6f601Srie 	 * Insure the size is sufficient to contain the minimum return
3443c1c6f601Srie 	 * instruction.
3444c1c6f601Srie 	 */
3445ba2be530Sab196087 	if (size < ld_targ.t_nf.nf_size)
3446ba2be530Sab196087 		size = ld_targ.t_nf.nf_size;
3447c1c6f601Srie 
34489039eeafSab196087 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_TEXT), 0,
34499039eeafSab196087 	    &isec, &shdr, &data) == S_ERROR)
3450c1c6f601Srie 		return ((Is_desc *)S_ERROR);
34519039eeafSab196087 
3452c1c6f601Srie 	data->d_size = size;
3453c1c6f601Srie 	shdr->sh_size = (Xword)size;
34549039eeafSab196087 	shdr->sh_flags |= SHF_EXECINSTR;
3455c1c6f601Srie 
3456ba2be530Sab196087 	/*
3457ba2be530Sab196087 	 * Fill the buffer with the appropriate return instruction.
3458ba2be530Sab196087 	 * Note that there is no need to swap bytes on a non-native,
3459ba2be530Sab196087 	 * link, as the data being copied is given in bytes.
3460ba2be530Sab196087 	 */
346157ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(size, 1)) == NULL)
3462c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3463ba2be530Sab196087 	(void) memcpy(data->d_buf, ld_targ.t_nf.nf_template,
3464ba2be530Sab196087 	    ld_targ.t_nf.nf_size);
3465c1c6f601Srie 
34663c573fccSAli Bahrami 	/*
34673c573fccSAli Bahrami 	 * If size was larger than required, and the target supplies
34683c573fccSAli Bahrami 	 * a fill function, use it to fill the balance. If there is no
34693c573fccSAli Bahrami 	 * fill function, we accept the 0-fill supplied by libld_calloc().
34703c573fccSAli Bahrami 	 */
34713c573fccSAli Bahrami 	if ((ld_targ.t_ff.ff_execfill != NULL) && (size > ld_targ.t_nf.nf_size))
34723c573fccSAli Bahrami 		ld_targ.t_ff.ff_execfill(data->d_buf, ld_targ.t_nf.nf_size,
34733c573fccSAli Bahrami 		    size - ld_targ.t_nf.nf_size);
34743c573fccSAli Bahrami 
347557ef7aa9SRod Evans 	if (aplist_append(&ofl->ofl_maptext, isec, AL_CNT_OFL_MAPSECS) == NULL)
3476c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3477c1c6f601Srie 
3478c1c6f601Srie 	return (isec);
3479c1c6f601Srie }
3480ef16f6b5SRichard Lowe 
3481ef16f6b5SRichard Lowe void
3482ef16f6b5SRichard Lowe ld_comdat_validate(Ofl_desc *ofl, Ifl_desc *ifl)
3483ef16f6b5SRichard Lowe {
3484ef16f6b5SRichard Lowe 	int i;
3485ef16f6b5SRichard Lowe 
3486ef16f6b5SRichard Lowe 	for (i = 0; i < ifl->ifl_shnum; i++) {
3487ef16f6b5SRichard Lowe 		Is_desc *isp = ifl->ifl_isdesc[i];
3488ef16f6b5SRichard Lowe 		int types = 0;
3489ef16f6b5SRichard Lowe 		char buf[1024] = "";
3490ef16f6b5SRichard Lowe 		Group_desc *gr = NULL;
3491ef16f6b5SRichard Lowe 
3492ef16f6b5SRichard Lowe 		if ((isp == NULL) || (isp->is_flags & FLG_IS_COMDAT) == 0)
3493ef16f6b5SRichard Lowe 			continue;
3494ef16f6b5SRichard Lowe 
3495ef16f6b5SRichard Lowe 		if (isp->is_shdr->sh_type == SHT_SUNW_COMDAT) {
3496ef16f6b5SRichard Lowe 			types++;
3497ef16f6b5SRichard Lowe 			(void) strlcpy(buf, MSG_ORIG(MSG_STR_SUNW_COMDAT),
3498ef16f6b5SRichard Lowe 			    sizeof (buf));
3499ef16f6b5SRichard Lowe 		}
3500ef16f6b5SRichard Lowe 
3501ef16f6b5SRichard Lowe 		if (strncmp(MSG_ORIG(MSG_SCN_GNU_LINKONCE), isp->is_name,
3502ef16f6b5SRichard Lowe 		    MSG_SCN_GNU_LINKONCE_SIZE) == 0) {
3503ef16f6b5SRichard Lowe 			types++;
3504ef16f6b5SRichard Lowe 			if (types > 1)
3505ef16f6b5SRichard Lowe 				(void) strlcat(buf, ", ", sizeof (buf));
3506ef16f6b5SRichard Lowe 			(void) strlcat(buf, MSG_ORIG(MSG_SCN_GNU_LINKONCE),
3507ef16f6b5SRichard Lowe 			    sizeof (buf));
3508ef16f6b5SRichard Lowe 		}
3509ef16f6b5SRichard Lowe 
3510ef16f6b5SRichard Lowe 		if ((isp->is_shdr->sh_flags & SHF_GROUP) &&
3511ef16f6b5SRichard Lowe 		    ((gr = ld_get_group(ofl, isp)) != NULL) &&
3512ef16f6b5SRichard Lowe 		    (gr->gd_data[0] & GRP_COMDAT)) {
3513ef16f6b5SRichard Lowe 			types++;
3514ef16f6b5SRichard Lowe 			if (types > 1)
3515ef16f6b5SRichard Lowe 				(void) strlcat(buf, ", ", sizeof (buf));
3516ef16f6b5SRichard Lowe 			(void) strlcat(buf, MSG_ORIG(MSG_STR_GROUP),
3517ef16f6b5SRichard Lowe 			    sizeof (buf));
3518ef16f6b5SRichard Lowe 		}
3519ef16f6b5SRichard Lowe 
3520ef16f6b5SRichard Lowe 		if (types > 1)
3521ef16f6b5SRichard Lowe 			ld_eprintf(ofl, ERR_FATAL,
3522ef16f6b5SRichard Lowe 			    MSG_INTL(MSG_SCN_MULTICOMDAT), ifl->ifl_name,
3523ef16f6b5SRichard Lowe 			    EC_WORD(isp->is_scnndx), isp->is_name, buf);
3524ef16f6b5SRichard Lowe 	}
3525ef16f6b5SRichard Lowe }
3526