xref: /illumos-gate/usr/src/cmd/sgs/libld/common/place.c (revision a48fdbef)
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  */
215aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
257c478bd9Sstevel@tonic-gate  *
261007fd6fSAli Bahrami  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
273fc1e289SBryan Cantrill  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
28*a48fdbefSBryan Cantrill  * Copyright 2024 Oxide Computer Company
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Map file parsing and input section to output segment mapping.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate #include	<stdio.h>
357c478bd9Sstevel@tonic-gate #include	<string.h>
365aefb655Srie #include	<debug.h>
377c478bd9Sstevel@tonic-gate #include	"msg.h"
387c478bd9Sstevel@tonic-gate #include	"_libld.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
4154d82594Sseizo  * Each time a section is placed, the function set_addralign()
425aefb655Srie  * is called.  This function performs:
435aefb655Srie  *
4469112eddSAli Bahrami  * -	if the section is from an external file, check if this is empty or not.
455aefb655Srie  *	If not, we know the segment this section will belong needs a program
465aefb655Srie  *	header. (Of course, the program is needed only if this section falls
475aefb655Srie  *	into a loadable segment.)
4869112eddSAli Bahrami  * -	compute the Least Common Multiplier for setting the segment alignment.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate static void
set_addralign(Ofl_desc * ofl,Os_desc * osp,Is_desc * isp)517c478bd9Sstevel@tonic-gate set_addralign(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp)
527c478bd9Sstevel@tonic-gate {
530e233487SRod Evans 	Shdr	*shdr = isp->is_shdr;
5454d82594Sseizo 
55d2ef9fe9Sab 	/* A discarded section has no influence on the output */
56d2ef9fe9Sab 	if (isp->is_flags & FLG_IS_DISCARD)
57d2ef9fe9Sab 		return;
58d2ef9fe9Sab 
5954d82594Sseizo 	/*
6054d82594Sseizo 	 * If this section has data or will be assigned data
6154d82594Sseizo 	 * later, mark this segment not-empty.
6254d82594Sseizo 	 */
6354d82594Sseizo 	if ((shdr->sh_size != 0) ||
6454d82594Sseizo 	    ((isp->is_flags & FLG_IS_EXTERNAL) == 0))
6554d82594Sseizo 		osp->os_sgdesc->sg_flags |= FLG_SG_PHREQ;
6654d82594Sseizo 
674899432aSab 	if ((ofl->ofl_dtflags_1 & DF_1_NOHDR) &&
687c478bd9Sstevel@tonic-gate 	    (osp->os_sgdesc->sg_phdr).p_type != PT_LOAD)
697c478bd9Sstevel@tonic-gate 		return;
707c478bd9Sstevel@tonic-gate 
7169112eddSAli Bahrami 	osp->os_sgdesc->sg_align =
7269112eddSAli Bahrami 	    ld_lcm(osp->os_sgdesc->sg_align, shdr->sh_addralign);
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
75cce0e03bSab /*
761dd9d86fSAli Bahrami  * Return the first input descriptor for a given output descriptor,
771dd9d86fSAli Bahrami  * or NULL if there are none.
781dd9d86fSAli Bahrami  */
791dd9d86fSAli Bahrami 
801dd9d86fSAli Bahrami Is_desc *
ld_os_first_isdesc(Os_desc * osp)811dd9d86fSAli Bahrami ld_os_first_isdesc(Os_desc *osp)
821dd9d86fSAli Bahrami {
831dd9d86fSAli Bahrami 	int i;
841dd9d86fSAli Bahrami 
851dd9d86fSAli Bahrami 	for (i = 0; i < OS_ISD_NUM; i++) {
861dd9d86fSAli Bahrami 		APlist *ap_isdesc = osp->os_isdescs[i];
871dd9d86fSAli Bahrami 
881dd9d86fSAli Bahrami 		if (aplist_nitems(ap_isdesc) > 0)
891dd9d86fSAli Bahrami 			return ((Is_desc *)ap_isdesc->apl_data[0]);
901dd9d86fSAli Bahrami 	}
911dd9d86fSAli Bahrami 
921dd9d86fSAli Bahrami 	return (NULL);
931dd9d86fSAli Bahrami }
941dd9d86fSAli Bahrami 
951dd9d86fSAli Bahrami /*
961dd9d86fSAli Bahrami  * Attach an input section to an output section
97cce0e03bSab  *
98cce0e03bSab  * entry:
99cce0e03bSab  *	ofl - File descriptor
100cce0e03bSab  *	osp - Output section descriptor
1011dd9d86fSAli Bahrami  *	isp - Input section descriptor
1021dd9d86fSAli Bahrami  *	mapfile_sort - True (1) if segment supports mapfile specified ordering
1031dd9d86fSAli Bahrami  *		of otherwise unordered input sections, and False (0) otherwise.
104cce0e03bSab  *
105cce0e03bSab  * exit:
1061dd9d86fSAli Bahrami  *	- The input section has been attached to the output section
107cce0e03bSab  *	- If the input section is a candidate for string table merging,
108cce0e03bSab  *		then it is appended to the output section's list of merge
109cce0e03bSab  *		candidates (os_mstridescs).
110cce0e03bSab  *
111cce0e03bSab  *	On success, returns True (1). On failure, False (0).
112cce0e03bSab  */
1131dd9d86fSAli Bahrami static int
os_attach_isp(Ofl_desc * ofl,Os_desc * osp,Is_desc * isp,int mapfile_sort)1141dd9d86fSAli Bahrami os_attach_isp(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp, int mapfile_sort)
115cce0e03bSab {
1161dd9d86fSAli Bahrami 	Aliste	init_arritems;
1171dd9d86fSAli Bahrami 	int	os_isdescs_idx, do_append = 1;
1181dd9d86fSAli Bahrami 
1191dd9d86fSAli Bahrami 	if ((isp->is_flags & FLG_IS_ORDERED) == 0) {
1201dd9d86fSAli Bahrami 		init_arritems = AL_CNT_OS_ISDESCS;
1211dd9d86fSAli Bahrami 		os_isdescs_idx = OS_ISD_DEFAULT;
1221dd9d86fSAli Bahrami 
1231dd9d86fSAli Bahrami 		/*
1241dd9d86fSAli Bahrami 		 * If section ordering was specified for an unordered section
1251dd9d86fSAli Bahrami 		 * via the mapfile, then search in the OS_ISD_DEFAULT list
1261dd9d86fSAli Bahrami 		 * and insert it in the specified position. Ordered sections
1271dd9d86fSAli Bahrami 		 * are placed in ascending order before unordered sections
1281dd9d86fSAli Bahrami 		 * (sections with an is_ordndx value of zero).
1291dd9d86fSAli Bahrami 		 *
1301dd9d86fSAli Bahrami 		 * If no mapfile ordering was specified, we append it in
1311dd9d86fSAli Bahrami 		 * the usual way below.
1321dd9d86fSAli Bahrami 		 */
1331dd9d86fSAli Bahrami 		if (mapfile_sort && (isp->is_ordndx > 0)) {
1341dd9d86fSAli Bahrami 			APlist *ap_isdesc = osp->os_isdescs[OS_ISD_DEFAULT];
1351dd9d86fSAli Bahrami 			Aliste	idx2;
1361dd9d86fSAli Bahrami 			Is_desc	*isp2;
1371dd9d86fSAli Bahrami 
1381dd9d86fSAli Bahrami 			for (APLIST_TRAVERSE(ap_isdesc, idx2, isp2)) {
1391dd9d86fSAli Bahrami 				if (isp2->is_ordndx &&
1401dd9d86fSAli Bahrami 				    (isp2->is_ordndx <= isp->is_ordndx))
1411dd9d86fSAli Bahrami 						continue;
1421dd9d86fSAli Bahrami 
1431dd9d86fSAli Bahrami 				if (aplist_insert(
1441dd9d86fSAli Bahrami 				    &osp->os_isdescs[OS_ISD_DEFAULT],
1451dd9d86fSAli Bahrami 				    isp, init_arritems, idx2) == NULL)
1461dd9d86fSAli Bahrami 					return (0);
1471dd9d86fSAli Bahrami 				do_append = 0;
1481dd9d86fSAli Bahrami 				break;
1491dd9d86fSAli Bahrami 			}
1501dd9d86fSAli Bahrami 		}
1511dd9d86fSAli Bahrami 	} else {		/* Ordered section (via shdr flags) */
1521dd9d86fSAli Bahrami 		Word shndx;
1531dd9d86fSAli Bahrami 
1541dd9d86fSAli Bahrami 		/* SHF_ORDERED uses sh_info, SHF_LINK_ORDERED uses sh_link */
1551dd9d86fSAli Bahrami 		shndx = (isp->is_shdr->sh_flags & SHF_ORDERED) ?
1561dd9d86fSAli Bahrami 		    isp->is_shdr->sh_info : isp->is_shdr->sh_link;
1571dd9d86fSAli Bahrami 
1581dd9d86fSAli Bahrami 		if (shndx == SHN_BEFORE) {
1591dd9d86fSAli Bahrami 			init_arritems = AL_CNT_OS_ISDESCS_BA;
1601dd9d86fSAli Bahrami 			os_isdescs_idx = OS_ISD_BEFORE;
1611dd9d86fSAli Bahrami 		} else if (shndx == SHN_AFTER) {
1621dd9d86fSAli Bahrami 			init_arritems = AL_CNT_OS_ISDESCS_BA;
1631dd9d86fSAli Bahrami 			os_isdescs_idx = OS_ISD_AFTER;
1641dd9d86fSAli Bahrami 		} else {
1651dd9d86fSAli Bahrami 			init_arritems = AL_CNT_OS_ISDESCS;
1661dd9d86fSAli Bahrami 			os_isdescs_idx = OS_ISD_ORDERED;
1671dd9d86fSAli Bahrami 		}
1681dd9d86fSAli Bahrami 	}
1691dd9d86fSAli Bahrami 
1701dd9d86fSAli Bahrami 	/*
1711dd9d86fSAli Bahrami 	 * If we didn't insert a section into the default list using
1721dd9d86fSAli Bahrami 	 * mapfile specified ordering above, then append the input
1731dd9d86fSAli Bahrami 	 * section to the appropriate list.
1741dd9d86fSAli Bahrami 	 */
1751dd9d86fSAli Bahrami 	if (do_append && aplist_append(&(osp->os_isdescs[os_isdescs_idx]),
1761dd9d86fSAli Bahrami 	    isp, init_arritems) == NULL)
177cce0e03bSab 		return (0);
1781dd9d86fSAli Bahrami 	isp->is_osdesc = osp;
179cce0e03bSab 
180cce0e03bSab 	/*
1811dd9d86fSAli Bahrami 	 * A section can be merged if the following are true:
1821dd9d86fSAli Bahrami 	 * -	The SHF_MERGE|SHF_STRINGS flags must be set
1831dd9d86fSAli Bahrami 	 * -	String table compression must not be disabled (-znocompstrtab)
1841dd9d86fSAli Bahrami 	 * -	Mapfile ordering must not have been used.
1851dd9d86fSAli Bahrami 	 * -	The section must not be ordered via section header flags.
1861dd9d86fSAli Bahrami 	 * -	It must not be the generated section being built to
1871dd9d86fSAli Bahrami 	 *	replace the sections on this list.
188cce0e03bSab 	 */
189cce0e03bSab 	if (((isp->is_shdr->sh_flags & (SHF_MERGE | SHF_STRINGS)) !=
190cce0e03bSab 	    (SHF_MERGE | SHF_STRINGS)) ||
191cce0e03bSab 	    ((ofl->ofl_flags1 & FLG_OF1_NCSTTAB) != 0) ||
1921dd9d86fSAli Bahrami 	    !do_append ||
1931dd9d86fSAli Bahrami 	    ((isp->is_flags & (FLG_IS_ORDERED | FLG_IS_GNSTRMRG)) != 0))
194cce0e03bSab 		return (1);
195cce0e03bSab 
196cce0e03bSab 	/*
197cce0e03bSab 	 * Skip sections with (sh_entsize > 1) or (sh_addralign > 1).
198cce0e03bSab 	 *
199cce0e03bSab 	 * sh_entsize:
200cce0e03bSab 	 *	We are currently only able to merge string tables containing
201cce0e03bSab 	 *	strings with 1-byte (char) characters. Support for wide
202cce0e03bSab 	 *	characters will require our string table compression code
203cce0e03bSab 	 *	to be extended to handle larger character sizes.
204cce0e03bSab 	 *
205cce0e03bSab 	 * sh_addralign:
206cce0e03bSab 	 *	Alignments greater than 1 would require our string table
207cce0e03bSab 	 *	compression code to insert null bytes to move each
208cce0e03bSab 	 *	string to the required alignment.
209cce0e03bSab 	 */
210cce0e03bSab 	if ((isp->is_shdr->sh_entsize > 1) ||
211cce0e03bSab 	    (isp->is_shdr->sh_addralign > 1)) {
212cce0e03bSab 		DBG_CALL(Dbg_sec_unsup_strmerge(ofl->ofl_lml, isp));
213cce0e03bSab 		return (1);
214cce0e03bSab 	}
215cce0e03bSab 
216cce0e03bSab 	if (aplist_append(&osp->os_mstrisdescs, isp,
217cce0e03bSab 	    AL_CNT_OS_MSTRISDESCS) == NULL)
218cce0e03bSab 		return (0);
219cce0e03bSab 
220cce0e03bSab 	/*
221cce0e03bSab 	 * The SHF_MERGE|SHF_STRINGS flags tell us that the program that
222cce0e03bSab 	 * created the section intended it to be mergeable. The
223cce0e03bSab 	 * FLG_IS_INSTRMRG flag says that we have done validity testing
224cce0e03bSab 	 * and decided that it is safe to act on that hint.
225cce0e03bSab 	 */
226cce0e03bSab 	isp->is_flags |= FLG_IS_INSTRMRG;
227cce0e03bSab 
228cce0e03bSab 	return (1);
229cce0e03bSab }
230cce0e03bSab 
2310e233487SRod Evans /*
2320e233487SRod Evans  * Determine whether this input COMDAT section already exists for the associated
2330e233487SRod Evans  * output section.  If so, then discard this input section.  Otherwise, this
2340e233487SRod Evans  * must be the first COMDAT section, thus it is kept for future comparisons.
2350e233487SRod Evans  */
2360e233487SRod Evans static uintptr_t
add_comdat(Ofl_desc * ofl,Os_desc * osp,Is_desc * isp)2370e233487SRod Evans add_comdat(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp)
2380e233487SRod Evans {
2396b3ba5bdSAli Bahrami 	Isd_node	isd, *isdp;
2406b3ba5bdSAli Bahrami 	avl_tree_t	*avlt;
2416b3ba5bdSAli Bahrami 	avl_index_t	where;
242ef16f6b5SRichard Lowe 	Group_desc	*gr;
243ef16f6b5SRichard Lowe 
244ef16f6b5SRichard Lowe 	/*
245ef16f6b5SRichard Lowe 	 * Sections to which COMDAT groups apply are FLG_IS_COMDAT but are
246ef16f6b5SRichard Lowe 	 * discarded separately by the group logic so should never be
247ef16f6b5SRichard Lowe 	 * discarded here.
248ef16f6b5SRichard Lowe 	 */
249ef16f6b5SRichard Lowe 	if ((isp->is_shdr->sh_flags & SHF_GROUP) &&
250ef16f6b5SRichard Lowe 	    ((gr = ld_get_group(ofl, isp)) != NULL) &&
251ef16f6b5SRichard Lowe 	    (gr->gd_data[0] & GRP_COMDAT))
252ef16f6b5SRichard Lowe 		return (1);
2530e233487SRod Evans 
2546b3ba5bdSAli Bahrami 	/*
2556b3ba5bdSAli Bahrami 	 * Create a COMDAT avl tree for this output section if required.
2566b3ba5bdSAli Bahrami 	 */
2576b3ba5bdSAli Bahrami 	if ((avlt = osp->os_comdats) == NULL) {
258fb12490aSRichard Lowe 		if ((avlt = libld_calloc(1, sizeof (avl_tree_t))) == NULL)
2596b3ba5bdSAli Bahrami 			return (S_ERROR);
2606b3ba5bdSAli Bahrami 		avl_create(avlt, isdavl_compare, sizeof (Isd_node),
2616b3ba5bdSAli Bahrami 		    SGSOFFSETOF(Isd_node, isd_avl));
2626b3ba5bdSAli Bahrami 		osp->os_comdats = avlt;
2636b3ba5bdSAli Bahrami 	}
264e64d0ff9SAli Bahrami 
265e64d0ff9SAli Bahrami 	/*
266e64d0ff9SAli Bahrami 	 * A standard COMDAT section uses the section name as search key.
267e64d0ff9SAli Bahrami 	 */
268e64d0ff9SAli Bahrami 	isd.isd_name = isp->is_name;
269e64d0ff9SAli Bahrami 	isd.isd_hash = sgs_str_hash(isd.isd_name);
2700e233487SRod Evans 
2716b3ba5bdSAli Bahrami 	if ((isdp = avl_find(avlt, &isd, &where)) != NULL) {
2720e233487SRod Evans 		isp->is_osdesc = osp;
2730e233487SRod Evans 
2740e233487SRod Evans 		/*
2750e233487SRod Evans 		 * If this section hasn't already been identified as discarded,
2760e233487SRod Evans 		 * generate a suitable diagnostic.
2770e233487SRod Evans 		 */
2780e233487SRod Evans 		if ((isp->is_flags & FLG_IS_DISCARD) == 0) {
2790e233487SRod Evans 			isp->is_flags |= FLG_IS_DISCARD;
2806b3ba5bdSAli Bahrami 			isp->is_comdatkeep = isdp->isd_isp;
2816b3ba5bdSAli Bahrami 			DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, isp,
2826b3ba5bdSAli Bahrami 			    isdp->isd_isp));
2830e233487SRod Evans 		}
2840e233487SRod Evans 
2850e233487SRod Evans 		/*
2860e233487SRod Evans 		 * A discarded section does not require assignment to an output
2870e233487SRod Evans 		 * section.  However, if relaxed relocations have been enabled
2880e233487SRod Evans 		 * (either from -z relaxreloc, or asserted with .gnu.linkonce
2890e233487SRod Evans 		 * processing), then this section must still be assigned to an
2900e233487SRod Evans 		 * output section so that the sloppy relocation logic will have
2910e233487SRod Evans 		 * the information necessary to do its work.
2920e233487SRod Evans 		 */
2936b3ba5bdSAli Bahrami 		return (0);
2940e233487SRod Evans 	}
2950e233487SRod Evans 
2960e233487SRod Evans 	/*
2970e233487SRod Evans 	 * This is a new COMDAT section - so keep it.
2980e233487SRod Evans 	 */
299fb12490aSRichard Lowe 	if ((isdp = libld_calloc(1, sizeof (Isd_node))) == NULL)
3000e233487SRod Evans 		return (S_ERROR);
3010e233487SRod Evans 
302e64d0ff9SAli Bahrami 	isdp->isd_name = isd.isd_name;
3036b3ba5bdSAli Bahrami 	isdp->isd_hash = isd.isd_hash;
3046b3ba5bdSAli Bahrami 	isdp->isd_isp = isp;
3056b3ba5bdSAli Bahrami 
3066b3ba5bdSAli Bahrami 	avl_insert(avlt, isdp, where);
3070e233487SRod Evans 	return (1);
3080e233487SRod Evans }
3090e233487SRod Evans 
3100e233487SRod Evans /*
3110e233487SRod Evans  * Determine whether a GNU group COMDAT section name follows the convention
3120e233487SRod Evans  *
3130e233487SRod Evans  *	section-name.symbol-name
3140e233487SRod Evans  *
3150e233487SRod Evans  * Each section within the input file is compared to see if the full section
3160e233487SRod Evans  * name matches the beginning of the COMDAT section, with a following '.'.
3170e233487SRod Evans  * A pointer to the symbol name, starting with the '.' is returned so that the
3180e233487SRod Evans  * caller can strip off the required section name.
3190e233487SRod Evans  */
3200e233487SRod Evans static char *
gnu_comdat_sym(Ifl_desc * ifl,Is_desc * gisp)3210e233487SRod Evans gnu_comdat_sym(Ifl_desc *ifl, Is_desc *gisp)
3220e233487SRod Evans {
3230e233487SRod Evans 	size_t	ndx;
3240e233487SRod Evans 
3250e233487SRod Evans 	for (ndx = 1; ndx < ifl->ifl_shnum; ndx++) {
3260e233487SRod Evans 		Is_desc	*isp;
3270e233487SRod Evans 		size_t	ssize;
3280e233487SRod Evans 
3290e233487SRod Evans 		if (((isp = ifl->ifl_isdesc[ndx]) == NULL) ||
3300e233487SRod Evans 		    (isp == gisp) || (isp->is_name == NULL))
3310e233487SRod Evans 			continue;
3320e233487SRod Evans 
3330e233487SRod Evans 		/*
3340e233487SRod Evans 		 * It's questionable whether this size should be cached in the
3350e233487SRod Evans 		 * Is_desc.  However, this seems an infrequent operation and
3360e233487SRod Evans 		 * adding Is_desc members can escalate memory usage for large
3370e233487SRod Evans 		 * link-edits.  For now, size the section name dynamically.
3380e233487SRod Evans 		 */
3390e233487SRod Evans 		ssize = strlen(isp->is_name);
34084f7afedSRichard Lowe 		if ((strncmp(isp->is_name, gisp->is_name, ssize) == 0) &&
3410e233487SRod Evans 		    (gisp->is_name[ssize] == '.'))
3420e233487SRod Evans 			return ((char *)&gisp->is_name[ssize]);
3430e233487SRod Evans 	}
3440e233487SRod Evans 	return (NULL);
3450e233487SRod Evans }
3460e233487SRod Evans 
3470e233487SRod Evans /*
3480e233487SRod Evans  * GNU .gnu.linkonce sections follow a naming convention that indicates the
3490e233487SRod Evans  * required association with an output section.  Determine whether this input
3500e233487SRod Evans  * section follows the convention, and if so return the appropriate output
3510e233487SRod Evans  * section name.
3520e233487SRod Evans  *
3530e233487SRod Evans  *	.gnu.linkonce.b.*    ->	.bss
3540e233487SRod Evans  *	.gnu.linkonce.d.*    ->	.data
3550e233487SRod Evans  *	.gnu.linkonce.l.*    ->	.ldata
3560e233487SRod Evans  *	.gnu.linkonce.lb.*   ->	.lbss
3570e233487SRod Evans  *	.gnu.linkonce.lr.*   ->	.lrodata
3580e233487SRod Evans  *	.gnu.linkonce.r.*    ->	.rodata
3590e233487SRod Evans  *	.gnu.linkonce.s.*    ->	.sdata
3600e233487SRod Evans  *	.gnu.linkonce.s2.*   ->	.sdata2
3610e233487SRod Evans  *	.gnu.linkonce.sb.*   ->	.sbss
3620e233487SRod Evans  *	.gnu.linkonce.sb2.*  ->	.sbss2
3630e233487SRod Evans  *	.gnu.linkonce.t.*    ->	.text
3640e233487SRod Evans  *	.gnu.linkonce.tb.*   ->	.tbss
3650e233487SRod Evans  *	.gnu.linkonce.td.*   ->	.tdata
3660e233487SRod Evans  *	.gnu.linkonce.wi.*   ->	.debug_info
3670e233487SRod Evans  */
3680e233487SRod Evans #define	NSTR_CH1(ch) (*(nstr + 1) == (ch))
3690e233487SRod Evans #define	NSTR_CH2(ch) (*(nstr + 2) == (ch))
3700e233487SRod Evans #define	NSTR_CH3(ch) (*(nstr + 3) == (ch))
3710e233487SRod Evans 
3720e233487SRod Evans static const char *
gnu_linkonce_sec(const char * ostr)3730e233487SRod Evans gnu_linkonce_sec(const char *ostr)
3740e233487SRod Evans {
3750e233487SRod Evans 	const char	*nstr = &ostr[MSG_SCN_GNU_LINKONCE_SIZE];
3760e233487SRod Evans 
3770e233487SRod Evans 	switch (*nstr) {
3780e233487SRod Evans 	case 'b':
3790e233487SRod Evans 		if (NSTR_CH1('.'))
3800e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_BSS));
3810e233487SRod Evans 		break;
3820e233487SRod Evans 	case 'd':
3830e233487SRod Evans 		if (NSTR_CH1('.'))
3840e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_DATA));
3850e233487SRod Evans 		break;
3860e233487SRod Evans 	case 'l':
3870e233487SRod Evans 		if (NSTR_CH1('.'))
3880e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_LDATA));
3890e233487SRod Evans 		else if (NSTR_CH1('b') && NSTR_CH2('.'))
3900e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_LBSS));
3910e233487SRod Evans 		else if (NSTR_CH1('r') && NSTR_CH2('.'))
3920e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_LRODATA));
3930e233487SRod Evans 		break;
3940e233487SRod Evans 	case 'r':
3950e233487SRod Evans 		if (NSTR_CH1('.'))
3960e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_RODATA));
3970e233487SRod Evans 		break;
3980e233487SRod Evans 	case 's':
3990e233487SRod Evans 		if (NSTR_CH1('.'))
4000e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_SDATA));
4010e233487SRod Evans 		else if (NSTR_CH1('2') && NSTR_CH2('.'))
4020e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_SDATA2));
4030e233487SRod Evans 		else if (NSTR_CH1('b') && NSTR_CH2('.'))
4040e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_SBSS));
4050e233487SRod Evans 		else if (NSTR_CH1('b') && NSTR_CH2('2') && NSTR_CH3('.'))
4060e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_SBSS2));
4070e233487SRod Evans 		break;
4080e233487SRod Evans 	case 't':
4090e233487SRod Evans 		if (NSTR_CH1('.'))
4100e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_TEXT));
4110e233487SRod Evans 		else if (NSTR_CH1('b') && NSTR_CH2('.'))
4120e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_TBSS));
4130e233487SRod Evans 		else if (NSTR_CH1('d') && NSTR_CH2('.'))
4140e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_TDATA));
4150e233487SRod Evans 		break;
4160e233487SRod Evans 	case 'w':
4170e233487SRod Evans 		if (NSTR_CH1('i') && NSTR_CH2('.'))
4180e233487SRod Evans 			return (MSG_ORIG(MSG_SCN_DEBUG_INFO));
4190e233487SRod Evans 		break;
4200e233487SRod Evans 	default:
4210e233487SRod Evans 		break;
4220e233487SRod Evans 	}
4230e233487SRod Evans 
4240e233487SRod Evans 	/*
4250e233487SRod Evans 	 * No special name match found.
4260e233487SRod Evans 	 */
4270e233487SRod Evans 	return (ostr);
4280e233487SRod Evans }
4290e233487SRod Evans #undef	NSTR_CH1
4300e233487SRod Evans #undef	NSTR_CH2
4310e233487SRod Evans #undef	NSTR_CH3
4320e233487SRod Evans 
433ce686298SRichard Lowe /*
434ce686298SRichard Lowe  * The GNU link-editor maps sections generated by the GNU compiler separately
435ce686298SRichard Lowe  * due to -ffunction-sections, -fdata-sections or for other reasons into the
436ce686298SRichard Lowe  * "normal" section represented.
437ce686298SRichard Lowe  *
438ce686298SRichard Lowe  * Sections are named .<main>.<symbol> where <main> is the usual section to
439ce686298SRichard Lowe  * which it should be mapped, and <symbol> is providing the unique name for
440ce686298SRichard Lowe  * the original section.  Both parts of the name may contain periods, in cases
441ce686298SRichard Lowe  * where the unique part of the name contains a '.' and/or the section it
442ce686298SRichard Lowe  * contributes to does (such as .data.rel.ro)
443ce686298SRichard Lowe  *
444ce686298SRichard Lowe  * .rodata.str* and .rodata.cst* are mapped to .rodata.
445ce686298SRichard Lowe  *
446ce686298SRichard Lowe  * As a further complication, the GNU link-editor may or may not merge
447ce686298SRichard Lowe  * .ctors.* and .dtors.* into init_array and fini_array, rather than ctors and
448ce686298SRichard Lowe  * dtors.  We do not implement this at this time.
449ce686298SRichard Lowe  *
450ce686298SRichard Lowe  * The GNU link editor may also arrange for sections with .local in their name
451ce686298SRichard Lowe  * to be mapped as above, but grouped together.  We do not implement this (and
452ce686298SRichard Lowe  * do not merge them at all, to make this clear)
453ce686298SRichard Lowe  *
454ce686298SRichard Lowe  * This table is processed in order.  Longer mappings must come first.
455ce686298SRichard Lowe  */
456ce686298SRichard Lowe static struct split_sec_mapping {
457ce686298SRichard Lowe 	char *leader;
458ce686298SRichard Lowe 	char *section;
459ce686298SRichard Lowe 	boolean_t precise;
460ce686298SRichard Lowe } split_sec_mapping[] = {
461ce686298SRichard Lowe 	{ ".bss.",			".bss",			B_FALSE },
462ce686298SRichard Lowe 	{ ".ctors.",			".ctors",		B_FALSE },
463ce686298SRichard Lowe 	{ ".data.rel.local.",		".data.rel.local",	B_FALSE },
464ce686298SRichard Lowe 	{ ".data.rel.local",		".data.rel.local",	B_TRUE },
465ce686298SRichard Lowe 	{ ".data.rel.ro.local.",	".data.rel.ro",		B_FALSE },
466ce686298SRichard Lowe 	{ ".data.rel.ro.",		".data.rel.ro",		B_FALSE },
467ce686298SRichard Lowe 	{ ".data.rel.ro",		".data.rel.ro",		B_TRUE },
468ce686298SRichard Lowe 	{ ".data.rel.",			".data.rel",		B_FALSE },
469ce686298SRichard Lowe 	{ ".data.rel",			".data.rel",		B_TRUE },
470ce686298SRichard Lowe 	{ ".data.",			".data",		B_FALSE },
471ce686298SRichard Lowe 	{ ".dtors.",			".dtors",		B_FALSE },
472ce686298SRichard Lowe 	{ ".fini_array.",		".fini_array",		B_FALSE },
473ce686298SRichard Lowe 	{ ".init_array.",		".init_array",		B_FALSE },
474ce686298SRichard Lowe 	{ ".lbss.",			".lbss",		B_FALSE },
475ce686298SRichard Lowe 	{ ".ldata.",			".ldata",		B_FALSE },
476ce686298SRichard Lowe 	{ ".lrodata.",			".lrodata",		B_FALSE },
477ce686298SRichard Lowe 	/* This intentionally applies to .rodata.cstN and .rodata.strN, too */
478ce686298SRichard Lowe 	{ ".rodata.",			".rodata",		B_FALSE },
479ce686298SRichard Lowe 	{ ".sbss2.",			".sbss2",		B_FALSE },
480ce686298SRichard Lowe 	{ ".sbss.",			".sbss",		B_FALSE },
481ce686298SRichard Lowe 	{ ".sdata2.",			".sdata2",		B_FALSE },
482ce686298SRichard Lowe 	{ ".sdata.",			".sdata",		B_FALSE },
483ce686298SRichard Lowe 	{ ".tbss.",			".tbss",		B_FALSE },
484ce686298SRichard Lowe 	{ ".tdata.",			".tdata",		B_FALSE },
485ce686298SRichard Lowe 	{ ".text.",			".text",		B_FALSE },
486ce686298SRichard Lowe 	{ NULL,				NULL,			B_FALSE }
487ce686298SRichard Lowe };
488ce686298SRichard Lowe 
489ce686298SRichard Lowe static const char *
gnu_split_sec(const char * ostr)490ce686298SRichard Lowe gnu_split_sec(const char *ostr)
491ce686298SRichard Lowe {
492ce686298SRichard Lowe 	struct split_sec_mapping *mp;
493ce686298SRichard Lowe 
494ce686298SRichard Lowe 	for (mp = split_sec_mapping; mp->leader != NULL; mp++) {
495ce686298SRichard Lowe 		if (mp->precise) {
496ce686298SRichard Lowe 			if (strcmp(ostr, mp->leader) == 0)
497ce686298SRichard Lowe 				return (mp->section);
498ce686298SRichard Lowe 		} else if (strncmp(ostr, mp->leader, strlen(mp->leader)) == 0) {
499ce686298SRichard Lowe 			return (mp->section);
500ce686298SRichard Lowe 		}
501ce686298SRichard Lowe 	}
502ce686298SRichard Lowe 
503ce686298SRichard Lowe 	return (ostr);
504ce686298SRichard Lowe }
50569112eddSAli Bahrami 
50669112eddSAli Bahrami /*
50769112eddSAli Bahrami  * Initialize a path info buffer for use with ld_place_section().
50869112eddSAli Bahrami  *
50969112eddSAli Bahrami  * entry:
51069112eddSAli Bahrami  *	ofl - Output descriptor
51169112eddSAli Bahrami  *	ifl - Descriptor for input file, or NULL if there is none.
51269112eddSAli Bahrami  *	info - Address of buffer to be initialized.
51369112eddSAli Bahrami  *
51469112eddSAli Bahrami  * exit:
51569112eddSAli Bahrami  *	If this is an input file, and if the entrance criteria list
51669112eddSAli Bahrami  *	contains at least one criteria that has a non-empty file string
51769112eddSAli Bahrami  *	match list (ec_files), then the block pointed at by info is
51869112eddSAli Bahrami  *	initialized, and info is returned.
51969112eddSAli Bahrami  *
52069112eddSAli Bahrami  *	If there is no input file, and/or no entrance criteria containing
52169112eddSAli Bahrami  *	a non-empty ec_files list, then NULL is returned. This is not
52269112eddSAli Bahrami  *	an error --- the NULL is simply an optimization, understood by
52369112eddSAli Bahrami  *	ld_place_path(), that allows it to skip unnecessary work.
52469112eddSAli Bahrami  */
52569112eddSAli Bahrami Place_path_info *
ld_place_path_info_init(Ofl_desc * ofl,Ifl_desc * ifl,Place_path_info * info)52669112eddSAli Bahrami ld_place_path_info_init(Ofl_desc *ofl, Ifl_desc *ifl, Place_path_info *info)
52769112eddSAli Bahrami {
52869112eddSAli Bahrami 	/*
52969112eddSAli Bahrami 	 * Return NULL if there is no input file (internally generated section)
53069112eddSAli Bahrami 	 * or if the entrance criteria list does not contain any items that will
53169112eddSAli Bahrami 	 * need to be compared to the path (all the ec_files lists are empty).
53269112eddSAli Bahrami 	 */
53369112eddSAli Bahrami 	if ((ifl == NULL) || !(ofl->ofl_flags & FLG_OF_EC_FILES))
53469112eddSAli Bahrami 		return (NULL);
53569112eddSAli Bahrami 
53669112eddSAli Bahrami 	info->ppi_path = ifl->ifl_name;
53769112eddSAli Bahrami 	info->ppi_path_len = strlen(info->ppi_path);
53869112eddSAli Bahrami 	info->ppi_isar = (ifl->ifl_flags & FLG_IF_EXTRACT) != 0;
53969112eddSAli Bahrami 
54069112eddSAli Bahrami 	/*
54169112eddSAli Bahrami 	 * The basename is the final segment of the path, equivalent to
54269112eddSAli Bahrami 	 * the path itself if there are no '/' delimiters.
54369112eddSAli Bahrami 	 */
54469112eddSAli Bahrami 	info->ppi_bname = strrchr(info->ppi_path, '/');
54569112eddSAli Bahrami 	if (info->ppi_bname == NULL)
54669112eddSAli Bahrami 		info->ppi_bname = info->ppi_path;
54769112eddSAli Bahrami 	else
54869112eddSAli Bahrami 		info->ppi_bname++;	/* Skip leading '/' */
54969112eddSAli Bahrami 	info->ppi_bname_len =
55069112eddSAli Bahrami 	    info->ppi_path_len - (info->ppi_bname - info->ppi_path);
55169112eddSAli Bahrami 
55269112eddSAli Bahrami 	/*
55369112eddSAli Bahrami 	 * For an archive, the object name is the member name, which is
55469112eddSAli Bahrami 	 * enclosed in () at the end of the name string. Otherwise, it is
55569112eddSAli Bahrami 	 * the same as the basename.
55669112eddSAli Bahrami 	 */
55769112eddSAli Bahrami 	if (info->ppi_isar) {
55869112eddSAli Bahrami 		info->ppi_oname = strrchr(info->ppi_bname, '(');
55969112eddSAli Bahrami 		/* There must be an archive member suffix delimited by parens */
56069112eddSAli Bahrami 		assert((info->ppi_bname[info->ppi_bname_len - 1] == ')') &&
56169112eddSAli Bahrami 		    (info->ppi_oname != NULL));
56269112eddSAli Bahrami 		info->ppi_oname++;	/* skip leading '(' */
56369112eddSAli Bahrami 		info->ppi_oname_len = info->ppi_bname_len -
56469112eddSAli Bahrami 		    (info->ppi_oname - info->ppi_bname + 1);
56569112eddSAli Bahrami 	} else {
56669112eddSAli Bahrami 		info->ppi_oname = info->ppi_bname;
56769112eddSAli Bahrami 		info->ppi_oname_len = info->ppi_bname_len;
56869112eddSAli Bahrami 	}
56969112eddSAli Bahrami 
57069112eddSAli Bahrami 	return (info);
57169112eddSAli Bahrami }
57269112eddSAli Bahrami 
57369112eddSAli Bahrami /*
57469112eddSAli Bahrami  * Compare an input section path to the file comparison list the given
57569112eddSAli Bahrami  * entrance criteria.
57669112eddSAli Bahrami  *
57769112eddSAli Bahrami  * entry:
57869112eddSAli Bahrami  *	path_info - A non-NULL Place_path_info block for the file
57969112eddSAli Bahrami  *		containing the input section, initialized by
58069112eddSAli Bahrami  *		ld_place_path_info_init()
58169112eddSAli Bahrami  *	enp - Entrance criteria with a non-empty ec_files list of file
58269112eddSAli Bahrami  *		comparisons to be carried out.
58369112eddSAli Bahrami  *
58469112eddSAli Bahrami  * exit:
58569112eddSAli Bahrami  *	Return TRUE if a match is seen, and FALSE otherwise.
58669112eddSAli Bahrami  */
58769112eddSAli Bahrami static Boolean
eval_ec_files(Place_path_info * path_info,Ent_desc * enp)58869112eddSAli Bahrami eval_ec_files(Place_path_info *path_info, Ent_desc *enp)
58969112eddSAli Bahrami {
59069112eddSAli Bahrami 	Aliste		idx;
59169112eddSAli Bahrami 	Ent_desc_file	*edfp;
59269112eddSAli Bahrami 	size_t		cmp_len;
59369112eddSAli Bahrami 	const char	*cmp_str;
59469112eddSAli Bahrami 
59569112eddSAli Bahrami 	for (ALIST_TRAVERSE(enp->ec_files, idx, edfp)) {
59669112eddSAli Bahrami 		Word	type = edfp->edf_flags & TYP_ECF_MASK;
59769112eddSAli Bahrami 
59869112eddSAli Bahrami 		/*
59969112eddSAli Bahrami 		 * Determine the starting character, and # of characters,
60069112eddSAli Bahrami 		 * from the file path to compare against this entrance criteria
60169112eddSAli Bahrami 		 * file string.
60269112eddSAli Bahrami 		 */
60369112eddSAli Bahrami 		if (type == TYP_ECF_OBJNAME) {
60469112eddSAli Bahrami 			cmp_str = path_info->ppi_oname;
60569112eddSAli Bahrami 			cmp_len = path_info->ppi_oname_len;
60669112eddSAli Bahrami 		} else {
60769112eddSAli Bahrami 			int ar_stat_diff = path_info->ppi_isar !=
60869112eddSAli Bahrami 			    ((edfp->edf_flags & FLG_ECF_ARMEMBER) != 0);
60969112eddSAli Bahrami 
61069112eddSAli Bahrami 			/*
61169112eddSAli Bahrami 			 * If the entrance criteria specifies an archive member
61269112eddSAli Bahrami 			 * and the file does not, then there can be no match.
61369112eddSAli Bahrami 			 */
61469112eddSAli Bahrami 
61569112eddSAli Bahrami 			if (ar_stat_diff && !path_info->ppi_isar)
61669112eddSAli Bahrami 				continue;
61769112eddSAli Bahrami 
61869112eddSAli Bahrami 			if (type == TYP_ECF_PATH) {
61969112eddSAli Bahrami 				cmp_str = path_info->ppi_path;
62069112eddSAli Bahrami 				cmp_len = path_info->ppi_path_len;
62169112eddSAli Bahrami 			} else {	/* TYP_ECF_BASENAME */
62269112eddSAli Bahrami 				cmp_str = path_info->ppi_bname;
62369112eddSAli Bahrami 				cmp_len = path_info->ppi_bname_len;
62469112eddSAli Bahrami 			}
62569112eddSAli Bahrami 
62669112eddSAli Bahrami 			/*
62769112eddSAli Bahrami 			 * If the entrance criteria does not specify an archive
62869112eddSAli Bahrami 			 * member and the file does, then a match just requires
62969112eddSAli Bahrami 			 * the paths (without the archive member) to match.
63069112eddSAli Bahrami 			 * Reduce the length to not include the ar member or
63169112eddSAli Bahrami 			 * the '(' that precedes it.
63269112eddSAli Bahrami 			 */
63369112eddSAli Bahrami 			if (ar_stat_diff && path_info->ppi_isar)
63469112eddSAli Bahrami 				cmp_len = path_info->ppi_oname - cmp_str - 1;
63569112eddSAli Bahrami 		}
63669112eddSAli Bahrami 
63769112eddSAli Bahrami 		/*
63869112eddSAli Bahrami 		 * Compare the resulting string to the one from the
63969112eddSAli Bahrami 		 * entrance criteria.
64069112eddSAli Bahrami 		 */
64169112eddSAli Bahrami 		if ((cmp_len == edfp->edf_name_len) &&
64269112eddSAli Bahrami 		    (strncmp(edfp->edf_name, cmp_str, cmp_len) == 0))
64369112eddSAli Bahrami 			return (TRUE);
64469112eddSAli Bahrami 	}
64569112eddSAli Bahrami 
64669112eddSAli Bahrami 	return (FALSE);
64769112eddSAli Bahrami }
64869112eddSAli Bahrami 
649d444b03eSAli Bahrami /*
650d444b03eSAli Bahrami  * Replace the section header for the given input section with a new section
651d444b03eSAli Bahrami  * header of the specified type. All values in the replacement header other
652d444b03eSAli Bahrami  * than the type retain their previous values.
653d444b03eSAli Bahrami  *
654d444b03eSAli Bahrami  * entry:
655d444b03eSAli Bahrami  *	isp - Input section to replace
656d444b03eSAli Bahrami  *	sh_type - New section type to apply
657d444b03eSAli Bahrami  *
658d444b03eSAli Bahrami  * exit:
659d444b03eSAli Bahrami  *	Returns the pointer to the new section header on success, and
660d444b03eSAli Bahrami  *	NULL for failure.
661d444b03eSAli Bahrami  */
662d444b03eSAli Bahrami static Shdr *
isp_convert_type(Is_desc * isp,Word sh_type)663d444b03eSAli Bahrami isp_convert_type(Is_desc *isp, Word sh_type)
664d444b03eSAli Bahrami {
665d444b03eSAli Bahrami 	Shdr	*shdr;
666d444b03eSAli Bahrami 
667d444b03eSAli Bahrami 	if ((shdr = libld_malloc(sizeof (Shdr))) == NULL)
668d444b03eSAli Bahrami 		return (NULL);
669d444b03eSAli Bahrami 	*shdr = *isp->is_shdr;
670d444b03eSAli Bahrami 	isp->is_shdr = shdr;
671d444b03eSAli Bahrami 	shdr->sh_type = sh_type;
672d444b03eSAli Bahrami 	return (shdr);
673d444b03eSAli Bahrami }
674d444b03eSAli Bahrami 
675d444b03eSAli Bahrami /*
676d444b03eSAli Bahrami  * Issue a fatal warning for the given .eh_frame section, which
677d444b03eSAli Bahrami  * cannot be merged with the existing .eh_frame output section.
678d444b03eSAli Bahrami  */
679d444b03eSAli Bahrami static void
eh_frame_muldef(Ofl_desc * ofl,Is_desc * isp)680d444b03eSAli Bahrami eh_frame_muldef(Ofl_desc *ofl, Is_desc *isp)
681d444b03eSAli Bahrami {
682d444b03eSAli Bahrami 	Sg_desc	*sgp;
683d444b03eSAli Bahrami 	Is_desc *isp1;
684d444b03eSAli Bahrami 	Os_desc	*osp;
685d444b03eSAli Bahrami 	Aliste	idx1, idx2, idx3;
686d444b03eSAli Bahrami 
687d444b03eSAli Bahrami 	/*
688d444b03eSAli Bahrami 	 * Locate the .eh_frame output section, and use the first section
689d444b03eSAli Bahrami 	 * assigned to it in the error message. The user can then compare
690d444b03eSAli Bahrami 	 * the two sections to determine what attribute prevented the merge.
691d444b03eSAli Bahrami 	 */
692d444b03eSAli Bahrami 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
693d444b03eSAli Bahrami 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
694d444b03eSAli Bahrami 			if ((osp->os_flags & FLG_OS_EHFRAME) == 0)
695d444b03eSAli Bahrami 				continue;
696d444b03eSAli Bahrami 
697d444b03eSAli Bahrami 			for (idx3 = 0; idx3 < OS_ISD_NUM; idx3++) {
698d444b03eSAli Bahrami 				APlist *lst = osp->os_isdescs[idx3];
699d444b03eSAli Bahrami 
700d444b03eSAli Bahrami 				if (aplist_nitems(lst) == 0)
701d444b03eSAli Bahrami 					continue;
702d444b03eSAli Bahrami 
703d444b03eSAli Bahrami 				isp1 = lst->apl_data[0];
7041007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_FATAL,
705d444b03eSAli Bahrami 				    MSG_INTL(MSG_UPD_MULEHFRAME),
706d444b03eSAli Bahrami 				    isp1->is_file->ifl_name,
707d444b03eSAli Bahrami 				    EC_WORD(isp1->is_scnndx), isp1->is_name,
708d444b03eSAli Bahrami 				    isp->is_file->ifl_name,
709d444b03eSAli Bahrami 				    EC_WORD(isp->is_scnndx), isp->is_name);
710d444b03eSAli Bahrami 				return;
711d444b03eSAli Bahrami 			}
712d444b03eSAli Bahrami 		}
713d444b03eSAli Bahrami 	}
714d444b03eSAli Bahrami }
715d444b03eSAli Bahrami 
716*a48fdbefSBryan Cantrill /*
717*a48fdbefSBryan Cantrill  * Hash the specified Os_desc on the specified segment descriptor, allocating
718*a48fdbefSBryan Cantrill  * and resizing the hash table as necessary.  (We only hash when the number of
719*a48fdbefSBryan Cantrill  * output secctions exceeds a minimum, below which we deem it not worth it to
720*a48fdbefSBryan Cantrill  * have the auxiliary structure.)
721*a48fdbefSBryan Cantrill  */
722*a48fdbefSBryan Cantrill static void
os_desc_hash(Sg_desc * sgp,Os_desc * osp)723*a48fdbefSBryan Cantrill os_desc_hash(Sg_desc *sgp, Os_desc *osp)
724*a48fdbefSBryan Cantrill {
725*a48fdbefSBryan Cantrill 	const size_t min_size = 31;
726*a48fdbefSBryan Cantrill 	Aliste nitems, idx, idx1;
727*a48fdbefSBryan Cantrill 	os_desc_hash_t *hash;
728*a48fdbefSBryan Cantrill 	size_t new_size;
729*a48fdbefSBryan Cantrill 
730*a48fdbefSBryan Cantrill 	if ((nitems = aplist_nitems(sgp->sg_osdescs)) < min_size) {
731*a48fdbefSBryan Cantrill 		return;
732*a48fdbefSBryan Cantrill 	}
733*a48fdbefSBryan Cantrill 
734*a48fdbefSBryan Cantrill 	if ((hash = sgp->sg_hashtab) != NULL && hash->osh_hashtab != NULL) {
735*a48fdbefSBryan Cantrill 		if (nitems < hash->osh_size) {
736*a48fdbefSBryan Cantrill 			/*
737*a48fdbefSBryan Cantrill 			 * We have a hash table, and it's not undersized -- just
738*a48fdbefSBryan Cantrill 			 * add our newest element.
739*a48fdbefSBryan Cantrill 			 */
740*a48fdbefSBryan Cantrill 			idx = osp->os_namehash % hash->osh_size;
741*a48fdbefSBryan Cantrill 			osp->os_hashnext = hash->osh_hashtab[idx];
742*a48fdbefSBryan Cantrill 			hash->osh_hashtab[idx] = osp;
743*a48fdbefSBryan Cantrill 			return;
744*a48fdbefSBryan Cantrill 		}
745*a48fdbefSBryan Cantrill 
746*a48fdbefSBryan Cantrill 		/*
747*a48fdbefSBryan Cantrill 		 * We have a hash table, but it's full:  we are going to want
748*a48fdbefSBryan Cantrill 		 * to double our size and rehash all of the output section
749*a48fdbefSBryan Cantrill 		 * descriptions.  First, free our old hash table...
750*a48fdbefSBryan Cantrill 		 */
751*a48fdbefSBryan Cantrill 		libld_free(hash->osh_hashtab);
752*a48fdbefSBryan Cantrill 		new_size = (hash->osh_size << 1) - 1;
753*a48fdbefSBryan Cantrill 	} else {
754*a48fdbefSBryan Cantrill 		/*
755*a48fdbefSBryan Cantrill 		 * We either don't have a hash structure or we don't have a
756*a48fdbefSBryan Cantrill 		 * hash table (the partial construction of which may be due to
757*a48fdbefSBryan Cantrill 		 * a previous allocation failure).  Determine what we want
758*a48fdbefSBryan Cantrill 		 * our new size to be, and allocate our hash structure as
759*a48fdbefSBryan Cantrill 		 * needed.
760*a48fdbefSBryan Cantrill 		 */
761*a48fdbefSBryan Cantrill 		new_size = min_size;
762*a48fdbefSBryan Cantrill 
763*a48fdbefSBryan Cantrill 		while (new_size <= nitems)
764*a48fdbefSBryan Cantrill 			new_size = (new_size << 1) - 1;
765*a48fdbefSBryan Cantrill 
766*a48fdbefSBryan Cantrill 		if (hash == NULL) {
767*a48fdbefSBryan Cantrill 			hash = libld_calloc(1, sizeof (os_desc_hash_t));
768*a48fdbefSBryan Cantrill 
769*a48fdbefSBryan Cantrill 			if ((sgp->sg_hashtab = hash) == NULL)
770*a48fdbefSBryan Cantrill 				return;
771*a48fdbefSBryan Cantrill 		}
772*a48fdbefSBryan Cantrill 	}
773*a48fdbefSBryan Cantrill 
774*a48fdbefSBryan Cantrill 	if ((hash->osh_hashtab =
775*a48fdbefSBryan Cantrill 	    libld_calloc(new_size, sizeof (void *))) == NULL) {
776*a48fdbefSBryan Cantrill 		return;
777*a48fdbefSBryan Cantrill 	}
778*a48fdbefSBryan Cantrill 
779*a48fdbefSBryan Cantrill 	/*
780*a48fdbefSBryan Cantrill 	 * Set our new size, and scan everything and hash it in.
781*a48fdbefSBryan Cantrill 	 */
782*a48fdbefSBryan Cantrill 	hash->osh_size = new_size;
783*a48fdbefSBryan Cantrill 
784*a48fdbefSBryan Cantrill 	for (APLIST_TRAVERSE(sgp->sg_osdescs, idx1, osp)) {
785*a48fdbefSBryan Cantrill 		idx = osp->os_namehash % hash->osh_size;
786*a48fdbefSBryan Cantrill 		osp->os_hashnext = hash->osh_hashtab[idx];
787*a48fdbefSBryan Cantrill 		hash->osh_hashtab[idx] = osp;
788*a48fdbefSBryan Cantrill 	}
789*a48fdbefSBryan Cantrill }
790*a48fdbefSBryan Cantrill 
7917c478bd9Sstevel@tonic-gate /*
7921dd9d86fSAli Bahrami  * Place a section into the appropriate segment and output section.
7931dd9d86fSAli Bahrami  *
7941dd9d86fSAli Bahrami  * entry:
7951dd9d86fSAli Bahrami  *	ofl - File descriptor
7961dd9d86fSAli Bahrami  *	isp - Input section descriptor of section to be placed.
79769112eddSAli Bahrami  *	path_info - NULL, or pointer to Place_path_info buffer initialized
79869112eddSAli Bahrami  *		by ld_place_path_info_init() for the file associated to isp,
79969112eddSAli Bahrami  *		for use in processing entrance criteria with non-empty
80069112eddSAli Bahrami  *		file matching string list (ec_files)
8011dd9d86fSAli Bahrami  *	ident - Section identifier, used to order sections relative to
8021dd9d86fSAli Bahrami  *		others within the output segment.
8031dd9d86fSAli Bahrami  *	alt_os_name - If non-NULL, the name of the output section to place
8041dd9d86fSAli Bahrami  *		isp into. If NULL, input sections go to an output section
8051dd9d86fSAli Bahrami  *		with the same name as the input section.
8067c478bd9Sstevel@tonic-gate  */
8077c478bd9Sstevel@tonic-gate Os_desc *
ld_place_section(Ofl_desc * ofl,Is_desc * isp,Place_path_info * path_info,int ident,const char * alt_os_name)80869112eddSAli Bahrami ld_place_section(Ofl_desc *ofl, Is_desc *isp, Place_path_info *path_info,
80969112eddSAli Bahrami     int ident, const char *alt_os_name)
8107c478bd9Sstevel@tonic-gate {
8110e233487SRod Evans 	Ent_desc	*enp;
8120e233487SRod Evans 	Sg_desc		*sgp;
813cce0e03bSab 	Os_desc		*osp;
81457ef7aa9SRod Evans 	Aliste		idx1, iidx;
815cc7efc4fSrie 	int		os_ndx;
8160e233487SRod Evans 	Shdr		*shdr = isp->is_shdr;
8177c478bd9Sstevel@tonic-gate 	Xword		shflagmask, shflags = shdr->sh_flags;
8180e233487SRod Evans 	Ifl_desc	*ifl = isp->is_file;
8190e233487SRod Evans 	char		*oname, *sname;
8200e233487SRod Evans 	uint_t		onamehash;
821d444b03eSAli Bahrami 	Boolean		is_ehframe = (isp->is_flags & FLG_IS_EHFRAME) != 0;
822*a48fdbefSBryan Cantrill 	Boolean		linear_scan = TRUE;
823*a48fdbefSBryan Cantrill 	os_desc_hash_t	*hash;
8247c478bd9Sstevel@tonic-gate 
8250bc07c75Srie 	/*
8260bc07c75Srie 	 * Define any sections that must be thought of as referenced.  These
82708278a5eSRod Evans 	 * sections may not be referenced externally in a manner ld(1) can
8280bc07c75Srie 	 * discover, but they must be retained (ie. not removed by -zignore).
8290bc07c75Srie 	 */
8300bc07c75Srie 	static const Msg RefSecs[] = {
8310bc07c75Srie 		MSG_SCN_INIT,		/* MSG_ORIG(MSG_SCN_INIT) */
8320bc07c75Srie 		MSG_SCN_FINI,		/* MSG_ORIG(MSG_SCN_FINI) */
8330bc07c75Srie 		MSG_SCN_EX_RANGES,	/* MSG_ORIG(MSG_SCN_EX_RANGES) */
8340bc07c75Srie 		MSG_SCN_EX_SHARED,	/* MSG_ORIG(MSG_SCN_EX_SHARED) */
8350bc07c75Srie 		MSG_SCN_CTORS,		/* MSG_ORIG(MSG_SCN_CTORS) */
8360bc07c75Srie 		MSG_SCN_DTORS,		/* MSG_ORIG(MSG_SCN_DTORS) */
8370bc07c75Srie 		MSG_SCN_EHFRAME,	/* MSG_ORIG(MSG_SCN_EHFRAME) */
8380bc07c75Srie 		MSG_SCN_EHFRAME_HDR,	/* MSG_ORIG(MSG_SCN_EHFRAME_HDR) */
8390bc07c75Srie 		MSG_SCN_JCR,		/* MSG_ORIG(MSG_SCN_JCR) */
840a0fb1590SRichard Lowe 		MSG_SCN_INITARRAY,	/* MSG_ORIG(MSG_SCN_INITARRAY) */
841a0fb1590SRichard Lowe 		MSG_SCN_FINIARRAY,	/* MSG_ORIG(MSG_SCN_FINIARRAY) */
842a0fb1590SRichard Lowe 		MSG_SCN_PREINITARRAY,	/* MSG_ORIG(MSG_SCN_PREINITARRAY) */
8430bc07c75Srie 		0
8440bc07c75Srie 	};
8450bc07c75Srie 
8465aefb655Srie 	DBG_CALL(Dbg_sec_in(ofl->ofl_lml, isp));
8477c478bd9Sstevel@tonic-gate 
8480e233487SRod Evans 	/*
84908278a5eSRod Evans 	 * If this section identifies group members, or this section indicates
8500e233487SRod Evans 	 * that it is a member of a group, determine whether the section is
8510e233487SRod Evans 	 * still required.
8520e233487SRod Evans 	 */
8537c478bd9Sstevel@tonic-gate 	if ((shflags & SHF_GROUP) || (shdr->sh_type == SHT_GROUP)) {
8540e233487SRod Evans 		Group_desc	*gdesc;
8557c478bd9Sstevel@tonic-gate 
8560e233487SRod Evans 		if ((gdesc = ld_get_group(ofl, isp)) != NULL) {
8575aefb655Srie 			DBG_CALL(Dbg_sec_group(ofl->ofl_lml, isp, gdesc));
858cc7efc4fSrie 
859cc7efc4fSrie 			/*
8600e233487SRod Evans 			 * If this group has been replaced by another group,
8610e233487SRod Evans 			 * then this section needs to be discarded.
862cc7efc4fSrie 			 */
8630e233487SRod Evans 			if (gdesc->gd_oisc) {
864cc7efc4fSrie 				isp->is_flags |= FLG_IS_DISCARD;
8650e233487SRod Evans 
866d2ef9fe9Sab 				/*
867d2ef9fe9Sab 				 * Since we're discarding the section, we
868d2ef9fe9Sab 				 * can skip assigning it to an output section.
869d2ef9fe9Sab 				 * The exception is that if the user
870d2ef9fe9Sab 				 * specifies -z relaxreloc, then
871d2ef9fe9Sab 				 * we need to assign the output section so
872d2ef9fe9Sab 				 * that the sloppy relocation logic will have
873d2ef9fe9Sab 				 * the information necessary to do its work.
874d2ef9fe9Sab 				 */
875d2ef9fe9Sab 				if (!(ofl->ofl_flags1 & FLG_OF1_RLXREL))
8766b3ba5bdSAli Bahrami 					return (NULL);
877cc7efc4fSrie 			}
8787c478bd9Sstevel@tonic-gate 		}
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 		/*
881cc7efc4fSrie 		 * SHT_GROUP sections can only be included into relocatable
8827c478bd9Sstevel@tonic-gate 		 * objects.
8837c478bd9Sstevel@tonic-gate 		 */
884cc7efc4fSrie 		if (shdr->sh_type == SHT_GROUP) {
885cc7efc4fSrie 			if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
886cc7efc4fSrie 				isp->is_flags |= FLG_IS_DISCARD;
8876b3ba5bdSAli Bahrami 				return (NULL);
888cc7efc4fSrie 			}
889cc7efc4fSrie 		}
8907c478bd9Sstevel@tonic-gate 	}
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	/*
893cc7efc4fSrie 	 * Always assign SHF_TLS sections to the DATA segment (and then the
894cc7efc4fSrie 	 * PT_TLS embedded inside of there).
8957c478bd9Sstevel@tonic-gate 	 */
8967c478bd9Sstevel@tonic-gate 	if (shflags & SHF_TLS)
8977c478bd9Sstevel@tonic-gate 		shflags |= SHF_WRITE;
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	/*
9007c478bd9Sstevel@tonic-gate 	 * Traverse the entrance criteria list searching for a segment that
9017c478bd9Sstevel@tonic-gate 	 * matches the input section we have.  If an entrance criterion is set
9027c478bd9Sstevel@tonic-gate 	 * then there must be an exact match.  If we complete the loop without
9037c478bd9Sstevel@tonic-gate 	 * finding a segment, then sgp will be NULL.
9047c478bd9Sstevel@tonic-gate 	 */
9057c478bd9Sstevel@tonic-gate 	sgp = NULL;
90669112eddSAli Bahrami 	for (APLIST_TRAVERSE(ofl->ofl_ents, idx1, enp)) {
90769112eddSAli Bahrami 
90869112eddSAli Bahrami 		/* Disabled segments are not available for assignment */
90969112eddSAli Bahrami 		if (enp->ec_segment->sg_flags & FLG_SG_DISABLED)
9107c478bd9Sstevel@tonic-gate 			continue;
91169112eddSAli Bahrami 
91269112eddSAli Bahrami 		/*
91369112eddSAli Bahrami 		 * If an entrance criteria doesn't have any of its fields
91469112eddSAli Bahrami 		 * set, it will match any section it is tested against.
91569112eddSAli Bahrami 		 * We set the FLG_EC_CATCHALL flag on these, primarily because
91669112eddSAli Bahrami 		 * it helps readers of our debug output to understand what
91769112eddSAli Bahrami 		 * the criteria means --- otherwise the user would just see
91869112eddSAli Bahrami 		 * that every field is 0, but might not understand the
91969112eddSAli Bahrami 		 * significance of that.
92069112eddSAli Bahrami 		 *
92169112eddSAli Bahrami 		 * Given that we set this flag, we can use it here as an
92269112eddSAli Bahrami 		 * optimization to short circuit all of the tests in this
92369112eddSAli Bahrami 		 * loop. Note however, that if we did not do this, the end
92469112eddSAli Bahrami 		 * result would be the same --- the empty criteria will sail
92569112eddSAli Bahrami 		 * past the following tests and reach the end of the loop.
92669112eddSAli Bahrami 		 */
92769112eddSAli Bahrami 		if (enp->ec_flags & FLG_EC_CATCHALL) {
92869112eddSAli Bahrami 			sgp = enp->ec_segment;
92969112eddSAli Bahrami 			break;
93069112eddSAli Bahrami 		}
93169112eddSAli Bahrami 
9327c478bd9Sstevel@tonic-gate 		if (enp->ec_type && (enp->ec_type != shdr->sh_type))
9337c478bd9Sstevel@tonic-gate 			continue;
9347c478bd9Sstevel@tonic-gate 		if (enp->ec_attrmask &&
9357c478bd9Sstevel@tonic-gate 		    /* LINTED */
9367c478bd9Sstevel@tonic-gate 		    (enp->ec_attrmask & enp->ec_attrbits) !=
9377c478bd9Sstevel@tonic-gate 		    (enp->ec_attrmask & shflags))
9387c478bd9Sstevel@tonic-gate 			continue;
93969112eddSAli Bahrami 		if (enp->ec_is_name &&
94069112eddSAli Bahrami 		    (strcmp(enp->ec_is_name, isp->is_name) != 0))
9417c478bd9Sstevel@tonic-gate 			continue;
9427c478bd9Sstevel@tonic-gate 
94369112eddSAli Bahrami 		if ((alist_nitems(enp->ec_files) > 0) &&
94469112eddSAli Bahrami 		    ((path_info == NULL) || !eval_ec_files(path_info, enp)))
94569112eddSAli Bahrami 			continue;
9467c478bd9Sstevel@tonic-gate 
94769112eddSAli Bahrami 		/* All entrance criteria tests passed */
94857ef7aa9SRod Evans 		sgp = enp->ec_segment;
9497c478bd9Sstevel@tonic-gate 		break;
9507c478bd9Sstevel@tonic-gate 	}
9517c478bd9Sstevel@tonic-gate 
95269112eddSAli Bahrami 	/*
95369112eddSAli Bahrami 	 * The final entrance criteria record is a FLG_EC_CATCHALL that points
95469112eddSAli Bahrami 	 * at the final predefined segment "extra", and this final segment is
95569112eddSAli Bahrami 	 * tagged FLG_SG_NODISABLE. Therefore, the above loop must always find
95669112eddSAli Bahrami 	 * a segment.
95769112eddSAli Bahrami 	 */
95869112eddSAli Bahrami 	assert(sgp != NULL);
95969112eddSAli Bahrami 
96069112eddSAli Bahrami 	/*
96169112eddSAli Bahrami 	 * Transfer the input section sorting key from the entrance criteria
96269112eddSAli Bahrami 	 * to the input section. A non-zero value means that the section
96369112eddSAli Bahrami 	 * will be sorted on this key amoung the other sections that have a
96469112eddSAli Bahrami 	 * non-zero key. These sorted sections are collectively placed at the
96569112eddSAli Bahrami 	 * head of the output section.
96669112eddSAli Bahrami 	 *
96769112eddSAli Bahrami 	 * If the sort key is 0, the section is placed after the sorted
96869112eddSAli Bahrami 	 * sections in the order they are encountered.
96969112eddSAli Bahrami 	 */
97069112eddSAli Bahrami 	isp->is_ordndx = enp->ec_ordndx;
97169112eddSAli Bahrami 
97269112eddSAli Bahrami 	/* Remember that this entrance criteria has placed a section */
97369112eddSAli Bahrami 	enp->ec_flags |= FLG_EC_USED;
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 	/*
9761dd9d86fSAli Bahrami 	 * If our caller has supplied an alternative name for the output
9771dd9d86fSAli Bahrami 	 * section, then we defer to their request. Otherwise, the default
9781dd9d86fSAli Bahrami 	 * is to use the same name as that of the input section being placed.
9791dd9d86fSAli Bahrami 	 *
9801dd9d86fSAli Bahrami 	 * The COMDAT, SHT_GROUP and GNU name translations that follow have
9811dd9d86fSAli Bahrami 	 * the potential to alter this initial name.
9827c478bd9Sstevel@tonic-gate 	 */
9831dd9d86fSAli Bahrami 	oname = (char *)((alt_os_name == NULL) ? isp->is_name : alt_os_name);
9847c478bd9Sstevel@tonic-gate 
9850e233487SRod Evans 	/*
9860e233487SRod Evans 	 * Solaris section names may follow the convention:
9870e233487SRod Evans 	 *
9880e233487SRod Evans 	 *	section-name%symbol-name
9890e233487SRod Evans 	 *
9900e233487SRod Evans 	 * This convention has been used to order the layout of sections within
9910e233487SRod Evans 	 * segments for objects built with the compilers -xF option.  However,
9920e233487SRod Evans 	 * the final object should not contain individual section headers for
9930e233487SRod Evans 	 * all such input sections, instead the symbol name is stripped from the
9940e233487SRod Evans 	 * name to establish the final output section name.
9950e233487SRod Evans 	 *
9960e233487SRod Evans 	 * This convention has also been followed for COMDAT and sections
9970e233487SRod Evans 	 * identified though SHT_GROUP data.
9980e233487SRod Evans 	 *
99969112eddSAli Bahrami 	 * Strip out the % from the section name for:
100069112eddSAli Bahrami 	 *	- Non-relocatable objects
100169112eddSAli Bahrami 	 *	- Relocatable objects if input section sorting is
100269112eddSAli Bahrami 	 *	  in force for the segment in question.
10030e233487SRod Evans 	 */
10040e233487SRod Evans 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) ||
100569112eddSAli Bahrami 	    (sgp->sg_flags & FLG_SG_IS_ORDER)) {
10060e233487SRod Evans 		if ((sname = strchr(isp->is_name, '%')) != NULL) {
10070e233487SRod Evans 			size_t	size = sname - isp->is_name;
10087c478bd9Sstevel@tonic-gate 
10090e233487SRod Evans 			if ((oname = libld_malloc(size + 1)) == NULL)
10107c478bd9Sstevel@tonic-gate 				return ((Os_desc *)S_ERROR);
10110e233487SRod Evans 			(void) strncpy(oname, isp->is_name, size);
10120e233487SRod Evans 			oname[size] = '\0';
1013e23c41c9SAli Bahrami 			DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname));
10147c478bd9Sstevel@tonic-gate 		}
10157c478bd9Sstevel@tonic-gate 	}
10167c478bd9Sstevel@tonic-gate 
1017396f90f9SRichard Lowe 	/*
1018396f90f9SRichard Lowe 	 * When building relocatable objects, we must not redirect COMDAT
1019396f90f9SRichard Lowe 	 * section names into their outputs, such that our output object may
1020396f90f9SRichard Lowe 	 * be successfully used as an input object also requiring COMDAT
1021396f90f9SRichard Lowe 	 * processing
1022396f90f9SRichard Lowe 	 */
1023396f90f9SRichard Lowe 
10247c478bd9Sstevel@tonic-gate 	/*
10250e233487SRod Evans 	 * GNU section names may follow the convention:
10260e233487SRod Evans 	 *
10270e233487SRod Evans 	 *	.gnu.linkonce.*
10280e233487SRod Evans 	 *
10290e233487SRod Evans 	 * The .gnu.linkonce is a section naming convention that indicates a
10300e233487SRod Evans 	 * COMDAT requirement.  Determine whether this section follows the GNU
10310e233487SRod Evans 	 * pattern, and if so, determine whether this section should be
1032ca4eed8bSAli Bahrami 	 * discarded or retained.  The comparison of is_name[1] with 'g'
1033ca4eed8bSAli Bahrami 	 * is an optimization to skip using strncmp() too much. This is safe,
1034ca4eed8bSAli Bahrami 	 * because we know the name is not NULL, and therefore must have
1035ca4eed8bSAli Bahrami 	 * at least one character plus a NULL termination.
10360e233487SRod Evans 	 */
1037396f90f9SRichard Lowe 	if ((isp->is_name == oname) && (isp->is_name[1] == 'g') &&
10380e233487SRod Evans 	    (strncmp(MSG_ORIG(MSG_SCN_GNU_LINKONCE), isp->is_name,
10390e233487SRod Evans 	    MSG_SCN_GNU_LINKONCE_SIZE) == 0)) {
1040396f90f9SRichard Lowe 		if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
1041396f90f9SRichard Lowe 			if ((oname = (char *)gnu_linkonce_sec(isp->is_name)) !=
1042396f90f9SRichard Lowe 			    isp->is_name) {
1043396f90f9SRichard Lowe 				DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp,
1044396f90f9SRichard Lowe 				    oname));
1045396f90f9SRichard Lowe 			}
10460e233487SRod Evans 		}
10470e233487SRod Evans 
10480e233487SRod Evans 		/*
10490e233487SRod Evans 		 * Explicitly identify this section type as COMDAT.  Also,
1050e64d0ff9SAli Bahrami 		 * enable relaxed relocation processing, as this is typically
1051e64d0ff9SAli Bahrami 		 * a requirement with .gnu.linkonce sections.
10520e233487SRod Evans 		 */
10530e233487SRod Evans 		isp->is_flags |= FLG_IS_COMDAT;
10540e233487SRod Evans 		if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0)
10550e233487SRod Evans 			ofl->ofl_flags1 |= FLG_OF1_RLXREL;
105669112eddSAli Bahrami 		DBG_CALL(Dbg_sec_gnu_comdat(ofl->ofl_lml, isp, TRUE,
105769112eddSAli Bahrami 		    (ofl->ofl_flags1 & FLG_OF1_RLXREL) != 0));
10580e233487SRod Evans 	}
10590e233487SRod Evans 
10600e233487SRod Evans 	/*
10610e233487SRod Evans 	 * GNU section names may also follow the convention:
10620e233487SRod Evans 	 *
10630e233487SRod Evans 	 *	section-name.symbol-name
10640e233487SRod Evans 	 *
10650e233487SRod Evans 	 * This convention is used when defining SHT_GROUP sections of type
10660e233487SRod Evans 	 * COMDAT.  Thus, any group processing will have discovered any group
10670e233487SRod Evans 	 * sections, and this identification can be triggered by a pattern
10680e233487SRod Evans 	 * match section names.
10697c478bd9Sstevel@tonic-gate 	 */
1070396f90f9SRichard Lowe 	if ((isp->is_name == oname) && (isp->is_flags & FLG_IS_COMDAT) &&
10710e233487SRod Evans 	    ((sname = gnu_comdat_sym(ifl, isp)) != NULL)) {
10720e233487SRod Evans 		size_t	size = sname - isp->is_name;
10730e233487SRod Evans 
1074396f90f9SRichard Lowe 		if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
1075396f90f9SRichard Lowe 			if ((oname = libld_malloc(size + 1)) == NULL)
1076396f90f9SRichard Lowe 				return ((Os_desc *)S_ERROR);
1077396f90f9SRichard Lowe 			(void) strncpy(oname, isp->is_name, size);
1078396f90f9SRichard Lowe 			oname[size] = '\0';
1079396f90f9SRichard Lowe 			DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname));
1080396f90f9SRichard Lowe 		}
10810e233487SRod Evans 
10820e233487SRod Evans 		/*
1083e64d0ff9SAli Bahrami 		 * Enable relaxed relocation processing, as this is
1084e64d0ff9SAli Bahrami 		 * typically a requirement with GNU COMDAT sections.
10850e233487SRod Evans 		 */
10860e233487SRod Evans 		if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0) {
10870e233487SRod Evans 			ofl->ofl_flags1 |= FLG_OF1_RLXREL;
108869112eddSAli Bahrami 			DBG_CALL(Dbg_sec_gnu_comdat(ofl->ofl_lml, isp,
108969112eddSAli Bahrami 			    FALSE, TRUE));
10900e233487SRod Evans 		}
10910e233487SRod Evans 	}
10920e233487SRod Evans 
1093ce686298SRichard Lowe 	/*
1094ce686298SRichard Lowe 	 * GNU section names named section-name.symbol-name which are not
1095ce686298SRichard Lowe 	 * members of COMDAT groups are merged according to the behaviour of
1096ce686298SRichard Lowe 	 * the GNU link-editor.
1097ce686298SRichard Lowe 	 *
1098ce686298SRichard Lowe 	 * See the description of gnu_split_sec().
1099ce686298SRichard Lowe 	 */
1100ce686298SRichard Lowe 	if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
1101ce686298SRichard Lowe 	    (isp->is_name == oname) &&
1102ce686298SRichard Lowe 	    ((oname = (char *)gnu_split_sec(oname)) != isp->is_name)) {
1103ce686298SRichard Lowe 		DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname));
1104ce686298SRichard Lowe 	}
1105ce686298SRichard Lowe 
11060e233487SRod Evans 	/*
11070e233487SRod Evans 	 * Assign a hash value now that the output section name has been
11080e233487SRod Evans 	 * finalized.
11090e233487SRod Evans 	 */
11100e233487SRod Evans 	onamehash = sgs_str_hash(oname);
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	/*
111369112eddSAli Bahrami 	 * Determine if output section ordering is turned on. If so, return
111469112eddSAli Bahrami 	 * the appropriate ordering index for the section. This information
111569112eddSAli Bahrami 	 * is derived from the Sg_desc->sg_os_order list that was built
11161dd9d86fSAli Bahrami 	 * up from the Mapfile.
111769112eddSAli Bahrami 	 *
111869112eddSAli Bahrami 	 * A value of 0 for os_ndx means that the section is not sorted
111969112eddSAli Bahrami 	 * (i.e. is not found in the sg_os_order). The items in sg_os_order
112069112eddSAli Bahrami 	 * are in the desired sort order, so adding 1 to their alist index
112169112eddSAli Bahrami 	 * gives a suitable index for sorting.
11227c478bd9Sstevel@tonic-gate 	 */
11230bc07c75Srie 	os_ndx = 0;
112469112eddSAli Bahrami 	if (alist_nitems(sgp->sg_os_order) > 0) {
1125cce0e03bSab 		Sec_order	*scop;
11260bc07c75Srie 
112769112eddSAli Bahrami 		for (ALIST_TRAVERSE(sgp->sg_os_order, idx1, scop)) {
11280e233487SRod Evans 			if (strcmp(scop->sco_secname, oname) == 0) {
11290bc07c75Srie 				scop->sco_flags |= FLG_SGO_USED;
113069112eddSAli Bahrami 				os_ndx = idx1 + 1;
11310bc07c75Srie 				break;
11320bc07c75Srie 			}
11330bc07c75Srie 		}
11340bc07c75Srie 	}
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 	/*
11371dd9d86fSAli Bahrami 	 * Mask of section header flags to ignore when matching sections. We
11381dd9d86fSAli Bahrami 	 * are more strict with relocatable objects, ignoring only the order
11391dd9d86fSAli Bahrami 	 * flags, and keeping sections apart if they differ otherwise. This
11401dd9d86fSAli Bahrami 	 * follows the policy that sections in a relative object should only
11411dd9d86fSAli Bahrami 	 * be merged if their flags are the same, and avoids destroying
11421dd9d86fSAli Bahrami 	 * information prematurely. For final products however, we ignore all
1143240e56feSab 	 * flags that do not prevent a merge.
11447c478bd9Sstevel@tonic-gate 	 */
114557ef7aa9SRod Evans 	shflagmask =
114657ef7aa9SRod Evans 	    (ofl->ofl_flags & FLG_OF_RELOBJ) ? ALL_SHF_ORDER : ALL_SHF_IGNORE;
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 	/*
11497c478bd9Sstevel@tonic-gate 	 * Traverse the input section list for the output section we have been
1150240e56feSab 	 * assigned. If we find a matching section simply add this new section.
11517c478bd9Sstevel@tonic-gate 	 */
115257ef7aa9SRod Evans 	iidx = 0;
1153*a48fdbefSBryan Cantrill 
1154*a48fdbefSBryan Cantrill 	/*
1155*a48fdbefSBryan Cantrill 	 * To not become quadratic with respect to the number of output
1156*a48fdbefSBryan Cantrill 	 * sections, we want to avoid a scan of the existing output sections
1157*a48fdbefSBryan Cantrill 	 * on every section placement.  To effect this, we use a hash table
1158*a48fdbefSBryan Cantrill 	 * for sections when the number of sections gets sufficiently large;
1159*a48fdbefSBryan Cantrill 	 * if this hash table is present, we check the absence of the other
1160*a48fdbefSBryan Cantrill 	 * (uncommon) conditions that necessitate a linear scan, using the
1161*a48fdbefSBryan Cantrill 	 * hash chain if we can.
1162*a48fdbefSBryan Cantrill 	 */
1163*a48fdbefSBryan Cantrill 	if (os_ndx == 0 && (hash = sgp->sg_hashtab) != NULL) {
1164*a48fdbefSBryan Cantrill 		APlist *list = sgp->sg_osdescs;
1165*a48fdbefSBryan Cantrill 
1166*a48fdbefSBryan Cantrill 		osp = list->apl_data[list->apl_nitems - 1];
1167*a48fdbefSBryan Cantrill 
1168*a48fdbefSBryan Cantrill 		if (ident >= osp->os_identndx) {
1169*a48fdbefSBryan Cantrill 			linear_scan = FALSE;
1170*a48fdbefSBryan Cantrill 			osp = hash->osh_hashtab[onamehash % hash->osh_size];
1171*a48fdbefSBryan Cantrill 		}
1172*a48fdbefSBryan Cantrill 	}
1173*a48fdbefSBryan Cantrill 
1174*a48fdbefSBryan Cantrill 	/*
1175*a48fdbefSBryan Cantrill 	 * We now want to iterate over output sections, looking for a match
1176*a48fdbefSBryan Cantrill 	 * or an insertion point.  Note that this loop condition is a bit
1177*a48fdbefSBryan Cantrill 	 * convoluted because it's encoding two different ways of iterating
1178*a48fdbefSBryan Cantrill 	 * over output section descriptors:  if it's a linear scan, we will
1179*a48fdbefSBryan Cantrill 	 * iterate over the list elements, and if it's not a linear scan we
1180*a48fdbefSBryan Cantrill 	 * will iterate over the hash chain that we discovered above.  (The
1181*a48fdbefSBryan Cantrill 	 * only condition that will actually change over the loop is osp; the
1182*a48fdbefSBryan Cantrill 	 * mechanics of iterating to the next section depend on linear_scan
1183*a48fdbefSBryan Cantrill 	 * and are contained in the body of the loop.)
1184*a48fdbefSBryan Cantrill 	 */
1185*a48fdbefSBryan Cantrill 	while ((linear_scan && sgp->sg_osdescs != NULL) ||
1186*a48fdbefSBryan Cantrill 	    (!linear_scan && osp != NULL)) {
1187*a48fdbefSBryan Cantrill 		if (linear_scan) {
1188*a48fdbefSBryan Cantrill 			if ((idx1 = iidx) >= sgp->sg_osdescs->apl_nitems)
1189*a48fdbefSBryan Cantrill 				break;
1190*a48fdbefSBryan Cantrill 
1191*a48fdbefSBryan Cantrill 			osp = sgp->sg_osdescs->apl_data[idx1];
1192*a48fdbefSBryan Cantrill 		}
1193*a48fdbefSBryan Cantrill 
1194d444b03eSAli Bahrami 		Shdr	*os_shdr = osp->os_shdr;
11957c478bd9Sstevel@tonic-gate 
1196d444b03eSAli Bahrami 		/*
1197d444b03eSAli Bahrami 		 * An input section matches an output section if:
1198d444b03eSAli Bahrami 		 * -	The ident values match
1199d444b03eSAli Bahrami 		 * -	The names match
1200d444b03eSAli Bahrami 		 * -	Not a GROUP section
1201a196c3ffSRichard Lowe 		 * -	Not a GROUP member, if producing a relocatable object
1202fb12490aSRichard Lowe 		 * -	Not a DTrace dof section
1203d444b03eSAli Bahrami 		 * -	Section types match
1204d444b03eSAli Bahrami 		 * -	Matching section flags, after screening out the
1205d444b03eSAli Bahrami 		 *	shflagmask flags.
1206d444b03eSAli Bahrami 		 *
1207d444b03eSAli Bahrami 		 * Section types are considered to match if any one of
1208d444b03eSAli Bahrami 		 * the following are true:
1209d444b03eSAli Bahrami 		 * -	The type codes are the same
12103fc1e289SBryan Cantrill 		 * -	Both are .eh_frame sections (regardless of type code)
1211d444b03eSAli Bahrami 		 * -	The input section is COMDAT, and the output section
1212d444b03eSAli Bahrami 		 *	is SHT_PROGBITS.
1213d444b03eSAli Bahrami 		 */
121457ef7aa9SRod Evans 		if ((ident == osp->os_identndx) &&
1215ba2be530Sab 		    (ident != ld_targ.t_id.id_rel) &&
12160e233487SRod Evans 		    (onamehash == osp->os_namehash) &&
12170bc07c75Srie 		    (shdr->sh_type != SHT_GROUP) &&
1218a196c3ffSRichard Lowe 		    (((shdr->sh_flags & SHF_GROUP) == 0) ||
1219a196c3ffSRichard Lowe 		    ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) &&
12207c478bd9Sstevel@tonic-gate 		    (shdr->sh_type != SHT_SUNW_dof) &&
1221d444b03eSAli Bahrami 		    ((shdr->sh_type == os_shdr->sh_type) ||
12223fc1e289SBryan Cantrill 		    (is_ehframe && (osp->os_flags & FLG_OS_EHFRAME)) ||
12237c478bd9Sstevel@tonic-gate 		    ((shdr->sh_type == SHT_SUNW_COMDAT) &&
1224d444b03eSAli Bahrami 		    (os_shdr->sh_type == SHT_PROGBITS))) &&
12257c478bd9Sstevel@tonic-gate 		    ((shflags & ~shflagmask) ==
1226d444b03eSAli Bahrami 		    (os_shdr->sh_flags & ~shflagmask)) &&
12270e233487SRod Evans 		    (strcmp(oname, osp->os_name) == 0)) {
12280e233487SRod Evans 			uintptr_t	err;
12290e233487SRod Evans 
12307c478bd9Sstevel@tonic-gate 			/*
12310e233487SRod Evans 			 * Process any COMDAT section, keeping the first and
12320e233487SRod Evans 			 * discarding all others.
12337c478bd9Sstevel@tonic-gate 			 */
12340e233487SRod Evans 			if ((isp->is_flags & FLG_IS_COMDAT) &&
12350e233487SRod Evans 			    ((err = add_comdat(ofl, osp, isp)) != 1))
12360e233487SRod Evans 				return ((Os_desc *)err);
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate 			/*
12397c478bd9Sstevel@tonic-gate 			 * Set alignment
12407c478bd9Sstevel@tonic-gate 			 */
12417c478bd9Sstevel@tonic-gate 			set_addralign(ofl, osp, isp);
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 			/*
1244dd94ecefSrie 			 * If this section is a non-empty TLS section indicate
1245dd94ecefSrie 			 * that a PT_TLS program header is required.
12467c478bd9Sstevel@tonic-gate 			 */
1247dd94ecefSrie 			if ((shflags & SHF_TLS) && shdr->sh_size &&
1248dd94ecefSrie 			    ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0))
1249dd94ecefSrie 				ofl->ofl_flags |= FLG_OF_TLSPHDR;
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 			/*
12521dd9d86fSAli Bahrami 			 * Insert the input section descriptor on the proper
12531dd9d86fSAli Bahrami 			 * output section descriptor list.
12541dd9d86fSAli Bahrami 			 *
12551dd9d86fSAli Bahrami 			 * If this segment requires input section ordering,
12561dd9d86fSAli Bahrami 			 * honor any mapfile specified ordering for otherwise
12571dd9d86fSAli Bahrami 			 * unordered sections by setting the mapfile_sort
12581dd9d86fSAli Bahrami 			 * argument of os_attach_isp() to True.
12597c478bd9Sstevel@tonic-gate 			 */
126057ef7aa9SRod Evans 
12611dd9d86fSAli Bahrami 			if (os_attach_isp(ofl, osp, isp,
126269112eddSAli Bahrami 			    (sgp->sg_flags & FLG_SG_IS_ORDER) != 0) == 0)
1263cce0e03bSab 				return ((Os_desc *)S_ERROR);
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 			/*
12667c478bd9Sstevel@tonic-gate 			 * If this input section and file is associated to an
12677c478bd9Sstevel@tonic-gate 			 * artificially referenced output section, make sure
1268e23c41c9SAli Bahrami 			 * they are marked as referenced also. This ensures
1269e23c41c9SAli Bahrami 			 * that this input section and file isn't eliminated
1270e23c41c9SAli Bahrami 			 * when -zignore is in effect.
1271e23c41c9SAli Bahrami 			 *
12727c478bd9Sstevel@tonic-gate 			 * See -zignore comments when creating a new output
12737c478bd9Sstevel@tonic-gate 			 * section below.
12747c478bd9Sstevel@tonic-gate 			 */
12750bc07c75Srie 			if (((ifl &&
12760bc07c75Srie 			    (ifl->ifl_flags & FLG_IF_IGNORE)) || DBG_ENABLED) &&
12777c478bd9Sstevel@tonic-gate 			    (osp->os_flags & FLG_OS_SECTREF)) {
12787c478bd9Sstevel@tonic-gate 				isp->is_flags |= FLG_IS_SECTREF;
12797c478bd9Sstevel@tonic-gate 				if (ifl)
12800bc07c75Srie 					ifl->ifl_flags |= FLG_IF_FILEREF;
12817c478bd9Sstevel@tonic-gate 			}
12827c478bd9Sstevel@tonic-gate 
12835aefb655Srie 			DBG_CALL(Dbg_sec_added(ofl->ofl_lml, osp, sgp));
12847c478bd9Sstevel@tonic-gate 			return (osp);
12857c478bd9Sstevel@tonic-gate 		}
12867c478bd9Sstevel@tonic-gate 
1287*a48fdbefSBryan Cantrill 		if (!linear_scan) {
1288*a48fdbefSBryan Cantrill 			osp = osp->os_hashnext;
1289*a48fdbefSBryan Cantrill 			continue;
1290*a48fdbefSBryan Cantrill 		}
1291*a48fdbefSBryan Cantrill 
12927c478bd9Sstevel@tonic-gate 		/*
12930bc07c75Srie 		 * Do we need to worry about section ordering?
12947c478bd9Sstevel@tonic-gate 		 */
12957c478bd9Sstevel@tonic-gate 		if (os_ndx) {
129657ef7aa9SRod Evans 			if (osp->os_ordndx) {
129757ef7aa9SRod Evans 				if (os_ndx < osp->os_ordndx)
12987c478bd9Sstevel@tonic-gate 					/* insert section here. */
12997c478bd9Sstevel@tonic-gate 					break;
13007c478bd9Sstevel@tonic-gate 				else {
130157ef7aa9SRod Evans 					iidx = idx1 + 1;
13027c478bd9Sstevel@tonic-gate 					continue;
13037c478bd9Sstevel@tonic-gate 				}
13047c478bd9Sstevel@tonic-gate 			} else {
13057c478bd9Sstevel@tonic-gate 				/* insert section here. */
13067c478bd9Sstevel@tonic-gate 				break;
13077c478bd9Sstevel@tonic-gate 			}
130857ef7aa9SRod Evans 		} else if (osp->os_ordndx) {
130957ef7aa9SRod Evans 			iidx = idx1 + 1;
13107c478bd9Sstevel@tonic-gate 			continue;
13117c478bd9Sstevel@tonic-gate 		}
13127c478bd9Sstevel@tonic-gate 
13137c478bd9Sstevel@tonic-gate 		/*
13147c478bd9Sstevel@tonic-gate 		 * If the new sections identifier is less than that of the
13157c478bd9Sstevel@tonic-gate 		 * present input section we need to insert the new section
13167c478bd9Sstevel@tonic-gate 		 * at this point.
13177c478bd9Sstevel@tonic-gate 		 */
131857ef7aa9SRod Evans 		if (ident < osp->os_identndx)
13197c478bd9Sstevel@tonic-gate 			break;
13200bc07c75Srie 
132157ef7aa9SRod Evans 		iidx = idx1 + 1;
13227c478bd9Sstevel@tonic-gate 	}
13237c478bd9Sstevel@tonic-gate 
1324*a48fdbefSBryan Cantrill 	if (!linear_scan) {
1325*a48fdbefSBryan Cantrill 		iidx = sgp->sg_osdescs->apl_nitems;
1326*a48fdbefSBryan Cantrill 	}
1327*a48fdbefSBryan Cantrill 
13287c478bd9Sstevel@tonic-gate 	/*
13297c478bd9Sstevel@tonic-gate 	 * We are adding a new output section.  Update the section header
13307c478bd9Sstevel@tonic-gate 	 * count and associated string size.
1331e64d0ff9SAli Bahrami 	 *
1332e64d0ff9SAli Bahrami 	 * If the input section triggering this output section has been marked
1333e64d0ff9SAli Bahrami 	 * for discard, and if no other non-discarded input section comes along
1334e64d0ff9SAli Bahrami 	 * to join it, then we will over count. We cannot know if this will
1335e64d0ff9SAli Bahrami 	 * happen or not until all input is seen. Set FLG_OF_AJDOSCNT to
1336e64d0ff9SAli Bahrami 	 * trigger a final count readjustment.
13377c478bd9Sstevel@tonic-gate 	 */
1338e64d0ff9SAli Bahrami 	if (isp->is_flags & FLG_IS_DISCARD)
1339e64d0ff9SAli Bahrami 		ofl->ofl_flags |= FLG_OF_ADJOSCNT;
13407c478bd9Sstevel@tonic-gate 	ofl->ofl_shdrcnt++;
13410e233487SRod Evans 	if (st_insert(ofl->ofl_shdrsttab, oname) == -1)
13427c478bd9Sstevel@tonic-gate 		return ((Os_desc *)S_ERROR);
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 	/*
13457c478bd9Sstevel@tonic-gate 	 * Create a new output section descriptor.
13467c478bd9Sstevel@tonic-gate 	 */
1347fb12490aSRichard Lowe 	if ((osp = libld_calloc(1, sizeof (Os_desc))) == NULL)
13487c478bd9Sstevel@tonic-gate 		return ((Os_desc *)S_ERROR);
1349fb12490aSRichard Lowe 	if ((osp->os_shdr = libld_calloc(1, sizeof (Shdr))) == NULL)
13507c478bd9Sstevel@tonic-gate 		return ((Os_desc *)S_ERROR);
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	/*
13530e233487SRod Evans 	 * Convert COMDAT section to PROGBITS as this the first section of the
13540e233487SRod Evans 	 * output section.  Save any COMDAT section for later processing, as
13550e233487SRod Evans 	 * additional COMDAT sections that match this section need discarding.
13567c478bd9Sstevel@tonic-gate 	 */
1357d444b03eSAli Bahrami 	if ((shdr->sh_type == SHT_SUNW_COMDAT) &&
1358d444b03eSAli Bahrami 	    ((shdr = isp_convert_type(isp, SHT_PROGBITS)) == NULL))
1359d444b03eSAli Bahrami 		return ((Os_desc *)S_ERROR);
13600e233487SRod Evans 	if ((isp->is_flags & FLG_IS_COMDAT) &&
13616b3ba5bdSAli Bahrami 	    (add_comdat(ofl, osp, isp) == S_ERROR))
13620e233487SRod Evans 		return ((Os_desc *)S_ERROR);
13637c478bd9Sstevel@tonic-gate 
1364d444b03eSAli Bahrami 	if (is_ehframe) {
1365d444b03eSAli Bahrami 		/*
1366d444b03eSAli Bahrami 		 * Executable or sharable objects can have at most a single
1367d444b03eSAli Bahrami 		 * .eh_frame section. Detect attempts to create more than
1368d444b03eSAli Bahrami 		 * one. This occurs if the input sections have incompatible
1369d444b03eSAli Bahrami 		 * attributes.
1370d444b03eSAli Bahrami 		 */
1371d444b03eSAli Bahrami 		if ((ofl->ofl_flags & FLG_OF_EHFRAME) &&
1372d444b03eSAli Bahrami 		    !(ofl->ofl_flags & FLG_OF_RELOBJ)) {
1373d444b03eSAli Bahrami 			eh_frame_muldef(ofl, isp);
1374d444b03eSAli Bahrami 			return ((Os_desc *)S_ERROR);
1375d444b03eSAli Bahrami 		}
1376d444b03eSAli Bahrami 		ofl->ofl_flags |= FLG_OF_EHFRAME;
13773fc1e289SBryan Cantrill 
13783fc1e289SBryan Cantrill 		/*
13793fc1e289SBryan Cantrill 		 * For .eh_frame sections, we always set the type to be the
13803fc1e289SBryan Cantrill 		 * type specified by the ABI.  This allows .eh_frame sections
13813fc1e289SBryan Cantrill 		 * of type SHT_PROGBITS to be correctly merged with .eh_frame
13823fc1e289SBryan Cantrill 		 * sections of the ABI-defined type (e.g. SHT_AMD64_UNWIND),
13833fc1e289SBryan Cantrill 		 * with the output being of the ABI-defined type.
13843fc1e289SBryan Cantrill 		 */
13853fc1e289SBryan Cantrill 		osp->os_shdr->sh_type = ld_targ.t_m.m_sht_unwind;
13863fc1e289SBryan Cantrill 	} else {
13873fc1e289SBryan Cantrill 		osp->os_shdr->sh_type = shdr->sh_type;
1388d444b03eSAli Bahrami 	}
1389d444b03eSAli Bahrami 
13907c478bd9Sstevel@tonic-gate 	osp->os_shdr->sh_flags = shdr->sh_flags;
13917c478bd9Sstevel@tonic-gate 	osp->os_shdr->sh_entsize = shdr->sh_entsize;
13920e233487SRod Evans 	osp->os_name = oname;
13930e233487SRod Evans 	osp->os_namehash = onamehash;
139457ef7aa9SRod Evans 	osp->os_ordndx = os_ndx;
13957c478bd9Sstevel@tonic-gate 	osp->os_sgdesc = sgp;
1396d444b03eSAli Bahrami 	if (is_ehframe)
1397d444b03eSAli Bahrami 		osp->os_flags |= FLG_OS_EHFRAME;
13980bc07c75Srie 
13997c478bd9Sstevel@tonic-gate 	if (ifl && (shdr->sh_type == SHT_PROGBITS)) {
14007c478bd9Sstevel@tonic-gate 		/*
14014899432aSab 		 * Try to preserve the intended meaning of sh_link/sh_info.
14020bc07c75Srie 		 * See the translate_link() in update.c.
14037c478bd9Sstevel@tonic-gate 		 */
14047c478bd9Sstevel@tonic-gate 		osp->os_shdr->sh_link = shdr->sh_link;
14057c478bd9Sstevel@tonic-gate 		if (shdr->sh_flags & SHF_INFO_LINK)
14067c478bd9Sstevel@tonic-gate 			osp->os_shdr->sh_info = shdr->sh_info;
14077c478bd9Sstevel@tonic-gate 	}
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	/*
14100bc07c75Srie 	 * When -zignore is in effect, user supplied sections and files that are
14110bc07c75Srie 	 * not referenced from other sections, are eliminated from the object
14120bc07c75Srie 	 * being produced.  Some sections, although unreferenced, are special,
14130bc07c75Srie 	 * and must not be eliminated.  Determine if this new output section is
14140bc07c75Srie 	 * one of those special sections, and if so mark it artificially as
14150bc07c75Srie 	 * referenced.  Any input section and file associated to this output
14160bc07c75Srie 	 * section is also be marked as referenced, and thus won't be eliminated
14177c478bd9Sstevel@tonic-gate 	 * from the final output.
14187c478bd9Sstevel@tonic-gate 	 */
14190bc07c75Srie 	if (ifl && ((ofl->ofl_flags1 & FLG_OF1_IGNPRC) || DBG_ENABLED)) {
14200bc07c75Srie 		const Msg	*refsec;
14210bc07c75Srie 
14220bc07c75Srie 		for (refsec = RefSecs; *refsec; refsec++) {
14230bc07c75Srie 			if (strcmp(osp->os_name, MSG_ORIG(*refsec)) == 0) {
14240bc07c75Srie 				osp->os_flags |= FLG_OS_SECTREF;
14250bc07c75Srie 
14260bc07c75Srie 				if ((ifl->ifl_flags & FLG_IF_IGNORE) ||
14270bc07c75Srie 				    DBG_ENABLED) {
14280bc07c75Srie 					isp->is_flags |= FLG_IS_SECTREF;
14290bc07c75Srie 					ifl->ifl_flags |= FLG_IF_FILEREF;
14300bc07c75Srie 				}
14310bc07c75Srie 				break;
14320bc07c75Srie 			}
14337c478bd9Sstevel@tonic-gate 		}
14347c478bd9Sstevel@tonic-gate 	}
14357c478bd9Sstevel@tonic-gate 
14367c478bd9Sstevel@tonic-gate 	/*
143757ef7aa9SRod Evans 	 * Sections of type SHT_GROUP are added to the ofl->ofl_osgroups list,
143857ef7aa9SRod Evans 	 * so that they can be updated as a group later.
14397c478bd9Sstevel@tonic-gate 	 */
144057ef7aa9SRod Evans 	if ((shdr->sh_type == SHT_GROUP) &&
1441c866e237SRichard Lowe 	    ((isp->is_flags & FLG_IS_DISCARD) == 0) &&
144257ef7aa9SRod Evans 	    (aplist_append(&ofl->ofl_osgroups, osp,
144357ef7aa9SRod Evans 	    AL_CNT_OFL_OSGROUPS) == NULL))
144457ef7aa9SRod Evans 		return ((Os_desc *)S_ERROR);
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 	/*
1447dd94ecefSrie 	 * If this section is a non-empty TLS section indicate that a PT_TLS
1448dd94ecefSrie 	 * program header is required.
14497c478bd9Sstevel@tonic-gate 	 */
1450dd94ecefSrie 	if ((shflags & SHF_TLS) && shdr->sh_size &&
1451dd94ecefSrie 	    ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0))
1452dd94ecefSrie 		ofl->ofl_flags |= FLG_OF_TLSPHDR;
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 	/*
14557c478bd9Sstevel@tonic-gate 	 * If a non-allocatable section is going to be put into a loadable
14567c478bd9Sstevel@tonic-gate 	 * segment then turn on the allocate bit for this section and warn the
14577c478bd9Sstevel@tonic-gate 	 * user that we have done so.  This could only happen through the use
14587c478bd9Sstevel@tonic-gate 	 * of a mapfile.
14597c478bd9Sstevel@tonic-gate 	 */
14600bc07c75Srie 	if ((sgp->sg_phdr.p_type == PT_LOAD) &&
14610bc07c75Srie 	    ((osp->os_shdr->sh_flags & SHF_ALLOC) == 0)) {
14621007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SCN_NONALLOC),
146369112eddSAli Bahrami 		    ofl->ofl_name, osp->os_name, sgp->sg_name);
14640bc07c75Srie 		osp->os_shdr->sh_flags |= SHF_ALLOC;
14657c478bd9Sstevel@tonic-gate 	}
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 	/*
14687c478bd9Sstevel@tonic-gate 	 * Retain this sections identifier for future comparisons when placing
14697c478bd9Sstevel@tonic-gate 	 * a section (after all sections have been processed this variable will
14707c478bd9Sstevel@tonic-gate 	 * be used to hold the sections symbol index as we don't need to retain
14717c478bd9Sstevel@tonic-gate 	 * the identifier any more).
14727c478bd9Sstevel@tonic-gate 	 */
147357ef7aa9SRod Evans 	osp->os_identndx = ident;
14747c478bd9Sstevel@tonic-gate 
14757c478bd9Sstevel@tonic-gate 	/*
147657ef7aa9SRod Evans 	 * Set alignment.
14777c478bd9Sstevel@tonic-gate 	 */
14787c478bd9Sstevel@tonic-gate 	set_addralign(ofl, osp, isp);
14797c478bd9Sstevel@tonic-gate 
14801dd9d86fSAli Bahrami 	if (os_attach_isp(ofl, osp, isp, 0) == 0)
14817c478bd9Sstevel@tonic-gate 		return ((Os_desc *)S_ERROR);
14827c478bd9Sstevel@tonic-gate 
14835aefb655Srie 	DBG_CALL(Dbg_sec_created(ofl->ofl_lml, osp, sgp));
14840bc07c75Srie 
1485cce0e03bSab 	/*
148657ef7aa9SRod Evans 	 * Insert the new section at the offset given by iidx.  If no position
148757ef7aa9SRod Evans 	 * for it was identified above, this will be index 0, causing the new
148857ef7aa9SRod Evans 	 * section to be prepended to the beginning of the section list.
148957ef7aa9SRod Evans 	 * Otherwise, it is the index following the section that was identified.
1490cce0e03bSab 	 */
1491cce0e03bSab 	if (aplist_insert(&sgp->sg_osdescs, osp, AL_CNT_SG_OSDESC,
149257ef7aa9SRod Evans 	    iidx) == NULL)
1493cce0e03bSab 		return ((Os_desc *)S_ERROR);
1494*a48fdbefSBryan Cantrill 
1495*a48fdbefSBryan Cantrill 	os_desc_hash(sgp, osp);
1496*a48fdbefSBryan Cantrill 
14977c478bd9Sstevel@tonic-gate 	return (osp);
14987c478bd9Sstevel@tonic-gate }
1499