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.
27*56726c7eSRobert Mustacchi  * Copyright 2022 Oxide Computer Company
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Module sections. Initialize special sections
327c478bd9Sstevel@tonic-gate  */
33ba2be530Sab 
34ba2be530Sab #define	ELF_TARGET_AMD64
35ba2be530Sab 
36252adeb3SRichard Lowe #include	<sys/debug.h>
37252adeb3SRichard Lowe 
387c478bd9Sstevel@tonic-gate #include	<string.h>
397c478bd9Sstevel@tonic-gate #include	<strings.h>
407c478bd9Sstevel@tonic-gate #include	<stdio.h>
417c478bd9Sstevel@tonic-gate #include	<link.h>
425aefb655Srie #include	<debug.h>
437c478bd9Sstevel@tonic-gate #include	"msg.h"
447c478bd9Sstevel@tonic-gate #include	"_libld.h"
457c478bd9Sstevel@tonic-gate 
46a194faf8Srie inline static void
remove_local(Ofl_desc * ofl,Sym_desc * sdp,int allow_ldynsym)4760758829Srie remove_local(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
4860758829Srie {
4960758829Srie 	Sym	*sym = sdp->sd_sym;
5060758829Srie 	uchar_t	type = ELF_ST_TYPE(sym->st_info);
5160758829Srie 	/* LINTED - only used for assert() */
5260758829Srie 	int	err;
5360758829Srie 
5444bac77bSrie 	if ((ofl->ofl_flags & FLG_OF_REDLSYM) == 0) {
5560758829Srie 		ofl->ofl_locscnt--;
56a194faf8Srie 
5760758829Srie 		err = st_delstring(ofl->ofl_strtab, sdp->sd_name);
5860758829Srie 		assert(err != -1);
5960758829Srie 
6060758829Srie 		if (allow_ldynsym && ldynsym_symtype[type]) {
6160758829Srie 			ofl->ofl_dynlocscnt--;
62a194faf8Srie 
6360758829Srie 			err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
6460758829Srie 			assert(err != -1);
6560758829Srie 			/* Remove from sort section? */
6660758829Srie 			DYNSORT_COUNT(sdp, sym, type, --);
6760758829Srie 		}
6860758829Srie 	}
6960758829Srie 	sdp->sd_flags |= FLG_SY_ISDISC;
7060758829Srie }
7160758829Srie 
72a194faf8Srie inline static void
remove_scoped(Ofl_desc * ofl,Sym_desc * sdp,int allow_ldynsym)7360758829Srie remove_scoped(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
7460758829Srie {
7560758829Srie 	Sym	*sym = sdp->sd_sym;
7660758829Srie 	uchar_t	type = ELF_ST_TYPE(sym->st_info);
7760758829Srie 	/* LINTED - only used for assert() */
7860758829Srie 	int	err;
7960758829Srie 
8060758829Srie 	ofl->ofl_scopecnt--;
8160758829Srie 	ofl->ofl_elimcnt++;
8260758829Srie 
8360758829Srie 	err = st_delstring(ofl->ofl_strtab, sdp->sd_name);
8460758829Srie 	assert(err != -1);
8560758829Srie 
8660758829Srie 	if (allow_ldynsym && ldynsym_symtype[type]) {
8760758829Srie 		ofl->ofl_dynscopecnt--;
88a194faf8Srie 
8960758829Srie 		err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
9060758829Srie 		assert(err != -1);
9160758829Srie 		/* Remove from sort section? */
9260758829Srie 		DYNSORT_COUNT(sdp, sym, type, --);
9360758829Srie 	}
94635216b6SRod Evans 	sdp->sd_flags |= FLG_SY_ELIM;
9560758829Srie }
9660758829Srie 
97a194faf8Srie inline static void
ignore_sym(Ofl_desc * ofl,Ifl_desc * ifl,Sym_desc * sdp,int allow_ldynsym)98a194faf8Srie ignore_sym(Ofl_desc *ofl, Ifl_desc *ifl, Sym_desc *sdp, int allow_ldynsym)
99a194faf8Srie {
100a194faf8Srie 	Os_desc	*osp;
101a194faf8Srie 	Is_desc	*isp = sdp->sd_isc;
102a194faf8Srie 	uchar_t	bind = ELF_ST_BIND(sdp->sd_sym->st_info);
103a194faf8Srie 
104a194faf8Srie 	if (bind == STB_LOCAL) {
105a194faf8Srie 		uchar_t	type = ELF_ST_TYPE(sdp->sd_sym->st_info);
106a194faf8Srie 
107a194faf8Srie 		/*
108a194faf8Srie 		 * Skip section symbols, these were never collected in the
109a194faf8Srie 		 * first place.
110a194faf8Srie 		 */
111a194faf8Srie 		if (type == STT_SECTION)
112a194faf8Srie 			return;
113a194faf8Srie 
114a194faf8Srie 		/*
115a194faf8Srie 		 * Determine if the whole file is being removed.  Remove any
116a194faf8Srie 		 * file symbol, and any symbol that is not associated with a
117a194faf8Srie 		 * section, provided the symbol has not been identified as
118a194faf8Srie 		 * (update) required.
119a194faf8Srie 		 */
120a194faf8Srie 		if (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) &&
121a194faf8Srie 		    ((type == STT_FILE) || ((isp == NULL) &&
122a194faf8Srie 		    ((sdp->sd_flags & FLG_SY_UPREQD) == 0)))) {
123a194faf8Srie 			DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
124a194faf8Srie 			if (ifl->ifl_flags & FLG_IF_IGNORE)
125a194faf8Srie 				remove_local(ofl, sdp, allow_ldynsym);
126a194faf8Srie 			return;
127a194faf8Srie 		}
128a194faf8Srie 
129a194faf8Srie 	} else {
130a194faf8Srie 		/*
131a194faf8Srie 		 * Global symbols can only be eliminated when the interfaces of
132a194faf8Srie 		 * an object have been defined via versioning/scoping.
133a194faf8Srie 		 */
13408278a5eSRod Evans 		if (!SYM_IS_HIDDEN(sdp))
135a194faf8Srie 			return;
136a194faf8Srie 
137a194faf8Srie 		/*
138a194faf8Srie 		 * Remove any unreferenced symbols that are not associated with
139a194faf8Srie 		 * a section.
140a194faf8Srie 		 */
141a194faf8Srie 		if ((isp == NULL) && ((sdp->sd_flags & FLG_SY_UPREQD) == 0)) {
142a194faf8Srie 			DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
143a194faf8Srie 			if (ifl->ifl_flags & FLG_IF_IGNORE)
144a194faf8Srie 				remove_scoped(ofl, sdp, allow_ldynsym);
145a194faf8Srie 			return;
146a194faf8Srie 		}
147a194faf8Srie 	}
148a194faf8Srie 
149a194faf8Srie 	/*
150a194faf8Srie 	 * Do not discard any symbols that are associated with non-allocable
151a194faf8Srie 	 * segments.
152a194faf8Srie 	 */
153a194faf8Srie 	if (isp && ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
154a194faf8Srie 	    ((osp = isp->is_osdesc) != 0) &&
155a194faf8Srie 	    (osp->os_sgdesc->sg_phdr.p_type == PT_LOAD)) {
156a194faf8Srie 		DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
157a194faf8Srie 		if (ifl->ifl_flags & FLG_IF_IGNORE) {
158a194faf8Srie 			if (bind == STB_LOCAL)
159a194faf8Srie 				remove_local(ofl, sdp, allow_ldynsym);
160a194faf8Srie 			else
161a194faf8Srie 				remove_scoped(ofl, sdp, allow_ldynsym);
162a194faf8Srie 		}
163a194faf8Srie 	}
164a194faf8Srie }
1657c478bd9Sstevel@tonic-gate 
166d9c5840bSRichard Lowe static Boolean
isdesc_discarded(Is_desc * isp)167d9c5840bSRichard Lowe isdesc_discarded(Is_desc *isp)
168d9c5840bSRichard Lowe {
169d9c5840bSRichard Lowe 	Ifl_desc	*ifl = isp->is_file;
170d9c5840bSRichard Lowe 	Os_desc		*osp = isp->is_osdesc;
171d9c5840bSRichard Lowe 	Word		ptype = osp->os_sgdesc->sg_phdr.p_type;
172d9c5840bSRichard Lowe 
173d9c5840bSRichard Lowe 	if (isp->is_flags & FLG_IS_DISCARD)
174d9c5840bSRichard Lowe 		return (TRUE);
175d9c5840bSRichard Lowe 
176d9c5840bSRichard Lowe 	/*
177d9c5840bSRichard Lowe 	 * If the file is discarded, it will take
178d9c5840bSRichard Lowe 	 * the section with it.
179d9c5840bSRichard Lowe 	 */
180d9c5840bSRichard Lowe 	if (ifl &&
181d9c5840bSRichard Lowe 	    (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) ||
182d9c5840bSRichard Lowe 	    ((ptype == PT_LOAD) &&
183d9c5840bSRichard Lowe 	    ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
184d9c5840bSRichard Lowe 	    (isp->is_shdr->sh_size > 0))) &&
185d9c5840bSRichard Lowe 	    (ifl->ifl_flags & FLG_IF_IGNORE))
186d9c5840bSRichard Lowe 		return (TRUE);
187d9c5840bSRichard Lowe 
188d9c5840bSRichard Lowe 	return (FALSE);
189d9c5840bSRichard Lowe }
190d9c5840bSRichard Lowe 
191e64d0ff9SAli Bahrami /*
192e64d0ff9SAli Bahrami  * There are situations where we may count output sections (ofl_shdrcnt)
193e64d0ff9SAli Bahrami  * that are subsequently eliminated from the output object. Whether or
194e64d0ff9SAli Bahrami  * not this happens cannot be known until all input has been seen and
195e64d0ff9SAli Bahrami  * section elimination code has run. However, the situations where this
196e64d0ff9SAli Bahrami  * outcome is possible are known, and are flagged by setting FLG_OF_ADJOSCNT.
197e64d0ff9SAli Bahrami  *
198e64d0ff9SAli Bahrami  * If FLG_OF_ADJOSCNT is set, this routine makes a pass over the output
199e64d0ff9SAli Bahrami  * sections. If an unused output section is encountered, we decrement
200e64d0ff9SAli Bahrami  * ofl->ofl_shdrcnt and remove the section name from the .shstrtab string
201e64d0ff9SAli Bahrami  * table (ofl->ofl_shdrsttab).
202e64d0ff9SAli Bahrami  *
203e64d0ff9SAli Bahrami  * This code must be kept in sync with the similar code
204e64d0ff9SAli Bahrami  * found in outfile.c:ld_create_outfile().
205e64d0ff9SAli Bahrami  */
206e64d0ff9SAli Bahrami static void
adjust_os_count(Ofl_desc * ofl)207e64d0ff9SAli Bahrami adjust_os_count(Ofl_desc *ofl)
208e64d0ff9SAli Bahrami {
209e64d0ff9SAli Bahrami 	Sg_desc		*sgp;
210e64d0ff9SAli Bahrami 	Is_desc		*isp;
211e64d0ff9SAli Bahrami 	Os_desc		*osp;
212e64d0ff9SAli Bahrami 	Aliste		idx1;
213e64d0ff9SAli Bahrami 
214e64d0ff9SAli Bahrami 	if ((ofl->ofl_flags & FLG_OF_ADJOSCNT) == 0)
215e64d0ff9SAli Bahrami 		return;
216e64d0ff9SAli Bahrami 
217e64d0ff9SAli Bahrami 	/*
218e64d0ff9SAli Bahrami 	 * For each output section, look at the input sections to find at least
219e64d0ff9SAli Bahrami 	 * one input section that has not been eliminated. If none are found,
220e64d0ff9SAli Bahrami 	 * the -z ignore processing above has eliminated that output section.
221e64d0ff9SAli Bahrami 	 */
222e64d0ff9SAli Bahrami 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
223e64d0ff9SAli Bahrami 		Aliste	idx2;
224e64d0ff9SAli Bahrami 
225e64d0ff9SAli Bahrami 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
226e64d0ff9SAli Bahrami 			Aliste	idx3;
227e64d0ff9SAli Bahrami 			int	keep = 0, os_isdescs_idx;
228e64d0ff9SAli Bahrami 
229e64d0ff9SAli Bahrami 			OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx3, isp) {
230e64d0ff9SAli Bahrami 				/*
231e64d0ff9SAli Bahrami 				 * We have found a kept input section,
232e64d0ff9SAli Bahrami 				 * so the output section will be created.
233e64d0ff9SAli Bahrami 				 */
234d9c5840bSRichard Lowe 				if (!isdesc_discarded(isp)) {
235d9c5840bSRichard Lowe 					keep = 1;
236d9c5840bSRichard Lowe 					break;
237d9c5840bSRichard Lowe 				}
238e64d0ff9SAli Bahrami 			}
239e64d0ff9SAli Bahrami 			/*
240e64d0ff9SAli Bahrami 			 * If no section of this name was kept, decrement
241e64d0ff9SAli Bahrami 			 * the count and remove the name from .shstrtab.
242e64d0ff9SAli Bahrami 			 */
243e64d0ff9SAli Bahrami 			if (keep == 0) {
244e64d0ff9SAli Bahrami 				/* LINTED - only used for assert() */
245e64d0ff9SAli Bahrami 				int err;
246e64d0ff9SAli Bahrami 
247e64d0ff9SAli Bahrami 				ofl->ofl_shdrcnt--;
248e64d0ff9SAli Bahrami 				err = st_delstring(ofl->ofl_shdrsttab,
249e64d0ff9SAli Bahrami 				    osp->os_name);
250e64d0ff9SAli Bahrami 				assert(err != -1);
251e64d0ff9SAli Bahrami 			}
252e64d0ff9SAli Bahrami 		}
253e64d0ff9SAli Bahrami 	}
254e64d0ff9SAli Bahrami }
255e64d0ff9SAli Bahrami 
2567c478bd9Sstevel@tonic-gate /*
257a194faf8Srie  * If -zignore has been in effect, scan all input files to determine if the
258a194faf8Srie  * file, or sections from the file, have been referenced.  If not, the file or
2591da7e599SAli Bahrami  * some of the files sections can be discarded. If sections are to be
2601da7e599SAli Bahrami  * discarded, rescan the output relocations and the symbol table and remove
2611da7e599SAli Bahrami  * the relocations and symbol entries that are no longer required.
2627c478bd9Sstevel@tonic-gate  *
2637c478bd9Sstevel@tonic-gate  * Note:  It's possible that a section which is being discarded has contributed
2647c478bd9Sstevel@tonic-gate  *	  to the GOT table or the PLT table.  However, we can't at this point
2657c478bd9Sstevel@tonic-gate  *	  eliminate the corresponding entries.  This is because there could well
2667c478bd9Sstevel@tonic-gate  *	  be other sections referencing those same entries, but we don't have
2677c478bd9Sstevel@tonic-gate  *	  the infrastructure to determine this.  So, keep the PLT and GOT
2687c478bd9Sstevel@tonic-gate  *	  entries in the table in case someone wants them.
2697c478bd9Sstevel@tonic-gate  * Note:  The section to be affected needs to be allocatable.
2707c478bd9Sstevel@tonic-gate  *	  So even if -zignore is in effect, if the section is not allocatable,
2717c478bd9Sstevel@tonic-gate  *	  we do not eliminate it.
2727c478bd9Sstevel@tonic-gate  */
2735aefb655Srie static uintptr_t
ignore_section_processing(Ofl_desc * ofl)2747c478bd9Sstevel@tonic-gate ignore_section_processing(Ofl_desc *ofl)
2757c478bd9Sstevel@tonic-gate {
2761da7e599SAli Bahrami 	Sg_desc		*sgp;
2771da7e599SAli Bahrami 	Is_desc		*isp;
2781da7e599SAli Bahrami 	Os_desc		*osp;
2797c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
280bf994817SAli Bahrami 	Rel_cachebuf	*rcbp;
281bf994817SAli Bahrami 	Rel_desc	*rsp;
282a194faf8Srie 	int		allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
28357ef7aa9SRod Evans 	Aliste		idx1;
2847c478bd9Sstevel@tonic-gate 
28557ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_objs, idx1, ifl)) {
286fb1354edSrie 		uint_t	num, discard;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 		/*
2897c478bd9Sstevel@tonic-gate 		 * Diagnose (-D unused) a completely unreferenced file.
2907c478bd9Sstevel@tonic-gate 		 */
2917c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_flags & FLG_IF_FILEREF) == 0)
2925aefb655Srie 			DBG_CALL(Dbg_unused_file(ofl->ofl_lml,
2935aefb655Srie 			    ifl->ifl_name, 0, 0));
294fb1354edSrie 		if (((ofl->ofl_flags1 & FLG_OF1_IGNPRC) == 0) ||
295fb1354edSrie 		    ((ifl->ifl_flags & FLG_IF_IGNORE) == 0))
2967c478bd9Sstevel@tonic-gate 			continue;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		/*
299fb1354edSrie 		 * Before scanning the whole symbol table to determine if
300fb1354edSrie 		 * symbols should be discard - quickly (relatively) scan the
301fb1354edSrie 		 * sections to determine if any are to be discarded.
3027c478bd9Sstevel@tonic-gate 		 */
303fb1354edSrie 		discard = 0;
304fb1354edSrie 		if (ifl->ifl_flags & FLG_IF_FILEREF) {
305fb1354edSrie 			for (num = 1; num < ifl->ifl_shnum; num++) {
3061da7e599SAli Bahrami 				if (((isp = ifl->ifl_isdesc[num]) != NULL) &&
307fb1354edSrie 				    ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
3081da7e599SAli Bahrami 				    ((osp = isp->is_osdesc) != NULL) &&
3091da7e599SAli Bahrami 				    ((sgp = osp->os_sgdesc) != NULL) &&
310fb1354edSrie 				    (sgp->sg_phdr.p_type == PT_LOAD)) {
311fb1354edSrie 					discard++;
312fb1354edSrie 					break;
313fb1354edSrie 				}
3147c478bd9Sstevel@tonic-gate 			}
3157c478bd9Sstevel@tonic-gate 		}
316fb1354edSrie 
3177c478bd9Sstevel@tonic-gate 		/*
3187c478bd9Sstevel@tonic-gate 		 * No sections are to be 'ignored'
3197c478bd9Sstevel@tonic-gate 		 */
320fb1354edSrie 		if ((discard == 0) && (ifl->ifl_flags & FLG_IF_FILEREF))
3217c478bd9Sstevel@tonic-gate 			continue;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 		/*
324fb1354edSrie 		 * We know that we have discarded sections.  Scan the symbol
325fb1354edSrie 		 * table for this file to determine if symbols need to be
326fb1354edSrie 		 * discarded that are associated with the 'ignored' sections.
3277c478bd9Sstevel@tonic-gate 		 */
3287c478bd9Sstevel@tonic-gate 		for (num = 1; num < ifl->ifl_symscnt; num++) {
3297c478bd9Sstevel@tonic-gate 			Sym_desc	*sdp;
330fb1354edSrie 
3317c478bd9Sstevel@tonic-gate 			/*
332a194faf8Srie 			 * If the symbol definition has been resolved to another
333a194faf8Srie 			 * file, or the symbol has already been discarded or
334a194faf8Srie 			 * eliminated, skip it.
3357c478bd9Sstevel@tonic-gate 			 */
336a194faf8Srie 			sdp = ifl->ifl_oldndx[num];
337a194faf8Srie 			if ((sdp->sd_file != ifl) ||
338635216b6SRod Evans 			    (sdp->sd_flags &
339635216b6SRod Evans 			    (FLG_SY_ISDISC | FLG_SY_INVALID | FLG_SY_ELIM)))
3407c478bd9Sstevel@tonic-gate 				continue;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 			/*
343a194faf8Srie 			 * Complete the investigation of the symbol.
3447c478bd9Sstevel@tonic-gate 			 */
345a194faf8Srie 			ignore_sym(ofl, ifl, sdp, allow_ldynsym);
3467c478bd9Sstevel@tonic-gate 		}
3477c478bd9Sstevel@tonic-gate 	}
3487c478bd9Sstevel@tonic-gate 
349a194faf8Srie 	/*
350a194faf8Srie 	 * If we were only here to solicit debugging diagnostics, we're done.
351a194faf8Srie 	 */
352fb1354edSrie 	if ((ofl->ofl_flags1 & FLG_OF1_IGNPRC) == 0)
353fb1354edSrie 		return (1);
354fb1354edSrie 
3557c478bd9Sstevel@tonic-gate 	/*
356fb1354edSrie 	 * Scan all output relocations searching for those against discarded or
357fb1354edSrie 	 * ignored sections.  If one is found, decrement the total outrel count.
3587c478bd9Sstevel@tonic-gate 	 */
359bf994817SAli Bahrami 	REL_CACHE_TRAVERSE(&ofl->ofl_outrels, idx1, rcbp, rsp) {
360bf994817SAli Bahrami 		Is_desc		*isc = rsp->rel_isdesc;
361bf994817SAli Bahrami 		uint_t		flags, entsize;
362bf994817SAli Bahrami 		Shdr		*shdr;
3637c478bd9Sstevel@tonic-gate 
364bf994817SAli Bahrami 		if ((isc == NULL) || ((isc->is_flags & (FLG_IS_SECTREF))) ||
365bf994817SAli Bahrami 		    ((ifl = isc->is_file) == NULL) ||
366bf994817SAli Bahrami 		    ((ifl->ifl_flags & FLG_IF_IGNORE) == 0) ||
367bf994817SAli Bahrami 		    ((shdr = isc->is_shdr) == NULL) ||
368bf994817SAli Bahrami 		    ((shdr->sh_flags & SHF_ALLOC) == 0))
369bf994817SAli Bahrami 			continue;
3707c478bd9Sstevel@tonic-gate 
371bf994817SAli Bahrami 		flags = rsp->rel_flags;
3727c478bd9Sstevel@tonic-gate 
373bf994817SAli Bahrami 		if (flags & (FLG_REL_GOT | FLG_REL_BSS |
374bf994817SAli Bahrami 		    FLG_REL_NOINFO | FLG_REL_PLT))
375bf994817SAli Bahrami 			continue;
3767c478bd9Sstevel@tonic-gate 
377bf994817SAli Bahrami 		osp = RELAUX_GET_OSDESC(rsp);
378bf994817SAli Bahrami 
379bf994817SAli Bahrami 		if (rsp->rel_flags & FLG_REL_RELA)
380bf994817SAli Bahrami 			entsize = sizeof (Rela);
381bf994817SAli Bahrami 		else
382bf994817SAli Bahrami 			entsize = sizeof (Rel);
3837c478bd9Sstevel@tonic-gate 
384bf994817SAli Bahrami 		assert(osp->os_szoutrels > 0);
385bf994817SAli Bahrami 		osp->os_szoutrels -= entsize;
3867c478bd9Sstevel@tonic-gate 
387bf994817SAli Bahrami 		if (!(flags & FLG_REL_PLT))
388bf994817SAli Bahrami 			ofl->ofl_reloccntsub++;
3897c478bd9Sstevel@tonic-gate 
390bf994817SAli Bahrami 		if (rsp->rel_rtype == ld_targ.t_m.m_r_relative)
391bf994817SAli Bahrami 			ofl->ofl_relocrelcnt--;
3927c478bd9Sstevel@tonic-gate 	}
3931da7e599SAli Bahrami 
3941da7e599SAli Bahrami 	/*
395e64d0ff9SAli Bahrami 	 * As a result of our work here, the number of output sections may
396e64d0ff9SAli Bahrami 	 * have decreased. Trigger a call to adjust_os_count().
3971da7e599SAli Bahrami 	 */
398e64d0ff9SAli Bahrami 	ofl->ofl_flags |= FLG_OF_ADJOSCNT;
3991da7e599SAli Bahrami 
4007c478bd9Sstevel@tonic-gate 	return (1);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate /*
4049039eeafSab  * Allocate Elf_Data, Shdr, and Is_desc structures for a new
4059039eeafSab  * section.
4069039eeafSab  *
4079039eeafSab  * entry:
4089039eeafSab  *	ofl - Output file descriptor
4099039eeafSab  *	shtype - SHT_ type code for section.
4109039eeafSab  *	shname - String giving the name for the new section.
4119039eeafSab  *	entcnt - # of items contained in the data part of the new section.
4129039eeafSab  *		This value is multiplied against the known element size
4139039eeafSab  *		for the section type to determine the size of the data
4149039eeafSab  *		area for the section. It is only meaningful in cases where
4159039eeafSab  *		the section type has a non-zero element size. In other cases,
4169039eeafSab  *		the caller must set the size fields in the *ret_data and
4179039eeafSab  *		*ret_shdr structs manually.
4189039eeafSab  *	ret_isec, ret_shdr, ret_data - Address of pointers to
4199039eeafSab  *		receive address of newly allocated structs.
4209039eeafSab  *
4219039eeafSab  * exit:
4229039eeafSab  *	On error, returns S_ERROR. On success, returns (1), and the
4239039eeafSab  *	ret_ pointers have been updated to point at the new structures,
424cce0e03bSab  *	which have been filled in. To finish the task, the caller must
4259039eeafSab  *	update any fields within the supplied descriptors that differ
4269039eeafSab  *	from its needs, and then call ld_place_section().
4277c478bd9Sstevel@tonic-gate  */
4289039eeafSab static uintptr_t
new_section(Ofl_desc * ofl,Word shtype,const char * shname,Xword entcnt,Is_desc ** ret_isec,Shdr ** ret_shdr,Elf_Data ** ret_data)4299039eeafSab new_section(Ofl_desc *ofl, Word shtype, const char *shname, Xword entcnt,
430d2a70789SRichard Lowe     Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
4317c478bd9Sstevel@tonic-gate {
4329039eeafSab 	typedef struct sec_info {
4339039eeafSab 		Word d_type;
4349039eeafSab 		Word align;	/* Used in both data and section header */
4359039eeafSab 		Word sh_flags;
4369039eeafSab 		Word sh_entsize;
4379039eeafSab 	} SEC_INFO_T;
4389039eeafSab 
4399039eeafSab 	const SEC_INFO_T	*sec_info;
4409039eeafSab 
4417c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
4427c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
4437c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
4449039eeafSab 	size_t		size;
4459039eeafSab 
4469039eeafSab 	/*
4479039eeafSab 	 * For each type of section, we have a distinct set of
4489039eeafSab 	 * SEC_INFO_T values. This macro defines a static structure
4499039eeafSab 	 * containing those values and generates code to set the sec_info
4509039eeafSab 	 * pointer to refer to it. The pointer in sec_info remains valid
4519039eeafSab 	 * outside of the declaration scope because the info_s struct is static.
452ba2be530Sab 	 *
453ba2be530Sab 	 * We can't determine the value of M_WORD_ALIGN at compile time, so
454ba2be530Sab 	 * a different variant is used for those cases.
4559039eeafSab 	 */
4569039eeafSab #define	SET_SEC_INFO(d_type, d_align, sh_flags, sh_entsize) \
4579039eeafSab 	{ \
4589039eeafSab 		static const SEC_INFO_T info_s = { d_type, d_align, sh_flags, \
4599039eeafSab 		    sh_entsize}; \
4609039eeafSab 		sec_info = &info_s; \
4619039eeafSab 	}
462ba2be530Sab #define	SET_SEC_INFO_WORD_ALIGN(d_type, sh_flags, sh_entsize) \
463ba2be530Sab 	{ \
464ba2be530Sab 		static SEC_INFO_T info_s = { d_type, 0, sh_flags, \
465ba2be530Sab 		    sh_entsize}; \
466ba2be530Sab 		info_s.align = ld_targ.t_m.m_word_align; \
467ba2be530Sab 		sec_info = &info_s; \
468ba2be530Sab 	}
4699039eeafSab 
4709039eeafSab 	switch (shtype) {
4719039eeafSab 	case SHT_PROGBITS:
4729039eeafSab 		/*
4739039eeafSab 		 * SHT_PROGBITS sections contain are used for many
4749039eeafSab 		 * different sections. Alignments and flags differ.
4759039eeafSab 		 * Some have a standard entsize, and others don't.
4769039eeafSab 		 * We set some defaults here, but there is no expectation
4779039eeafSab 		 * that they are correct or complete for any specific
4789039eeafSab 		 * purpose. The caller must provide the correct values.
4799039eeafSab 		 */
480ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0)
4819039eeafSab 		break;
4829039eeafSab 
4839039eeafSab 	case SHT_SYMTAB:
484ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, 0, sizeof (Sym))
4859039eeafSab 		break;
4869039eeafSab 
4879039eeafSab 	case SHT_DYNSYM:
4884f680cc6SAli Bahrami 		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, SHF_ALLOC, sizeof (Sym))
4894f680cc6SAli Bahrami 		break;
4904f680cc6SAli Bahrami 
4919039eeafSab 	case SHT_SUNW_LDYNSYM:
4924f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
493ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, SHF_ALLOC, sizeof (Sym))
4949039eeafSab 		break;
4959039eeafSab 
4969039eeafSab 	case SHT_STRTAB:
4979039eeafSab 		/*
4989039eeafSab 		 * A string table may or may not be allocable, depending
4999039eeafSab 		 * on context, so we leave that flag unset and leave it to
5009039eeafSab 		 * the caller to add it if necessary.
5019039eeafSab 		 *
5029039eeafSab 		 * String tables do not have a standard entsize, so
5039039eeafSab 		 * we set it to 0.
5049039eeafSab 		 */
5059039eeafSab 		SET_SEC_INFO(ELF_T_BYTE, 1, SHF_STRINGS, 0)
5069039eeafSab 		break;
5079039eeafSab 
5089039eeafSab 	case SHT_RELA:
5099039eeafSab 		/*
5109039eeafSab 		 * Relocations with an addend (Everything except 32-bit X86).
5119039eeafSab 		 * The caller is expected to set all section header flags.
5129039eeafSab 		 */
513ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_RELA, 0, sizeof (Rela))
5149039eeafSab 		break;
5159039eeafSab 
5169039eeafSab 	case SHT_REL:
5179039eeafSab 		/*
5189039eeafSab 		 * Relocations without an addend (32-bit X86 only).
5199039eeafSab 		 * The caller is expected to set all section header flags.
5209039eeafSab 		 */
521ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_REL, 0, sizeof (Rel))
5229039eeafSab 		break;
5239039eeafSab 
5249039eeafSab 	case SHT_HASH:
5254f680cc6SAli Bahrami 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, sizeof (Word))
5264f680cc6SAli Bahrami 		break;
5274f680cc6SAli Bahrami 
528d579eb63Sab 	case SHT_SUNW_symsort:
529d579eb63Sab 	case SHT_SUNW_tlssort:
5304f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
531ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, sizeof (Word))
5329039eeafSab 		break;
5339039eeafSab 
5349039eeafSab 	case SHT_DYNAMIC:
5359039eeafSab 		/*
53694c044f4SRod Evans 		 * A dynamic section may or may not be allocable, and may or
53794c044f4SRod Evans 		 * may not be writable, depending on context, so we leave the
53894c044f4SRod Evans 		 * flags unset and leave it to the caller to add them if
53994c044f4SRod Evans 		 * necessary.
5409039eeafSab 		 */
54194c044f4SRod Evans 		SET_SEC_INFO_WORD_ALIGN(ELF_T_DYN, 0, sizeof (Dyn))
5429039eeafSab 		break;
5439039eeafSab 
5449039eeafSab 	case SHT_NOBITS:
5459039eeafSab 		/*
5469039eeafSab 		 * SHT_NOBITS is used for BSS-type sections. The size and
5479039eeafSab 		 * alignment depend on the specific use and must be adjusted
5489039eeafSab 		 * by the caller.
5499039eeafSab 		 */
5509039eeafSab 		SET_SEC_INFO(ELF_T_BYTE, 0, SHF_ALLOC | SHF_WRITE, 0)
5519039eeafSab 		break;
5529039eeafSab 
5539039eeafSab 	case SHT_INIT_ARRAY:
5549039eeafSab 	case SHT_FINI_ARRAY:
5559039eeafSab 	case SHT_PREINIT_ARRAY:
5569039eeafSab 		SET_SEC_INFO(ELF_T_ADDR, sizeof (Addr), SHF_ALLOC | SHF_WRITE,
5579039eeafSab 		    sizeof (Addr))
5589039eeafSab 		break;
5599039eeafSab 
5609039eeafSab 	case SHT_SYMTAB_SHNDX:
5619039eeafSab 		/*
5629039eeafSab 		 * Note that these sections are created to be associated
5639039eeafSab 		 * with both symtab and dynsym symbol tables. However, they
5649039eeafSab 		 * are non-allocable in all cases, because the runtime
5659039eeafSab 		 * linker has no need for this information. It is purely
5669039eeafSab 		 * informational, used by elfdump(1), debuggers, etc.
5679039eeafSab 		 */
568ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, 0, sizeof (Word));
5699039eeafSab 		break;
5709039eeafSab 
5719039eeafSab 	case SHT_SUNW_cap:
5724f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
573ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_CAP, SHF_ALLOC, sizeof (Cap));
5749039eeafSab 		break;
5759039eeafSab 
57608278a5eSRod Evans 	case SHT_SUNW_capchain:
57708278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_OSABI;
57808278a5eSRod Evans 		SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC,
57908278a5eSRod Evans 		    sizeof (Capchain));
58008278a5eSRod Evans 		break;
58108278a5eSRod Evans 
58208278a5eSRod Evans 	case SHT_SUNW_capinfo:
58308278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_OSABI;
58408278a5eSRod Evans #if	_ELF64
58508278a5eSRod Evans 		SET_SEC_INFO(ELF_T_XWORD, sizeof (Xword), SHF_ALLOC,
58608278a5eSRod Evans 		    sizeof (Capinfo));
58708278a5eSRod Evans #else
58808278a5eSRod Evans 		SET_SEC_INFO(ELF_T_WORD, sizeof (Word), SHF_ALLOC,
58908278a5eSRod Evans 		    sizeof (Capinfo));
59008278a5eSRod Evans #endif
59108278a5eSRod Evans 		break;
59208278a5eSRod Evans 
5939039eeafSab 	case SHT_SUNW_move:
5944f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
5959039eeafSab 		SET_SEC_INFO(ELF_T_BYTE, sizeof (Lword),
5969039eeafSab 		    SHF_ALLOC | SHF_WRITE, sizeof (Move));
5979039eeafSab 		break;
5989039eeafSab 
5999039eeafSab 	case SHT_SUNW_syminfo:
6004f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
6019039eeafSab 		/*
6029039eeafSab 		 * The sh_info field of the SHT_*_syminfo section points
6039039eeafSab 		 * to the header index of the associated .dynamic section,
6049039eeafSab 		 * so we also set SHF_INFO_LINK.
6059039eeafSab 		 */
606ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE,
6079039eeafSab 		    SHF_ALLOC | SHF_INFO_LINK, sizeof (Syminfo));
6089039eeafSab 		break;
6099039eeafSab 
6109039eeafSab 	case SHT_SUNW_verneed:
6119039eeafSab 	case SHT_SUNW_verdef:
6124f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
6139039eeafSab 		/*
6149039eeafSab 		 * The info for verneed and versym happen to be the same.
6159039eeafSab 		 * The entries in these sections are not of uniform size,
6169039eeafSab 		 * so we set the entsize to 0.
6179039eeafSab 		 */
618ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0);
6199039eeafSab 		break;
6209039eeafSab 
6219039eeafSab 	case SHT_SUNW_versym:
6224f680cc6SAli Bahrami 		ofl->ofl_flags |= FLG_OF_OSABI;
623ba2be530Sab 		SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC,
6249039eeafSab 		    sizeof (Versym));
6259039eeafSab 		break;
6269039eeafSab 
6279039eeafSab 	default:
6289039eeafSab 		/* Should not happen: fcn called with unknown section type */
6299039eeafSab 		assert(0);
6309039eeafSab 		return (S_ERROR);
6319039eeafSab 	}
6329039eeafSab #undef	SET_SEC_INFO
633ba2be530Sab #undef	SET_SEC_INFO_WORD_ALIGN
6349039eeafSab 
6359039eeafSab 	size = entcnt * sec_info->sh_entsize;
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	/*
6387c478bd9Sstevel@tonic-gate 	 * Allocate and initialize the Elf_Data structure.
6397c478bd9Sstevel@tonic-gate 	 */
640fb12490aSRichard Lowe 	if ((data = libld_calloc(1, sizeof (Elf_Data))) == NULL)
6417c478bd9Sstevel@tonic-gate 		return (S_ERROR);
6429039eeafSab 	data->d_type = sec_info->d_type;
6439039eeafSab 	data->d_size = size;
6449039eeafSab 	data->d_align = sec_info->align;
6455aefb655Srie 	data->d_version = ofl->ofl_dehdr->e_version;
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	/*
6487c478bd9Sstevel@tonic-gate 	 * Allocate and initialize the Shdr structure.
6497c478bd9Sstevel@tonic-gate 	 */
650fb12490aSRichard Lowe 	if ((shdr = libld_calloc(1, sizeof (Shdr))) == NULL)
6517c478bd9Sstevel@tonic-gate 		return (S_ERROR);
6529039eeafSab 	shdr->sh_type = shtype;
6537c478bd9Sstevel@tonic-gate 	shdr->sh_size = size;
6549039eeafSab 	shdr->sh_flags = sec_info->sh_flags;
6559039eeafSab 	shdr->sh_addralign = sec_info->align;
6569039eeafSab 	shdr->sh_entsize = sec_info->sh_entsize;
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	/*
6597c478bd9Sstevel@tonic-gate 	 * Allocate and initialize the Is_desc structure.
6607c478bd9Sstevel@tonic-gate 	 */
66157ef7aa9SRod Evans 	if ((isec = libld_calloc(1, sizeof (Is_desc))) == NULL)
6627c478bd9Sstevel@tonic-gate 		return (S_ERROR);
6639039eeafSab 	isec->is_name = shname;
6647c478bd9Sstevel@tonic-gate 	isec->is_shdr = shdr;
6657c478bd9Sstevel@tonic-gate 	isec->is_indata = data;
6667c478bd9Sstevel@tonic-gate 
6679039eeafSab 
6689039eeafSab 	*ret_isec = isec;
6699039eeafSab 	*ret_shdr = shdr;
6709039eeafSab 	*ret_data = data;
6719039eeafSab 	return (1);
6729039eeafSab }
6739039eeafSab 
674cce0e03bSab /*
675cce0e03bSab  * Use an existing input section as a template to create a new
676cce0e03bSab  * input section with the same values as the original, other than
677cce0e03bSab  * the size of the data area which is supplied by the caller.
678cce0e03bSab  *
679cce0e03bSab  * entry:
680cce0e03bSab  *	ofl - Output file descriptor
681cce0e03bSab  *	ifl - Input file section to use as a template
682cce0e03bSab  *	size - Size of data area for new section
683cce0e03bSab  *	ret_isec, ret_shdr, ret_data - Address of pointers to
684cce0e03bSab  *		receive address of newly allocated structs.
685cce0e03bSab  *
686cce0e03bSab  * exit:
687cce0e03bSab  *	On error, returns S_ERROR. On success, returns (1), and the
688cce0e03bSab  *	ret_ pointers have been updated to point at the new structures,
689cce0e03bSab  *	which have been filled in. To finish the task, the caller must
690cce0e03bSab  *	update any fields within the supplied descriptors that differ
691cce0e03bSab  *	from its needs, and then call ld_place_section().
692cce0e03bSab  */
693cce0e03bSab static uintptr_t
new_section_from_template(Ofl_desc * ofl,Is_desc * tmpl_isp,size_t size,Is_desc ** ret_isec,Shdr ** ret_shdr,Elf_Data ** ret_data)694cce0e03bSab new_section_from_template(Ofl_desc *ofl, Is_desc *tmpl_isp, size_t size,
695d2a70789SRichard Lowe     Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
696cce0e03bSab {
697cce0e03bSab 	Shdr		*shdr;
698cce0e03bSab 	Elf_Data	*data;
699cce0e03bSab 	Is_desc		*isec;
700cce0e03bSab 
701cce0e03bSab 	/*
702cce0e03bSab 	 * Allocate and initialize the Elf_Data structure.
703cce0e03bSab 	 */
704fb12490aSRichard Lowe 	if ((data = libld_calloc(1, sizeof (Elf_Data))) == NULL)
705cce0e03bSab 		return (S_ERROR);
706cce0e03bSab 	data->d_type = tmpl_isp->is_indata->d_type;
707cce0e03bSab 	data->d_size = size;
708cce0e03bSab 	data->d_align = tmpl_isp->is_shdr->sh_addralign;
709cce0e03bSab 	data->d_version = ofl->ofl_dehdr->e_version;
710cce0e03bSab 
711cce0e03bSab 	/*
712cce0e03bSab 	 * Allocate and initialize the Shdr structure.
713cce0e03bSab 	 */
71457ef7aa9SRod Evans 	if ((shdr = libld_malloc(sizeof (Shdr))) == NULL)
715cce0e03bSab 		return (S_ERROR);
716cce0e03bSab 	*shdr = *tmpl_isp->is_shdr;
717cce0e03bSab 	shdr->sh_addr = 0;
718cce0e03bSab 	shdr->sh_offset = 0;
719cce0e03bSab 	shdr->sh_size = size;
720cce0e03bSab 
721cce0e03bSab 	/*
722cce0e03bSab 	 * Allocate and initialize the Is_desc structure.
723cce0e03bSab 	 */
72457ef7aa9SRod Evans 	if ((isec = libld_calloc(1, sizeof (Is_desc))) == NULL)
725cce0e03bSab 		return (S_ERROR);
726cce0e03bSab 	isec->is_name = tmpl_isp->is_name;
727cce0e03bSab 	isec->is_shdr = shdr;
728cce0e03bSab 	isec->is_indata = data;
729cce0e03bSab 
730cce0e03bSab 
731cce0e03bSab 	*ret_isec = isec;
732cce0e03bSab 	*ret_shdr = shdr;
733cce0e03bSab 	*ret_data = data;
734cce0e03bSab 	return (1);
735cce0e03bSab }
736cce0e03bSab 
7379039eeafSab /*
7389039eeafSab  * Build a .bss section for allocation of tentative definitions.  Any `static'
7399039eeafSab  * .bss definitions would have been associated to their own .bss sections and
7409039eeafSab  * thus collected from the input files.  `global' .bss definitions are tagged
7419039eeafSab  * as COMMON and do not cause any associated .bss section elements to be
7429039eeafSab  * generated.  Here we add up all these COMMON symbols and generate the .bss
7439039eeafSab  * section required to represent them.
7449039eeafSab  */
7459039eeafSab uintptr_t
ld_make_bss(Ofl_desc * ofl,Xword size,Xword align,uint_t ident)74657ef7aa9SRod Evans ld_make_bss(Ofl_desc *ofl, Xword size, Xword align, uint_t ident)
7479039eeafSab {
7489039eeafSab 	Shdr		*shdr;
7499039eeafSab 	Elf_Data	*data;
7509039eeafSab 	Is_desc		*isec;
7519039eeafSab 	Os_desc		*osp;
7529039eeafSab 	Xword		rsize = (Xword)ofl->ofl_relocbsssz;
7539039eeafSab 
7549039eeafSab 	/*
7559039eeafSab 	 * Allocate header structs. We will set the name ourselves below,
7569039eeafSab 	 * and there is no entcnt for a BSS. So, the shname and entcnt
7579039eeafSab 	 * arguments are 0.
7589039eeafSab 	 */
7599039eeafSab 	if (new_section(ofl, SHT_NOBITS, NULL, 0,
7609039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
7619039eeafSab 		return (S_ERROR);
7629039eeafSab 
7639039eeafSab 	data->d_size = (size_t)size;
7649039eeafSab 	data->d_align = (size_t)align;
7659039eeafSab 
7669039eeafSab 	shdr->sh_size = size;
7679039eeafSab 	shdr->sh_addralign = align;
7689039eeafSab 
76957ef7aa9SRod Evans 	if (ident == ld_targ.t_id.id_tlsbss) {
7707c478bd9Sstevel@tonic-gate 		isec->is_name = MSG_ORIG(MSG_SCN_TBSS);
7717c478bd9Sstevel@tonic-gate 		ofl->ofl_istlsbss = isec;
77254d82594Sseizo 		shdr->sh_flags |= SHF_TLS;
7730bc07c75Srie 
77457ef7aa9SRod Evans 	} else if (ident == ld_targ.t_id.id_bss) {
7757c478bd9Sstevel@tonic-gate 		isec->is_name = MSG_ORIG(MSG_SCN_BSS);
7767c478bd9Sstevel@tonic-gate 		ofl->ofl_isbss = isec;
77754d82594Sseizo 
778ba2be530Sab #if	defined(_ELF64)
77957ef7aa9SRod Evans 	} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
78057ef7aa9SRod Evans 	    (ident == ld_targ.t_id.id_lbss)) {
78154d82594Sseizo 		isec->is_name = MSG_ORIG(MSG_SCN_LBSS);
78254d82594Sseizo 		ofl->ofl_islbss = isec;
78354d82594Sseizo 		shdr->sh_flags |= SHF_AMD64_LARGE;
78454d82594Sseizo #endif
7857c478bd9Sstevel@tonic-gate 	}
78654d82594Sseizo 
7877c478bd9Sstevel@tonic-gate 	/*
78857ef7aa9SRod Evans 	 * Retain this .*bss input section as this will be where global symbol
78957ef7aa9SRod Evans 	 * references are added.
7907c478bd9Sstevel@tonic-gate 	 */
79169112eddSAli Bahrami 	if ((osp = ld_place_section(ofl, isec, NULL, ident, NULL)) ==
7921dd9d86fSAli Bahrami 	    (Os_desc *)S_ERROR)
7937c478bd9Sstevel@tonic-gate 		return (S_ERROR);
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	/*
79657ef7aa9SRod Evans 	 * If relocations exist against a .*bss section, a section symbol must
79757ef7aa9SRod Evans 	 * be created for the section in the .dynsym symbol table.
7987c478bd9Sstevel@tonic-gate 	 */
7997c478bd9Sstevel@tonic-gate 	if (!(osp->os_flags & FLG_OS_OUTREL)) {
8001d9df23bSab 		ofl_flag_t	flagtotest;
80157ef7aa9SRod Evans 
80257ef7aa9SRod Evans 		if (ident == ld_targ.t_id.id_tlsbss)
8037c478bd9Sstevel@tonic-gate 			flagtotest = FLG_OF1_TLSOREL;
8047c478bd9Sstevel@tonic-gate 		else
8057c478bd9Sstevel@tonic-gate 			flagtotest = FLG_OF1_BSSOREL;
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 		if (ofl->ofl_flags1 & flagtotest) {
8087c478bd9Sstevel@tonic-gate 			ofl->ofl_dynshdrcnt++;
8097c478bd9Sstevel@tonic-gate 			osp->os_flags |= FLG_OS_OUTREL;
8107c478bd9Sstevel@tonic-gate 		}
8117c478bd9Sstevel@tonic-gate 	}
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	osp->os_szoutrels = rsize;
8147c478bd9Sstevel@tonic-gate 	return (1);
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate /*
8187c478bd9Sstevel@tonic-gate  * Build a SHT_{INIT|FINI|PREINIT}ARRAY section (specified via
81957ef7aa9SRod Evans  * ld -z *array=name).
8207c478bd9Sstevel@tonic-gate  */
8215aefb655Srie static uintptr_t
make_array(Ofl_desc * ofl,Word shtype,const char * sectname,APlist * alp)82257ef7aa9SRod Evans make_array(Ofl_desc *ofl, Word shtype, const char *sectname, APlist *alp)
8237c478bd9Sstevel@tonic-gate {
8247c478bd9Sstevel@tonic-gate 	uint_t		entcount;
82557ef7aa9SRod Evans 	Aliste		idx;
8267c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
8277c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
8287c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
8297c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
8307c478bd9Sstevel@tonic-gate 	Rel_desc	reld;
8317c478bd9Sstevel@tonic-gate 	Rela		reloc;
8327c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
83302ca3e02Srie 	uintptr_t	ret = 1;
8347c478bd9Sstevel@tonic-gate 
83557ef7aa9SRod Evans 	if (alp == NULL)
8367c478bd9Sstevel@tonic-gate 		return (1);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	entcount = 0;
83957ef7aa9SRod Evans 	for (APLIST_TRAVERSE(alp, idx, sdp))
8407c478bd9Sstevel@tonic-gate 		entcount++;
8417c478bd9Sstevel@tonic-gate 
8429039eeafSab 	if (new_section(ofl, shtype, sectname, entcount, &isec, &shdr, &data) ==
8439039eeafSab 	    S_ERROR)
8447c478bd9Sstevel@tonic-gate 		return (S_ERROR);
8457c478bd9Sstevel@tonic-gate 
846fb12490aSRichard Lowe 	if ((data->d_buf = libld_calloc(entcount, sizeof (Addr))) == NULL)
8477c478bd9Sstevel@tonic-gate 		return (S_ERROR);
8487c478bd9Sstevel@tonic-gate 
84969112eddSAli Bahrami 	if (ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_array, NULL) ==
850ba2be530Sab 	    (Os_desc *)S_ERROR)
8517c478bd9Sstevel@tonic-gate 		return (S_ERROR);
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	osp = isec->is_osdesc;
8547c478bd9Sstevel@tonic-gate 
8550e233487SRod Evans 	if ((ofl->ofl_osinitarray == NULL) && (shtype == SHT_INIT_ARRAY))
8567c478bd9Sstevel@tonic-gate 		ofl->ofl_osinitarray = osp;
8570e233487SRod Evans 	if ((ofl->ofl_ospreinitarray == NULL) && (shtype == SHT_PREINIT_ARRAY))
8587c478bd9Sstevel@tonic-gate 		ofl->ofl_ospreinitarray = osp;
8590e233487SRod Evans 	else if ((ofl->ofl_osfiniarray == NULL) && (shtype == SHT_FINI_ARRAY))
8607c478bd9Sstevel@tonic-gate 		ofl->ofl_osfiniarray = osp;
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	/*
8637c478bd9Sstevel@tonic-gate 	 * Create relocations against this section to initialize it to the
8647c478bd9Sstevel@tonic-gate 	 * function addresses.
8657c478bd9Sstevel@tonic-gate 	 */
8667c478bd9Sstevel@tonic-gate 	reld.rel_isdesc = isec;
867bf994817SAli Bahrami 	reld.rel_aux = NULL;
8687c478bd9Sstevel@tonic-gate 	reld.rel_flags = FLG_REL_LOAD;
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	/*
8717c478bd9Sstevel@tonic-gate 	 * Fabricate the relocation information (as if a relocation record had
8727c478bd9Sstevel@tonic-gate 	 * been input - see init_rel()).
8737c478bd9Sstevel@tonic-gate 	 */
874ba2be530Sab 	reld.rel_rtype = ld_targ.t_m.m_r_arrayaddr;
8757c478bd9Sstevel@tonic-gate 	reld.rel_roffset = 0;
8767c478bd9Sstevel@tonic-gate 	reld.rel_raddend = 0;
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	/*
8797c478bd9Sstevel@tonic-gate 	 * Create a minimal relocation record to satisfy process_sym_reloc()
8807c478bd9Sstevel@tonic-gate 	 * debugging requirements.
8817c478bd9Sstevel@tonic-gate 	 */
8827c478bd9Sstevel@tonic-gate 	reloc.r_offset = 0;
883ba2be530Sab 	reloc.r_info = ELF_R_INFO(0, ld_targ.t_m.m_r_arrayaddr);
8847c478bd9Sstevel@tonic-gate 	reloc.r_addend = 0;
8857c478bd9Sstevel@tonic-gate 
886ba2be530Sab 	DBG_CALL(Dbg_reloc_generate(ofl->ofl_lml, osp,
887ba2be530Sab 	    ld_targ.t_m.m_rel_sht_type));
88857ef7aa9SRod Evans 	for (APLIST_TRAVERSE(alp, idx, sdp)) {
8897c478bd9Sstevel@tonic-gate 		reld.rel_sym = sdp;
8907c478bd9Sstevel@tonic-gate 
8915aefb655Srie 		if (ld_process_sym_reloc(ofl, &reld, (Rel *)&reloc, isec,
892e23c41c9SAli Bahrami 		    MSG_INTL(MSG_STR_COMMAND), 0) == S_ERROR) {
89302ca3e02Srie 			ret = S_ERROR;
89402ca3e02Srie 			continue;
89502ca3e02Srie 		}
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 		reld.rel_roffset += (Xword)sizeof (Addr);
8987c478bd9Sstevel@tonic-gate 		reloc.r_offset = reld.rel_roffset;
8997c478bd9Sstevel@tonic-gate 	}
9007c478bd9Sstevel@tonic-gate 
90102ca3e02Srie 	return (ret);
9027c478bd9Sstevel@tonic-gate }
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate /*
9057c478bd9Sstevel@tonic-gate  * Build a comment section (-Qy option).
9067c478bd9Sstevel@tonic-gate  */
9075aefb655Srie static uintptr_t
make_comment(Ofl_desc * ofl)9087c478bd9Sstevel@tonic-gate make_comment(Ofl_desc *ofl)
9097c478bd9Sstevel@tonic-gate {
9107c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
9117c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
9127c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
9137c478bd9Sstevel@tonic-gate 
9149039eeafSab 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_COMMENT), 0,
9159039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
9167c478bd9Sstevel@tonic-gate 		return (S_ERROR);
9179039eeafSab 
9187c478bd9Sstevel@tonic-gate 	data->d_buf = (void *)ofl->ofl_sgsid;
9197c478bd9Sstevel@tonic-gate 	data->d_size = strlen(ofl->ofl_sgsid) + 1;
9207c478bd9Sstevel@tonic-gate 	data->d_align = 1;
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)data->d_size;
9239039eeafSab 	shdr->sh_flags = 0;
9247c478bd9Sstevel@tonic-gate 	shdr->sh_addralign = 1;
9257c478bd9Sstevel@tonic-gate 
92669112eddSAli Bahrami 	return ((uintptr_t)ld_place_section(ofl, isec, NULL,
9271dd9d86fSAli Bahrami 	    ld_targ.t_id.id_note, NULL));
9287c478bd9Sstevel@tonic-gate }
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate /*
9317c478bd9Sstevel@tonic-gate  * Make the dynamic section.  Calculate the size of any strings referenced
9327c478bd9Sstevel@tonic-gate  * within this structure, they will be added to the global string table
9337c478bd9Sstevel@tonic-gate  * (.dynstr).  This routine should be called before make_dynstr().
9341d9df23bSab  *
9351d9df23bSab  * This routine must be maintained in parallel with update_odynamic()
9361d9df23bSab  * in update.c
9377c478bd9Sstevel@tonic-gate  */
9385aefb655Srie static uintptr_t
make_dynamic(Ofl_desc * ofl)9397c478bd9Sstevel@tonic-gate make_dynamic(Ofl_desc *ofl)
9407c478bd9Sstevel@tonic-gate {
9417c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
9427c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
9437c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
9447c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
9457c478bd9Sstevel@tonic-gate 	size_t		cnt = 0;
94657ef7aa9SRod Evans 	Aliste		idx;
9477c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
9487c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
9497c478bd9Sstevel@tonic-gate 	size_t		size;
950635216b6SRod Evans 	Str_tbl		*strtbl;
9511d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
9521d9df23bSab 	int		not_relobj = !(flags & FLG_OF_RELOBJ);
9537c478bd9Sstevel@tonic-gate 	int		unused = 0;
9547c478bd9Sstevel@tonic-gate 
955635216b6SRod Evans 	/*
956635216b6SRod Evans 	 * Select the required string table.
957635216b6SRod Evans 	 */
958635216b6SRod Evans 	if (OFL_IS_STATIC_OBJ(ofl))
959635216b6SRod Evans 		strtbl = ofl->ofl_strtab;
960635216b6SRod Evans 	else
961635216b6SRod Evans 		strtbl = ofl->ofl_dynstrtab;
962635216b6SRod Evans 
9631d9df23bSab 	/*
9641d9df23bSab 	 * Only a limited subset of DT_ entries apply to relocatable
9651d9df23bSab 	 * objects. See the comment at the head of update_odynamic() in
9661d9df23bSab 	 * update.c for details.
9671d9df23bSab 	 */
9689039eeafSab 	if (new_section(ofl, SHT_DYNAMIC, MSG_ORIG(MSG_SCN_DYNAMIC), 0,
9699039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
9707c478bd9Sstevel@tonic-gate 		return (S_ERROR);
9719039eeafSab 
97294c044f4SRod Evans 	/*
97394c044f4SRod Evans 	 * new_section() does not set SHF_ALLOC.  If we're building anything
97494c044f4SRod Evans 	 * besides a relocatable object, then the .dynamic section should
97594c044f4SRod Evans 	 * reside in allocatable memory.
97694c044f4SRod Evans 	 */
9771d9df23bSab 	if (not_relobj)
9787c478bd9Sstevel@tonic-gate 		shdr->sh_flags |= SHF_ALLOC;
9797c478bd9Sstevel@tonic-gate 
98094c044f4SRod Evans 	/*
98194c044f4SRod Evans 	 * new_section() does not set SHF_WRITE.  If we're building an object
98294c044f4SRod Evans 	 * that specifies an interpretor, then a DT_DEBUG entry is created,
98394c044f4SRod Evans 	 * which is initialized to the applications link-map list at runtime.
98494c044f4SRod Evans 	 */
98594c044f4SRod Evans 	if (ofl->ofl_osinterp)
98694c044f4SRod Evans 		shdr->sh_flags |= SHF_WRITE;
98794c044f4SRod Evans 
988ba2be530Sab 	osp = ofl->ofl_osdynamic =
98969112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynamic, NULL);
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	/*
9927c478bd9Sstevel@tonic-gate 	 * Reserve entries for any needed dependencies.
9937c478bd9Sstevel@tonic-gate 	 */
99457ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_sos, idx, ifl)) {
9957c478bd9Sstevel@tonic-gate 		if (!(ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR)))
9967c478bd9Sstevel@tonic-gate 			continue;
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 		/*
999fb1354edSrie 		 * If this dependency didn't satisfy any symbol references,
10007c478bd9Sstevel@tonic-gate 		 * generate a debugging diagnostic (ld(1) -Dunused can be used
10017c478bd9Sstevel@tonic-gate 		 * to display these).  If this is a standard needed dependency,
10027c478bd9Sstevel@tonic-gate 		 * and -z ignore is in effect, drop the dependency.  Explicitly
10037c478bd9Sstevel@tonic-gate 		 * defined dependencies (i.e., -N dep) don't get dropped, and
10047c478bd9Sstevel@tonic-gate 		 * are flagged as being required to simplify update_odynamic()
10057c478bd9Sstevel@tonic-gate 		 * processing.
10067c478bd9Sstevel@tonic-gate 		 */
1007fb1354edSrie 		if ((ifl->ifl_flags & FLG_IF_NEEDSTR) ||
1008fb1354edSrie 		    ((ifl->ifl_flags & FLG_IF_DEPREQD) == 0)) {
10097c478bd9Sstevel@tonic-gate 			if (unused++ == 0)
10105aefb655Srie 				DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
10115aefb655Srie 			DBG_CALL(Dbg_unused_file(ofl->ofl_lml, ifl->ifl_soname,
1012fb1354edSrie 			    (ifl->ifl_flags & FLG_IF_NEEDSTR), 0));
10137c478bd9Sstevel@tonic-gate 
10141007fd6fSAli Bahrami 			/*
10151007fd6fSAli Bahrami 			 * Guidance: Remove unused dependency.
10161007fd6fSAli Bahrami 			 *
10171007fd6fSAli Bahrami 			 * If -z ignore is in effect, this warning is not
10181007fd6fSAli Bahrami 			 * needed because we will quietly remove the unused
10191007fd6fSAli Bahrami 			 * dependency.
10201007fd6fSAli Bahrami 			 */
10211007fd6fSAli Bahrami 			if (OFL_GUIDANCE(ofl, FLG_OFG_NO_UNUSED) &&
10221007fd6fSAli Bahrami 			    ((ifl->ifl_flags & FLG_IF_IGNORE) == 0))
10231007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_GUIDANCE,
10241007fd6fSAli Bahrami 				    MSG_INTL(MSG_GUIDE_UNUSED),
10251007fd6fSAli Bahrami 				    ifl->ifl_soname);
10261007fd6fSAli Bahrami 
10277c478bd9Sstevel@tonic-gate 			if (ifl->ifl_flags & FLG_IF_NEEDSTR)
10287c478bd9Sstevel@tonic-gate 				ifl->ifl_flags |= FLG_IF_DEPREQD;
10297c478bd9Sstevel@tonic-gate 			else if (ifl->ifl_flags & FLG_IF_IGNORE)
10307c478bd9Sstevel@tonic-gate 				continue;
10317c478bd9Sstevel@tonic-gate 		}
10327c478bd9Sstevel@tonic-gate 
10337c478bd9Sstevel@tonic-gate 		/*
1034f441771bSRod Evans 		 * If this object requires a DT_POSFLAG_1 entry, reserve it.
10357c478bd9Sstevel@tonic-gate 		 */
1036f441771bSRod Evans 		if ((ifl->ifl_flags & MSK_IF_POSFLAG1) && not_relobj)
10377c478bd9Sstevel@tonic-gate 			cnt++;
10387c478bd9Sstevel@tonic-gate 
1039635216b6SRod Evans 		if (st_insert(strtbl, ifl->ifl_soname) == -1)
10407c478bd9Sstevel@tonic-gate 			return (S_ERROR);
10417c478bd9Sstevel@tonic-gate 		cnt++;
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 		/*
10447c478bd9Sstevel@tonic-gate 		 * If the needed entry contains the $ORIGIN token make sure
10457c478bd9Sstevel@tonic-gate 		 * the associated DT_1_FLAGS entry is created.
10467c478bd9Sstevel@tonic-gate 		 */
10477c478bd9Sstevel@tonic-gate 		if (strstr(ifl->ifl_soname, MSG_ORIG(MSG_STR_ORIGIN))) {
10487c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
10497c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags |= DF_ORIGIN;
10507c478bd9Sstevel@tonic-gate 		}
10517c478bd9Sstevel@tonic-gate 	}
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate 	if (unused)
10545aefb655Srie 		DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
10557c478bd9Sstevel@tonic-gate 
10561d9df23bSab 	if (not_relobj) {
10571d9df23bSab 		/*
10581d9df23bSab 		 * Reserve entries for any per-symbol auxiliary/filter strings.
10591d9df23bSab 		 */
10601d9df23bSab 		cnt += alist_nitems(ofl->ofl_dtsfltrs);
10617c478bd9Sstevel@tonic-gate 
10621d9df23bSab 		/*
10631d9df23bSab 		 * Reserve entries for _init() and _fini() section addresses.
10641d9df23bSab 		 */
10651d9df23bSab 		if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U),
1066635216b6SRod Evans 		    SYM_NOHASH, NULL, ofl)) != NULL) &&
10671d9df23bSab 		    (sdp->sd_ref == REF_REL_NEED) &&
10681d9df23bSab 		    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
10691d9df23bSab 			sdp->sd_flags |= FLG_SY_UPREQD;
10701d9df23bSab 			cnt++;
10711d9df23bSab 		}
10721d9df23bSab 		if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U),
1073635216b6SRod Evans 		    SYM_NOHASH, NULL, ofl)) != NULL) &&
10741d9df23bSab 		    (sdp->sd_ref == REF_REL_NEED) &&
10751d9df23bSab 		    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
10761d9df23bSab 			sdp->sd_flags |= FLG_SY_UPREQD;
10771d9df23bSab 			cnt++;
10781d9df23bSab 		}
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 		/*
10811d9df23bSab 		 * Reserve entries for any soname, filter name (shared libs
10821d9df23bSab 		 * only), run-path pointers, cache names and audit requirements.
10837c478bd9Sstevel@tonic-gate 		 */
10841d9df23bSab 		if (ofl->ofl_soname) {
10851d9df23bSab 			cnt++;
1086635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_soname) == -1)
10871d9df23bSab 				return (S_ERROR);
10881d9df23bSab 		}
10891d9df23bSab 		if (ofl->ofl_filtees) {
10901d9df23bSab 			cnt++;
1091635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_filtees) == -1)
10921d9df23bSab 				return (S_ERROR);
10931d9df23bSab 
10941d9df23bSab 			/*
10951d9df23bSab 			 * If the filtees entry contains the $ORIGIN token
10961d9df23bSab 			 * make sure the associated DT_1_FLAGS entry is created.
10971d9df23bSab 			 */
10981d9df23bSab 			if (strstr(ofl->ofl_filtees,
10991d9df23bSab 			    MSG_ORIG(MSG_STR_ORIGIN))) {
11001d9df23bSab 				ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
11011d9df23bSab 				ofl->ofl_dtflags |= DF_ORIGIN;
11021d9df23bSab 			}
11037c478bd9Sstevel@tonic-gate 		}
11047c478bd9Sstevel@tonic-gate 	}
11051d9df23bSab 
11067c478bd9Sstevel@tonic-gate 	if (ofl->ofl_rpath) {
11077c478bd9Sstevel@tonic-gate 		cnt += 2;	/* DT_RPATH & DT_RUNPATH */
1108635216b6SRod Evans 		if (st_insert(strtbl, ofl->ofl_rpath) == -1)
11097c478bd9Sstevel@tonic-gate 			return (S_ERROR);
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 		/*
11127c478bd9Sstevel@tonic-gate 		 * If the rpath entry contains the $ORIGIN token make sure
11137c478bd9Sstevel@tonic-gate 		 * the associated DT_1_FLAGS entry is created.
11147c478bd9Sstevel@tonic-gate 		 */
11157c478bd9Sstevel@tonic-gate 		if (strstr(ofl->ofl_rpath, MSG_ORIG(MSG_STR_ORIGIN))) {
11167c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
11177c478bd9Sstevel@tonic-gate 			ofl->ofl_dtflags |= DF_ORIGIN;
11187c478bd9Sstevel@tonic-gate 		}
11197c478bd9Sstevel@tonic-gate 	}
11207c478bd9Sstevel@tonic-gate 
11211d9df23bSab 	if (not_relobj) {
112257ef7aa9SRod Evans 		Aliste	idx;
112394c044f4SRod Evans 		Sg_desc	*sgp;
112457ef7aa9SRod Evans 
11251d9df23bSab 		if (ofl->ofl_config) {
11261d9df23bSab 			cnt++;
1127635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_config) == -1)
11281d9df23bSab 				return (S_ERROR);
11297c478bd9Sstevel@tonic-gate 
11301d9df23bSab 			/*
11311d9df23bSab 			 * If the config entry contains the $ORIGIN token
11321d9df23bSab 			 * make sure the associated DT_1_FLAGS entry is created.
11331d9df23bSab 			 */
11341d9df23bSab 			if (strstr(ofl->ofl_config, MSG_ORIG(MSG_STR_ORIGIN))) {
11351d9df23bSab 				ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
11361d9df23bSab 				ofl->ofl_dtflags |= DF_ORIGIN;
11371d9df23bSab 			}
11381d9df23bSab 		}
11391d9df23bSab 		if (ofl->ofl_depaudit) {
11401d9df23bSab 			cnt++;
1141635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_depaudit) == -1)
11421d9df23bSab 				return (S_ERROR);
11431d9df23bSab 		}
11441d9df23bSab 		if (ofl->ofl_audit) {
11451d9df23bSab 			cnt++;
1146635216b6SRod Evans 			if (st_insert(strtbl, ofl->ofl_audit) == -1)
11471d9df23bSab 				return (S_ERROR);
11481d9df23bSab 		}
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 		/*
115194c044f4SRod Evans 		 * Reserve entries for the DT_HASH, DT_STRTAB, DT_STRSZ,
115294c044f4SRod Evans 		 * DT_SYMTAB, DT_SYMENT, and DT_CHECKSUM.
11537c478bd9Sstevel@tonic-gate 		 */
11547c478bd9Sstevel@tonic-gate 		cnt += 6;
11557c478bd9Sstevel@tonic-gate 
11569039eeafSab 		/*
11579039eeafSab 		 * If we are including local functions at the head of
11589039eeafSab 		 * the dynsym, then also reserve entries for DT_SUNW_SYMTAB
11599039eeafSab 		 * and DT_SUNW_SYMSZ.
11609039eeafSab 		 */
1161d579eb63Sab 		if (OFL_ALLOW_LDYNSYM(ofl))
11629039eeafSab 			cnt += 2;
11639039eeafSab 
1164d579eb63Sab 		if ((ofl->ofl_dynsymsortcnt > 0) ||
1165d579eb63Sab 		    (ofl->ofl_dyntlssortcnt > 0))
1166d579eb63Sab 			cnt++;		/* DT_SUNW_SORTENT */
1167d579eb63Sab 
1168d579eb63Sab 		if (ofl->ofl_dynsymsortcnt > 0)
1169d579eb63Sab 			cnt += 2;	/* DT_SUNW_[SYMSORT|SYMSORTSZ] */
1170d579eb63Sab 
1171d579eb63Sab 		if (ofl->ofl_dyntlssortcnt > 0)
1172d579eb63Sab 			cnt += 2;	/* DT_SUNW_[TLSSORT|TLSSORTSZ] */
1173d579eb63Sab 
11747c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) ==
11757c478bd9Sstevel@tonic-gate 		    FLG_OF_VERDEF)
11767c478bd9Sstevel@tonic-gate 			cnt += 2;		/* DT_VERDEF & DT_VERDEFNUM */
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) ==
11797c478bd9Sstevel@tonic-gate 		    FLG_OF_VERNEED)
11807c478bd9Sstevel@tonic-gate 			cnt += 2;		/* DT_VERNEED & DT_VERNEEDNUM */
11817c478bd9Sstevel@tonic-gate 
11821d9df23bSab 		if ((flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt)
118394c044f4SRod Evans 			cnt++;			/* DT_RELACOUNT */
11847c478bd9Sstevel@tonic-gate 
118594c044f4SRod Evans 		if (flags & FLG_OF_TEXTREL)	/* DT_TEXTREL */
11867c478bd9Sstevel@tonic-gate 			cnt++;
11877c478bd9Sstevel@tonic-gate 
118894c044f4SRod Evans 		if (ofl->ofl_osfiniarray)	/* DT_FINI_ARRAY */
118994c044f4SRod Evans 			cnt += 2;		/*    DT_FINI_ARRAYSZ */
11907c478bd9Sstevel@tonic-gate 
119194c044f4SRod Evans 		if (ofl->ofl_osinitarray)	/* DT_INIT_ARRAY */
119294c044f4SRod Evans 			cnt += 2;		/*    DT_INIT_ARRAYSZ */
11937c478bd9Sstevel@tonic-gate 
119494c044f4SRod Evans 		if (ofl->ofl_ospreinitarray)	/* DT_PREINIT_ARRAY & */
119594c044f4SRod Evans 			cnt += 2;		/*    DT_PREINIT_ARRAYSZ */
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 		/*
119894c044f4SRod Evans 		 * If we have plt's reserve a DT_PLTRELSZ, DT_PLTREL and
119994c044f4SRod Evans 		 * DT_JMPREL.
12007c478bd9Sstevel@tonic-gate 		 */
12017c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltcnt)
12027c478bd9Sstevel@tonic-gate 			cnt += 3;
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 		/*
120594c044f4SRod Evans 		 * If plt padding is needed (Sparcv9).
12067c478bd9Sstevel@tonic-gate 		 */
12077c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltpad)
12087c478bd9Sstevel@tonic-gate 			cnt += 2;		/* DT_PLTPAD & DT_PLTPADSZ */
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 		/*
121194c044f4SRod Evans 		 * If we have any relocations reserve a DT_REL, DT_RELSZ and
121294c044f4SRod Evans 		 * DT_RELENT entry.
12137c478bd9Sstevel@tonic-gate 		 */
12147c478bd9Sstevel@tonic-gate 		if (ofl->ofl_relocsz)
12157c478bd9Sstevel@tonic-gate 			cnt += 3;
12167c478bd9Sstevel@tonic-gate 
12177c478bd9Sstevel@tonic-gate 		/*
121894c044f4SRod Evans 		 * If a syminfo section is required create DT_SYMINFO,
121994c044f4SRod Evans 		 * DT_SYMINSZ, and DT_SYMINENT entries.
12207c478bd9Sstevel@tonic-gate 		 */
12211d9df23bSab 		if (flags & FLG_OF_SYMINFO)
12227c478bd9Sstevel@tonic-gate 			cnt += 3;
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 		/*
12257c478bd9Sstevel@tonic-gate 		 * If there are any partially initialized sections allocate
122694c044f4SRod Evans 		 * DT_MOVETAB, DT_MOVESZ and DT_MOVEENT.
12277c478bd9Sstevel@tonic-gate 		 */
12287c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osmove)
12297c478bd9Sstevel@tonic-gate 			cnt += 3;
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate 		/*
12329039eeafSab 		 * Allocate one DT_REGISTER entry for every register symbol.
12337c478bd9Sstevel@tonic-gate 		 */
12347c478bd9Sstevel@tonic-gate 		cnt += ofl->ofl_regsymcnt;
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 		/*
12377c478bd9Sstevel@tonic-gate 		 * Reserve a entry for each '-zrtldinfo=...' specified
12387c478bd9Sstevel@tonic-gate 		 * on the command line.
12397c478bd9Sstevel@tonic-gate 		 */
124057ef7aa9SRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_rtldinfo, idx, sdp))
12417c478bd9Sstevel@tonic-gate 			cnt++;
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 		/*
124494c044f4SRod Evans 		 * The following entry should only be placed in a segment that
124594c044f4SRod Evans 		 * is writable.
12467c478bd9Sstevel@tonic-gate 		 */
124794c044f4SRod Evans 		if (((sgp = osp->os_sgdesc) != NULL) &&
124894c044f4SRod Evans 		    (sgp->sg_phdr.p_flags & PF_W) && ofl->ofl_osinterp)
124994c044f4SRod Evans 			cnt++;		/* DT_DEBUG */
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 		/*
125208278a5eSRod Evans 		 * Capabilities require a .dynamic entry for the .SUNW_cap
125308278a5eSRod Evans 		 * section.
12547c478bd9Sstevel@tonic-gate 		 */
12557c478bd9Sstevel@tonic-gate 		if (ofl->ofl_oscap)
125694c044f4SRod Evans 			cnt++;			/* DT_SUNW_CAP */
12577c478bd9Sstevel@tonic-gate 
125808278a5eSRod Evans 		/*
125908278a5eSRod Evans 		 * Symbol capabilities require a .dynamic entry for the
126008278a5eSRod Evans 		 * .SUNW_capinfo section.
126108278a5eSRod Evans 		 */
126208278a5eSRod Evans 		if (ofl->ofl_oscapinfo)
126394c044f4SRod Evans 			cnt++;			/* DT_SUNW_CAPINFO */
126408278a5eSRod Evans 
126508278a5eSRod Evans 		/*
126608278a5eSRod Evans 		 * Capabilities chain information requires a .SUNW_capchain
126794c044f4SRod Evans 		 * entry (DT_SUNW_CAPCHAIN), entry size (DT_SUNW_CAPCHAINENT),
126894c044f4SRod Evans 		 * and total size (DT_SUNW_CAPCHAINSZ).
126908278a5eSRod Evans 		 */
127008278a5eSRod Evans 		if (ofl->ofl_oscapchain)
127194c044f4SRod Evans 			cnt += 3;
127208278a5eSRod Evans 
12731d9df23bSab 		if (flags & FLG_OF_SYMBOLIC)
127494c044f4SRod Evans 			cnt++;			/* DT_SYMBOLIC */
1275d2a70789SRichard Lowe 
1276d2a70789SRichard Lowe 		if (ofl->ofl_aslr != 0)		/* DT_SUNW_ASLR */
1277d2a70789SRichard Lowe 			cnt++;
12781d9df23bSab 	}
12797c478bd9Sstevel@tonic-gate 
1280b6a0e2cdSRichard Lowe 	/* DT_SUNW_KMOD */
1281b6a0e2cdSRichard Lowe 	if (ofl->ofl_flags & FLG_OF_KMOD)
1282b6a0e2cdSRichard Lowe 		cnt++;
1283b6a0e2cdSRichard Lowe 
12847c478bd9Sstevel@tonic-gate 	/*
12855aefb655Srie 	 * Account for Architecture dependent .dynamic entries, and defaults.
12867c478bd9Sstevel@tonic-gate 	 */
1287ba2be530Sab 	(*ld_targ.t_mr.mr_mach_make_dynamic)(ofl, &cnt);
12887c478bd9Sstevel@tonic-gate 
12893244bcaaSab 	/*
12903244bcaaSab 	 * DT_FLAGS, DT_FLAGS_1, DT_SUNW_STRPAD, and DT_NULL. Also,
12913244bcaaSab 	 * allow room for the unused extra DT_NULLs. These are included
12923244bcaaSab 	 * to allow an ELF editor room to add items later.
12933244bcaaSab 	 */
12943244bcaaSab 	cnt += 4 + DYNAMIC_EXTRA_ELTS;
12957c478bd9Sstevel@tonic-gate 
1296ba2be530Sab 	/*
1297ba2be530Sab 	 * DT_SUNW_LDMACH. Used to hold the ELF machine code of the
1298ba2be530Sab 	 * linker that produced the output object. This information
1299ba2be530Sab 	 * allows us to determine whether a given object was linked
1300ba2be530Sab 	 * natively, or by a linker running on a different type of
1301ba2be530Sab 	 * system. This information can be valuable if one suspects
1302ba2be530Sab 	 * that a problem might be due to alignment or byte order issues.
1303ba2be530Sab 	 */
1304ba2be530Sab 	cnt++;
1305ba2be530Sab 
13067c478bd9Sstevel@tonic-gate 	/*
13077c478bd9Sstevel@tonic-gate 	 * Determine the size of the section from the number of entries.
13087c478bd9Sstevel@tonic-gate 	 */
13097c478bd9Sstevel@tonic-gate 	size = cnt * (size_t)shdr->sh_entsize;
13107c478bd9Sstevel@tonic-gate 
13117c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
13127c478bd9Sstevel@tonic-gate 	data->d_size = size;
13137c478bd9Sstevel@tonic-gate 
13144f680cc6SAli Bahrami 	/*
13154f680cc6SAli Bahrami 	 * There are several tags that are specific to the Solaris osabi
13164f680cc6SAli Bahrami 	 * range which we unconditionally put into any dynamic section
13174f680cc6SAli Bahrami 	 * we create (e.g. DT_SUNW_STRPAD or DT_SUNW_LDMACH). As such,
13184f680cc6SAli Bahrami 	 * any Solaris object with a dynamic section should be tagged as
13194f680cc6SAli Bahrami 	 * ELFOSABI_SOLARIS.
13204f680cc6SAli Bahrami 	 */
13214f680cc6SAli Bahrami 	ofl->ofl_flags |= FLG_OF_OSABI;
13224f680cc6SAli Bahrami 
13237c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osdynamic);
13247c478bd9Sstevel@tonic-gate }
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate /*
13277c478bd9Sstevel@tonic-gate  * Build the GOT section and its associated relocation entries.
13287c478bd9Sstevel@tonic-gate  */
13297c478bd9Sstevel@tonic-gate uintptr_t
ld_make_got(Ofl_desc * ofl)13305aefb655Srie ld_make_got(Ofl_desc *ofl)
13317c478bd9Sstevel@tonic-gate {
13327c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
1333ba2be530Sab 	Shdr	*shdr;
1334ba2be530Sab 	Is_desc	*isec;
1335ba2be530Sab 	size_t	size = (size_t)ofl->ofl_gotcnt * ld_targ.t_m.m_got_entsize;
1336ba2be530Sab 	size_t	rsize = (size_t)ofl->ofl_relocgotsz;
13377c478bd9Sstevel@tonic-gate 
13389039eeafSab 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_GOT), 0,
13399039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
13407c478bd9Sstevel@tonic-gate 		return (S_ERROR);
13419039eeafSab 
13427c478bd9Sstevel@tonic-gate 	data->d_size = size;
13437c478bd9Sstevel@tonic-gate 
13449039eeafSab 	shdr->sh_flags |= SHF_WRITE;
13457c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
1346ba2be530Sab 	shdr->sh_entsize = ld_targ.t_m.m_got_entsize;
13477c478bd9Sstevel@tonic-gate 
134869112eddSAli Bahrami 	ofl->ofl_osgot = ld_place_section(ofl, isec, NULL,
134969112eddSAli Bahrami 	    ld_targ.t_id.id_got, NULL);
1350ba2be530Sab 	if (ofl->ofl_osgot == (Os_desc *)S_ERROR)
13517c478bd9Sstevel@tonic-gate 		return (S_ERROR);
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 	ofl->ofl_osgot->os_szoutrels = (Xword)rsize;
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	return (1);
13567c478bd9Sstevel@tonic-gate }
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate /*
135970d3e49eSrie  * Build an interpreter section.
13607c478bd9Sstevel@tonic-gate  */
13615aefb655Srie static uintptr_t
make_interp(Ofl_desc * ofl)13627c478bd9Sstevel@tonic-gate make_interp(Ofl_desc *ofl)
13637c478bd9Sstevel@tonic-gate {
13647c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
13657c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
13667c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
13677c478bd9Sstevel@tonic-gate 	const char	*iname = ofl->ofl_interp;
13687c478bd9Sstevel@tonic-gate 	size_t		size;
13697c478bd9Sstevel@tonic-gate 
137070d3e49eSrie 	/*
137170d3e49eSrie 	 * If -z nointerp is in effect, don't create an interpreter section.
137270d3e49eSrie 	 */
137370d3e49eSrie 	if (ofl->ofl_flags1 & FLG_OF1_NOINTRP)
137470d3e49eSrie 		return (1);
137570d3e49eSrie 
13767c478bd9Sstevel@tonic-gate 	/*
137794c044f4SRod Evans 	 * An .interp section is always created for a dynamic executable.
137894c044f4SRod Evans 	 * A user can define the interpreter to use.  This definition overrides
137994c044f4SRod Evans 	 * the default that would be recorded in an executable, and triggers
138094c044f4SRod Evans 	 * the creation of an .interp section in any other object.  Presumably
138194c044f4SRod Evans 	 * the user knows what they are doing.  Refer to the generic ELF ABI
138294c044f4SRod Evans 	 * section 5-4, and the ld(1) -I option.
13837c478bd9Sstevel@tonic-gate 	 */
13847c478bd9Sstevel@tonic-gate 	if (((ofl->ofl_flags & (FLG_OF_DYNAMIC | FLG_OF_EXEC |
13857c478bd9Sstevel@tonic-gate 	    FLG_OF_RELOBJ)) != (FLG_OF_DYNAMIC | FLG_OF_EXEC)) && !iname)
13867c478bd9Sstevel@tonic-gate 		return (1);
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate 	/*
138994c044f4SRod Evans 	 * In the case of a dynamic executable, supply a default interpreter
139094c044f4SRod Evans 	 * if the user has not specified their own.
13917c478bd9Sstevel@tonic-gate 	 */
1392ba2be530Sab 	if (iname == NULL)
1393ba2be530Sab 		iname = ofl->ofl_interp = ld_targ.t_m.m_def_interp;
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 	size = strlen(iname) + 1;
13967c478bd9Sstevel@tonic-gate 
13979039eeafSab 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_INTERP), 0,
13989039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
13997c478bd9Sstevel@tonic-gate 		return (S_ERROR);
14007c478bd9Sstevel@tonic-gate 
14019039eeafSab 	data->d_size = size;
14027c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
14039039eeafSab 	data->d_align = shdr->sh_addralign = 1;
14047c478bd9Sstevel@tonic-gate 
1405ba2be530Sab 	ofl->ofl_osinterp =
140669112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_interp, NULL);
14077c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osinterp);
14087c478bd9Sstevel@tonic-gate }
14097c478bd9Sstevel@tonic-gate 
141069112eddSAli Bahrami /*
141108278a5eSRod Evans  * Common function used to build the SHT_SUNW_versym section, SHT_SUNW_syminfo
141208278a5eSRod Evans  * section, and SHT_SUNW_capinfo section.  Each of these sections provide
141308278a5eSRod Evans  * additional symbol information, and their size parallels the associated
141408278a5eSRod Evans  * symbol table.
141508278a5eSRod Evans  */
141608278a5eSRod Evans static Os_desc *
make_sym_sec(Ofl_desc * ofl,const char * sectname,Word stype,int ident)141708278a5eSRod Evans make_sym_sec(Ofl_desc *ofl, const char *sectname, Word stype, int ident)
141808278a5eSRod Evans {
141908278a5eSRod Evans 	Shdr		*shdr;
142008278a5eSRod Evans 	Elf_Data	*data;
142108278a5eSRod Evans 	Is_desc		*isec;
142208278a5eSRod Evans 
142308278a5eSRod Evans 	/*
142408278a5eSRod Evans 	 * We don't know the size of this section yet, so set it to 0.  The
142508278a5eSRod Evans 	 * size gets filled in after the associated symbol table is sized.
142608278a5eSRod Evans 	 */
142708278a5eSRod Evans 	if (new_section(ofl, stype, sectname, 0, &isec, &shdr, &data) ==
142808278a5eSRod Evans 	    S_ERROR)
142908278a5eSRod Evans 		return ((Os_desc *)S_ERROR);
143008278a5eSRod Evans 
143108278a5eSRod Evans 	return (ld_place_section(ofl, isec, NULL, ident, NULL));
143208278a5eSRod Evans }
143308278a5eSRod Evans 
143408278a5eSRod Evans /*
143508278a5eSRod Evans  * Determine whether a symbol capability is redundant because the object
143608278a5eSRod Evans  * capabilities are more restrictive.
143708278a5eSRod Evans  */
143808278a5eSRod Evans inline static int
is_cap_redundant(Objcapset * ocapset,Objcapset * scapset)143908278a5eSRod Evans is_cap_redundant(Objcapset *ocapset, Objcapset *scapset)
144008278a5eSRod Evans {
144108278a5eSRod Evans 	Alist		*oalp, *salp;
144208278a5eSRod Evans 	elfcap_mask_t	omsk, smsk;
144308278a5eSRod Evans 
144408278a5eSRod Evans 	/*
144508278a5eSRod Evans 	 * Inspect any platform capabilities.  If the object defines platform
144608278a5eSRod Evans 	 * capabilities, then the object will only be loaded for those
144708278a5eSRod Evans 	 * platforms.  A symbol capability set that doesn't define the same
144808278a5eSRod Evans 	 * platforms is redundant, and a symbol capability that does not provide
144908278a5eSRod Evans 	 * at least one platform name that matches a platform name in the object
145008278a5eSRod Evans 	 * capabilities will never execute (as the object wouldn't have been
145108278a5eSRod Evans 	 * loaded).
145208278a5eSRod Evans 	 */
145308278a5eSRod Evans 	oalp = ocapset->oc_plat.cl_val;
145408278a5eSRod Evans 	salp = scapset->oc_plat.cl_val;
145508278a5eSRod Evans 	if (oalp && ((salp == NULL) || cap_names_match(oalp, salp)))
145608278a5eSRod Evans 		return (1);
145708278a5eSRod Evans 
145808278a5eSRod Evans 	/*
145908278a5eSRod Evans 	 * If the symbol capability set defines platforms, and the object
146008278a5eSRod Evans 	 * doesn't, then the symbol set is more restrictive.
146108278a5eSRod Evans 	 */
146208278a5eSRod Evans 	if (salp && (oalp == NULL))
146308278a5eSRod Evans 		return (0);
146408278a5eSRod Evans 
146508278a5eSRod Evans 	/*
146608278a5eSRod Evans 	 * Next, inspect any machine name capabilities.  If the object defines
146708278a5eSRod Evans 	 * machine name capabilities, then the object will only be loaded for
146808278a5eSRod Evans 	 * those machines.  A symbol capability set that doesn't define the same
146908278a5eSRod Evans 	 * machine names is redundant, and a symbol capability that does not
147008278a5eSRod Evans 	 * provide at least one machine name that matches a machine name in the
147108278a5eSRod Evans 	 * object capabilities will never execute (as the object wouldn't have
147208278a5eSRod Evans 	 * been loaded).
147308278a5eSRod Evans 	 */
147408278a5eSRod Evans 	oalp = ocapset->oc_plat.cl_val;
147508278a5eSRod Evans 	salp = scapset->oc_plat.cl_val;
147608278a5eSRod Evans 	if (oalp && ((salp == NULL) || cap_names_match(oalp, salp)))
147708278a5eSRod Evans 		return (1);
147808278a5eSRod Evans 
147908278a5eSRod Evans 	/*
148008278a5eSRod Evans 	 * If the symbol capability set defines machine names, and the object
148108278a5eSRod Evans 	 * doesn't, then the symbol set is more restrictive.
148208278a5eSRod Evans 	 */
148308278a5eSRod Evans 	if (salp && (oalp == NULL))
148408278a5eSRod Evans 		return (0);
148508278a5eSRod Evans 
148608278a5eSRod Evans 	/*
148708278a5eSRod Evans 	 * Next, inspect any hardware capabilities.  If the objects hardware
148808278a5eSRod Evans 	 * capabilities are greater than or equal to that of the symbols
148908278a5eSRod Evans 	 * capabilities, then the symbol capability set is redundant.  If the
149008278a5eSRod Evans 	 * symbols hardware capabilities are greater that the objects, then the
149108278a5eSRod Evans 	 * symbol set is more restrictive.
149208278a5eSRod Evans 	 *
149308278a5eSRod Evans 	 * Note that this is a somewhat arbitrary definition, as each capability
149408278a5eSRod Evans 	 * bit is independent of the others, and some of the higher order bits
149508278a5eSRod Evans 	 * could be considered to be less important than lower ones.  However,
149608278a5eSRod Evans 	 * this is the only reasonable non-subjective definition.
149708278a5eSRod Evans 	 */
1498*56726c7eSRobert Mustacchi 	omsk = ocapset->oc_hw_3.cm_val;
1499*56726c7eSRobert Mustacchi 	smsk = scapset->oc_hw_3.cm_val;
1500*56726c7eSRobert Mustacchi 	if ((omsk > smsk) || (omsk && (omsk == smsk)))
1501*56726c7eSRobert Mustacchi 		return (1);
1502*56726c7eSRobert Mustacchi 	if (omsk < smsk)
1503*56726c7eSRobert Mustacchi 		return (0);
1504*56726c7eSRobert Mustacchi 
1505*56726c7eSRobert Mustacchi 
150608278a5eSRod Evans 	omsk = ocapset->oc_hw_2.cm_val;
150708278a5eSRod Evans 	smsk = scapset->oc_hw_2.cm_val;
150808278a5eSRod Evans 	if ((omsk > smsk) || (omsk && (omsk == smsk)))
150908278a5eSRod Evans 		return (1);
151008278a5eSRod Evans 	if (omsk < smsk)
151108278a5eSRod Evans 		return (0);
151208278a5eSRod Evans 
151308278a5eSRod Evans 	/*
151408278a5eSRod Evans 	 * Finally, inspect the remaining hardware capabilities.
151508278a5eSRod Evans 	 */
151608278a5eSRod Evans 	omsk = ocapset->oc_hw_1.cm_val;
151708278a5eSRod Evans 	smsk = scapset->oc_hw_1.cm_val;
151808278a5eSRod Evans 	if ((omsk > smsk) || (omsk && (omsk == smsk)))
151908278a5eSRod Evans 		return (1);
152008278a5eSRod Evans 
152108278a5eSRod Evans 	return (0);
152208278a5eSRod Evans }
152308278a5eSRod Evans 
152408278a5eSRod Evans /*
152508278a5eSRod Evans  * Capabilities values might have been assigned excluded values.  These
152608278a5eSRod Evans  * excluded values should be removed before calculating any capabilities
152708278a5eSRod Evans  * sections size.
152869112eddSAli Bahrami  */
152969112eddSAli Bahrami static void
capmask_value(Lm_list * lml,Word type,Capmask * capmask,int * title)153008278a5eSRod Evans capmask_value(Lm_list *lml, Word type, Capmask *capmask, int *title)
153169112eddSAli Bahrami {
153269112eddSAli Bahrami 	/*
153308278a5eSRod Evans 	 * First determine whether any bits should be excluded.
153469112eddSAli Bahrami 	 */
153508278a5eSRod Evans 	if ((capmask->cm_val & capmask->cm_exc) == 0)
153608278a5eSRod Evans 		return;
153708278a5eSRod Evans 
153808278a5eSRod Evans 	DBG_CALL(Dbg_cap_post_title(lml, title));
153908278a5eSRod Evans 
154008278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_CURRENT, type,
154108278a5eSRod Evans 	    capmask->cm_val, ld_targ.t_m.m_mach));
154208278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_EXCLUDE, type,
154308278a5eSRod Evans 	    capmask->cm_exc, ld_targ.t_m.m_mach));
154408278a5eSRod Evans 
154508278a5eSRod Evans 	capmask->cm_val &= ~capmask->cm_exc;
154608278a5eSRod Evans 
154708278a5eSRod Evans 	DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_RESOLVED, type,
154808278a5eSRod Evans 	    capmask->cm_val, ld_targ.t_m.m_mach));
154908278a5eSRod Evans }
155008278a5eSRod Evans 
155108278a5eSRod Evans static void
capstr_value(Lm_list * lml,Word type,Caplist * caplist,int * title)155208278a5eSRod Evans capstr_value(Lm_list *lml, Word type, Caplist *caplist, int *title)
155308278a5eSRod Evans {
155408278a5eSRod Evans 	Aliste	idx1, idx2;
155508278a5eSRod Evans 	char	*estr;
155608278a5eSRod Evans 	Capstr	*capstr;
155708278a5eSRod Evans 	Boolean	found = FALSE;
155869112eddSAli Bahrami 
155908278a5eSRod Evans 	/*
156008278a5eSRod Evans 	 * First determine whether any strings should be excluded.
156108278a5eSRod Evans 	 */
156208278a5eSRod Evans 	for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) {
156308278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
156408278a5eSRod Evans 			if (strcmp(estr, capstr->cs_str) == 0) {
156508278a5eSRod Evans 				found = TRUE;
156608278a5eSRod Evans 				break;
156708278a5eSRod Evans 			}
156808278a5eSRod Evans 		}
156908278a5eSRod Evans 	}
157008278a5eSRod Evans 
157108278a5eSRod Evans 	if (found == FALSE)
157208278a5eSRod Evans 		return;
157308278a5eSRod Evans 
157408278a5eSRod Evans 	/*
157508278a5eSRod Evans 	 * Traverse the current strings, then delete the excluded strings,
157608278a5eSRod Evans 	 * and finally display the resolved strings.
157708278a5eSRod Evans 	 */
157808278a5eSRod Evans 	if (DBG_ENABLED) {
157908278a5eSRod Evans 		Dbg_cap_post_title(lml, title);
158008278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
158108278a5eSRod Evans 			Dbg_cap_ptr_entry(lml, DBG_STATE_CURRENT, type,
158208278a5eSRod Evans 			    capstr->cs_str);
158308278a5eSRod Evans 		}
158408278a5eSRod Evans 	}
158508278a5eSRod Evans 	for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) {
158608278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
158708278a5eSRod Evans 			if (strcmp(estr, capstr->cs_str) == 0) {
158808278a5eSRod Evans 				DBG_CALL(Dbg_cap_ptr_entry(lml,
158908278a5eSRod Evans 				    DBG_STATE_EXCLUDE, type, capstr->cs_str));
159008278a5eSRod Evans 				alist_delete(caplist->cl_val, &idx2);
159108278a5eSRod Evans 				break;
159208278a5eSRod Evans 			}
159308278a5eSRod Evans 		}
159408278a5eSRod Evans 	}
159508278a5eSRod Evans 	if (DBG_ENABLED) {
159608278a5eSRod Evans 		for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
159708278a5eSRod Evans 			Dbg_cap_ptr_entry(lml, DBG_STATE_RESOLVED, type,
159808278a5eSRod Evans 			    capstr->cs_str);
159908278a5eSRod Evans 		}
160008278a5eSRod Evans 	}
160169112eddSAli Bahrami }
160269112eddSAli Bahrami 
16037c478bd9Sstevel@tonic-gate /*
160408278a5eSRod Evans  * Build a capabilities section.
16057c478bd9Sstevel@tonic-gate  */
160608278a5eSRod Evans #define	CAP_UPDATE(cap, capndx, tag, val)	\
160708278a5eSRod Evans 	cap->c_tag = tag; \
160808278a5eSRod Evans 	cap->c_un.c_val = val; \
160908278a5eSRod Evans 	cap++, capndx++;
161008278a5eSRod Evans 
16115aefb655Srie static uintptr_t
make_cap(Ofl_desc * ofl,Word shtype,const char * shname,int ident)161208278a5eSRod Evans make_cap(Ofl_desc *ofl, Word shtype, const char *shname, int ident)
16137c478bd9Sstevel@tonic-gate {
16147c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
16157c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
16167c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
16177c478bd9Sstevel@tonic-gate 	Cap		*cap;
16187c478bd9Sstevel@tonic-gate 	size_t		size = 0;
161908278a5eSRod Evans 	Word		capndx = 0;
162008278a5eSRod Evans 	Str_tbl		*strtbl;
162108278a5eSRod Evans 	Objcapset	*ocapset = &ofl->ofl_ocapset;
162208278a5eSRod Evans 	Aliste		idx1;
162308278a5eSRod Evans 	Capstr		*capstr;
162408278a5eSRod Evans 	int		title = 0;
162569112eddSAli Bahrami 
162608278a5eSRod Evans 	/*
162708278a5eSRod Evans 	 * Determine which string table to use for any CA_SUNW_MACH,
162808278a5eSRod Evans 	 * CA_SUNW_PLAT, or CA_SUNW_ID strings.
162908278a5eSRod Evans 	 */
163008278a5eSRod Evans 	if (OFL_IS_STATIC_OBJ(ofl))
163108278a5eSRod Evans 		strtbl = ofl->ofl_strtab;
163208278a5eSRod Evans 	else
163308278a5eSRod Evans 		strtbl = ofl->ofl_dynstrtab;
163408278a5eSRod Evans 
1635d47ecb8cSRod Evans 	/*
1636d47ecb8cSRod Evans 	 * If symbol capabilities have been requested, but none have been
1637d47ecb8cSRod Evans 	 * created, warn the user.  This scenario can occur if none of the
1638d47ecb8cSRod Evans 	 * input relocatable objects defined any object capabilities.
1639d47ecb8cSRod Evans 	 */
16401007fd6fSAli Bahrami 	if ((ofl->ofl_flags & FLG_OF_OTOSCAP) && (ofl->ofl_capsymcnt == 0))
16411007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_CAP_NOSYMSFOUND));
1642d47ecb8cSRod Evans 
164308278a5eSRod Evans 	/*
164408278a5eSRod Evans 	 * If symbol capabilities have been collected, but no symbols are left
164508278a5eSRod Evans 	 * referencing these capabilities, promote the capability groups back
164608278a5eSRod Evans 	 * to an object capability definition.
164708278a5eSRod Evans 	 */
164808278a5eSRod Evans 	if ((ofl->ofl_flags & FLG_OF_OTOSCAP) && ofl->ofl_capsymcnt &&
164908278a5eSRod Evans 	    (ofl->ofl_capfamilies == NULL)) {
16501007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_CAP_NOSYMSFOUND));
165108278a5eSRod Evans 		ld_cap_move_symtoobj(ofl);
165208278a5eSRod Evans 		ofl->ofl_capsymcnt = 0;
165308278a5eSRod Evans 		ofl->ofl_capgroups = NULL;
1654f441771bSRod Evans 		ofl->ofl_flags &= ~FLG_OF_OTOSCAP;
165508278a5eSRod Evans 	}
165608278a5eSRod Evans 
165708278a5eSRod Evans 	/*
165808278a5eSRod Evans 	 * Remove any excluded capabilities.
165908278a5eSRod Evans 	 */
166008278a5eSRod Evans 	capstr_value(ofl->ofl_lml, CA_SUNW_PLAT, &ocapset->oc_plat, &title);
166108278a5eSRod Evans 	capstr_value(ofl->ofl_lml, CA_SUNW_MACH, &ocapset->oc_mach, &title);
1662*56726c7eSRobert Mustacchi 	capmask_value(ofl->ofl_lml, CA_SUNW_HW_3, &ocapset->oc_hw_3, &title);
166308278a5eSRod Evans 	capmask_value(ofl->ofl_lml, CA_SUNW_HW_2, &ocapset->oc_hw_2, &title);
166408278a5eSRod Evans 	capmask_value(ofl->ofl_lml, CA_SUNW_HW_1, &ocapset->oc_hw_1, &title);
166508278a5eSRod Evans 	capmask_value(ofl->ofl_lml, CA_SUNW_SF_1, &ocapset->oc_sf_1, &title);
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	/*
166808278a5eSRod Evans 	 * Determine how many entries are required for any object capabilities.
16697c478bd9Sstevel@tonic-gate 	 */
167008278a5eSRod Evans 	size += alist_nitems(ocapset->oc_plat.cl_val);
167108278a5eSRod Evans 	size += alist_nitems(ocapset->oc_mach.cl_val);
1672*56726c7eSRobert Mustacchi 	if (ocapset->oc_hw_3.cm_val)
1673*56726c7eSRobert Mustacchi 		size++;
167408278a5eSRod Evans 	if (ocapset->oc_hw_2.cm_val)
16757c478bd9Sstevel@tonic-gate 		size++;
167608278a5eSRod Evans 	if (ocapset->oc_hw_1.cm_val)
167708278a5eSRod Evans 		size++;
167808278a5eSRod Evans 	if (ocapset->oc_sf_1.cm_val)
16797c478bd9Sstevel@tonic-gate 		size++;
168069112eddSAli Bahrami 
168108278a5eSRod Evans 	/*
168208278a5eSRod Evans 	 * Only identify a capabilities group if the group has content.  If a
168308278a5eSRod Evans 	 * capabilities identifier exists, and no other capabilities have been
168408278a5eSRod Evans 	 * supplied, remove the identifier.  This scenario could exist if a
168508278a5eSRod Evans 	 * user mistakenly defined a lone identifier, or if an identified group
168608278a5eSRod Evans 	 * was overridden so as to clear the existing capabilities and the
168708278a5eSRod Evans 	 * identifier was not also cleared.
168808278a5eSRod Evans 	 */
168908278a5eSRod Evans 	if (ocapset->oc_id.cs_str) {
169008278a5eSRod Evans 		if (size)
169108278a5eSRod Evans 			size++;
169208278a5eSRod Evans 		else
169308278a5eSRod Evans 			ocapset->oc_id.cs_str = NULL;
169408278a5eSRod Evans 	}
169508278a5eSRod Evans 	if (size)
169608278a5eSRod Evans 		size++;			/* Add CA_SUNW_NULL */
169769112eddSAli Bahrami 
169808278a5eSRod Evans 	/*
169908278a5eSRod Evans 	 * Determine how many entries are required for any symbol capabilities.
170008278a5eSRod Evans 	 */
170108278a5eSRod Evans 	if (ofl->ofl_capsymcnt) {
170208278a5eSRod Evans 		/*
170308278a5eSRod Evans 		 * If there are no object capabilities, a CA_SUNW_NULL entry
170408278a5eSRod Evans 		 * is required before any symbol capabilities.
170508278a5eSRod Evans 		 */
170608278a5eSRod Evans 		if (size == 0)
170708278a5eSRod Evans 			size++;
170808278a5eSRod Evans 		size += ofl->ofl_capsymcnt;
170969112eddSAli Bahrami 	}
171069112eddSAli Bahrami 
171108278a5eSRod Evans 	if (size == 0)
1712fb8f92baSToomas Soome 		return (0);
171369112eddSAli Bahrami 
171408278a5eSRod Evans 	if (new_section(ofl, shtype, shname, size, &isec,
171508278a5eSRod Evans 	    &shdr, &data) == S_ERROR)
17167c478bd9Sstevel@tonic-gate 		return (S_ERROR);
17177c478bd9Sstevel@tonic-gate 
171857ef7aa9SRod Evans 	if ((data->d_buf = libld_malloc(shdr->sh_size)) == NULL)
17197c478bd9Sstevel@tonic-gate 		return (S_ERROR);
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	cap = (Cap *)data->d_buf;
172208278a5eSRod Evans 
172308278a5eSRod Evans 	/*
172408278a5eSRod Evans 	 * Fill in any object capabilities.  If there is an identifier, then the
172508278a5eSRod Evans 	 * identifier comes first.  The remaining items follow in precedence
172608278a5eSRod Evans 	 * order, although the order isn't important for runtime verification.
172708278a5eSRod Evans 	 */
172808278a5eSRod Evans 	if (ocapset->oc_id.cs_str) {
172908278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_CAPSTRS;
173008278a5eSRod Evans 		if (st_insert(strtbl, ocapset->oc_id.cs_str) == -1)
173108278a5eSRod Evans 			return (S_ERROR);
173208278a5eSRod Evans 		ocapset->oc_id.cs_ndx = capndx;
173308278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0);
17347c478bd9Sstevel@tonic-gate 	}
173508278a5eSRod Evans 	if (ocapset->oc_plat.cl_val) {
173608278a5eSRod Evans 		ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS);
173708278a5eSRod Evans 
173808278a5eSRod Evans 		/*
173908278a5eSRod Evans 		 * Insert any platform name strings in the appropriate string
174008278a5eSRod Evans 		 * table.  The capability value can't be filled in yet, as the
174108278a5eSRod Evans 		 * final offset of the strings isn't known until later.
174208278a5eSRod Evans 		 */
174308278a5eSRod Evans 		for (ALIST_TRAVERSE(ocapset->oc_plat.cl_val, idx1, capstr)) {
174408278a5eSRod Evans 			if (st_insert(strtbl, capstr->cs_str) == -1)
174508278a5eSRod Evans 				return (S_ERROR);
174608278a5eSRod Evans 			capstr->cs_ndx = capndx;
174708278a5eSRod Evans 			CAP_UPDATE(cap, capndx, CA_SUNW_PLAT, 0);
174808278a5eSRod Evans 		}
174908278a5eSRod Evans 	}
175008278a5eSRod Evans 	if (ocapset->oc_mach.cl_val) {
175108278a5eSRod Evans 		ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS);
175208278a5eSRod Evans 
175308278a5eSRod Evans 		/*
175408278a5eSRod Evans 		 * Insert the machine name strings in the appropriate string
175508278a5eSRod Evans 		 * table.  The capability value can't be filled in yet, as the
175608278a5eSRod Evans 		 * final offset of the strings isn't known until later.
175708278a5eSRod Evans 		 */
175808278a5eSRod Evans 		for (ALIST_TRAVERSE(ocapset->oc_mach.cl_val, idx1, capstr)) {
175908278a5eSRod Evans 			if (st_insert(strtbl, capstr->cs_str) == -1)
176008278a5eSRod Evans 				return (S_ERROR);
176108278a5eSRod Evans 			capstr->cs_ndx = capndx;
176208278a5eSRod Evans 			CAP_UPDATE(cap, capndx, CA_SUNW_MACH, 0);
176308278a5eSRod Evans 		}
176408278a5eSRod Evans 	}
1765*56726c7eSRobert Mustacchi 	if (ocapset->oc_hw_3.cm_val) {
1766*56726c7eSRobert Mustacchi 		ofl->ofl_flags |= FLG_OF_PTCAP;
1767*56726c7eSRobert Mustacchi 		CAP_UPDATE(cap, capndx, CA_SUNW_HW_3, ocapset->oc_hw_3.cm_val);
1768*56726c7eSRobert Mustacchi 	}
176908278a5eSRod Evans 	if (ocapset->oc_hw_2.cm_val) {
177008278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_PTCAP;
177108278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_HW_2, ocapset->oc_hw_2.cm_val);
17727c478bd9Sstevel@tonic-gate 	}
177308278a5eSRod Evans 	if (ocapset->oc_hw_1.cm_val) {
177408278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_PTCAP;
177508278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_HW_1, ocapset->oc_hw_1.cm_val);
177608278a5eSRod Evans 	}
177708278a5eSRod Evans 	if (ocapset->oc_sf_1.cm_val) {
177808278a5eSRod Evans 		ofl->ofl_flags |= FLG_OF_PTCAP;
177908278a5eSRod Evans 		CAP_UPDATE(cap, capndx, CA_SUNW_SF_1, ocapset->oc_sf_1.cm_val);
178008278a5eSRod Evans 	}
178108278a5eSRod Evans 	CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0);
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 	/*
178408278a5eSRod Evans 	 * Fill in any symbol capabilities.
17857c478bd9Sstevel@tonic-gate 	 */
178608278a5eSRod Evans 	if (ofl->ofl_capgroups) {
178708278a5eSRod Evans 		Cap_group	*cgp;
178808278a5eSRod Evans 
178908278a5eSRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) {
179008278a5eSRod Evans 			Objcapset	*scapset = &cgp->cg_set;
179108278a5eSRod Evans 			Aliste		idx2;
179208278a5eSRod Evans 			Is_desc		*isp;
17937c478bd9Sstevel@tonic-gate 
179408278a5eSRod Evans 			cgp->cg_ndx = capndx;
179508278a5eSRod Evans 
179608278a5eSRod Evans 			if (scapset->oc_id.cs_str) {
179708278a5eSRod Evans 				ofl->ofl_flags |= FLG_OF_CAPSTRS;
179808278a5eSRod Evans 				/*
179908278a5eSRod Evans 				 * Insert the identifier string in the
180008278a5eSRod Evans 				 * appropriate string table.  The capability
180108278a5eSRod Evans 				 * value can't be filled in yet, as the final
180208278a5eSRod Evans 				 * offset of the string isn't known until later.
180308278a5eSRod Evans 				 */
180408278a5eSRod Evans 				if (st_insert(strtbl,
180508278a5eSRod Evans 				    scapset->oc_id.cs_str) == -1)
180608278a5eSRod Evans 					return (S_ERROR);
180708278a5eSRod Evans 				scapset->oc_id.cs_ndx = capndx;
180808278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0);
180908278a5eSRod Evans 			}
181008278a5eSRod Evans 
181108278a5eSRod Evans 			if (scapset->oc_plat.cl_val) {
181208278a5eSRod Evans 				ofl->ofl_flags |= FLG_OF_CAPSTRS;
181308278a5eSRod Evans 
181408278a5eSRod Evans 				/*
181508278a5eSRod Evans 				 * Insert the platform name string in the
181608278a5eSRod Evans 				 * appropriate string table.  The capability
181708278a5eSRod Evans 				 * value can't be filled in yet, as the final
181808278a5eSRod Evans 				 * offset of the string isn't known until later.
181908278a5eSRod Evans 				 */
182008278a5eSRod Evans 				for (ALIST_TRAVERSE(scapset->oc_plat.cl_val,
182108278a5eSRod Evans 				    idx2, capstr)) {
182208278a5eSRod Evans 					if (st_insert(strtbl,
182308278a5eSRod Evans 					    capstr->cs_str) == -1)
182408278a5eSRod Evans 						return (S_ERROR);
182508278a5eSRod Evans 					capstr->cs_ndx = capndx;
182608278a5eSRod Evans 					CAP_UPDATE(cap, capndx,
182708278a5eSRod Evans 					    CA_SUNW_PLAT, 0);
182808278a5eSRod Evans 				}
182908278a5eSRod Evans 			}
183008278a5eSRod Evans 			if (scapset->oc_mach.cl_val) {
183108278a5eSRod Evans 				ofl->ofl_flags |= FLG_OF_CAPSTRS;
183208278a5eSRod Evans 
183308278a5eSRod Evans 				/*
183408278a5eSRod Evans 				 * Insert the machine name string in the
183508278a5eSRod Evans 				 * appropriate string table.  The capability
183608278a5eSRod Evans 				 * value can't be filled in yet, as the final
183708278a5eSRod Evans 				 * offset of the string isn't known until later.
183808278a5eSRod Evans 				 */
183908278a5eSRod Evans 				for (ALIST_TRAVERSE(scapset->oc_mach.cl_val,
184008278a5eSRod Evans 				    idx2, capstr)) {
184108278a5eSRod Evans 					if (st_insert(strtbl,
184208278a5eSRod Evans 					    capstr->cs_str) == -1)
184308278a5eSRod Evans 						return (S_ERROR);
184408278a5eSRod Evans 					capstr->cs_ndx = capndx;
184508278a5eSRod Evans 					CAP_UPDATE(cap, capndx,
184608278a5eSRod Evans 					    CA_SUNW_MACH, 0);
184708278a5eSRod Evans 				}
184808278a5eSRod Evans 			}
1849*56726c7eSRobert Mustacchi 			if (scapset->oc_hw_3.cm_val) {
1850*56726c7eSRobert Mustacchi 				CAP_UPDATE(cap, capndx, CA_SUNW_HW_3,
1851*56726c7eSRobert Mustacchi 				    scapset->oc_hw_3.cm_val);
1852*56726c7eSRobert Mustacchi 			}
185308278a5eSRod Evans 			if (scapset->oc_hw_2.cm_val) {
185408278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_HW_2,
185508278a5eSRod Evans 				    scapset->oc_hw_2.cm_val);
185608278a5eSRod Evans 			}
185708278a5eSRod Evans 			if (scapset->oc_hw_1.cm_val) {
185808278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_HW_1,
185908278a5eSRod Evans 				    scapset->oc_hw_1.cm_val);
186008278a5eSRod Evans 			}
186108278a5eSRod Evans 			if (scapset->oc_sf_1.cm_val) {
186208278a5eSRod Evans 				CAP_UPDATE(cap, capndx, CA_SUNW_SF_1,
186308278a5eSRod Evans 				    scapset->oc_sf_1.cm_val);
186408278a5eSRod Evans 			}
186508278a5eSRod Evans 			CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0);
186608278a5eSRod Evans 
186708278a5eSRod Evans 			/*
186808278a5eSRod Evans 			 * If any object capabilities are available, determine
186908278a5eSRod Evans 			 * whether these symbol capabilities are less
187008278a5eSRod Evans 			 * restrictive, and hence redundant.
187108278a5eSRod Evans 			 */
187208278a5eSRod Evans 			if (((ofl->ofl_flags & FLG_OF_PTCAP) == 0) ||
187308278a5eSRod Evans 			    (is_cap_redundant(ocapset, scapset) == 0))
187408278a5eSRod Evans 				continue;
187508278a5eSRod Evans 
187608278a5eSRod Evans 			/*
187708278a5eSRod Evans 			 * Indicate any files that provide redundant symbol
187808278a5eSRod Evans 			 * capabilities.
187908278a5eSRod Evans 			 */
188008278a5eSRod Evans 			for (APLIST_TRAVERSE(cgp->cg_secs, idx2, isp)) {
18811007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
188208278a5eSRod Evans 				    MSG_INTL(MSG_CAP_REDUNDANT),
188308278a5eSRod Evans 				    isp->is_file->ifl_name,
188408278a5eSRod Evans 				    EC_WORD(isp->is_scnndx), isp->is_name);
188508278a5eSRod Evans 			}
188608278a5eSRod Evans 		}
188708278a5eSRod Evans 	}
188808278a5eSRod Evans 
188908278a5eSRod Evans 	/*
189008278a5eSRod Evans 	 * If capabilities strings are required, the sh_info field of the
189108278a5eSRod Evans 	 * section header will be set to the associated string table.
189208278a5eSRod Evans 	 */
189308278a5eSRod Evans 	if (ofl->ofl_flags & FLG_OF_CAPSTRS)
189408278a5eSRod Evans 		shdr->sh_flags |= SHF_INFO_LINK;
189508278a5eSRod Evans 
189608278a5eSRod Evans 	/*
189708278a5eSRod Evans 	 * Place these capabilities in the output file.
189808278a5eSRod Evans 	 */
189908278a5eSRod Evans 	if ((ofl->ofl_oscap = ld_place_section(ofl, isec,
190008278a5eSRod Evans 	    NULL, ident, NULL)) == (Os_desc *)S_ERROR)
190108278a5eSRod Evans 		return (S_ERROR);
190208278a5eSRod Evans 
190308278a5eSRod Evans 	/*
190408278a5eSRod Evans 	 * If symbol capabilities are required, then a .SUNW_capinfo section is
190508278a5eSRod Evans 	 * also created.  This table will eventually be sized to match the
190608278a5eSRod Evans 	 * associated symbol table.
190708278a5eSRod Evans 	 */
190808278a5eSRod Evans 	if (ofl->ofl_capfamilies) {
190908278a5eSRod Evans 		if ((ofl->ofl_oscapinfo = make_sym_sec(ofl,
191008278a5eSRod Evans 		    MSG_ORIG(MSG_SCN_SUNWCAPINFO), SHT_SUNW_capinfo,
191108278a5eSRod Evans 		    ld_targ.t_id.id_capinfo)) == (Os_desc *)S_ERROR)
191208278a5eSRod Evans 			return (S_ERROR);
191308278a5eSRod Evans 
191408278a5eSRod Evans 		/*
191508278a5eSRod Evans 		 * If we're generating a dynamic object, capabilities family
191608278a5eSRod Evans 		 * members are maintained in a .SUNW_capchain section.
191708278a5eSRod Evans 		 */
191808278a5eSRod Evans 		if (ofl->ofl_capchaincnt &&
191908278a5eSRod Evans 		    ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) {
192008278a5eSRod Evans 			if (new_section(ofl, SHT_SUNW_capchain,
192108278a5eSRod Evans 			    MSG_ORIG(MSG_SCN_SUNWCAPCHAIN),
192208278a5eSRod Evans 			    ofl->ofl_capchaincnt, &isec, &shdr,
192308278a5eSRod Evans 			    &data) == S_ERROR)
192408278a5eSRod Evans 				return (S_ERROR);
192508278a5eSRod Evans 
192608278a5eSRod Evans 			ofl->ofl_oscapchain = ld_place_section(ofl, isec,
192708278a5eSRod Evans 			    NULL, ld_targ.t_id.id_capchain, NULL);
192808278a5eSRod Evans 			if (ofl->ofl_oscapchain == (Os_desc *)S_ERROR)
192908278a5eSRod Evans 				return (S_ERROR);
193008278a5eSRod Evans 
193108278a5eSRod Evans 		}
193208278a5eSRod Evans 	}
193308278a5eSRod Evans 	return (1);
19347c478bd9Sstevel@tonic-gate }
193508278a5eSRod Evans #undef	CAP_UPDATE
19367c478bd9Sstevel@tonic-gate 
19377c478bd9Sstevel@tonic-gate /*
19387c478bd9Sstevel@tonic-gate  * Build the PLT section and its associated relocation entries.
19397c478bd9Sstevel@tonic-gate  */
19405aefb655Srie static uintptr_t
make_plt(Ofl_desc * ofl)19417c478bd9Sstevel@tonic-gate make_plt(Ofl_desc *ofl)
19427c478bd9Sstevel@tonic-gate {
19437c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
19447c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
19457c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
1946ba2be530Sab 	size_t		size = ld_targ.t_m.m_plt_reservsz +
194760758829Srie 	    (((size_t)ofl->ofl_pltcnt + (size_t)ofl->ofl_pltpad) *
1948ba2be530Sab 	    ld_targ.t_m.m_plt_entsize);
19497c478bd9Sstevel@tonic-gate 	size_t		rsize = (size_t)ofl->ofl_relocpltsz;
19507c478bd9Sstevel@tonic-gate 
19517c478bd9Sstevel@tonic-gate 	/*
1952ba2be530Sab 	 * On sparc, account for the NOP at the end of the plt.
19537c478bd9Sstevel@tonic-gate 	 */
1954ba2be530Sab 	if (ld_targ.t_m.m_mach == LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
1955ba2be530Sab 		size += sizeof (Word);
19567c478bd9Sstevel@tonic-gate 
19579039eeafSab 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_PLT), 0,
19589039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
19597c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19609039eeafSab 
19617c478bd9Sstevel@tonic-gate 	data->d_size = size;
1962ba2be530Sab 	data->d_align = ld_targ.t_m.m_plt_align;
19637c478bd9Sstevel@tonic-gate 
1964ba2be530Sab 	shdr->sh_flags = ld_targ.t_m.m_plt_shf_flags;
19657c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
1966ba2be530Sab 	shdr->sh_addralign = ld_targ.t_m.m_plt_align;
1967ba2be530Sab 	shdr->sh_entsize = ld_targ.t_m.m_plt_entsize;
19687c478bd9Sstevel@tonic-gate 
196969112eddSAli Bahrami 	ofl->ofl_osplt = ld_place_section(ofl, isec, NULL,
197069112eddSAli Bahrami 	    ld_targ.t_id.id_plt, NULL);
1971ba2be530Sab 	if (ofl->ofl_osplt == (Os_desc *)S_ERROR)
19727c478bd9Sstevel@tonic-gate 		return (S_ERROR);
19737c478bd9Sstevel@tonic-gate 
19747c478bd9Sstevel@tonic-gate 	ofl->ofl_osplt->os_szoutrels = (Xword)rsize;
19757c478bd9Sstevel@tonic-gate 
19767c478bd9Sstevel@tonic-gate 	return (1);
19777c478bd9Sstevel@tonic-gate }
19787c478bd9Sstevel@tonic-gate 
19797c478bd9Sstevel@tonic-gate /*
19807c478bd9Sstevel@tonic-gate  * Make the hash table.  Only built for dynamic executables and shared
19817c478bd9Sstevel@tonic-gate  * libraries, and provides hashed lookup into the global symbol table
19827c478bd9Sstevel@tonic-gate  * (.dynsym) for the run-time linker to resolve symbol lookups.
19837c478bd9Sstevel@tonic-gate  */
19845aefb655Srie static uintptr_t
make_hash(Ofl_desc * ofl)19857c478bd9Sstevel@tonic-gate make_hash(Ofl_desc *ofl)
19867c478bd9Sstevel@tonic-gate {
19877c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
19887c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
19897c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
19907c478bd9Sstevel@tonic-gate 	size_t		size;
19917c478bd9Sstevel@tonic-gate 	Word		nsyms = ofl->ofl_globcnt;
19927c478bd9Sstevel@tonic-gate 	size_t		cnt;
19937c478bd9Sstevel@tonic-gate 
19947c478bd9Sstevel@tonic-gate 	/*
19959039eeafSab 	 * Allocate section header structures. We set entcnt to 0
19969039eeafSab 	 * because it's going to change after we place this section.
19977c478bd9Sstevel@tonic-gate 	 */
19989039eeafSab 	if (new_section(ofl, SHT_HASH, MSG_ORIG(MSG_SCN_HASH), 0,
19999039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
20007c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20017c478bd9Sstevel@tonic-gate 
20027c478bd9Sstevel@tonic-gate 	/*
20037c478bd9Sstevel@tonic-gate 	 * Place the section first since it will affect the local symbol
20047c478bd9Sstevel@tonic-gate 	 * count.
20057c478bd9Sstevel@tonic-gate 	 */
20061dd9d86fSAli Bahrami 	ofl->ofl_oshash =
200769112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_hash, NULL);
2008ba2be530Sab 	if (ofl->ofl_oshash == (Os_desc *)S_ERROR)
20097c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20107c478bd9Sstevel@tonic-gate 
20117c478bd9Sstevel@tonic-gate 	/*
20127c478bd9Sstevel@tonic-gate 	 * Calculate the number of output hash buckets.
20137c478bd9Sstevel@tonic-gate 	 */
20147c478bd9Sstevel@tonic-gate 	ofl->ofl_hashbkts = findprime(nsyms);
20157c478bd9Sstevel@tonic-gate 
20167c478bd9Sstevel@tonic-gate 	/*
20177c478bd9Sstevel@tonic-gate 	 * The size of the hash table is determined by
20187c478bd9Sstevel@tonic-gate 	 *
20197c478bd9Sstevel@tonic-gate 	 *	i.	the initial nbucket and nchain entries (2)
20207c478bd9Sstevel@tonic-gate 	 *	ii.	the number of buckets (calculated above)
20217c478bd9Sstevel@tonic-gate 	 *	iii.	the number of chains (this is based on the number of
2022635216b6SRod Evans 	 *		symbols in the .dynsym array).
20237c478bd9Sstevel@tonic-gate 	 */
2024635216b6SRod Evans 	cnt = 2 + ofl->ofl_hashbkts + DYNSYM_ALL_CNT(ofl);
20257c478bd9Sstevel@tonic-gate 	size = cnt * shdr->sh_entsize;
20267c478bd9Sstevel@tonic-gate 
20277c478bd9Sstevel@tonic-gate 	/*
20287c478bd9Sstevel@tonic-gate 	 * Finalize the section header and data buffer initialization.
20297c478bd9Sstevel@tonic-gate 	 */
203057ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(size, 1)) == NULL)
20317c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20327c478bd9Sstevel@tonic-gate 	data->d_size = size;
20337c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
20347c478bd9Sstevel@tonic-gate 
20357c478bd9Sstevel@tonic-gate 	return (1);
20367c478bd9Sstevel@tonic-gate }
20377c478bd9Sstevel@tonic-gate 
20387c478bd9Sstevel@tonic-gate /*
20397c478bd9Sstevel@tonic-gate  * Generate the standard symbol table.  Contains all locals and globals,
20407c478bd9Sstevel@tonic-gate  * and resides in a non-allocatable section (ie. it can be stripped).
20417c478bd9Sstevel@tonic-gate  */
20425aefb655Srie static uintptr_t
make_symtab(Ofl_desc * ofl)20437c478bd9Sstevel@tonic-gate make_symtab(Ofl_desc *ofl)
20447c478bd9Sstevel@tonic-gate {
20457c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
20467c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
20477c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
20487c478bd9Sstevel@tonic-gate 	Is_desc		*xisec = 0;
20497c478bd9Sstevel@tonic-gate 	size_t		size;
20507c478bd9Sstevel@tonic-gate 	Word		symcnt;
20517c478bd9Sstevel@tonic-gate 
20527c478bd9Sstevel@tonic-gate 	/*
20539039eeafSab 	 * Create the section headers. Note that we supply an ent_cnt
20549039eeafSab 	 * of 0. We won't know the count until the section has been placed.
20557c478bd9Sstevel@tonic-gate 	 */
20569039eeafSab 	if (new_section(ofl, SHT_SYMTAB, MSG_ORIG(MSG_SCN_SYMTAB), 0,
20579039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
20587c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20597c478bd9Sstevel@tonic-gate 
20607c478bd9Sstevel@tonic-gate 	/*
20617c478bd9Sstevel@tonic-gate 	 * Place the section first since it will affect the local symbol
20627c478bd9Sstevel@tonic-gate 	 * count.
20637c478bd9Sstevel@tonic-gate 	 */
206469112eddSAli Bahrami 	if ((ofl->ofl_ossymtab = ld_place_section(ofl, isec, NULL,
2065635216b6SRod Evans 	    ld_targ.t_id.id_symtab, NULL)) == (Os_desc *)S_ERROR)
20667c478bd9Sstevel@tonic-gate 		return (S_ERROR);
20677c478bd9Sstevel@tonic-gate 
20687c478bd9Sstevel@tonic-gate 	/*
20697c478bd9Sstevel@tonic-gate 	 * At this point we've created all but the 'shstrtab' section.
20707c478bd9Sstevel@tonic-gate 	 * Determine if we have to use 'Extended Sections'.  If so - then
20717c478bd9Sstevel@tonic-gate 	 * also create a SHT_SYMTAB_SHNDX section.
20727c478bd9Sstevel@tonic-gate 	 */
20737c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_shdrcnt + 1) >= SHN_LORESERVE) {
20747c478bd9Sstevel@tonic-gate 		Shdr		*xshdr;
20757c478bd9Sstevel@tonic-gate 		Elf_Data	*xdata;
20767c478bd9Sstevel@tonic-gate 
20779039eeafSab 		if (new_section(ofl, SHT_SYMTAB_SHNDX,
20789039eeafSab 		    MSG_ORIG(MSG_SCN_SYMTAB_SHNDX), 0, &xisec,
20799039eeafSab 		    &xshdr, &xdata) == S_ERROR)
20807c478bd9Sstevel@tonic-gate 			return (S_ERROR);
20819039eeafSab 
208269112eddSAli Bahrami 		if ((ofl->ofl_ossymshndx = ld_place_section(ofl, xisec, NULL,
20831dd9d86fSAli Bahrami 		    ld_targ.t_id.id_symtab_ndx, NULL)) == (Os_desc *)S_ERROR)
20847c478bd9Sstevel@tonic-gate 			return (S_ERROR);
20857c478bd9Sstevel@tonic-gate 	}
20860e233487SRod Evans 
20877c478bd9Sstevel@tonic-gate 	/*
20887c478bd9Sstevel@tonic-gate 	 * Calculated number of symbols, which need to be augmented by
2089635216b6SRod Evans 	 * the (yet to be created) .shstrtab entry.
20907c478bd9Sstevel@tonic-gate 	 */
2091635216b6SRod Evans 	symcnt = (size_t)(1 + SYMTAB_ALL_CNT(ofl));
20927c478bd9Sstevel@tonic-gate 	size = symcnt * shdr->sh_entsize;
20937c478bd9Sstevel@tonic-gate 
20947c478bd9Sstevel@tonic-gate 	/*
20957c478bd9Sstevel@tonic-gate 	 * Finalize the section header and data buffer initialization.
20967c478bd9Sstevel@tonic-gate 	 */
20977c478bd9Sstevel@tonic-gate 	data->d_size = size;
20987c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
20997c478bd9Sstevel@tonic-gate 
21007c478bd9Sstevel@tonic-gate 	/*
21017c478bd9Sstevel@tonic-gate 	 * If we created a SHT_SYMTAB_SHNDX - then set it's sizes too.
21027c478bd9Sstevel@tonic-gate 	 */
21037c478bd9Sstevel@tonic-gate 	if (xisec) {
21047c478bd9Sstevel@tonic-gate 		size_t	xsize = symcnt * sizeof (Word);
21057c478bd9Sstevel@tonic-gate 
21067c478bd9Sstevel@tonic-gate 		xisec->is_indata->d_size = xsize;
21077c478bd9Sstevel@tonic-gate 		xisec->is_shdr->sh_size = (Xword)xsize;
21087c478bd9Sstevel@tonic-gate 	}
21097c478bd9Sstevel@tonic-gate 
21107c478bd9Sstevel@tonic-gate 	return (1);
21117c478bd9Sstevel@tonic-gate }
21127c478bd9Sstevel@tonic-gate 
21137c478bd9Sstevel@tonic-gate /*
2114d579eb63Sab  * Build a dynamic symbol table. These tables reside in the text
2115d579eb63Sab  * segment of a dynamic executable or shared library.
2116d579eb63Sab  *
2117d579eb63Sab  *	.SUNW_ldynsym contains local function symbols
2118d579eb63Sab  *	.dynsym contains only globals symbols
2119d579eb63Sab  *
2120d579eb63Sab  * The two tables are created adjacent to each other, with .SUNW_ldynsym
2121d579eb63Sab  * coming first.
21227c478bd9Sstevel@tonic-gate  */
21235aefb655Srie static uintptr_t
make_dynsym(Ofl_desc * ofl)21247c478bd9Sstevel@tonic-gate make_dynsym(Ofl_desc *ofl)
21257c478bd9Sstevel@tonic-gate {
21269039eeafSab 	Shdr		*shdr, *lshdr;
21279039eeafSab 	Elf_Data	*data, *ldata;
21289039eeafSab 	Is_desc		*isec, *lisec;
21297c478bd9Sstevel@tonic-gate 	size_t		size;
21307c478bd9Sstevel@tonic-gate 	Xword		cnt;
2131d579eb63Sab 	int		allow_ldynsym;
21327c478bd9Sstevel@tonic-gate 
2133d579eb63Sab 	/*
2134d579eb63Sab 	 * Unless explicitly disabled, always produce a .SUNW_ldynsym section
2135d579eb63Sab 	 * when it is allowed by the file type, even if the resulting
2136d579eb63Sab 	 * table only ends up with a single STT_FILE in it. There are
2137d579eb63Sab 	 * two reasons: (1) It causes the generation of the DT_SUNW_SYMTAB
2138d579eb63Sab 	 * entry in the .dynamic section, which is something we would
2139d579eb63Sab 	 * like to encourage, and (2) Without it, we cannot generate
2140d579eb63Sab 	 * the associated .SUNW_dyn[sym|tls]sort sections, which are of
2141d579eb63Sab 	 * value to DTrace.
2142d579eb63Sab 	 *
2143d579eb63Sab 	 * In practice, it is extremely rare for an object not to have
2144d579eb63Sab 	 * local symbols for .SUNW_ldynsym, so 99% of the time, we'd be
2145d579eb63Sab 	 * doing it anyway.
2146d579eb63Sab 	 */
2147d579eb63Sab 	allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
21487c478bd9Sstevel@tonic-gate 
21497c478bd9Sstevel@tonic-gate 	/*
21509039eeafSab 	 * Create the section headers. Note that we supply an ent_cnt
21519039eeafSab 	 * of 0. We won't know the count until the section has been placed.
21527c478bd9Sstevel@tonic-gate 	 */
2153d579eb63Sab 	if (allow_ldynsym && new_section(ofl, SHT_SUNW_LDYNSYM,
21549039eeafSab 	    MSG_ORIG(MSG_SCN_LDYNSYM), 0, &lisec, &lshdr, &ldata) == S_ERROR)
21557c478bd9Sstevel@tonic-gate 		return (S_ERROR);
21567c478bd9Sstevel@tonic-gate 
21579039eeafSab 	if (new_section(ofl, SHT_DYNSYM, MSG_ORIG(MSG_SCN_DYNSYM), 0,
21589039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
21597c478bd9Sstevel@tonic-gate 		return (S_ERROR);
21607c478bd9Sstevel@tonic-gate 
21617c478bd9Sstevel@tonic-gate 	/*
21629039eeafSab 	 * Place the section(s) first since it will affect the local symbol
21637c478bd9Sstevel@tonic-gate 	 * count.
21647c478bd9Sstevel@tonic-gate 	 */
2165d579eb63Sab 	if (allow_ldynsym &&
216669112eddSAli Bahrami 	    ((ofl->ofl_osldynsym = ld_place_section(ofl, lisec, NULL,
21671dd9d86fSAli Bahrami 	    ld_targ.t_id.id_ldynsym, NULL)) == (Os_desc *)S_ERROR))
21689039eeafSab 		return (S_ERROR);
2169ba2be530Sab 	ofl->ofl_osdynsym =
217069112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynsym, NULL);
2171ba2be530Sab 	if (ofl->ofl_osdynsym == (Os_desc *)S_ERROR)
21727c478bd9Sstevel@tonic-gate 		return (S_ERROR);
21737c478bd9Sstevel@tonic-gate 
2174635216b6SRod Evans 	cnt = DYNSYM_ALL_CNT(ofl);
21757c478bd9Sstevel@tonic-gate 	size = (size_t)cnt * shdr->sh_entsize;
21767c478bd9Sstevel@tonic-gate 
21777c478bd9Sstevel@tonic-gate 	/*
21787c478bd9Sstevel@tonic-gate 	 * Finalize the section header and data buffer initialization.
21797c478bd9Sstevel@tonic-gate 	 */
21807c478bd9Sstevel@tonic-gate 	data->d_size = size;
21817c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
21827c478bd9Sstevel@tonic-gate 
21839039eeafSab 	/*
21849039eeafSab 	 * An ldynsym contains local function symbols. It is not
21859039eeafSab 	 * used for linking, but if present, serves to allow better
21869039eeafSab 	 * stack traces to be generated in contexts where the symtab
21879039eeafSab 	 * is not available. (dladdr(), or stripped executable/library files).
21889039eeafSab 	 */
2189d579eb63Sab 	if (allow_ldynsym) {
21909039eeafSab 		cnt = 1 + ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt;
21919039eeafSab 		size = (size_t)cnt * shdr->sh_entsize;
21929039eeafSab 
21939039eeafSab 		ldata->d_size = size;
21949039eeafSab 		lshdr->sh_size = (Xword)size;
21959039eeafSab 	}
21969039eeafSab 
21977c478bd9Sstevel@tonic-gate 	return (1);
21987c478bd9Sstevel@tonic-gate }
21997c478bd9Sstevel@tonic-gate 
2200d579eb63Sab /*
2201d579eb63Sab  * Build .SUNW_dynsymsort and/or .SUNW_dyntlssort sections. These are
2202d579eb63Sab  * index sections for the .SUNW_ldynsym/.dynsym pair that present data
2203d579eb63Sab  * and function symbols sorted by address.
2204d579eb63Sab  */
2205d579eb63Sab static uintptr_t
make_dynsort(Ofl_desc * ofl)2206d579eb63Sab make_dynsort(Ofl_desc *ofl)
2207d579eb63Sab {
2208d579eb63Sab 	Shdr		*shdr;
2209d579eb63Sab 	Elf_Data	*data;
2210d579eb63Sab 	Is_desc		*isec;
2211d579eb63Sab 
2212d579eb63Sab 	/* Only do it if the .SUNW_ldynsym section is present */
2213d579eb63Sab 	if (!OFL_ALLOW_LDYNSYM(ofl))
2214d579eb63Sab 		return (1);
2215d579eb63Sab 
2216d579eb63Sab 	/* .SUNW_dynsymsort */
2217d579eb63Sab 	if (ofl->ofl_dynsymsortcnt > 0) {
2218d579eb63Sab 		if (new_section(ofl, SHT_SUNW_symsort,
2219d579eb63Sab 		    MSG_ORIG(MSG_SCN_DYNSYMSORT), ofl->ofl_dynsymsortcnt,
2220d579eb63Sab 		    &isec, &shdr, &data) == S_ERROR)
2221fb12490aSRichard Lowe 			return (S_ERROR);
2222d579eb63Sab 
222369112eddSAli Bahrami 		if ((ofl->ofl_osdynsymsort = ld_place_section(ofl, isec, NULL,
22241dd9d86fSAli Bahrami 		    ld_targ.t_id.id_dynsort, NULL)) == (Os_desc *)S_ERROR)
2225d579eb63Sab 			return (S_ERROR);
2226d579eb63Sab 	}
2227d579eb63Sab 
2228d579eb63Sab 	/* .SUNW_dyntlssort */
2229d579eb63Sab 	if (ofl->ofl_dyntlssortcnt > 0) {
2230d579eb63Sab 		if (new_section(ofl, SHT_SUNW_tlssort,
2231d579eb63Sab 		    MSG_ORIG(MSG_SCN_DYNTLSSORT),
2232d579eb63Sab 		    ofl->ofl_dyntlssortcnt, &isec, &shdr, &data) == S_ERROR)
2233fb12490aSRichard Lowe 			return (S_ERROR);
2234d579eb63Sab 
223569112eddSAli Bahrami 		if ((ofl->ofl_osdyntlssort = ld_place_section(ofl, isec, NULL,
22361dd9d86fSAli Bahrami 		    ld_targ.t_id.id_dynsort, NULL)) == (Os_desc *)S_ERROR)
2237d579eb63Sab 			return (S_ERROR);
2238d579eb63Sab 	}
2239d579eb63Sab 
2240d579eb63Sab 	return (1);
2241d579eb63Sab }
2242d579eb63Sab 
22437c478bd9Sstevel@tonic-gate /*
22449039eeafSab  * Helper routine for make_dynsym_shndx. Builds a
2245d579eb63Sab  * a SHT_SYMTAB_SHNDX for .dynsym or .SUNW_ldynsym, without knowing
22469039eeafSab  * which one it is.
22477c478bd9Sstevel@tonic-gate  */
22485aefb655Srie static uintptr_t
make_dyn_shndx(Ofl_desc * ofl,const char * shname,Os_desc * symtab,Os_desc ** ret_os)22499039eeafSab make_dyn_shndx(Ofl_desc *ofl, const char *shname, Os_desc *symtab,
22509039eeafSab     Os_desc **ret_os)
22517c478bd9Sstevel@tonic-gate {
22527c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
22537c478bd9Sstevel@tonic-gate 	Is_desc		*dynsymisp;
22547c478bd9Sstevel@tonic-gate 	Shdr		*shdr, *dynshdr;
22557c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
22567c478bd9Sstevel@tonic-gate 
22571dd9d86fSAli Bahrami 	dynsymisp = ld_os_first_isdesc(symtab);
22589039eeafSab 	dynshdr = dynsymisp->is_shdr;
22599039eeafSab 
22609039eeafSab 	if (new_section(ofl, SHT_SYMTAB_SHNDX, shname,
22619039eeafSab 	    (dynshdr->sh_size / dynshdr->sh_entsize),
22629039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
22637c478bd9Sstevel@tonic-gate 		return (S_ERROR);
22647c478bd9Sstevel@tonic-gate 
226569112eddSAli Bahrami 	if ((*ret_os = ld_place_section(ofl, isec, NULL,
22661dd9d86fSAli Bahrami 	    ld_targ.t_id.id_dynsym_ndx, NULL)) == (Os_desc *)S_ERROR)
22677c478bd9Sstevel@tonic-gate 		return (S_ERROR);
22687c478bd9Sstevel@tonic-gate 
22699039eeafSab 	assert(*ret_os);
22709039eeafSab 
22719039eeafSab 	return (1);
22729039eeafSab }
22739039eeafSab 
22749039eeafSab /*
22759039eeafSab  * Build a SHT_SYMTAB_SHNDX for the .dynsym, and .SUNW_ldynsym
22769039eeafSab  */
22779039eeafSab static uintptr_t
make_dynsym_shndx(Ofl_desc * ofl)22789039eeafSab make_dynsym_shndx(Ofl_desc *ofl)
22799039eeafSab {
22807c478bd9Sstevel@tonic-gate 	/*
2281d579eb63Sab 	 * If there is a .SUNW_ldynsym, generate a section for its extended
22829039eeafSab 	 * index section as well.
22837c478bd9Sstevel@tonic-gate 	 */
2284d579eb63Sab 	if (OFL_ALLOW_LDYNSYM(ofl)) {
22859039eeafSab 		if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_LDYNSYM_SHNDX),
22869039eeafSab 		    ofl->ofl_osldynsym, &ofl->ofl_osldynshndx) == S_ERROR)
22879039eeafSab 			return (S_ERROR);
22889039eeafSab 	}
22897c478bd9Sstevel@tonic-gate 
22909039eeafSab 	/* The Generate a section for the dynsym */
22919039eeafSab 	if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_DYNSYM_SHNDX),
22929039eeafSab 	    ofl->ofl_osdynsym, &ofl->ofl_osdynshndx) == S_ERROR)
22937c478bd9Sstevel@tonic-gate 		return (S_ERROR);
22947c478bd9Sstevel@tonic-gate 
22957c478bd9Sstevel@tonic-gate 	return (1);
22967c478bd9Sstevel@tonic-gate }
22977c478bd9Sstevel@tonic-gate 
22987c478bd9Sstevel@tonic-gate 
22997c478bd9Sstevel@tonic-gate /*
23007c478bd9Sstevel@tonic-gate  * Build a string table for the section headers.
23017c478bd9Sstevel@tonic-gate  */
23025aefb655Srie static uintptr_t
make_shstrtab(Ofl_desc * ofl)23037c478bd9Sstevel@tonic-gate make_shstrtab(Ofl_desc *ofl)
23047c478bd9Sstevel@tonic-gate {
23057c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
23067c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
23077c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
23087c478bd9Sstevel@tonic-gate 	size_t		size;
23097c478bd9Sstevel@tonic-gate 
23109039eeafSab 	if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_SHSTRTAB),
23119039eeafSab 	    0, &isec, &shdr, &data) == S_ERROR)
23127c478bd9Sstevel@tonic-gate 		return (S_ERROR);
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 	/*
23157c478bd9Sstevel@tonic-gate 	 * Place the section first, as it may effect the number of section
23167c478bd9Sstevel@tonic-gate 	 * headers to account for.
23177c478bd9Sstevel@tonic-gate 	 */
2318ba2be530Sab 	ofl->ofl_osshstrtab =
231969112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_note, NULL);
2320ba2be530Sab 	if (ofl->ofl_osshstrtab == (Os_desc *)S_ERROR)
23217c478bd9Sstevel@tonic-gate 		return (S_ERROR);
23227c478bd9Sstevel@tonic-gate 
23237c478bd9Sstevel@tonic-gate 	size = st_getstrtab_sz(ofl->ofl_shdrsttab);
23247c478bd9Sstevel@tonic-gate 	assert(size > 0);
23257c478bd9Sstevel@tonic-gate 
23267c478bd9Sstevel@tonic-gate 	data->d_size = size;
23277c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
23287c478bd9Sstevel@tonic-gate 
23297c478bd9Sstevel@tonic-gate 	return (1);
23307c478bd9Sstevel@tonic-gate }
23317c478bd9Sstevel@tonic-gate 
23327c478bd9Sstevel@tonic-gate /*
23337c478bd9Sstevel@tonic-gate  * Build a string section for the standard symbol table.
23347c478bd9Sstevel@tonic-gate  */
23355aefb655Srie static uintptr_t
make_strtab(Ofl_desc * ofl)23367c478bd9Sstevel@tonic-gate make_strtab(Ofl_desc *ofl)
23377c478bd9Sstevel@tonic-gate {
23387c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
23397c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
23407c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
23417c478bd9Sstevel@tonic-gate 	size_t		size;
23427c478bd9Sstevel@tonic-gate 
23437c478bd9Sstevel@tonic-gate 	/*
23447c478bd9Sstevel@tonic-gate 	 * This string table consists of all the global and local symbols.
23457c478bd9Sstevel@tonic-gate 	 * Account for null bytes at end of the file name and the beginning
23467c478bd9Sstevel@tonic-gate 	 * of section.
23477c478bd9Sstevel@tonic-gate 	 */
23487c478bd9Sstevel@tonic-gate 	if (st_insert(ofl->ofl_strtab, ofl->ofl_name) == -1)
23497c478bd9Sstevel@tonic-gate 		return (S_ERROR);
23507c478bd9Sstevel@tonic-gate 
23517c478bd9Sstevel@tonic-gate 	size = st_getstrtab_sz(ofl->ofl_strtab);
23527c478bd9Sstevel@tonic-gate 	assert(size > 0);
23537c478bd9Sstevel@tonic-gate 
23549039eeafSab 	if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_STRTAB),
23559039eeafSab 	    0, &isec, &shdr, &data) == S_ERROR)
23567c478bd9Sstevel@tonic-gate 		return (S_ERROR);
23577c478bd9Sstevel@tonic-gate 
23589039eeafSab 	/* Set the size of the data area */
23599039eeafSab 	data->d_size = size;
23607c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
23617c478bd9Sstevel@tonic-gate 
2362ba2be530Sab 	ofl->ofl_osstrtab =
236369112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_strtab, NULL);
23647c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osstrtab);
23657c478bd9Sstevel@tonic-gate }
23667c478bd9Sstevel@tonic-gate 
23677c478bd9Sstevel@tonic-gate /*
23687c478bd9Sstevel@tonic-gate  * Build a string table for the dynamic symbol table.
23697c478bd9Sstevel@tonic-gate  */
23705aefb655Srie static uintptr_t
make_dynstr(Ofl_desc * ofl)23717c478bd9Sstevel@tonic-gate make_dynstr(Ofl_desc *ofl)
23727c478bd9Sstevel@tonic-gate {
23737c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
23747c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
23757c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
23767c478bd9Sstevel@tonic-gate 	size_t		size;
23777c478bd9Sstevel@tonic-gate 
23789039eeafSab 	/*
2379d579eb63Sab 	 * If producing a .SUNW_ldynsym, account for the initial STT_FILE
2380d579eb63Sab 	 * symbol that precedes the scope reduced global symbols.
23819039eeafSab 	 */
2382d579eb63Sab 	if (OFL_ALLOW_LDYNSYM(ofl)) {
23839039eeafSab 		if (st_insert(ofl->ofl_dynstrtab, ofl->ofl_name) == -1)
23849039eeafSab 			return (S_ERROR);
23859039eeafSab 		ofl->ofl_dynscopecnt++;
23869039eeafSab 	}
23879039eeafSab 
23887c478bd9Sstevel@tonic-gate 	/*
23897c478bd9Sstevel@tonic-gate 	 * Account for any local, named register symbols.  These locals are
23907c478bd9Sstevel@tonic-gate 	 * required for reference from DT_REGISTER .dynamic entries.
23917c478bd9Sstevel@tonic-gate 	 */
23927c478bd9Sstevel@tonic-gate 	if (ofl->ofl_regsyms) {
23937c478bd9Sstevel@tonic-gate 		int	ndx;
23947c478bd9Sstevel@tonic-gate 
23957c478bd9Sstevel@tonic-gate 		for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
23960e233487SRod Evans 			Sym_desc	*sdp;
23977c478bd9Sstevel@tonic-gate 
239857ef7aa9SRod Evans 			if ((sdp = ofl->ofl_regsyms[ndx]) == NULL)
23997c478bd9Sstevel@tonic-gate 				continue;
24007c478bd9Sstevel@tonic-gate 
240108278a5eSRod Evans 			if (!SYM_IS_HIDDEN(sdp) &&
24027c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(sdp->sd_sym->st_info) != STB_LOCAL))
24037c478bd9Sstevel@tonic-gate 				continue;
24047c478bd9Sstevel@tonic-gate 
2405fb8f92baSToomas Soome 			if (sdp->sd_sym->st_name == 0)
24067c478bd9Sstevel@tonic-gate 				continue;
24077c478bd9Sstevel@tonic-gate 
24087c478bd9Sstevel@tonic-gate 			if (st_insert(ofl->ofl_dynstrtab, sdp->sd_name) == -1)
24097c478bd9Sstevel@tonic-gate 				return (S_ERROR);
24107c478bd9Sstevel@tonic-gate 		}
24117c478bd9Sstevel@tonic-gate 	}
24127c478bd9Sstevel@tonic-gate 
24137c478bd9Sstevel@tonic-gate 	/*
24147c478bd9Sstevel@tonic-gate 	 * Reserve entries for any per-symbol auxiliary/filter strings.
24157c478bd9Sstevel@tonic-gate 	 */
2416cce0e03bSab 	if (ofl->ofl_dtsfltrs != NULL) {
2417cce0e03bSab 		Dfltr_desc	*dftp;
2418cce0e03bSab 		Aliste		idx;
24197c478bd9Sstevel@tonic-gate 
2420cce0e03bSab 		for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, idx, dftp))
24217c478bd9Sstevel@tonic-gate 			if (st_insert(ofl->ofl_dynstrtab, dftp->dft_str) == -1)
24227c478bd9Sstevel@tonic-gate 				return (S_ERROR);
24237c478bd9Sstevel@tonic-gate 	}
24247c478bd9Sstevel@tonic-gate 
24257c478bd9Sstevel@tonic-gate 	size = st_getstrtab_sz(ofl->ofl_dynstrtab);
24267c478bd9Sstevel@tonic-gate 	assert(size > 0);
24277c478bd9Sstevel@tonic-gate 
24289039eeafSab 	if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_DYNSTR),
24299039eeafSab 	    0, &isec, &shdr, &data) == S_ERROR)
24307c478bd9Sstevel@tonic-gate 		return (S_ERROR);
24317c478bd9Sstevel@tonic-gate 
24329039eeafSab 	/* Make it allocable if necessary */
24337c478bd9Sstevel@tonic-gate 	if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
24349039eeafSab 		shdr->sh_flags |= SHF_ALLOC;
24357c478bd9Sstevel@tonic-gate 
24369039eeafSab 	/* Set the size of the data area */
24373244bcaaSab 	data->d_size = size + DYNSTR_EXTRA_PAD;
24383244bcaaSab 
24397c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
24407c478bd9Sstevel@tonic-gate 
2441ba2be530Sab 	ofl->ofl_osdynstr =
244269112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynstr, NULL);
24437c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osdynstr);
24447c478bd9Sstevel@tonic-gate }
24457c478bd9Sstevel@tonic-gate 
24467c478bd9Sstevel@tonic-gate /*
24477c478bd9Sstevel@tonic-gate  * Generate an output relocation section which will contain the relocation
24487c478bd9Sstevel@tonic-gate  * information to be applied to the `osp' section.
24497c478bd9Sstevel@tonic-gate  *
24507c478bd9Sstevel@tonic-gate  * If (osp == NULL) then we are creating the coalesced relocation section
24517c478bd9Sstevel@tonic-gate  * for an executable and/or a shared object.
24527c478bd9Sstevel@tonic-gate  */
24535aefb655Srie static uintptr_t
make_reloc(Ofl_desc * ofl,Os_desc * osp)24547c478bd9Sstevel@tonic-gate make_reloc(Ofl_desc *ofl, Os_desc *osp)
24557c478bd9Sstevel@tonic-gate {
24567c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
24577c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
24587c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
24597c478bd9Sstevel@tonic-gate 	size_t		size;
24607c478bd9Sstevel@tonic-gate 	Xword		sh_flags;
2461b6a0e2cdSRichard Lowe 	char		*sectname;
24627c478bd9Sstevel@tonic-gate 	Os_desc		*rosp;
24637c478bd9Sstevel@tonic-gate 	Word		relsize;
24647c478bd9Sstevel@tonic-gate 	const char	*rel_prefix;
24657c478bd9Sstevel@tonic-gate 
24667c478bd9Sstevel@tonic-gate 	/* LINTED */
2467ba2be530Sab 	if (ld_targ.t_m.m_rel_sht_type == SHT_REL) {
24687c478bd9Sstevel@tonic-gate 		/* REL */
24697c478bd9Sstevel@tonic-gate 		relsize = sizeof (Rel);
24707c478bd9Sstevel@tonic-gate 		rel_prefix = MSG_ORIG(MSG_SCN_REL);
24717c478bd9Sstevel@tonic-gate 	} else {
24727c478bd9Sstevel@tonic-gate 		/* RELA */
24737c478bd9Sstevel@tonic-gate 		relsize = sizeof (Rela);
24747c478bd9Sstevel@tonic-gate 		rel_prefix = MSG_ORIG(MSG_SCN_RELA);
24757c478bd9Sstevel@tonic-gate 	}
24767c478bd9Sstevel@tonic-gate 
24777c478bd9Sstevel@tonic-gate 	if (osp) {
24787c478bd9Sstevel@tonic-gate 		size = osp->os_szoutrels;
24797c478bd9Sstevel@tonic-gate 		sh_flags = osp->os_shdr->sh_flags;
24807c478bd9Sstevel@tonic-gate 		if ((sectname = libld_malloc(strlen(rel_prefix) +
24817c478bd9Sstevel@tonic-gate 		    strlen(osp->os_name) + 1)) == 0)
24827c478bd9Sstevel@tonic-gate 			return (S_ERROR);
24837c478bd9Sstevel@tonic-gate 		(void) strcpy(sectname, rel_prefix);
24847c478bd9Sstevel@tonic-gate 		(void) strcat(sectname, osp->os_name);
2485e38a713aSrie 	} else if (ofl->ofl_flags & FLG_OF_COMREL) {
24867c478bd9Sstevel@tonic-gate 		size = (ofl->ofl_reloccnt - ofl->ofl_reloccntsub) * relsize;
24877c478bd9Sstevel@tonic-gate 		sh_flags = SHF_ALLOC;
24887c478bd9Sstevel@tonic-gate 		sectname = (char *)MSG_ORIG(MSG_SCN_SUNWRELOC);
24897c478bd9Sstevel@tonic-gate 	} else {
24907c478bd9Sstevel@tonic-gate 		size = ofl->ofl_relocrelsz;
24917c478bd9Sstevel@tonic-gate 		sh_flags = SHF_ALLOC;
24927c478bd9Sstevel@tonic-gate 		sectname = (char *)rel_prefix;
24937c478bd9Sstevel@tonic-gate 	}
24947c478bd9Sstevel@tonic-gate 
24957c478bd9Sstevel@tonic-gate 	/*
24967c478bd9Sstevel@tonic-gate 	 * Keep track of total size of 'output relocations' (to be stored
24977c478bd9Sstevel@tonic-gate 	 * in .dynamic)
24987c478bd9Sstevel@tonic-gate 	 */
24997c478bd9Sstevel@tonic-gate 	/* LINTED */
25007c478bd9Sstevel@tonic-gate 	ofl->ofl_relocsz += (Xword)size;
25017c478bd9Sstevel@tonic-gate 
2502ba2be530Sab 	if (new_section(ofl, ld_targ.t_m.m_rel_sht_type, sectname, 0, &isec,
2503ba2be530Sab 	    &shdr, &data) == S_ERROR)
25047c478bd9Sstevel@tonic-gate 		return (S_ERROR);
25059039eeafSab 
25067c478bd9Sstevel@tonic-gate 	data->d_size = size;
25077c478bd9Sstevel@tonic-gate 
25087c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
25099039eeafSab 	if (OFL_ALLOW_DYNSYM(ofl) && (sh_flags & SHF_ALLOC))
25107c478bd9Sstevel@tonic-gate 		shdr->sh_flags = SHF_ALLOC;
25117c478bd9Sstevel@tonic-gate 
25127c478bd9Sstevel@tonic-gate 	if (osp) {
25137c478bd9Sstevel@tonic-gate 		/*
25147c478bd9Sstevel@tonic-gate 		 * The sh_info field of the SHT_REL* sections points to the
25157c478bd9Sstevel@tonic-gate 		 * section the relocations are to be applied to.
25167c478bd9Sstevel@tonic-gate 		 */
25177c478bd9Sstevel@tonic-gate 		shdr->sh_flags |= SHF_INFO_LINK;
25187c478bd9Sstevel@tonic-gate 	}
25197c478bd9Sstevel@tonic-gate 
252069112eddSAli Bahrami 	rosp = ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_rel, NULL);
2521ba2be530Sab 	if (rosp == (Os_desc *)S_ERROR)
25227c478bd9Sstevel@tonic-gate 		return (S_ERROR);
25237c478bd9Sstevel@tonic-gate 
25246b3ba5bdSAli Bahrami 	/*
25256b3ba5bdSAli Bahrami 	 * Associate this relocation section to the section its going to
25266b3ba5bdSAli Bahrami 	 * relocate.
25276b3ba5bdSAli Bahrami 	 */
25287c478bd9Sstevel@tonic-gate 	if (osp) {
25296b3ba5bdSAli Bahrami 		Aliste	idx;
25306b3ba5bdSAli Bahrami 		Is_desc	*risp;
25310bc07c75Srie 
25327c478bd9Sstevel@tonic-gate 		/*
25337c478bd9Sstevel@tonic-gate 		 * This is used primarily so that we can update
25347c478bd9Sstevel@tonic-gate 		 * SHT_GROUP[sect_no] entries to point to the
25357c478bd9Sstevel@tonic-gate 		 * created output relocation sections.
25367c478bd9Sstevel@tonic-gate 		 */
25376b3ba5bdSAli Bahrami 		for (APLIST_TRAVERSE(osp->os_relisdescs, idx, risp)) {
25387c478bd9Sstevel@tonic-gate 			risp->is_osdesc = rosp;
25390bc07c75Srie 
25407c478bd9Sstevel@tonic-gate 			/*
25410bc07c75Srie 			 * If the input relocation section had the SHF_GROUP
25427010c12aSrie 			 * flag set - propagate it to the output relocation
25430bc07c75Srie 			 * section.
25447c478bd9Sstevel@tonic-gate 			 */
25457c478bd9Sstevel@tonic-gate 			if (risp->is_shdr->sh_flags & SHF_GROUP) {
25467c478bd9Sstevel@tonic-gate 				rosp->os_shdr->sh_flags |= SHF_GROUP;
25477c478bd9Sstevel@tonic-gate 				break;
25487c478bd9Sstevel@tonic-gate 			}
25497c478bd9Sstevel@tonic-gate 		}
25507c478bd9Sstevel@tonic-gate 		osp->os_relosdesc = rosp;
25517c478bd9Sstevel@tonic-gate 	} else
25527c478bd9Sstevel@tonic-gate 		ofl->ofl_osrel = rosp;
25537c478bd9Sstevel@tonic-gate 
25547c478bd9Sstevel@tonic-gate 	/*
25557c478bd9Sstevel@tonic-gate 	 * If this is the first relocation section we've encountered save it
25567c478bd9Sstevel@tonic-gate 	 * so that the .dynamic entry can be initialized accordingly.
25577c478bd9Sstevel@tonic-gate 	 */
25587c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osrelhead == (Os_desc *)0)
25597c478bd9Sstevel@tonic-gate 		ofl->ofl_osrelhead = rosp;
25607c478bd9Sstevel@tonic-gate 
25617c478bd9Sstevel@tonic-gate 	return (1);
25627c478bd9Sstevel@tonic-gate }
25637c478bd9Sstevel@tonic-gate 
25647c478bd9Sstevel@tonic-gate /*
25657c478bd9Sstevel@tonic-gate  * Generate version needed section.
25667c478bd9Sstevel@tonic-gate  */
25675aefb655Srie static uintptr_t
make_verneed(Ofl_desc * ofl)25687c478bd9Sstevel@tonic-gate make_verneed(Ofl_desc *ofl)
25697c478bd9Sstevel@tonic-gate {
25707c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
25717c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
25727c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
25737c478bd9Sstevel@tonic-gate 
25747c478bd9Sstevel@tonic-gate 	/*
25759039eeafSab 	 * verneed sections do not have a constant element size, so the
25769039eeafSab 	 * value of ent_cnt specified here (0) is meaningless.
25777c478bd9Sstevel@tonic-gate 	 */
25789039eeafSab 	if (new_section(ofl, SHT_SUNW_verneed, MSG_ORIG(MSG_SCN_SUNWVERSION),
257960758829Srie 	    0, &isec, &shdr, &data) == S_ERROR)
25807c478bd9Sstevel@tonic-gate 		return (S_ERROR);
25817c478bd9Sstevel@tonic-gate 
25829039eeafSab 	/* During version processing we calculated the total size. */
25839039eeafSab 	data->d_size = ofl->ofl_verneedsz;
25849039eeafSab 	shdr->sh_size = (Xword)ofl->ofl_verneedsz;
25857c478bd9Sstevel@tonic-gate 
2586ba2be530Sab 	ofl->ofl_osverneed =
258769112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_version, NULL);
25887c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osverneed);
25897c478bd9Sstevel@tonic-gate }
25907c478bd9Sstevel@tonic-gate 
25917c478bd9Sstevel@tonic-gate /*
25927c478bd9Sstevel@tonic-gate  * Generate a version definition section.
25937c478bd9Sstevel@tonic-gate  *
25947c478bd9Sstevel@tonic-gate  *  o	the SHT_SUNW_verdef section defines the versions that exist within this
25957c478bd9Sstevel@tonic-gate  *	image.
25967c478bd9Sstevel@tonic-gate  */
25975aefb655Srie static uintptr_t
make_verdef(Ofl_desc * ofl)25987c478bd9Sstevel@tonic-gate make_verdef(Ofl_desc *ofl)
25997c478bd9Sstevel@tonic-gate {
26007c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
26017c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
26027c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
26037c478bd9Sstevel@tonic-gate 	Ver_desc	*vdp;
2604635216b6SRod Evans 	Str_tbl		*strtab;
26057c478bd9Sstevel@tonic-gate 
26067c478bd9Sstevel@tonic-gate 	/*
26077c478bd9Sstevel@tonic-gate 	 * Reserve a string table entry for the base version dependency (other
26087c478bd9Sstevel@tonic-gate 	 * dependencies have symbol representations, which will already be
26097c478bd9Sstevel@tonic-gate 	 * accounted for during symbol processing).
26107c478bd9Sstevel@tonic-gate 	 */
261157ef7aa9SRod Evans 	vdp = (Ver_desc *)ofl->ofl_verdesc->apl_data[0];
26127c478bd9Sstevel@tonic-gate 
2613635216b6SRod Evans 	if (OFL_IS_STATIC_OBJ(ofl))
2614635216b6SRod Evans 		strtab = ofl->ofl_strtab;
2615635216b6SRod Evans 	else
2616635216b6SRod Evans 		strtab = ofl->ofl_dynstrtab;
2617635216b6SRod Evans 
2618635216b6SRod Evans 	if (st_insert(strtab, vdp->vd_name) == -1)
2619635216b6SRod Evans 		return (S_ERROR);
26207c478bd9Sstevel@tonic-gate 
26217c478bd9Sstevel@tonic-gate 	/*
26229039eeafSab 	 * verdef sections do not have a constant element size, so the
26239039eeafSab 	 * value of ent_cnt specified here (0) is meaningless.
26247c478bd9Sstevel@tonic-gate 	 */
26259039eeafSab 	if (new_section(ofl, SHT_SUNW_verdef, MSG_ORIG(MSG_SCN_SUNWVERSION),
262660758829Srie 	    0, &isec, &shdr, &data) == S_ERROR)
26277c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26287c478bd9Sstevel@tonic-gate 
26299039eeafSab 	/* During version processing we calculated the total size. */
26309039eeafSab 	data->d_size = ofl->ofl_verdefsz;
26319039eeafSab 	shdr->sh_size = (Xword)ofl->ofl_verdefsz;
26327c478bd9Sstevel@tonic-gate 
2633ba2be530Sab 	ofl->ofl_osverdef =
263469112eddSAli Bahrami 	    ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_version, NULL);
26357c478bd9Sstevel@tonic-gate 	return ((uintptr_t)ofl->ofl_osverdef);
26367c478bd9Sstevel@tonic-gate }
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate /*
26397c478bd9Sstevel@tonic-gate  * This routine is called when -z nopartial is in effect.
26407c478bd9Sstevel@tonic-gate  */
26417c478bd9Sstevel@tonic-gate uintptr_t
ld_make_parexpn_data(Ofl_desc * ofl,size_t size,Xword align)264235450702SAli Bahrami ld_make_parexpn_data(Ofl_desc *ofl, size_t size, Xword align)
26437c478bd9Sstevel@tonic-gate {
26447c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
26457c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
26467c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
26477c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
26487c478bd9Sstevel@tonic-gate 
264935450702SAli Bahrami 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_DATA), 0,
26509039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
26517c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26527c478bd9Sstevel@tonic-gate 
26539039eeafSab 	shdr->sh_flags |= SHF_WRITE;
26549039eeafSab 	data->d_size = size;
26557c478bd9Sstevel@tonic-gate 	shdr->sh_size = (Xword)size;
26569039eeafSab 	if (align != 0) {
26579039eeafSab 		data->d_align = align;
26587c478bd9Sstevel@tonic-gate 		shdr->sh_addralign = align;
26599039eeafSab 	}
26607c478bd9Sstevel@tonic-gate 
266157ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(size, 1)) == NULL)
26627c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26637c478bd9Sstevel@tonic-gate 
26647c478bd9Sstevel@tonic-gate 	/*
266535450702SAli Bahrami 	 * Retain handle to this .data input section. Variables using move
266635450702SAli Bahrami 	 * sections (partial initialization) will be redirected here when
266735450702SAli Bahrami 	 * such global references are added and '-z nopartial' is in effect.
26687c478bd9Sstevel@tonic-gate 	 */
266935450702SAli Bahrami 	ofl->ofl_isparexpn = isec;
267069112eddSAli Bahrami 	osp = ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_data, NULL);
2671ba2be530Sab 	if (osp == (Os_desc *)S_ERROR)
26727c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26737c478bd9Sstevel@tonic-gate 
26747c478bd9Sstevel@tonic-gate 	if (!(osp->os_flags & FLG_OS_OUTREL)) {
26757c478bd9Sstevel@tonic-gate 		ofl->ofl_dynshdrcnt++;
26767c478bd9Sstevel@tonic-gate 		osp->os_flags |= FLG_OS_OUTREL;
26777c478bd9Sstevel@tonic-gate 	}
26787c478bd9Sstevel@tonic-gate 	return (1);
26797c478bd9Sstevel@tonic-gate }
26807c478bd9Sstevel@tonic-gate 
26817c478bd9Sstevel@tonic-gate /*
26827c478bd9Sstevel@tonic-gate  * Make .sunwmove section
26837c478bd9Sstevel@tonic-gate  */
26847c478bd9Sstevel@tonic-gate uintptr_t
ld_make_sunwmove(Ofl_desc * ofl,int mv_nums)26855aefb655Srie ld_make_sunwmove(Ofl_desc *ofl, int mv_nums)
26867c478bd9Sstevel@tonic-gate {
26877c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
26887c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
26897c478bd9Sstevel@tonic-gate 	Is_desc		*isec;
269057ef7aa9SRod Evans 	Aliste		idx;
269157ef7aa9SRod Evans 	Sym_desc	*sdp;
2692b6a0e2cdSRichard Lowe 	int		cnt = 1;
26937c478bd9Sstevel@tonic-gate 
26947c478bd9Sstevel@tonic-gate 
26959039eeafSab 	if (new_section(ofl, SHT_SUNW_move, MSG_ORIG(MSG_SCN_SUNWMOVE),
26969039eeafSab 	    mv_nums, &isec, &shdr, &data) == S_ERROR)
26977c478bd9Sstevel@tonic-gate 		return (S_ERROR);
26987c478bd9Sstevel@tonic-gate 
269957ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(data->d_size, 1)) == NULL)
27007c478bd9Sstevel@tonic-gate 		return (S_ERROR);
27017c478bd9Sstevel@tonic-gate 
27027c478bd9Sstevel@tonic-gate 	/*
27037c478bd9Sstevel@tonic-gate 	 * Copy move entries
27047c478bd9Sstevel@tonic-gate 	 */
270557ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_parsyms, idx, sdp)) {
270657ef7aa9SRod Evans 		Aliste		idx2;
270757ef7aa9SRod Evans 		Mv_desc		*mdp;
27087c478bd9Sstevel@tonic-gate 
270957ef7aa9SRod Evans 		if (sdp->sd_flags & FLG_SY_PAREXPN)
27107c478bd9Sstevel@tonic-gate 			continue;
271157ef7aa9SRod Evans 
271257ef7aa9SRod Evans 		for (ALIST_TRAVERSE(sdp->sd_move, idx2, mdp))
271357ef7aa9SRod Evans 			mdp->md_oidx = cnt++;
27147c478bd9Sstevel@tonic-gate 	}
271557ef7aa9SRod Evans 
271669112eddSAli Bahrami 	if ((ofl->ofl_osmove = ld_place_section(ofl, isec, NULL, 0, NULL)) ==
27177c478bd9Sstevel@tonic-gate 	    (Os_desc *)S_ERROR)
27187c478bd9Sstevel@tonic-gate 		return (S_ERROR);
27197c478bd9Sstevel@tonic-gate 
27207c478bd9Sstevel@tonic-gate 	return (1);
27217c478bd9Sstevel@tonic-gate }
27227c478bd9Sstevel@tonic-gate 
2723cce0e03bSab /*
2724cce0e03bSab  * Given a relocation descriptor that references a string table
2725cce0e03bSab  * input section, locate the string referenced and return a pointer
2726cce0e03bSab  * to it.
2727cce0e03bSab  */
2728cce0e03bSab static const char *
strmerge_get_reloc_str(Ofl_desc * ofl,Rel_desc * rsp)2729cce0e03bSab strmerge_get_reloc_str(Ofl_desc *ofl, Rel_desc *rsp)
2730cce0e03bSab {
2731cce0e03bSab 	Sym_desc *sdp = rsp->rel_sym;
2732cce0e03bSab 	Xword	 str_off;
2733cce0e03bSab 
2734cce0e03bSab 	/*
2735cce0e03bSab 	 * In the case of an STT_SECTION symbol, the addend of the
2736cce0e03bSab 	 * relocation gives the offset into the string section. For
2737cce0e03bSab 	 * other symbol types, the symbol value is the offset.
2738cce0e03bSab 	 */
2739cce0e03bSab 
2740cce0e03bSab 	if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_SECTION) {
2741cce0e03bSab 		str_off = sdp->sd_sym->st_value;
2742cce0e03bSab 	} else if ((rsp->rel_flags & FLG_REL_RELA) == FLG_REL_RELA) {
2743cce0e03bSab 		/*
2744cce0e03bSab 		 * For SHT_RELA, the addend value is found in the
2745cce0e03bSab 		 * rel_raddend field of the relocation.
2746cce0e03bSab 		 */
2747cce0e03bSab 		str_off = rsp->rel_raddend;
2748cce0e03bSab 	} else {	/* REL and STT_SECTION */
2749cce0e03bSab 		/*
2750cce0e03bSab 		 * For SHT_REL, the "addend" is not part of the relocation
2751cce0e03bSab 		 * record. Instead, it is found at the relocation target
2752cce0e03bSab 		 * address.
2753cce0e03bSab 		 */
2754cce0e03bSab 		uchar_t *addr = (uchar_t *)((uintptr_t)rsp->rel_roffset +
2755cce0e03bSab 		    (uintptr_t)rsp->rel_isdesc->is_indata->d_buf);
2756cce0e03bSab 
2757cce0e03bSab 		if (ld_reloc_targval_get(ofl, rsp, addr, &str_off) == 0)
2758cce0e03bSab 			return (0);
2759cce0e03bSab 	}
2760cce0e03bSab 
2761cce0e03bSab 	return (str_off + (char *)sdp->sd_isc->is_indata->d_buf);
2762cce0e03bSab }
2763cce0e03bSab 
2764cce0e03bSab /*
2765cce0e03bSab  * First pass over the relocation records for string table merging.
2766cce0e03bSab  * Build lists of relocations and symbols that will need modification,
2767252adeb3SRichard Lowe  * and insert the strings they reference into the output string table.
2768cce0e03bSab  *
2769cce0e03bSab  * entry:
2770252adeb3SRichard Lowe  *	ofl - Output file descriptor
2771cce0e03bSab  *
2772252adeb3SRichard Lowe  * exit: On success, the string merging specific members of each output
2773252adeb3SRichard Lowe  *	section descriptor in ofl are updated based on information from the
2774252adeb3SRichard Lowe  *	relocation entries, and 0 is returned.
2775cce0e03bSab  *
2776252adeb3SRichard Lowe  *	On error, S_ERROR is returned.
2777cce0e03bSab  */
2778252adeb3SRichard Lowe static uintptr_t
ld_gather_strmerge(Ofl_desc * ofl,Rel_cache * cache)2779252adeb3SRichard Lowe ld_gather_strmerge(Ofl_desc *ofl, Rel_cache *cache)
2780cce0e03bSab {
2781252adeb3SRichard Lowe 	Rel_cachebuf *rbcp;
2782252adeb3SRichard Lowe 	Rel_desc *rsp;
2783252adeb3SRichard Lowe 	Sym_desc *last_sdp = NULL;
2784252adeb3SRichard Lowe 	Aliste idx1;
2785cce0e03bSab 
2786252adeb3SRichard Lowe 	/*
2787252adeb3SRichard Lowe 	 * Pass 1:
2788252adeb3SRichard Lowe 	 *
2789252adeb3SRichard Lowe 	 * Build lists of relocations and symbols that will need
2790252adeb3SRichard Lowe 	 * modification, and insert the strings they reference into
2791252adeb3SRichard Lowe 	 * the output string table.
2792252adeb3SRichard Lowe 	 */
2793252adeb3SRichard Lowe 	REL_CACHE_TRAVERSE(cache, idx1, rbcp, rsp) {
2794252adeb3SRichard Lowe 		Sym_desc *sdp = rsp->rel_sym;
2795252adeb3SRichard Lowe 		Os_desc *osp;
2796252adeb3SRichard Lowe 		const char *name;
2797252adeb3SRichard Lowe 
2798252adeb3SRichard Lowe 		/*
2799252adeb3SRichard Lowe 		 * If there's no input section, or the input section is
2800252adeb3SRichard Lowe 		 * discarded or does not contain mergable strings, we have
2801252adeb3SRichard Lowe 		 * nothing to do.
2802252adeb3SRichard Lowe 		 */
2803bf994817SAli Bahrami 		if ((sdp->sd_isc == NULL) || ((sdp->sd_isc->is_flags &
2804252adeb3SRichard Lowe 		    (FLG_IS_DISCARD | FLG_IS_INSTRMRG)) != FLG_IS_INSTRMRG))
2805bf994817SAli Bahrami 			continue;
2806cce0e03bSab 
2807252adeb3SRichard Lowe 		osp = sdp->sd_isc->is_osdesc;
2808252adeb3SRichard Lowe 
2809bf994817SAli Bahrami 		/*
2810bf994817SAli Bahrami 		 * Remember symbol for use in the third pass. There is no
2811bf994817SAli Bahrami 		 * reason to save a given symbol more than once, so we take
2812bf994817SAli Bahrami 		 * advantage of the fact that relocations to a given symbol
2813bf994817SAli Bahrami 		 * tend to cluster in the list. If this is the same symbol
2814bf994817SAli Bahrami 		 * we saved last time, don't bother.
2815bf994817SAli Bahrami 		 */
2816bf994817SAli Bahrami 		if (last_sdp != sdp) {
2817252adeb3SRichard Lowe 			if (aplist_append(&osp->os_mstrsyms, sdp,
2818252adeb3SRichard Lowe 			    AL_CNT_STRMRGSYM) == NULL)
2819252adeb3SRichard Lowe 				return (S_ERROR);
2820bf994817SAli Bahrami 			last_sdp = sdp;
2821cce0e03bSab 		}
2822bf994817SAli Bahrami 
2823252adeb3SRichard Lowe 		if ((osp->os_mstrtab == NULL) &&
2824252adeb3SRichard Lowe 		    (osp->os_mstrtab = st_new(FLG_STNEW_COMPRESS)) == NULL)
2825252adeb3SRichard Lowe 			return (S_ERROR);
2826252adeb3SRichard Lowe 
2827bf994817SAli Bahrami 		/* Enter the string into our new string table */
2828bf994817SAli Bahrami 		name = strmerge_get_reloc_str(ofl, rsp);
2829252adeb3SRichard Lowe 		if (st_insert(osp->os_mstrtab, name) == -1)
2830252adeb3SRichard Lowe 			return (S_ERROR);
2831bf994817SAli Bahrami 
2832bf994817SAli Bahrami 		/*
2833bf994817SAli Bahrami 		 * If this is an STT_SECTION symbol, then the second pass
2834bf994817SAli Bahrami 		 * will need to modify this relocation, so hang on to it.
2835bf994817SAli Bahrami 		 */
2836bf994817SAli Bahrami 		if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) &&
2837252adeb3SRichard Lowe 		    (aplist_append(&osp->os_mstrrels, rsp,
2838252adeb3SRichard Lowe 		    AL_CNT_STRMRGREL) == NULL)) {
2839252adeb3SRichard Lowe 			return (S_ERROR);
2840252adeb3SRichard Lowe 		}
2841cce0e03bSab 	}
2842cce0e03bSab 
2843252adeb3SRichard Lowe 	return (0);
2844cce0e03bSab }
2845cce0e03bSab 
2846cce0e03bSab /*
2847252adeb3SRichard Lowe  * If any an output section has more than one SHF_MERGE|SHF_STRINGS input
2848252adeb3SRichard Lowe  * section, replace them with a single merged/compressed input section.
2849252adeb3SRichard Lowe  *
2850252adeb3SRichard Lowe  * This is done by making a Str_tbl (as we use for managing SHT_STRTAB
2851252adeb3SRichard Lowe  * sections) per output section with compression enabled to manage all strings
2852252adeb3SRichard Lowe  * in the mergeable input sections.  We then discard all inputs which
2853252adeb3SRichard Lowe  * contributed to this table and replace them with an input section we create
2854252adeb3SRichard Lowe  * taking data from this Str_tbl.  References to the now discarded sections
2855252adeb3SRichard Lowe  * are then updated to refer to our new merged input section, and the string
2856252adeb3SRichard Lowe  * table and other metadata are freed.
2857252adeb3SRichard Lowe  *
2858252adeb3SRichard Lowe  * This process is done in 3 passes.  For efficiency reasons half of pass 1 is
2859252adeb3SRichard Lowe  * done by ld_strmerge_gather() so relocations only need to be processed once.
2860252adeb3SRichard Lowe  * Steps 1.5 onward are performed here.  The steps are:
2861252adeb3SRichard Lowe  *
2862252adeb3SRichard Lowe  *	1) In ld_strmerge_gather() examine all relocations, insert strings
2863252adeb3SRichard Lowe  *		from relocations to the mergeable input sections into the string
2864252adeb3SRichard Lowe  *		table.
2865252adeb3SRichard Lowe  *	1.5) Gather every string from the mergeable input sections, regardless
2866252adeb3SRichard Lowe  *		of whether it is referenced from a relocation.	 All strings
2867252adeb3SRichard Lowe  *		must be processed, and relocations may point into the middle
2868252adeb3SRichard Lowe  *		of an actual NUL-terminated string, so we must enter both the
2869252adeb3SRichard Lowe  *		precise strings referenced by relocations and full strings
2870252adeb3SRichard Lowe  *		within the section.
2871252adeb3SRichard Lowe  *	2) Modify the relocation values to be correct for the
2872252adeb3SRichard Lowe  *		new merged section.
2873252adeb3SRichard Lowe  *	3) Modify the symbols used by the relocations to reference
2874252adeb3SRichard Lowe  *		the new section.
2875252adeb3SRichard Lowe  *
2876252adeb3SRichard Lowe  * These passes cannot be combined:
2877252adeb3SRichard Lowe  *	- The string table code works in two passes, and all
2878252adeb3SRichard Lowe  *		strings have to be loaded in pass one before the
2879252adeb3SRichard Lowe  *		offset of any strings can be determined.
2880252adeb3SRichard Lowe  *	- Multiple relocations reference a single symbol, so the
2881252adeb3SRichard Lowe  *		symbol cannot be modified until all relocations are
2882252adeb3SRichard Lowe  *		fixed.
2883cce0e03bSab  *
2884cce0e03bSab  * entry:
2885cce0e03bSab  *	ofl - Output file descriptor
2886252adeb3SRichard Lowe  *	osp - Outputs section descriptor
2887cce0e03bSab  *
2888cce0e03bSab  * exit:
2889252adeb3SRichard Lowe  *	If section merging is possible for this output section, it is done.
2890252adeb3SRichard Lowe  *	If no errors are encountered, 0 is returned. On error, S_ERROR is
2891252adeb3SRichard Lowe  *	returned.
2892cce0e03bSab  *
2893252adeb3SRichard Lowe  *	The contents of the string-merging specific members of this output
2894252adeb3SRichard Lowe  *	section descriptor are undefined after this function returns.
2895cce0e03bSab  */
2896cce0e03bSab static uintptr_t
ld_strmerge_sec(Ofl_desc * ofl,Os_desc * osp)2897252adeb3SRichard Lowe ld_strmerge_sec(Ofl_desc *ofl, Os_desc *osp)
2898cce0e03bSab {
2899252adeb3SRichard Lowe 	Is_desc		*isp = NULL;
2900cce0e03bSab 	Sym_desc	*sdp;
2901cce0e03bSab 	Rel_desc	*rsp;
2902252adeb3SRichard Lowe 	Is_desc		*mstrsec = NULL; /* Generated string merge section */
2903252adeb3SRichard Lowe 	Shdr		*mstr_shdr = NULL;
2904252adeb3SRichard Lowe 	Elf_Data	*mstr_data = NULL;
2905cce0e03bSab 	size_t		data_size;
2906252adeb3SRichard Lowe 	Aliste		idx;
2907252adeb3SRichard Lowe 	uintptr_t	ret = 0;
2908252adeb3SRichard Lowe 	Boolean		placed = FALSE;
2909cce0e03bSab 
2910cce0e03bSab 	/*
2911252adeb3SRichard Lowe 	 * Pass 1.5: Add all strings from all mergeable input sections.
2912252adeb3SRichard Lowe 	 *
2913252adeb3SRichard Lowe 	 * The last section we find also serves as the template for our
2914252adeb3SRichard Lowe 	 * replacement merged section, providing the section attributes, etc.
2915cce0e03bSab 	 */
2916cce0e03bSab 	for (APLIST_TRAVERSE(osp->os_mstrisdescs, idx, isp)) {
2917252adeb3SRichard Lowe 		const char *str, *end;
2918252adeb3SRichard Lowe 
2919d9c5840bSRichard Lowe 		if (isdesc_discarded(isp))
2920d9c5840bSRichard Lowe 			continue;
2921d9c5840bSRichard Lowe 
2922d9c5840bSRichard Lowe 		/*
2923d9c5840bSRichard Lowe 		 * Input sections of 0 size are dubiously valid since they do
2924d9c5840bSRichard Lowe 		 * not even contain the NUL string.  Ignore them.
2925d9c5840bSRichard Lowe 		 */
2926d9c5840bSRichard Lowe 		if (isp->is_shdr->sh_size == 0)
2927cce0e03bSab 			continue;
2928cce0e03bSab 
2929252adeb3SRichard Lowe 		if ((osp->os_mstrtab == NULL) &&
2930252adeb3SRichard Lowe 		    (osp->os_mstrtab = st_new(FLG_STNEW_COMPRESS)) == NULL) {
2931252adeb3SRichard Lowe 			ret = S_ERROR;
2932252adeb3SRichard Lowe 			goto out;
2933252adeb3SRichard Lowe 		}
2934cce0e03bSab 
2935252adeb3SRichard Lowe 		end = isp->is_indata->d_buf + isp->is_indata->d_size;
2936252adeb3SRichard Lowe 		for (str = isp->is_indata->d_buf; str < end;
2937252adeb3SRichard Lowe 		    str += strlen(str) + 1) {
2938252adeb3SRichard Lowe 			if (st_insert(osp->os_mstrtab, str) != 0) {
2939252adeb3SRichard Lowe 				ret = S_ERROR;
2940252adeb3SRichard Lowe 				goto out;
2941252adeb3SRichard Lowe 			}
2942252adeb3SRichard Lowe 		}
2943252adeb3SRichard Lowe 	}
2944cce0e03bSab 
2945252adeb3SRichard Lowe 	IMPLY(osp->os_mstrtab != NULL, isp != NULL);
2946252adeb3SRichard Lowe 	if (osp->os_mstrtab == NULL) {
2947252adeb3SRichard Lowe 		ret = 0;
2948252adeb3SRichard Lowe 		goto out;
2949252adeb3SRichard Lowe 	}
2950cce0e03bSab 
2951cce0e03bSab 	/*
2952252adeb3SRichard Lowe 	 * Get the size of the new input section. Requesting the string
2953252adeb3SRichard Lowe 	 * table size "cooks" the table, and finalizes its contents.
2954cce0e03bSab 	 */
2955252adeb3SRichard Lowe 	data_size = st_getstrtab_sz(osp->os_mstrtab);
2956cce0e03bSab 
2957cce0e03bSab 	/* Create a new input section to hold the merged strings */
2958cce0e03bSab 	if (new_section_from_template(ofl, isp, data_size,
2959252adeb3SRichard Lowe 	    &mstrsec, &mstr_shdr, &mstr_data) == S_ERROR) {
2960252adeb3SRichard Lowe 		ret = S_ERROR;
2961252adeb3SRichard Lowe 		goto out;
2962252adeb3SRichard Lowe 	}
2963cce0e03bSab 	mstrsec->is_flags |= FLG_IS_GNSTRMRG;
2964cce0e03bSab 
2965cce0e03bSab 	/*
2966252adeb3SRichard Lowe 	 * Allocate a data buffer for the new input section, associate the
2967252adeb3SRichard Lowe 	 * buffer with the string table descriptor, and fill it from the
2968252adeb3SRichard Lowe 	 * string table.
2969cce0e03bSab 	 */
2970252adeb3SRichard Lowe 	if ((mstr_data->d_buf = libld_malloc(data_size)) == NULL) {
2971252adeb3SRichard Lowe 		ret = S_ERROR;
2972252adeb3SRichard Lowe 		goto out;
2973252adeb3SRichard Lowe 	}
2974252adeb3SRichard Lowe 	if ((st_setstrbuf(osp->os_mstrtab, mstr_data->d_buf,
2975252adeb3SRichard Lowe 	    data_size) == -1)) {
2976252adeb3SRichard Lowe 		ret = S_ERROR;
2977252adeb3SRichard Lowe 		goto out;
2978252adeb3SRichard Lowe 	}
2979252adeb3SRichard Lowe 
2980252adeb3SRichard Lowe 	st_setallstrings(osp->os_mstrtab);
2981cce0e03bSab 
2982cce0e03bSab 	/* Add the new section to the output image */
298369112eddSAli Bahrami 	if (ld_place_section(ofl, mstrsec, NULL, osp->os_identndx, NULL) ==
2984252adeb3SRichard Lowe 	    (Os_desc *)S_ERROR) {
2985252adeb3SRichard Lowe 		ret = S_ERROR;
2986252adeb3SRichard Lowe 		goto out;
2987252adeb3SRichard Lowe 	}
2988252adeb3SRichard Lowe 	placed = TRUE;
2989cce0e03bSab 
2990cce0e03bSab 	/*
2991cce0e03bSab 	 * Pass 2:
2992cce0e03bSab 	 *
2993cce0e03bSab 	 * Revisit the relocation descriptors with STT_SECTION symbols
2994cce0e03bSab 	 * that were saved by the first pass. Update each relocation
2995cce0e03bSab 	 * record so that the offset it contains is for the new section
2996cce0e03bSab 	 * instead of the original.
2997cce0e03bSab 	 */
2998252adeb3SRichard Lowe 	for (APLIST_TRAVERSE(osp->os_mstrrels, idx, rsp)) {
2999cce0e03bSab 		const char	*name;
3000252adeb3SRichard Lowe 		size_t		stoff;
3001cce0e03bSab 
3002252adeb3SRichard Lowe 		/*
3003252adeb3SRichard Lowe 		 * Find the string to the merged table's buffer and get its
3004252adeb3SRichard Lowe 		 * offset.
3005252adeb3SRichard Lowe 		 */
3006cce0e03bSab 		name = strmerge_get_reloc_str(ofl, rsp);
3007252adeb3SRichard Lowe 		stoff = st_findstring(osp->os_mstrtab, name);
3008252adeb3SRichard Lowe 		VERIFY3S(stoff, !=, -1);
3009cce0e03bSab 
3010cce0e03bSab 		/*
3011cce0e03bSab 		 * Alter the relocation to access the string at the
3012cce0e03bSab 		 * new offset in our new string table.
3013cce0e03bSab 		 *
3014cce0e03bSab 		 * For SHT_RELA platforms, it suffices to simply
3015cce0e03bSab 		 * update the rel_raddend field of the relocation.
3016cce0e03bSab 		 *
3017cce0e03bSab 		 * For SHT_REL platforms, the new "addend" value
3018cce0e03bSab 		 * needs to be written at the address being relocated.
3019cce0e03bSab 		 * However, we can't alter the input sections which
3020cce0e03bSab 		 * are mapped readonly, and the output image has not
3021cce0e03bSab 		 * been created yet. So, we defer this operation,
3022cce0e03bSab 		 * using the rel_raddend field of the relocation
3023cce0e03bSab 		 * which is normally 0 on a REL platform, to pass the
3024cce0e03bSab 		 * new "addend" value to ld_perform_outreloc() or
3025cce0e03bSab 		 * ld_do_activerelocs(). The FLG_REL_NADDEND flag
3026cce0e03bSab 		 * tells them that this is the case.
3027cce0e03bSab 		 */
3028252adeb3SRichard Lowe 		if ((rsp->rel_flags & FLG_REL_RELA) == 0) {
3029252adeb3SRichard Lowe 			/* REL */
3030cce0e03bSab 			rsp->rel_flags |= FLG_REL_NADDEND;
3031252adeb3SRichard Lowe 		}
3032cce0e03bSab 		rsp->rel_raddend = (Sxword)stoff;
3033cce0e03bSab 
3034cce0e03bSab 		/*
3035bf994817SAli Bahrami 		 * Generate a symbol name string for STT_SECTION symbols
3036bf994817SAli Bahrami 		 * that might reference our merged section. This shows up
3037bf994817SAli Bahrami 		 * in debug output and helps show how the relocation has
3038252adeb3SRichard Lowe 		 * changed from its original input section to our merged
3039252adeb3SRichard Lowe 		 * one.
3040cce0e03bSab 		 */
3041252adeb3SRichard Lowe 		if (ld_stt_section_sym_name(mstrsec) == NULL) {
3042252adeb3SRichard Lowe 			ret = S_ERROR;
3043252adeb3SRichard Lowe 			goto out;
3044252adeb3SRichard Lowe 		}
3045cce0e03bSab 	}
3046cce0e03bSab 
3047cce0e03bSab 	/*
3048cce0e03bSab 	 * Pass 3:
3049cce0e03bSab 	 *
3050cce0e03bSab 	 * Modify the symbols referenced by the relocation descriptors
3051cce0e03bSab 	 * so that they reference the new input section containing the
3052cce0e03bSab 	 * merged strings instead of the original input sections.
3053cce0e03bSab 	 */
3054252adeb3SRichard Lowe 	for (APLIST_TRAVERSE(osp->os_mstrsyms, idx, sdp)) {
3055cce0e03bSab 		/*
3056252adeb3SRichard Lowe 		 * If we've already redirected this symbol to the merged data,
3057252adeb3SRichard Lowe 		 * don't do it again.  ld_gather_strmerge() uses a heuristic
3058252adeb3SRichard Lowe 		 * (relocations to the same symbol clump together) to avoid
3059252adeb3SRichard Lowe 		 * inserting a given symbol more than once, but repeat symbols
3060252adeb3SRichard Lowe 		 * in the list can occur.
3061cce0e03bSab 		 */
3062cce0e03bSab 		if ((sdp->sd_isc->is_flags & FLG_IS_INSTRMRG) == 0)
3063cce0e03bSab 			continue;
3064cce0e03bSab 
3065cce0e03bSab 		if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_SECTION) {
3066cce0e03bSab 			/*
3067cce0e03bSab 			 * This is not an STT_SECTION symbol, so its
3068cce0e03bSab 			 * value is the offset of the string within the
3069cce0e03bSab 			 * input section. Update the address to reflect
3070cce0e03bSab 			 * the address in our new merged section.
3071cce0e03bSab 			 */
3072252adeb3SRichard Lowe 			const char	*name;
3073252adeb3SRichard Lowe 			size_t		stoff;
3074252adeb3SRichard Lowe 
3075252adeb3SRichard Lowe 			/*
3076252adeb3SRichard Lowe 			 * Find the string in the merged table's buffer and get
3077252adeb3SRichard Lowe 			 * its offset.
3078252adeb3SRichard Lowe 			 */
3079252adeb3SRichard Lowe 			name = sdp->sd_sym->st_value +
3080cce0e03bSab 			    (char *)sdp->sd_isc->is_indata->d_buf;
3081252adeb3SRichard Lowe 			stoff = st_findstring(osp->os_mstrtab, name);
3082252adeb3SRichard Lowe 			VERIFY3S(stoff, !=, -1);
3083cce0e03bSab 
3084252adeb3SRichard Lowe 			if (ld_sym_copy(sdp) == S_ERROR) {
3085252adeb3SRichard Lowe 				ret = S_ERROR;
3086252adeb3SRichard Lowe 				goto out;
3087cce0e03bSab 			}
3088cce0e03bSab 			sdp->sd_sym->st_value = (Word)stoff;
3089cce0e03bSab 		}
3090cce0e03bSab 
3091cce0e03bSab 		/* Redirect the symbol to our new merged section */
3092cce0e03bSab 		sdp->sd_isc = mstrsec;
3093cce0e03bSab 	}
3094cce0e03bSab 
3095cce0e03bSab 	/*
3096cce0e03bSab 	 * There are no references left to the original input string sections.
3097cce0e03bSab 	 * Mark them as discarded so they don't go into the output image.
3098cce0e03bSab 	 * At the same time, add up the sizes of the replaced sections.
3099cce0e03bSab 	 */
3100cce0e03bSab 	data_size = 0;
3101cce0e03bSab 	for (APLIST_TRAVERSE(osp->os_mstrisdescs, idx, isp)) {
3102cce0e03bSab 		if (isp->is_flags & (FLG_IS_DISCARD | FLG_IS_GNSTRMRG))
3103cce0e03bSab 			continue;
3104cce0e03bSab 
3105cce0e03bSab 		data_size += isp->is_indata->d_size;
3106cce0e03bSab 
3107cce0e03bSab 		isp->is_flags |= FLG_IS_DISCARD;
3108cce0e03bSab 		DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, isp, mstrsec));
3109cce0e03bSab 	}
3110cce0e03bSab 
3111cce0e03bSab 	/* Report how much space we saved in the output section */
311269112eddSAli Bahrami 	DBG_CALL(Dbg_sec_genstr_compress(ofl->ofl_lml, osp->os_name, data_size,
311369112eddSAli Bahrami 	    mstr_data->d_size));
3114cce0e03bSab 
3115252adeb3SRichard Lowe out:
3116252adeb3SRichard Lowe 	if ((ret == S_ERROR) && !placed) {
3117252adeb3SRichard Lowe 		libld_free(mstrsec);
3118252adeb3SRichard Lowe 		if (mstr_data != NULL)
3119252adeb3SRichard Lowe 			libld_free(mstr_data->d_buf);
3120252adeb3SRichard Lowe 		libld_free(mstr_data);
3121252adeb3SRichard Lowe 		libld_free(mstr_shdr);
3122252adeb3SRichard Lowe 	}
3123cce0e03bSab 
3124252adeb3SRichard Lowe 	libld_free(osp->os_mstrsyms);
3125252adeb3SRichard Lowe 	osp->os_mstrsyms = NULL;
3126252adeb3SRichard Lowe 	libld_free(osp->os_mstrrels);
3127252adeb3SRichard Lowe 	osp->os_mstrrels = NULL;
3128252adeb3SRichard Lowe 
3129252adeb3SRichard Lowe 	if (osp->os_mstrtab != NULL) {
3130252adeb3SRichard Lowe 		st_destroy(osp->os_mstrtab);
3131252adeb3SRichard Lowe 		osp->os_mstrtab = NULL;
3132252adeb3SRichard Lowe 	}
3133252adeb3SRichard Lowe 
3134252adeb3SRichard Lowe 	return (ret);
3135252adeb3SRichard Lowe }
3136252adeb3SRichard Lowe 
3137252adeb3SRichard Lowe /*
3138252adeb3SRichard Lowe  * If any output section has SHF_MERGE|SHF_STRINGS input sections,
3139252adeb3SRichard Lowe  * replace them with a single merged/compressed input section.
3140252adeb3SRichard Lowe  *
3141252adeb3SRichard Lowe  * entry:
3142252adeb3SRichard Lowe  *	ofl - Output file descriptor
3143252adeb3SRichard Lowe  *
3144252adeb3SRichard Lowe  * exit:
3145252adeb3SRichard Lowe  *	If section merging is possible, it is done. If no errors are
3146252adeb3SRichard Lowe  *	encountered, 0 is returned. On error, S_ERROR is returned.
3147252adeb3SRichard Lowe  *
3148252adeb3SRichard Lowe  *	The contents of the string-merging specific members of any output
3149252adeb3SRichard Lowe  *	section descriptor are undefined after this function returns.
3150252adeb3SRichard Lowe  */
3151252adeb3SRichard Lowe static uintptr_t
ld_make_strmerge(Ofl_desc * ofl)3152252adeb3SRichard Lowe ld_make_strmerge(Ofl_desc *ofl)
3153252adeb3SRichard Lowe {
3154252adeb3SRichard Lowe 	Sg_desc *sgp;
3155252adeb3SRichard Lowe 	Aliste idx1;
3156252adeb3SRichard Lowe 
3157252adeb3SRichard Lowe 	if (ld_gather_strmerge(ofl, &ofl->ofl_actrels) == S_ERROR)
3158252adeb3SRichard Lowe 		return (S_ERROR);
3159252adeb3SRichard Lowe 	if (ld_gather_strmerge(ofl, &ofl->ofl_outrels) == S_ERROR)
3160252adeb3SRichard Lowe 		return (S_ERROR);
3161252adeb3SRichard Lowe 
3162252adeb3SRichard Lowe 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
3163252adeb3SRichard Lowe 		Os_desc	*osp;
3164252adeb3SRichard Lowe 		Aliste	idx2;
3165252adeb3SRichard Lowe 
3166252adeb3SRichard Lowe 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
3167252adeb3SRichard Lowe 			if (ld_strmerge_sec(ofl, osp) == S_ERROR)
3168252adeb3SRichard Lowe 				return (S_ERROR);
3169252adeb3SRichard Lowe 		}
3170252adeb3SRichard Lowe 	}
3171252adeb3SRichard Lowe 
3172252adeb3SRichard Lowe 	return (0);
3173cce0e03bSab }
3174cce0e03bSab 
3175635216b6SRod Evans /*
3176635216b6SRod Evans  * Update a data buffers size.  A number of sections have to be created, and
3177635216b6SRod Evans  * the sections header contributes to the size of the eventual section.  Thus,
3178635216b6SRod Evans  * a section may be created, and once all associated sections have been created,
3179635216b6SRod Evans  * we return to establish the required section size.
3180635216b6SRod Evans  */
3181635216b6SRod Evans inline static void
update_data_size(Os_desc * osp,ulong_t cnt)3182635216b6SRod Evans update_data_size(Os_desc *osp, ulong_t cnt)
3183635216b6SRod Evans {
3184635216b6SRod Evans 	Is_desc		*isec = ld_os_first_isdesc(osp);
3185635216b6SRod Evans 	Elf_Data	*data = isec->is_indata;
3186635216b6SRod Evans 	Shdr		*shdr = osp->os_shdr;
3187635216b6SRod Evans 	size_t		size = cnt * shdr->sh_entsize;
3188635216b6SRod Evans 
3189635216b6SRod Evans 	shdr->sh_size = (Xword)size;
3190635216b6SRod Evans 	data->d_size = size;
3191635216b6SRod Evans }
3192cce0e03bSab 
31937c478bd9Sstevel@tonic-gate /*
31947c478bd9Sstevel@tonic-gate  * The following sections are built after all input file processing and symbol
31957c478bd9Sstevel@tonic-gate  * validation has been carried out.  The order is important (because the
31967c478bd9Sstevel@tonic-gate  * addition of a section adds a new symbol there is a chicken and egg problem
31977c478bd9Sstevel@tonic-gate  * of maintaining the appropriate counts).  By maintaining a known order the
31987c478bd9Sstevel@tonic-gate  * individual routines can compensate for later, known, additions.
31997c478bd9Sstevel@tonic-gate  */
32007c478bd9Sstevel@tonic-gate uintptr_t
ld_make_sections(Ofl_desc * ofl)32015aefb655Srie ld_make_sections(Ofl_desc *ofl)
32027c478bd9Sstevel@tonic-gate {
32031d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
32047c478bd9Sstevel@tonic-gate 	Sg_desc		*sgp;
32057c478bd9Sstevel@tonic-gate 
32067c478bd9Sstevel@tonic-gate 	/*
32077c478bd9Sstevel@tonic-gate 	 * Generate any special sections.
32087c478bd9Sstevel@tonic-gate 	 */
32097c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_ADDVERS)
32107c478bd9Sstevel@tonic-gate 		if (make_comment(ofl) == S_ERROR)
32117c478bd9Sstevel@tonic-gate 			return (S_ERROR);
32127c478bd9Sstevel@tonic-gate 
32137c478bd9Sstevel@tonic-gate 	if (make_interp(ofl) == S_ERROR)
32147c478bd9Sstevel@tonic-gate 		return (S_ERROR);
32157c478bd9Sstevel@tonic-gate 
321608278a5eSRod Evans 	/*
321708278a5eSRod Evans 	 * Create a capabilities section if required.
321808278a5eSRod Evans 	 */
321908278a5eSRod Evans 	if (make_cap(ofl, SHT_SUNW_cap, MSG_ORIG(MSG_SCN_SUNWCAP),
322008278a5eSRod Evans 	    ld_targ.t_id.id_cap) == S_ERROR)
32217c478bd9Sstevel@tonic-gate 		return (S_ERROR);
32227c478bd9Sstevel@tonic-gate 
322308278a5eSRod Evans 	/*
322408278a5eSRod Evans 	 * Create any init/fini array sections.
322508278a5eSRod Evans 	 */
32267c478bd9Sstevel@tonic-gate 	if (make_array(ofl, SHT_INIT_ARRAY, MSG_ORIG(MSG_SCN_INITARRAY),
322757ef7aa9SRod Evans 	    ofl->ofl_initarray) == S_ERROR)
32287c478bd9Sstevel@tonic-gate 		return (S_ERROR);
32297c478bd9Sstevel@tonic-gate 
32307c478bd9Sstevel@tonic-gate 	if (make_array(ofl, SHT_FINI_ARRAY, MSG_ORIG(MSG_SCN_FINIARRAY),
323157ef7aa9SRod Evans 	    ofl->ofl_finiarray) == S_ERROR)
32327c478bd9Sstevel@tonic-gate 		return (S_ERROR);
32337c478bd9Sstevel@tonic-gate 
32347c478bd9Sstevel@tonic-gate 	if (make_array(ofl, SHT_PREINIT_ARRAY, MSG_ORIG(MSG_SCN_PREINITARRAY),
323557ef7aa9SRod Evans 	    ofl->ofl_preiarray) == S_ERROR)
32367c478bd9Sstevel@tonic-gate 		return (S_ERROR);
32377c478bd9Sstevel@tonic-gate 
32387c478bd9Sstevel@tonic-gate 	/*
32397c478bd9Sstevel@tonic-gate 	 * Make the .plt section.  This occurs after any other relocation
32407c478bd9Sstevel@tonic-gate 	 * sections are generated (see reloc_init()) to ensure that the
32417c478bd9Sstevel@tonic-gate 	 * associated relocation section is after all the other relocation
32427c478bd9Sstevel@tonic-gate 	 * sections.
32437c478bd9Sstevel@tonic-gate 	 */
32447c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_pltcnt) || (ofl->ofl_pltpad))
32457c478bd9Sstevel@tonic-gate 		if (make_plt(ofl) == S_ERROR)
32467c478bd9Sstevel@tonic-gate 			return (S_ERROR);
32477c478bd9Sstevel@tonic-gate 
3248fb1354edSrie 	/*
3249fb1354edSrie 	 * Determine whether any sections or files are not referenced.  Under
3250fb1354edSrie 	 * -Dunused a diagnostic for any unused components is generated, under
3251fb1354edSrie 	 * -zignore the component is removed from the final output.
3252fb1354edSrie 	 */
32535aefb655Srie 	if (DBG_ENABLED || (ofl->ofl_flags1 & FLG_OF1_IGNPRC)) {
32547c478bd9Sstevel@tonic-gate 		if (ignore_section_processing(ofl) == S_ERROR)
32557c478bd9Sstevel@tonic-gate 			return (S_ERROR);
32567c478bd9Sstevel@tonic-gate 	}
32577c478bd9Sstevel@tonic-gate 
3258e64d0ff9SAli Bahrami 	/*
3259e64d0ff9SAli Bahrami 	 * If we have detected a situation in which previously placed
3260e64d0ff9SAli Bahrami 	 * output sections may have been discarded, perform the necessary
3261e64d0ff9SAli Bahrami 	 * readjustment.
3262e64d0ff9SAli Bahrami 	 */
3263e64d0ff9SAli Bahrami 	if (ofl->ofl_flags & FLG_OF_ADJOSCNT)
3264e64d0ff9SAli Bahrami 		adjust_os_count(ofl);
3265e64d0ff9SAli Bahrami 
3266cce0e03bSab 	/*
3267cce0e03bSab 	 * Do any of the output sections contain input sections that
3268cce0e03bSab 	 * are candidates for string table merging? For each such case,
3269cce0e03bSab 	 * we create a replacement section, insert it, and discard the
3270cce0e03bSab 	 * originals.
3271cce0e03bSab 	 *
327257ef7aa9SRod Evans 	 * rel_alpp and sym_alpp are used by ld_make_strmerge()
3273cce0e03bSab 	 * for its internal processing. We are responsible for the
3274cce0e03bSab 	 * initialization and cleanup, and ld_make_strmerge() handles the rest.
327557ef7aa9SRod Evans 	 * This allows us to reuse a single pair of memory buffers, allocated
327657ef7aa9SRod Evans 	 * for this processing, for all the output sections.
3277cce0e03bSab 	 */
3278cce0e03bSab 	if ((ofl->ofl_flags1 & FLG_OF1_NCSTTAB) == 0) {
3279252adeb3SRichard Lowe 		if (ld_make_strmerge(ofl) == S_ERROR)
3280cce0e03bSab 			return (S_ERROR);
3281cce0e03bSab 	}
3282cce0e03bSab 
32837c478bd9Sstevel@tonic-gate 	/*
32847c478bd9Sstevel@tonic-gate 	 * Add any necessary versioning information.
32857c478bd9Sstevel@tonic-gate 	 */
3286090a8d9eSAli Bahrami 	if (!(flags & FLG_OF_NOVERSEC)) {
3287090a8d9eSAli Bahrami 		if ((flags & FLG_OF_VERNEED) &&
3288090a8d9eSAli Bahrami 		    (make_verneed(ofl) == S_ERROR))
32897c478bd9Sstevel@tonic-gate 			return (S_ERROR);
3290090a8d9eSAli Bahrami 		if ((flags & FLG_OF_VERDEF) &&
3291090a8d9eSAli Bahrami 		    (make_verdef(ofl) == S_ERROR))
32927c478bd9Sstevel@tonic-gate 			return (S_ERROR);
3293090a8d9eSAli Bahrami 		if ((flags & (FLG_OF_VERNEED | FLG_OF_VERDEF)) &&
3294090a8d9eSAli Bahrami 		    ((ofl->ofl_osversym = make_sym_sec(ofl,
32959039eeafSab 		    MSG_ORIG(MSG_SCN_SUNWVERSYM), SHT_SUNW_versym,
3296090a8d9eSAli Bahrami 		    ld_targ.t_id.id_version)) == (Os_desc*)S_ERROR))
32977c478bd9Sstevel@tonic-gate 			return (S_ERROR);
32987c478bd9Sstevel@tonic-gate 	}
32997c478bd9Sstevel@tonic-gate 
33007c478bd9Sstevel@tonic-gate 	/*
33019039eeafSab 	 * Create a syminfo section if necessary.
33027c478bd9Sstevel@tonic-gate 	 */
33031d9df23bSab 	if (flags & FLG_OF_SYMINFO) {
33047c478bd9Sstevel@tonic-gate 		if ((ofl->ofl_ossyminfo = make_sym_sec(ofl,
33059039eeafSab 		    MSG_ORIG(MSG_SCN_SUNWSYMINFO), SHT_SUNW_syminfo,
3306ba2be530Sab 		    ld_targ.t_id.id_syminfo)) == (Os_desc *)S_ERROR)
33077c478bd9Sstevel@tonic-gate 			return (S_ERROR);
33087c478bd9Sstevel@tonic-gate 	}
33097c478bd9Sstevel@tonic-gate 
33101d9df23bSab 	if (flags & FLG_OF_COMREL) {
33117c478bd9Sstevel@tonic-gate 		/*
33127c478bd9Sstevel@tonic-gate 		 * If -zcombreloc is enabled then all relocations (except for
33137c478bd9Sstevel@tonic-gate 		 * the PLT's) are coalesced into a single relocation section.
33147c478bd9Sstevel@tonic-gate 		 */
33157c478bd9Sstevel@tonic-gate 		if (ofl->ofl_reloccnt) {
33167c478bd9Sstevel@tonic-gate 			if (make_reloc(ofl, NULL) == S_ERROR)
33177c478bd9Sstevel@tonic-gate 				return (S_ERROR);
33187c478bd9Sstevel@tonic-gate 		}
33197c478bd9Sstevel@tonic-gate 	} else {
332057ef7aa9SRod Evans 		Aliste	idx1;
332157ef7aa9SRod Evans 
33227c478bd9Sstevel@tonic-gate 		/*
33230bc07c75Srie 		 * Create the required output relocation sections.  Note, new
33240bc07c75Srie 		 * sections may be added to the section list that is being
33250bc07c75Srie 		 * traversed.  These insertions can move the elements of the
33260bc07c75Srie 		 * Alist such that a section descriptor is re-read.  Recursion
33270bc07c75Srie 		 * is prevented by maintaining a previous section pointer and
33280bc07c75Srie 		 * insuring that this pointer isn't re-examined.
33297c478bd9Sstevel@tonic-gate 		 */
333057ef7aa9SRod Evans 		for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
3331cce0e03bSab 			Os_desc	*osp, *posp = 0;
333257ef7aa9SRod Evans 			Aliste	idx2;
33337c478bd9Sstevel@tonic-gate 
333457ef7aa9SRod Evans 			for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
33350bc07c75Srie 				if ((osp != posp) && osp->os_szoutrels &&
33367c478bd9Sstevel@tonic-gate 				    (osp != ofl->ofl_osplt)) {
33377c478bd9Sstevel@tonic-gate 					if (make_reloc(ofl, osp) == S_ERROR)
33387c478bd9Sstevel@tonic-gate 						return (S_ERROR);
33397c478bd9Sstevel@tonic-gate 				}
33400bc07c75Srie 				posp = osp;
33417c478bd9Sstevel@tonic-gate 			}
33427c478bd9Sstevel@tonic-gate 		}
33437c478bd9Sstevel@tonic-gate 
33447c478bd9Sstevel@tonic-gate 		/*
33457c478bd9Sstevel@tonic-gate 		 * If we're not building a combined relocation section, then
33467c478bd9Sstevel@tonic-gate 		 * build a .rel[a] section as required.
33477c478bd9Sstevel@tonic-gate 		 */
33487c478bd9Sstevel@tonic-gate 		if (ofl->ofl_relocrelsz) {
33497c478bd9Sstevel@tonic-gate 			if (make_reloc(ofl, NULL) == S_ERROR)
33507c478bd9Sstevel@tonic-gate 				return (S_ERROR);
33517c478bd9Sstevel@tonic-gate 		}
33527c478bd9Sstevel@tonic-gate 	}
33537c478bd9Sstevel@tonic-gate 
33547c478bd9Sstevel@tonic-gate 	/*
33557c478bd9Sstevel@tonic-gate 	 * The PLT relocations are always in their own section, and we try to
33567c478bd9Sstevel@tonic-gate 	 * keep them at the end of the PLT table.  We do this to keep the hot
33577c478bd9Sstevel@tonic-gate 	 * "data" PLT's at the head of the table nearer the .dynsym & .hash.
33587c478bd9Sstevel@tonic-gate 	 */
33597c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osplt && ofl->ofl_relocpltsz) {
33607c478bd9Sstevel@tonic-gate 		if (make_reloc(ofl, ofl->ofl_osplt) == S_ERROR)
33617c478bd9Sstevel@tonic-gate 			return (S_ERROR);
33627c478bd9Sstevel@tonic-gate 	}
33637c478bd9Sstevel@tonic-gate 
33647c478bd9Sstevel@tonic-gate 	/*
33657c478bd9Sstevel@tonic-gate 	 * Finally build the symbol and section header sections.
33667c478bd9Sstevel@tonic-gate 	 */
33677c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_DYNAMIC) {
33687c478bd9Sstevel@tonic-gate 		if (make_dynamic(ofl) == S_ERROR)
33697c478bd9Sstevel@tonic-gate 			return (S_ERROR);
3370635216b6SRod Evans 
33717c478bd9Sstevel@tonic-gate 		/*
3372635216b6SRod Evans 		 * A number of sections aren't necessary within a relocatable
3373635216b6SRod Evans 		 * object, even if -dy has been used.
33747c478bd9Sstevel@tonic-gate 		 */
33757c478bd9Sstevel@tonic-gate 		if (!(flags & FLG_OF_RELOBJ)) {
33767c478bd9Sstevel@tonic-gate 			if (make_hash(ofl) == S_ERROR)
33777c478bd9Sstevel@tonic-gate 				return (S_ERROR);
3378635216b6SRod Evans 			if (make_dynstr(ofl) == S_ERROR)
3379635216b6SRod Evans 				return (S_ERROR);
33807c478bd9Sstevel@tonic-gate 			if (make_dynsym(ofl) == S_ERROR)
33817c478bd9Sstevel@tonic-gate 				return (S_ERROR);
33827e16fca0SAli Bahrami 			if (ld_unwind_make_hdr(ofl) == S_ERROR)
33837c478bd9Sstevel@tonic-gate 				return (S_ERROR);
3384d579eb63Sab 			if (make_dynsort(ofl) == S_ERROR)
3385d579eb63Sab 				return (S_ERROR);
33867c478bd9Sstevel@tonic-gate 		}
33877c478bd9Sstevel@tonic-gate 	}
33887c478bd9Sstevel@tonic-gate 
33897c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) ||
33907c478bd9Sstevel@tonic-gate 	    ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) {
33917c478bd9Sstevel@tonic-gate 		/*
33927c478bd9Sstevel@tonic-gate 		 * Do we need to make a SHT_SYMTAB_SHNDX section
33937c478bd9Sstevel@tonic-gate 		 * for the dynsym.  If so - do it now.
33947c478bd9Sstevel@tonic-gate 		 */
33957c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynsym &&
33967c478bd9Sstevel@tonic-gate 		    ((ofl->ofl_shdrcnt + 3) >= SHN_LORESERVE)) {
33977c478bd9Sstevel@tonic-gate 			if (make_dynsym_shndx(ofl) == S_ERROR)
33987c478bd9Sstevel@tonic-gate 				return (S_ERROR);
33997c478bd9Sstevel@tonic-gate 		}
34007c478bd9Sstevel@tonic-gate 
34017c478bd9Sstevel@tonic-gate 		if (make_strtab(ofl) == S_ERROR)
34027c478bd9Sstevel@tonic-gate 			return (S_ERROR);
34037c478bd9Sstevel@tonic-gate 		if (make_symtab(ofl) == S_ERROR)
34047c478bd9Sstevel@tonic-gate 			return (S_ERROR);
34057c478bd9Sstevel@tonic-gate 	} else {
34067c478bd9Sstevel@tonic-gate 		/*
34077c478bd9Sstevel@tonic-gate 		 * Do we need to make a SHT_SYMTAB_SHNDX section
34087c478bd9Sstevel@tonic-gate 		 * for the dynsym.  If so - do it now.
34097c478bd9Sstevel@tonic-gate 		 */
34107c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynsym &&
34117c478bd9Sstevel@tonic-gate 		    ((ofl->ofl_shdrcnt + 1) >= SHN_LORESERVE)) {
34127c478bd9Sstevel@tonic-gate 			if (make_dynsym_shndx(ofl) == S_ERROR)
34137c478bd9Sstevel@tonic-gate 				return (S_ERROR);
34147c478bd9Sstevel@tonic-gate 		}
34157c478bd9Sstevel@tonic-gate 	}
34167c478bd9Sstevel@tonic-gate 
34177c478bd9Sstevel@tonic-gate 	if (make_shstrtab(ofl) == S_ERROR)
34187c478bd9Sstevel@tonic-gate 		return (S_ERROR);
34197c478bd9Sstevel@tonic-gate 
34207c478bd9Sstevel@tonic-gate 	/*
3421635216b6SRod Evans 	 * Now that we've created all output sections, adjust the size of the
3422635216b6SRod Evans 	 * SHT_SUNW_versym and SHT_SUNW_syminfo section, which are dependent on
3423635216b6SRod Evans 	 * the associated symbol table sizes.
34247c478bd9Sstevel@tonic-gate 	 */
34257c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osversym || ofl->ofl_ossyminfo) {
34267c478bd9Sstevel@tonic-gate 		ulong_t		cnt;
3427635216b6SRod Evans 		Is_desc		*isp;
342860758829Srie 		Os_desc		*osp;
34297c478bd9Sstevel@tonic-gate 
3430635216b6SRod Evans 		if (OFL_IS_STATIC_OBJ(ofl))
343160758829Srie 			osp = ofl->ofl_ossymtab;
3432635216b6SRod Evans 		else
343360758829Srie 			osp = ofl->ofl_osdynsym;
3434635216b6SRod Evans 
3435635216b6SRod Evans 		isp = ld_os_first_isdesc(osp);
3436635216b6SRod Evans 		cnt = (isp->is_shdr->sh_size / isp->is_shdr->sh_entsize);
3437635216b6SRod Evans 
3438635216b6SRod Evans 		if (ofl->ofl_osversym)
3439635216b6SRod Evans 			update_data_size(ofl->ofl_osversym, cnt);
3440635216b6SRod Evans 
3441635216b6SRod Evans 		if (ofl->ofl_ossyminfo)
3442635216b6SRod Evans 			update_data_size(ofl->ofl_ossyminfo, cnt);
34437c478bd9Sstevel@tonic-gate 	}
34447c478bd9Sstevel@tonic-gate 
344508278a5eSRod Evans 	/*
344608278a5eSRod Evans 	 * Now that we've created all output sections, adjust the size of the
344708278a5eSRod Evans 	 * SHT_SUNW_capinfo, which is dependent on the associated symbol table
344808278a5eSRod Evans 	 * size.
344908278a5eSRod Evans 	 */
345008278a5eSRod Evans 	if (ofl->ofl_oscapinfo) {
345108278a5eSRod Evans 		ulong_t	cnt;
345208278a5eSRod Evans 
345308278a5eSRod Evans 		/*
345408278a5eSRod Evans 		 * Symbol capabilities symbols are placed directly after the
345508278a5eSRod Evans 		 * STT_FILE symbol, section symbols, and any register symbols.
345608278a5eSRod Evans 		 * Effectively these are the first of any series of demoted
345708278a5eSRod Evans 		 * (scoped) symbols.
345808278a5eSRod Evans 		 */
345908278a5eSRod Evans 		if (OFL_IS_STATIC_OBJ(ofl))
346008278a5eSRod Evans 			cnt = SYMTAB_ALL_CNT(ofl);
346108278a5eSRod Evans 		else
346208278a5eSRod Evans 			cnt = DYNSYM_ALL_CNT(ofl);
346308278a5eSRod Evans 
346408278a5eSRod Evans 		update_data_size(ofl->ofl_oscapinfo, cnt);
346508278a5eSRod Evans 	}
34667c478bd9Sstevel@tonic-gate 	return (1);
34677c478bd9Sstevel@tonic-gate }
3468c1c6f601Srie 
3469c1c6f601Srie /*
3470c1c6f601Srie  * Build an additional data section - used to back OBJT symbol definitions
3471c1c6f601Srie  * added with a mapfile.
3472c1c6f601Srie  */
3473c1c6f601Srie Is_desc *
ld_make_data(Ofl_desc * ofl,size_t size)3474c1c6f601Srie ld_make_data(Ofl_desc *ofl, size_t size)
3475c1c6f601Srie {
3476c1c6f601Srie 	Shdr		*shdr;
3477c1c6f601Srie 	Elf_Data	*data;
3478c1c6f601Srie 	Is_desc		*isec;
3479c1c6f601Srie 
34809039eeafSab 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_DATA), 0,
34819039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
3482c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3483c1c6f601Srie 
34849039eeafSab 	data->d_size = size;
3485c1c6f601Srie 	shdr->sh_size = (Xword)size;
34869039eeafSab 	shdr->sh_flags |= SHF_WRITE;
3487c1c6f601Srie 
348857ef7aa9SRod Evans 	if (aplist_append(&ofl->ofl_mapdata, isec, AL_CNT_OFL_MAPSECS) == NULL)
3489c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3490c1c6f601Srie 
3491c1c6f601Srie 	return (isec);
3492c1c6f601Srie }
3493c1c6f601Srie 
3494c1c6f601Srie /*
3495c1c6f601Srie  * Build an additional text section - used to back FUNC symbol definitions
3496c1c6f601Srie  * added with a mapfile.
3497c1c6f601Srie  */
3498c1c6f601Srie Is_desc *
ld_make_text(Ofl_desc * ofl,size_t size)3499c1c6f601Srie ld_make_text(Ofl_desc *ofl, size_t size)
3500c1c6f601Srie {
3501c1c6f601Srie 	Shdr		*shdr;
3502c1c6f601Srie 	Elf_Data	*data;
3503c1c6f601Srie 	Is_desc		*isec;
3504c1c6f601Srie 
3505c1c6f601Srie 	/*
3506c1c6f601Srie 	 * Insure the size is sufficient to contain the minimum return
3507c1c6f601Srie 	 * instruction.
3508c1c6f601Srie 	 */
3509ba2be530Sab 	if (size < ld_targ.t_nf.nf_size)
3510ba2be530Sab 		size = ld_targ.t_nf.nf_size;
3511c1c6f601Srie 
35129039eeafSab 	if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_TEXT), 0,
35139039eeafSab 	    &isec, &shdr, &data) == S_ERROR)
3514c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3515c1c6f601Srie 
35169039eeafSab 	data->d_size = size;
3517c1c6f601Srie 	shdr->sh_size = (Xword)size;
35189039eeafSab 	shdr->sh_flags |= SHF_EXECINSTR;
3519c1c6f601Srie 
3520ba2be530Sab 	/*
3521ba2be530Sab 	 * Fill the buffer with the appropriate return instruction.
3522ba2be530Sab 	 * Note that there is no need to swap bytes on a non-native,
3523ba2be530Sab 	 * link, as the data being copied is given in bytes.
3524ba2be530Sab 	 */
352557ef7aa9SRod Evans 	if ((data->d_buf = libld_calloc(size, 1)) == NULL)
3526c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3527ba2be530Sab 	(void) memcpy(data->d_buf, ld_targ.t_nf.nf_template,
3528ba2be530Sab 	    ld_targ.t_nf.nf_size);
3529c1c6f601Srie 
35303c573fccSAli Bahrami 	/*
35313c573fccSAli Bahrami 	 * If size was larger than required, and the target supplies
35323c573fccSAli Bahrami 	 * a fill function, use it to fill the balance. If there is no
35333c573fccSAli Bahrami 	 * fill function, we accept the 0-fill supplied by libld_calloc().
35343c573fccSAli Bahrami 	 */
35353c573fccSAli Bahrami 	if ((ld_targ.t_ff.ff_execfill != NULL) && (size > ld_targ.t_nf.nf_size))
35363c573fccSAli Bahrami 		ld_targ.t_ff.ff_execfill(data->d_buf, ld_targ.t_nf.nf_size,
35373c573fccSAli Bahrami 		    size - ld_targ.t_nf.nf_size);
35383c573fccSAli Bahrami 
353957ef7aa9SRod Evans 	if (aplist_append(&ofl->ofl_maptext, isec, AL_CNT_OFL_MAPSECS) == NULL)
3540c1c6f601Srie 		return ((Is_desc *)S_ERROR);
3541c1c6f601Srie 
3542c1c6f601Srie 	return (isec);
3543c1c6f601Srie }
3544ef16f6b5SRichard Lowe 
3545ef16f6b5SRichard Lowe void
ld_comdat_validate(Ofl_desc * ofl,Ifl_desc * ifl)3546ef16f6b5SRichard Lowe ld_comdat_validate(Ofl_desc *ofl, Ifl_desc *ifl)
3547ef16f6b5SRichard Lowe {
3548ef16f6b5SRichard Lowe 	int i;
3549ef16f6b5SRichard Lowe 
3550ef16f6b5SRichard Lowe 	for (i = 0; i < ifl->ifl_shnum; i++) {
3551ef16f6b5SRichard Lowe 		Is_desc *isp = ifl->ifl_isdesc[i];
3552ef16f6b5SRichard Lowe 		int types = 0;
3553ef16f6b5SRichard Lowe 		char buf[1024] = "";
3554ef16f6b5SRichard Lowe 		Group_desc *gr = NULL;
3555ef16f6b5SRichard Lowe 
3556ef16f6b5SRichard Lowe 		if ((isp == NULL) || (isp->is_flags & FLG_IS_COMDAT) == 0)
3557ef16f6b5SRichard Lowe 			continue;
3558ef16f6b5SRichard Lowe 
3559ef16f6b5SRichard Lowe 		if (isp->is_shdr->sh_type == SHT_SUNW_COMDAT) {
3560ef16f6b5SRichard Lowe 			types++;
3561ef16f6b5SRichard Lowe 			(void) strlcpy(buf, MSG_ORIG(MSG_STR_SUNW_COMDAT),
3562ef16f6b5SRichard Lowe 			    sizeof (buf));
3563ef16f6b5SRichard Lowe 		}
3564ef16f6b5SRichard Lowe 
3565ef16f6b5SRichard Lowe 		if (strncmp(MSG_ORIG(MSG_SCN_GNU_LINKONCE), isp->is_name,
3566ef16f6b5SRichard Lowe 		    MSG_SCN_GNU_LINKONCE_SIZE) == 0) {
3567ef16f6b5SRichard Lowe 			types++;
3568ef16f6b5SRichard Lowe 			if (types > 1)
3569ef16f6b5SRichard Lowe 				(void) strlcat(buf, ", ", sizeof (buf));
3570ef16f6b5SRichard Lowe 			(void) strlcat(buf, MSG_ORIG(MSG_SCN_GNU_LINKONCE),
3571ef16f6b5SRichard Lowe 			    sizeof (buf));
3572ef16f6b5SRichard Lowe 		}
3573ef16f6b5SRichard Lowe 
3574ef16f6b5SRichard Lowe 		if ((isp->is_shdr->sh_flags & SHF_GROUP) &&
3575ef16f6b5SRichard Lowe 		    ((gr = ld_get_group(ofl, isp)) != NULL) &&
3576ef16f6b5SRichard Lowe 		    (gr->gd_data[0] & GRP_COMDAT)) {
3577ef16f6b5SRichard Lowe 			types++;
3578ef16f6b5SRichard Lowe 			if (types > 1)
3579ef16f6b5SRichard Lowe 				(void) strlcat(buf, ", ", sizeof (buf));
3580ef16f6b5SRichard Lowe 			(void) strlcat(buf, MSG_ORIG(MSG_STR_GROUP),
3581ef16f6b5SRichard Lowe 			    sizeof (buf));
3582ef16f6b5SRichard Lowe 		}
3583ef16f6b5SRichard Lowe 
3584ef16f6b5SRichard Lowe 		if (types > 1)
3585ef16f6b5SRichard Lowe 			ld_eprintf(ofl, ERR_FATAL,
3586ef16f6b5SRichard Lowe 			    MSG_INTL(MSG_SCN_MULTICOMDAT), ifl->ifl_name,
3587ef16f6b5SRichard Lowe 			    EC_WORD(isp->is_scnndx), isp->is_name, buf);
3588ef16f6b5SRichard Lowe 	}
3589ef16f6b5SRichard Lowe }
3590