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.
287c478bd9Sstevel@tonic-gate */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * Map file parsing and input section to output segment mapping.
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
355aefb655Srie #include <debug.h>
367c478bd9Sstevel@tonic-gate #include "msg.h"
377c478bd9Sstevel@tonic-gate #include "_libld.h"
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate /*
4054d82594Sseizo * Each time a section is placed, the function set_addralign()
4154d82594Sseizo * is called. This function performs:
425aefb655Srie *
4369112eddSAli Bahrami * - if the section is from an external file, check if this is empty or not.
445aefb655Srie * If not, we know the segment this section will belong needs a program
455aefb655Srie * header. (Of course, the program is needed only if this section falls
465aefb655Srie * into a loadable segment.)
4769112eddSAli Bahrami * - compute the Least Common Multiplier for setting the segment alignment.
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate static void
set_addralign(Ofl_desc * ofl,Os_desc * osp,Is_desc * isp)507c478bd9Sstevel@tonic-gate set_addralign(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp)
517c478bd9Sstevel@tonic-gate {
5254d82594Sseizo Shdr *shdr = isp->is_shdr;
5354d82594Sseizo
54d2ef9fe9Sab196087 /* A discarded section has no influence on the output */
55d2ef9fe9Sab196087 if (isp->is_flags & FLG_IS_DISCARD)
56d2ef9fe9Sab196087 return;
57d2ef9fe9Sab196087
5854d82594Sseizo /*
5954d82594Sseizo * If this section has data or will be assigned data
6054d82594Sseizo * later, mark this segment not-empty.
6154d82594Sseizo */
6254d82594Sseizo if ((shdr->sh_size != 0) ||
6354d82594Sseizo ((isp->is_flags & FLG_IS_EXTERNAL) == 0))
6454d82594Sseizo osp->os_sgdesc->sg_flags |= FLG_SG_PHREQ;
6554d82594Sseizo
664899432aSab196087 if ((ofl->ofl_dtflags_1 & DF_1_NOHDR) &&
677c478bd9Sstevel@tonic-gate (osp->os_sgdesc->sg_phdr).p_type != PT_LOAD)
687c478bd9Sstevel@tonic-gate return;
697c478bd9Sstevel@tonic-gate
7069112eddSAli Bahrami osp->os_sgdesc->sg_align =
7169112eddSAli Bahrami ld_lcm(osp->os_sgdesc->sg_align, shdr->sh_addralign);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /*
751dd9d86fSAli Bahrami * Return the first input descriptor for a given output descriptor,
761dd9d86fSAli Bahrami * or NULL if there are none.
771dd9d86fSAli Bahrami */
781dd9d86fSAli Bahrami
791dd9d86fSAli Bahrami Is_desc *
ld_os_first_isdesc(Os_desc * osp)801dd9d86fSAli Bahrami ld_os_first_isdesc(Os_desc *osp)
811dd9d86fSAli Bahrami {
821dd9d86fSAli Bahrami int i;
831dd9d86fSAli Bahrami
841dd9d86fSAli Bahrami for (i = 0; i < OS_ISD_NUM; i++) {
851dd9d86fSAli Bahrami APlist *ap_isdesc = osp->os_isdescs[i];
861dd9d86fSAli Bahrami
871dd9d86fSAli Bahrami if (aplist_nitems(ap_isdesc) > 0)
881dd9d86fSAli Bahrami return ((Is_desc *)ap_isdesc->apl_data[0]);
891dd9d86fSAli Bahrami }
901dd9d86fSAli Bahrami
911dd9d86fSAli Bahrami return (NULL);
921dd9d86fSAli Bahrami }
931dd9d86fSAli Bahrami
941dd9d86fSAli Bahrami /*
951dd9d86fSAli Bahrami * Attach an input section to an output section
96cce0e03bSab196087 *
97cce0e03bSab196087 * entry:
98cce0e03bSab196087 * ofl - File descriptor
99cce0e03bSab196087 * osp - Output section descriptor
1001dd9d86fSAli Bahrami * isp - Input section descriptor
1011dd9d86fSAli Bahrami * mapfile_sort - True (1) if segment supports mapfile specified ordering
1021dd9d86fSAli Bahrami * of otherwise unordered input sections, and False (0) otherwise.
103cce0e03bSab196087 *
104cce0e03bSab196087 * exit:
1051dd9d86fSAli Bahrami * - The input section has been attached to the output section
106cce0e03bSab196087 * - If the input section is a candidate for string table merging,
107cce0e03bSab196087 * then it is appended to the output section's list of merge
108cce0e03bSab196087 * candidates (os_mstridescs).
109cce0e03bSab196087 *
110cce0e03bSab196087 * On success, returns True (1). On failure, False (0).
111cce0e03bSab196087 */
1121dd9d86fSAli Bahrami static int
os_attach_isp(Ofl_desc * ofl,Os_desc * osp,Is_desc * isp,int mapfile_sort)1131dd9d86fSAli Bahrami os_attach_isp(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp, int mapfile_sort)
114cce0e03bSab196087 {
1151dd9d86fSAli Bahrami Aliste init_arritems;
1161dd9d86fSAli Bahrami int os_isdescs_idx, do_append = 1;
1171dd9d86fSAli Bahrami
1181dd9d86fSAli Bahrami if ((isp->is_flags & FLG_IS_ORDERED) == 0) {
1191dd9d86fSAli Bahrami init_arritems = AL_CNT_OS_ISDESCS;
1201dd9d86fSAli Bahrami os_isdescs_idx = OS_ISD_DEFAULT;
121cce0e03bSab196087
122cce0e03bSab196087 /*
1231dd9d86fSAli Bahrami * If section ordering was specified for an unordered section
1241dd9d86fSAli Bahrami * via the mapfile, then search in the OS_ISD_DEFAULT list
1251dd9d86fSAli Bahrami * and insert it in the specified position. Ordered sections
1261dd9d86fSAli Bahrami * are placed in ascending order before unordered sections
1271dd9d86fSAli Bahrami * (sections with an is_ordndx value of zero).
1281dd9d86fSAli Bahrami *
1291dd9d86fSAli Bahrami * If no mapfile ordering was specified, we append it in
1301dd9d86fSAli Bahrami * the usual way below.
1311dd9d86fSAli Bahrami */
1321dd9d86fSAli Bahrami if (mapfile_sort && (isp->is_ordndx > 0)) {
1331dd9d86fSAli Bahrami APlist *ap_isdesc = osp->os_isdescs[OS_ISD_DEFAULT];
1341dd9d86fSAli Bahrami Aliste idx2;
1351dd9d86fSAli Bahrami Is_desc *isp2;
1361dd9d86fSAli Bahrami
1371dd9d86fSAli Bahrami for (APLIST_TRAVERSE(ap_isdesc, idx2, isp2)) {
1381dd9d86fSAli Bahrami if (isp2->is_ordndx &&
1391dd9d86fSAli Bahrami (isp2->is_ordndx <= isp->is_ordndx))
1401dd9d86fSAli Bahrami continue;
1411dd9d86fSAli Bahrami
1421dd9d86fSAli Bahrami if (aplist_insert(
1431dd9d86fSAli Bahrami &osp->os_isdescs[OS_ISD_DEFAULT],
1441dd9d86fSAli Bahrami isp, init_arritems, idx2) == NULL)
1451dd9d86fSAli Bahrami return (0);
1461dd9d86fSAli Bahrami do_append = 0;
1471dd9d86fSAli Bahrami break;
1481dd9d86fSAli Bahrami }
1491dd9d86fSAli Bahrami }
1501dd9d86fSAli Bahrami } else { /* Ordered section (via shdr flags) */
1511dd9d86fSAli Bahrami Word shndx;
1521dd9d86fSAli Bahrami
1531dd9d86fSAli Bahrami /* SHF_ORDERED uses sh_info, SHF_LINK_ORDERED uses sh_link */
1541dd9d86fSAli Bahrami shndx = (isp->is_shdr->sh_flags & SHF_ORDERED) ?
1551dd9d86fSAli Bahrami isp->is_shdr->sh_info : isp->is_shdr->sh_link;
1561dd9d86fSAli Bahrami
1571dd9d86fSAli Bahrami if (shndx == SHN_BEFORE) {
1581dd9d86fSAli Bahrami init_arritems = AL_CNT_OS_ISDESCS_BA;
1591dd9d86fSAli Bahrami os_isdescs_idx = OS_ISD_BEFORE;
1601dd9d86fSAli Bahrami } else if (shndx == SHN_AFTER) {
1611dd9d86fSAli Bahrami init_arritems = AL_CNT_OS_ISDESCS_BA;
1621dd9d86fSAli Bahrami os_isdescs_idx = OS_ISD_AFTER;
1631dd9d86fSAli Bahrami } else {
1641dd9d86fSAli Bahrami init_arritems = AL_CNT_OS_ISDESCS;
1651dd9d86fSAli Bahrami os_isdescs_idx = OS_ISD_ORDERED;
1661dd9d86fSAli Bahrami }
1671dd9d86fSAli Bahrami }
1681dd9d86fSAli Bahrami
1691dd9d86fSAli Bahrami /*
1701dd9d86fSAli Bahrami * If we didn't insert a section into the default list using
1711dd9d86fSAli Bahrami * mapfile specified ordering above, then append the input
1721dd9d86fSAli Bahrami * section to the appropriate list.
1731dd9d86fSAli Bahrami */
1741dd9d86fSAli Bahrami if (do_append && aplist_append(&(osp->os_isdescs[os_isdescs_idx]),
1751dd9d86fSAli Bahrami isp, init_arritems) == NULL)
1761dd9d86fSAli Bahrami return (0);
1771dd9d86fSAli Bahrami isp->is_osdesc = osp;
1781dd9d86fSAli Bahrami
1791dd9d86fSAli Bahrami /*
1801dd9d86fSAli Bahrami * A section can be merged if the following are true:
181cce0e03bSab196087 * - The SHF_MERGE|SHF_STRINGS flags must be set
182cce0e03bSab196087 * - String table compression must not be disabled (-znocompstrtab)
1831dd9d86fSAli Bahrami * - Mapfile ordering must not have been used.
1841dd9d86fSAli Bahrami * - The section must not be ordered via section header flags.
185cce0e03bSab196087 * - It must not be the generated section being built to
186cce0e03bSab196087 * replace the sections on this list.
187cce0e03bSab196087 */
188cce0e03bSab196087 if (((isp->is_shdr->sh_flags & (SHF_MERGE | SHF_STRINGS)) !=
189cce0e03bSab196087 (SHF_MERGE | SHF_STRINGS)) ||
190cce0e03bSab196087 ((ofl->ofl_flags1 & FLG_OF1_NCSTTAB) != 0) ||
1911dd9d86fSAli Bahrami !do_append ||
1921dd9d86fSAli Bahrami ((isp->is_flags & (FLG_IS_ORDERED | FLG_IS_GNSTRMRG)) != 0))
193cce0e03bSab196087 return (1);
194cce0e03bSab196087
195cce0e03bSab196087 /*
196cce0e03bSab196087 * Skip sections with (sh_entsize > 1) or (sh_addralign > 1).
197cce0e03bSab196087 *
198cce0e03bSab196087 * sh_entsize:
199cce0e03bSab196087 * We are currently only able to merge string tables containing
200cce0e03bSab196087 * strings with 1-byte (char) characters. Support for wide
201cce0e03bSab196087 * characters will require our string table compression code
202cce0e03bSab196087 * to be extended to handle larger character sizes.
203cce0e03bSab196087 *
204cce0e03bSab196087 * sh_addralign:
205cce0e03bSab196087 * Alignments greater than 1 would require our string table
206cce0e03bSab196087 * compression code to insert null bytes to move each
207cce0e03bSab196087 * string to the required alignment.
208cce0e03bSab196087 */
209cce0e03bSab196087 if ((isp->is_shdr->sh_entsize > 1) ||
210cce0e03bSab196087 (isp->is_shdr->sh_addralign > 1)) {
211cce0e03bSab196087 DBG_CALL(Dbg_sec_unsup_strmerge(ofl->ofl_lml, isp));
212cce0e03bSab196087 return (1);
213cce0e03bSab196087 }
214cce0e03bSab196087
215cce0e03bSab196087 if (aplist_append(&osp->os_mstrisdescs, isp,
216cce0e03bSab196087 AL_CNT_OS_MSTRISDESCS) == NULL)
217cce0e03bSab196087 return (0);
218cce0e03bSab196087
219cce0e03bSab196087 /*
220cce0e03bSab196087 * The SHF_MERGE|SHF_STRINGS flags tell us that the program that
221cce0e03bSab196087 * created the section intended it to be mergeable. The
222cce0e03bSab196087 * FLG_IS_INSTRMRG flag says that we have done validity testing
223cce0e03bSab196087 * and decided that it is safe to act on that hint.
224cce0e03bSab196087 */
225cce0e03bSab196087 isp->is_flags |= FLG_IS_INSTRMRG;
226cce0e03bSab196087
227cce0e03bSab196087 return (1);
228cce0e03bSab196087 }
229cce0e03bSab196087
230cce0e03bSab196087 /*
2310e233487SRod Evans * Determine whether this input COMDAT section already exists for the associated
2320e233487SRod Evans * output section. If so, then discard this input section. Otherwise, this
2330e233487SRod Evans * must be the first COMDAT section, thus it is kept for future comparisons.
2340e233487SRod Evans */
2350e233487SRod Evans static uintptr_t
add_comdat(Ofl_desc * ofl,Os_desc * osp,Is_desc * isp)2360e233487SRod Evans add_comdat(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp)
2370e233487SRod Evans {
2386b3ba5bdSAli Bahrami Isd_node isd, *isdp;
2396b3ba5bdSAli Bahrami avl_tree_t *avlt;
2406b3ba5bdSAli Bahrami avl_index_t where;
241ef16f6b5SRichard Lowe Group_desc *gr;
242ef16f6b5SRichard Lowe
243ef16f6b5SRichard Lowe /*
244ef16f6b5SRichard Lowe * Sections to which COMDAT groups apply are FLG_IS_COMDAT but are
245ef16f6b5SRichard Lowe * discarded separately by the group logic so should never be
246ef16f6b5SRichard Lowe * discarded here.
247ef16f6b5SRichard Lowe */
248ef16f6b5SRichard Lowe if ((isp->is_shdr->sh_flags & SHF_GROUP) &&
249ef16f6b5SRichard Lowe ((gr = ld_get_group(ofl, isp)) != NULL) &&
250ef16f6b5SRichard Lowe (gr->gd_data[0] & GRP_COMDAT))
251ef16f6b5SRichard Lowe return (1);
2520e233487SRod Evans
2536b3ba5bdSAli Bahrami /*
2546b3ba5bdSAli Bahrami * Create a COMDAT avl tree for this output section if required.
2556b3ba5bdSAli Bahrami */
2566b3ba5bdSAli Bahrami if ((avlt = osp->os_comdats) == NULL) {
2576b3ba5bdSAli Bahrami if ((avlt = libld_calloc(sizeof (avl_tree_t), 1)) == NULL)
2586b3ba5bdSAli Bahrami return (S_ERROR);
2596b3ba5bdSAli Bahrami avl_create(avlt, isdavl_compare, sizeof (Isd_node),
2606b3ba5bdSAli Bahrami SGSOFFSETOF(Isd_node, isd_avl));
2616b3ba5bdSAli Bahrami osp->os_comdats = avlt;
2626b3ba5bdSAli Bahrami }
263e64d0ff9SAli Bahrami
264e64d0ff9SAli Bahrami /*
265e64d0ff9SAli Bahrami * A standard COMDAT section uses the section name as search key.
266e64d0ff9SAli Bahrami */
267e64d0ff9SAli Bahrami isd.isd_name = isp->is_name;
268e64d0ff9SAli Bahrami isd.isd_hash = sgs_str_hash(isd.isd_name);
2690e233487SRod Evans
2706b3ba5bdSAli Bahrami if ((isdp = avl_find(avlt, &isd, &where)) != NULL) {
2710e233487SRod Evans isp->is_osdesc = osp;
2720e233487SRod Evans
2730e233487SRod Evans /*
2740e233487SRod Evans * If this section hasn't already been identified as discarded,
2750e233487SRod Evans * generate a suitable diagnostic.
2760e233487SRod Evans */
2770e233487SRod Evans if ((isp->is_flags & FLG_IS_DISCARD) == 0) {
2780e233487SRod Evans isp->is_flags |= FLG_IS_DISCARD;
2796b3ba5bdSAli Bahrami isp->is_comdatkeep = isdp->isd_isp;
2806b3ba5bdSAli Bahrami DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, isp,
2816b3ba5bdSAli Bahrami isdp->isd_isp));
2820e233487SRod Evans }
2830e233487SRod Evans
2840e233487SRod Evans /*
2850e233487SRod Evans * A discarded section does not require assignment to an output
2860e233487SRod Evans * section. However, if relaxed relocations have been enabled
2870e233487SRod Evans * (either from -z relaxreloc, or asserted with .gnu.linkonce
2880e233487SRod Evans * processing), then this section must still be assigned to an
2890e233487SRod Evans * output section so that the sloppy relocation logic will have
2900e233487SRod Evans * the information necessary to do its work.
2910e233487SRod Evans */
2920e233487SRod Evans return (0);
2930e233487SRod Evans }
2940e233487SRod Evans
2950e233487SRod Evans /*
2960e233487SRod Evans * This is a new COMDAT section - so keep it.
2970e233487SRod Evans */
2986b3ba5bdSAli Bahrami if ((isdp = libld_calloc(sizeof (Isd_node), 1)) == NULL)
2990e233487SRod Evans return (S_ERROR);
3000e233487SRod Evans
301e64d0ff9SAli Bahrami isdp->isd_name = isd.isd_name;
3026b3ba5bdSAli Bahrami isdp->isd_hash = isd.isd_hash;
3036b3ba5bdSAli Bahrami isdp->isd_isp = isp;
3046b3ba5bdSAli Bahrami
3056b3ba5bdSAli Bahrami avl_insert(avlt, isdp, where);
3060e233487SRod Evans return (1);
3070e233487SRod Evans }
3080e233487SRod Evans
3090e233487SRod Evans /*
3100e233487SRod Evans * Determine whether a GNU group COMDAT section name follows the convention
3110e233487SRod Evans *
3120e233487SRod Evans * section-name.symbol-name
3130e233487SRod Evans *
3140e233487SRod Evans * Each section within the input file is compared to see if the full section
3150e233487SRod Evans * name matches the beginning of the COMDAT section, with a following '.'.
3160e233487SRod Evans * A pointer to the symbol name, starting with the '.' is returned so that the
3170e233487SRod Evans * caller can strip off the required section name.
3180e233487SRod Evans */
3190e233487SRod Evans static char *
gnu_comdat_sym(Ifl_desc * ifl,Is_desc * gisp)3200e233487SRod Evans gnu_comdat_sym(Ifl_desc *ifl, Is_desc *gisp)
3210e233487SRod Evans {
3220e233487SRod Evans size_t ndx;
3230e233487SRod Evans
3240e233487SRod Evans for (ndx = 1; ndx < ifl->ifl_shnum; ndx++) {
3250e233487SRod Evans Is_desc *isp;
3260e233487SRod Evans size_t ssize;
3270e233487SRod Evans
3280e233487SRod Evans if (((isp = ifl->ifl_isdesc[ndx]) == NULL) ||
3290e233487SRod Evans (isp == gisp) || (isp->is_name == NULL))
3300e233487SRod Evans continue;
3310e233487SRod Evans
3320e233487SRod Evans /*
3330e233487SRod Evans * It's questionable whether this size should be cached in the
3340e233487SRod Evans * Is_desc. However, this seems an infrequent operation and
3350e233487SRod Evans * adding Is_desc members can escalate memory usage for large
3360e233487SRod Evans * link-edits. For now, size the section name dynamically.
3370e233487SRod Evans */
3380e233487SRod Evans ssize = strlen(isp->is_name);
33984f7afedSRichard Lowe if ((strncmp(isp->is_name, gisp->is_name, ssize) == 0) &&
3400e233487SRod Evans (gisp->is_name[ssize] == '.'))
3410e233487SRod Evans return ((char *)&gisp->is_name[ssize]);
3420e233487SRod Evans }
3430e233487SRod Evans return (NULL);
3440e233487SRod Evans }
3450e233487SRod Evans
3460e233487SRod Evans /*
3470e233487SRod Evans * GNU .gnu.linkonce sections follow a naming convention that indicates the
3480e233487SRod Evans * required association with an output section. Determine whether this input
3490e233487SRod Evans * section follows the convention, and if so return the appropriate output
3500e233487SRod Evans * section name.
3510e233487SRod Evans *
3520e233487SRod Evans * .gnu.linkonce.b.* -> .bss
3530e233487SRod Evans * .gnu.linkonce.d.* -> .data
3540e233487SRod Evans * .gnu.linkonce.l.* -> .ldata
3550e233487SRod Evans * .gnu.linkonce.lb.* -> .lbss
3560e233487SRod Evans * .gnu.linkonce.lr.* -> .lrodata
3570e233487SRod Evans * .gnu.linkonce.r.* -> .rodata
3580e233487SRod Evans * .gnu.linkonce.s.* -> .sdata
3590e233487SRod Evans * .gnu.linkonce.s2.* -> .sdata2
3600e233487SRod Evans * .gnu.linkonce.sb.* -> .sbss
3610e233487SRod Evans * .gnu.linkonce.sb2.* -> .sbss2
3620e233487SRod Evans * .gnu.linkonce.t.* -> .text
3630e233487SRod Evans * .gnu.linkonce.tb.* -> .tbss
3640e233487SRod Evans * .gnu.linkonce.td.* -> .tdata
3650e233487SRod Evans * .gnu.linkonce.wi.* -> .debug_info
3660e233487SRod Evans */
3670e233487SRod Evans #define NSTR_CH1(ch) (*(nstr + 1) == (ch))
3680e233487SRod Evans #define NSTR_CH2(ch) (*(nstr + 2) == (ch))
3690e233487SRod Evans #define NSTR_CH3(ch) (*(nstr + 3) == (ch))
3700e233487SRod Evans
3710e233487SRod Evans static const char *
gnu_linkonce_sec(const char * ostr)3720e233487SRod Evans gnu_linkonce_sec(const char *ostr)
3730e233487SRod Evans {
3740e233487SRod Evans const char *nstr = &ostr[MSG_SCN_GNU_LINKONCE_SIZE];
3750e233487SRod Evans
3760e233487SRod Evans switch (*nstr) {
3770e233487SRod Evans case 'b':
3780e233487SRod Evans if (NSTR_CH1('.'))
3790e233487SRod Evans return (MSG_ORIG(MSG_SCN_BSS));
3800e233487SRod Evans break;
3810e233487SRod Evans case 'd':
3820e233487SRod Evans if (NSTR_CH1('.'))
3830e233487SRod Evans return (MSG_ORIG(MSG_SCN_DATA));
3840e233487SRod Evans break;
3850e233487SRod Evans case 'l':
3860e233487SRod Evans if (NSTR_CH1('.'))
3870e233487SRod Evans return (MSG_ORIG(MSG_SCN_LDATA));
3880e233487SRod Evans else if (NSTR_CH1('b') && NSTR_CH2('.'))
3890e233487SRod Evans return (MSG_ORIG(MSG_SCN_LBSS));
3900e233487SRod Evans else if (NSTR_CH1('r') && NSTR_CH2('.'))
3910e233487SRod Evans return (MSG_ORIG(MSG_SCN_LRODATA));
3920e233487SRod Evans break;
3930e233487SRod Evans case 'r':
3940e233487SRod Evans if (NSTR_CH1('.'))
3950e233487SRod Evans return (MSG_ORIG(MSG_SCN_RODATA));
3960e233487SRod Evans break;
3970e233487SRod Evans case 's':
3980e233487SRod Evans if (NSTR_CH1('.'))
3990e233487SRod Evans return (MSG_ORIG(MSG_SCN_SDATA));
4000e233487SRod Evans else if (NSTR_CH1('2') && NSTR_CH2('.'))
4010e233487SRod Evans return (MSG_ORIG(MSG_SCN_SDATA2));
4020e233487SRod Evans else if (NSTR_CH1('b') && NSTR_CH2('.'))
4030e233487SRod Evans return (MSG_ORIG(MSG_SCN_SBSS));
4040e233487SRod Evans else if (NSTR_CH1('b') && NSTR_CH2('2') && NSTR_CH3('.'))
4050e233487SRod Evans return (MSG_ORIG(MSG_SCN_SBSS2));
4060e233487SRod Evans break;
4070e233487SRod Evans case 't':
4080e233487SRod Evans if (NSTR_CH1('.'))
4090e233487SRod Evans return (MSG_ORIG(MSG_SCN_TEXT));
4100e233487SRod Evans else if (NSTR_CH1('b') && NSTR_CH2('.'))
4110e233487SRod Evans return (MSG_ORIG(MSG_SCN_TBSS));
4120e233487SRod Evans else if (NSTR_CH1('d') && NSTR_CH2('.'))
4130e233487SRod Evans return (MSG_ORIG(MSG_SCN_TDATA));
4140e233487SRod Evans break;
4150e233487SRod Evans case 'w':
4160e233487SRod Evans if (NSTR_CH1('i') && NSTR_CH2('.'))
4170e233487SRod Evans return (MSG_ORIG(MSG_SCN_DEBUG_INFO));
4180e233487SRod Evans break;
4190e233487SRod Evans default:
4200e233487SRod Evans break;
4210e233487SRod Evans }
4220e233487SRod Evans
4230e233487SRod Evans /*
4240e233487SRod Evans * No special name match found.
4250e233487SRod Evans */
4260e233487SRod Evans return (ostr);
4270e233487SRod Evans }
4280e233487SRod Evans #undef NSTR_CH1
4290e233487SRod Evans #undef NSTR_CH2
4300e233487SRod Evans #undef NSTR_CH3
4310e233487SRod Evans
432ce686298SRichard Lowe /*
433ce686298SRichard Lowe * The GNU link-editor maps sections generated by the GNU compiler separately
434ce686298SRichard Lowe * due to -ffunction-sections, -fdata-sections or for other reasons into the
435ce686298SRichard Lowe * "normal" section represented.
436ce686298SRichard Lowe *
437ce686298SRichard Lowe * Sections are named .<main>.<symbol> where <main> is the usual section to
438ce686298SRichard Lowe * which it should be mapped, and <symbol> is providing the unique name for
439ce686298SRichard Lowe * the original section. Both parts of the name may contain periods, in cases
440ce686298SRichard Lowe * where the unique part of the name contains a '.' and/or the section it
441ce686298SRichard Lowe * contributes to does (such as .data.rel.ro)
442ce686298SRichard Lowe *
443ce686298SRichard Lowe * .rodata.str* and .rodata.cst* are mapped to .rodata.
444ce686298SRichard Lowe *
445ce686298SRichard Lowe * As a further complication, the GNU link-editor may or may not merge
446ce686298SRichard Lowe * .ctors.* and .dtors.* into init_array and fini_array, rather than ctors and
447ce686298SRichard Lowe * dtors. We do not implement this at this time.
448ce686298SRichard Lowe *
449ce686298SRichard Lowe * The GNU link editor may also arrange for sections with .local in their name
450ce686298SRichard Lowe * to be mapped as above, but grouped together. We do not implement this (and
451ce686298SRichard Lowe * do not merge them at all, to make this clear)
452ce686298SRichard Lowe *
453ce686298SRichard Lowe * This table is processed in order. Longer mappings must come first.
454ce686298SRichard Lowe */
455ce686298SRichard Lowe static struct split_sec_mapping {
456ce686298SRichard Lowe char *leader;
457ce686298SRichard Lowe char *section;
458ce686298SRichard Lowe boolean_t precise;
459ce686298SRichard Lowe } split_sec_mapping[] = {
460ce686298SRichard Lowe { ".bss.", ".bss", B_FALSE },
461ce686298SRichard Lowe { ".ctors.", ".ctors", B_FALSE },
462ce686298SRichard Lowe { ".data.rel.local.", ".data.rel.local", B_FALSE },
463ce686298SRichard Lowe { ".data.rel.local", ".data.rel.local", B_TRUE },
464ce686298SRichard Lowe { ".data.rel.ro.local.", ".data.rel.ro", B_FALSE },
465ce686298SRichard Lowe { ".data.rel.ro.", ".data.rel.ro", B_FALSE },
466ce686298SRichard Lowe { ".data.rel.ro", ".data.rel.ro", B_TRUE },
467ce686298SRichard Lowe { ".data.rel.", ".data.rel", B_FALSE },
468ce686298SRichard Lowe { ".data.rel", ".data.rel", B_TRUE },
469ce686298SRichard Lowe { ".data.", ".data", B_FALSE },
470ce686298SRichard Lowe { ".dtors.", ".dtors", B_FALSE },
471ce686298SRichard Lowe { ".fini_array.", ".fini_array", B_FALSE },
472ce686298SRichard Lowe { ".init_array.", ".init_array", B_FALSE },
473ce686298SRichard Lowe { ".lbss.", ".lbss", B_FALSE },
474ce686298SRichard Lowe { ".ldata.", ".ldata", B_FALSE },
475ce686298SRichard Lowe { ".lrodata.", ".lrodata", B_FALSE },
476ce686298SRichard Lowe /* This intentionally applies to .rodata.cstN and .rodata.strN, too */
477ce686298SRichard Lowe { ".rodata.", ".rodata", B_FALSE },
478ce686298SRichard Lowe { ".sbss2.", ".sbss2", B_FALSE },
479ce686298SRichard Lowe { ".sbss.", ".sbss", B_FALSE },
480ce686298SRichard Lowe { ".sdata2.", ".sdata2", B_FALSE },
481ce686298SRichard Lowe { ".sdata.", ".sdata", B_FALSE },
482ce686298SRichard Lowe { ".tbss.", ".tbss", B_FALSE },
483ce686298SRichard Lowe { ".tdata.", ".tdata", B_FALSE },
484ce686298SRichard Lowe { ".text.", ".text", B_FALSE },
485ce686298SRichard Lowe { NULL, NULL, B_FALSE }
486ce686298SRichard Lowe };
487ce686298SRichard Lowe
488ce686298SRichard Lowe static const char *
gnu_split_sec(const char * ostr)489ce686298SRichard Lowe gnu_split_sec(const char *ostr)
490ce686298SRichard Lowe {
491ce686298SRichard Lowe struct split_sec_mapping *mp;
492ce686298SRichard Lowe
493ce686298SRichard Lowe for (mp = split_sec_mapping; mp->leader != NULL; mp++) {
494ce686298SRichard Lowe if (mp->precise) {
495ce686298SRichard Lowe if (strcmp(ostr, mp->leader) == 0)
496ce686298SRichard Lowe return (mp->section);
497ce686298SRichard Lowe } else if (strncmp(ostr, mp->leader, strlen(mp->leader)) == 0) {
498ce686298SRichard Lowe return (mp->section);
499ce686298SRichard Lowe }
500ce686298SRichard Lowe }
501ce686298SRichard Lowe
502ce686298SRichard Lowe return (ostr);
503ce686298SRichard Lowe }
50469112eddSAli Bahrami
50569112eddSAli Bahrami /*
50669112eddSAli Bahrami * Initialize a path info buffer for use with ld_place_section().
50769112eddSAli Bahrami *
50869112eddSAli Bahrami * entry:
50969112eddSAli Bahrami * ofl - Output descriptor
51069112eddSAli Bahrami * ifl - Descriptor for input file, or NULL if there is none.
51169112eddSAli Bahrami * info - Address of buffer to be initialized.
51269112eddSAli Bahrami *
51369112eddSAli Bahrami * exit:
51469112eddSAli Bahrami * If this is an input file, and if the entrance criteria list
51569112eddSAli Bahrami * contains at least one criteria that has a non-empty file string
51669112eddSAli Bahrami * match list (ec_files), then the block pointed at by info is
51769112eddSAli Bahrami * initialized, and info is returned.
51869112eddSAli Bahrami *
51969112eddSAli Bahrami * If there is no input file, and/or no entrance criteria containing
52069112eddSAli Bahrami * a non-empty ec_files list, then NULL is returned. This is not
52169112eddSAli Bahrami * an error --- the NULL is simply an optimization, understood by
52269112eddSAli Bahrami * ld_place_path(), that allows it to skip unnecessary work.
52369112eddSAli Bahrami */
52469112eddSAli Bahrami Place_path_info *
ld_place_path_info_init(Ofl_desc * ofl,Ifl_desc * ifl,Place_path_info * info)52569112eddSAli Bahrami ld_place_path_info_init(Ofl_desc *ofl, Ifl_desc *ifl, Place_path_info *info)
52669112eddSAli Bahrami {
52769112eddSAli Bahrami /*
52869112eddSAli Bahrami * Return NULL if there is no input file (internally generated section)
52969112eddSAli Bahrami * or if the entrance criteria list does not contain any items that will
53069112eddSAli Bahrami * need to be compared to the path (all the ec_files lists are empty).
53169112eddSAli Bahrami */
53269112eddSAli Bahrami if ((ifl == NULL) || !(ofl->ofl_flags & FLG_OF_EC_FILES))
53369112eddSAli Bahrami return (NULL);
53469112eddSAli Bahrami
53569112eddSAli Bahrami info->ppi_path = ifl->ifl_name;
53669112eddSAli Bahrami info->ppi_path_len = strlen(info->ppi_path);
53769112eddSAli Bahrami info->ppi_isar = (ifl->ifl_flags & FLG_IF_EXTRACT) != 0;
53869112eddSAli Bahrami
53969112eddSAli Bahrami /*
54069112eddSAli Bahrami * The basename is the final segment of the path, equivalent to
54169112eddSAli Bahrami * the path itself if there are no '/' delimiters.
54269112eddSAli Bahrami */
54369112eddSAli Bahrami info->ppi_bname = strrchr(info->ppi_path, '/');
54469112eddSAli Bahrami if (info->ppi_bname == NULL)
54569112eddSAli Bahrami info->ppi_bname = info->ppi_path;
54669112eddSAli Bahrami else
54769112eddSAli Bahrami info->ppi_bname++; /* Skip leading '/' */
54869112eddSAli Bahrami info->ppi_bname_len =
54969112eddSAli Bahrami info->ppi_path_len - (info->ppi_bname - info->ppi_path);
55069112eddSAli Bahrami
55169112eddSAli Bahrami /*
55269112eddSAli Bahrami * For an archive, the object name is the member name, which is
55369112eddSAli Bahrami * enclosed in () at the end of the name string. Otherwise, it is
55469112eddSAli Bahrami * the same as the basename.
55569112eddSAli Bahrami */
55669112eddSAli Bahrami if (info->ppi_isar) {
55769112eddSAli Bahrami info->ppi_oname = strrchr(info->ppi_bname, '(');
55869112eddSAli Bahrami /* There must be an archive member suffix delimited by parens */
55969112eddSAli Bahrami assert((info->ppi_bname[info->ppi_bname_len - 1] == ')') &&
56069112eddSAli Bahrami (info->ppi_oname != NULL));
56169112eddSAli Bahrami info->ppi_oname++; /* skip leading '(' */
56269112eddSAli Bahrami info->ppi_oname_len = info->ppi_bname_len -
56369112eddSAli Bahrami (info->ppi_oname - info->ppi_bname + 1);
56469112eddSAli Bahrami } else {
56569112eddSAli Bahrami info->ppi_oname = info->ppi_bname;
56669112eddSAli Bahrami info->ppi_oname_len = info->ppi_bname_len;
56769112eddSAli Bahrami }
56869112eddSAli Bahrami
56969112eddSAli Bahrami return (info);
57069112eddSAli Bahrami }
57169112eddSAli Bahrami
57269112eddSAli Bahrami /*
57369112eddSAli Bahrami * Compare an input section path to the file comparison list the given
57469112eddSAli Bahrami * entrance criteria.
57569112eddSAli Bahrami *
57669112eddSAli Bahrami * entry:
57769112eddSAli Bahrami * path_info - A non-NULL Place_path_info block for the file
57869112eddSAli Bahrami * containing the input section, initialized by
57969112eddSAli Bahrami * ld_place_path_info_init()
58069112eddSAli Bahrami * enp - Entrance criteria with a non-empty ec_files list of file
58169112eddSAli Bahrami * comparisons to be carried out.
58269112eddSAli Bahrami *
58369112eddSAli Bahrami * exit:
58469112eddSAli Bahrami * Return TRUE if a match is seen, and FALSE otherwise.
58569112eddSAli Bahrami */
58669112eddSAli Bahrami static Boolean
eval_ec_files(Place_path_info * path_info,Ent_desc * enp)58769112eddSAli Bahrami eval_ec_files(Place_path_info *path_info, Ent_desc *enp)
58869112eddSAli Bahrami {
58969112eddSAli Bahrami Aliste idx;
59069112eddSAli Bahrami Ent_desc_file *edfp;
59169112eddSAli Bahrami size_t cmp_len;
59269112eddSAli Bahrami const char *cmp_str;
59369112eddSAli Bahrami
59469112eddSAli Bahrami for (ALIST_TRAVERSE(enp->ec_files, idx, edfp)) {
59569112eddSAli Bahrami Word type = edfp->edf_flags & TYP_ECF_MASK;
59669112eddSAli Bahrami
59769112eddSAli Bahrami /*
59869112eddSAli Bahrami * Determine the starting character, and # of characters,
59969112eddSAli Bahrami * from the file path to compare against this entrance criteria
60069112eddSAli Bahrami * file string.
60169112eddSAli Bahrami */
60269112eddSAli Bahrami if (type == TYP_ECF_OBJNAME) {
60369112eddSAli Bahrami cmp_str = path_info->ppi_oname;
60469112eddSAli Bahrami cmp_len = path_info->ppi_oname_len;
60569112eddSAli Bahrami } else {
60669112eddSAli Bahrami int ar_stat_diff = path_info->ppi_isar !=
60769112eddSAli Bahrami ((edfp->edf_flags & FLG_ECF_ARMEMBER) != 0);
60869112eddSAli Bahrami
60969112eddSAli Bahrami /*
61069112eddSAli Bahrami * If the entrance criteria specifies an archive member
61169112eddSAli Bahrami * and the file does not, then there can be no match.
61269112eddSAli Bahrami */
61369112eddSAli Bahrami
61469112eddSAli Bahrami if (ar_stat_diff && !path_info->ppi_isar)
61569112eddSAli Bahrami continue;
61669112eddSAli Bahrami
61769112eddSAli Bahrami if (type == TYP_ECF_PATH) {
61869112eddSAli Bahrami cmp_str = path_info->ppi_path;
61969112eddSAli Bahrami cmp_len = path_info->ppi_path_len;
62069112eddSAli Bahrami } else { /* TYP_ECF_BASENAME */
62169112eddSAli Bahrami cmp_str = path_info->ppi_bname;
62269112eddSAli Bahrami cmp_len = path_info->ppi_bname_len;
62369112eddSAli Bahrami }
62469112eddSAli Bahrami
62569112eddSAli Bahrami /*
62669112eddSAli Bahrami * If the entrance criteria does not specify an archive
62769112eddSAli Bahrami * member and the file does, then a match just requires
62869112eddSAli Bahrami * the paths (without the archive member) to match.
62969112eddSAli Bahrami * Reduce the length to not include the ar member or
63069112eddSAli Bahrami * the '(' that precedes it.
63169112eddSAli Bahrami */
63269112eddSAli Bahrami if (ar_stat_diff && path_info->ppi_isar)
63369112eddSAli Bahrami cmp_len = path_info->ppi_oname - cmp_str - 1;
63469112eddSAli Bahrami }
63569112eddSAli Bahrami
63669112eddSAli Bahrami /*
63769112eddSAli Bahrami * Compare the resulting string to the one from the
63869112eddSAli Bahrami * entrance criteria.
63969112eddSAli Bahrami */
64069112eddSAli Bahrami if ((cmp_len == edfp->edf_name_len) &&
64169112eddSAli Bahrami (strncmp(edfp->edf_name, cmp_str, cmp_len) == 0))
64269112eddSAli Bahrami return (TRUE);
64369112eddSAli Bahrami }
64469112eddSAli Bahrami
64569112eddSAli Bahrami return (FALSE);
64669112eddSAli Bahrami }
64769112eddSAli Bahrami
6480e233487SRod Evans /*
649d444b03eSAli Bahrami * Replace the section header for the given input section with a new section
650d444b03eSAli Bahrami * header of the specified type. All values in the replacement header other
651d444b03eSAli Bahrami * than the type retain their previous values.
652d444b03eSAli Bahrami *
653d444b03eSAli Bahrami * entry:
654d444b03eSAli Bahrami * isp - Input section to replace
655d444b03eSAli Bahrami * sh_type - New section type to apply
656d444b03eSAli Bahrami *
657d444b03eSAli Bahrami * exit:
658d444b03eSAli Bahrami * Returns the pointer to the new section header on success, and
659d444b03eSAli Bahrami * NULL for failure.
660d444b03eSAli Bahrami */
661d444b03eSAli Bahrami static Shdr *
isp_convert_type(Is_desc * isp,Word sh_type)662d444b03eSAli Bahrami isp_convert_type(Is_desc *isp, Word sh_type)
663d444b03eSAli Bahrami {
664d444b03eSAli Bahrami Shdr *shdr;
665d444b03eSAli Bahrami
666d444b03eSAli Bahrami if ((shdr = libld_malloc(sizeof (Shdr))) == NULL)
667d444b03eSAli Bahrami return (NULL);
668d444b03eSAli Bahrami *shdr = *isp->is_shdr;
669d444b03eSAli Bahrami isp->is_shdr = shdr;
670d444b03eSAli Bahrami shdr->sh_type = sh_type;
671d444b03eSAli Bahrami return (shdr);
672d444b03eSAli Bahrami }
673d444b03eSAli Bahrami
674d444b03eSAli Bahrami /*
675d444b03eSAli Bahrami * Issue a fatal warning for the given .eh_frame section, which
676d444b03eSAli Bahrami * cannot be merged with the existing .eh_frame output section.
677d444b03eSAli Bahrami */
678d444b03eSAli Bahrami static void
eh_frame_muldef(Ofl_desc * ofl,Is_desc * isp)679d444b03eSAli Bahrami eh_frame_muldef(Ofl_desc *ofl, Is_desc *isp)
680d444b03eSAli Bahrami {
681d444b03eSAli Bahrami Sg_desc *sgp;
682d444b03eSAli Bahrami Is_desc *isp1;
683d444b03eSAli Bahrami Os_desc *osp;
684d444b03eSAli Bahrami Aliste idx1, idx2, idx3;
685d444b03eSAli Bahrami
686d444b03eSAli Bahrami /*
687d444b03eSAli Bahrami * Locate the .eh_frame output section, and use the first section
688d444b03eSAli Bahrami * assigned to it in the error message. The user can then compare
689d444b03eSAli Bahrami * the two sections to determine what attribute prevented the merge.
690d444b03eSAli Bahrami */
691d444b03eSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
692d444b03eSAli Bahrami for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
693d444b03eSAli Bahrami if ((osp->os_flags & FLG_OS_EHFRAME) == 0)
694d444b03eSAli Bahrami continue;
695d444b03eSAli Bahrami
696d444b03eSAli Bahrami for (idx3 = 0; idx3 < OS_ISD_NUM; idx3++) {
697d444b03eSAli Bahrami APlist *lst = osp->os_isdescs[idx3];
698d444b03eSAli Bahrami
699d444b03eSAli Bahrami if (aplist_nitems(lst) == 0)
700d444b03eSAli Bahrami continue;
701d444b03eSAli Bahrami
702d444b03eSAli Bahrami isp1 = lst->apl_data[0];
7031007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
704d444b03eSAli Bahrami MSG_INTL(MSG_UPD_MULEHFRAME),
705d444b03eSAli Bahrami isp1->is_file->ifl_name,
706d444b03eSAli Bahrami EC_WORD(isp1->is_scnndx), isp1->is_name,
707d444b03eSAli Bahrami isp->is_file->ifl_name,
708d444b03eSAli Bahrami EC_WORD(isp->is_scnndx), isp->is_name);
709d444b03eSAli Bahrami return;
710d444b03eSAli Bahrami }
711d444b03eSAli Bahrami }
712d444b03eSAli Bahrami }
713d444b03eSAli Bahrami }
714d444b03eSAli Bahrami
715d444b03eSAli Bahrami /*
7161dd9d86fSAli Bahrami * Place a section into the appropriate segment and output section.
7171dd9d86fSAli Bahrami *
7181dd9d86fSAli Bahrami * entry:
7191dd9d86fSAli Bahrami * ofl - File descriptor
7201dd9d86fSAli Bahrami * isp - Input section descriptor of section to be placed.
72169112eddSAli Bahrami * path_info - NULL, or pointer to Place_path_info buffer initialized
72269112eddSAli Bahrami * by ld_place_path_info_init() for the file associated to isp,
72369112eddSAli Bahrami * for use in processing entrance criteria with non-empty
72469112eddSAli Bahrami * file matching string list (ec_files)
7251dd9d86fSAli Bahrami * ident - Section identifier, used to order sections relative to
7261dd9d86fSAli Bahrami * others within the output segment.
7271dd9d86fSAli Bahrami * alt_os_name - If non-NULL, the name of the output section to place
7281dd9d86fSAli Bahrami * isp into. If NULL, input sections go to an output section
7291dd9d86fSAli Bahrami * with the same name as the input section.
7307c478bd9Sstevel@tonic-gate */
7317c478bd9Sstevel@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)73269112eddSAli Bahrami ld_place_section(Ofl_desc *ofl, Is_desc *isp, Place_path_info *path_info,
73369112eddSAli Bahrami int ident, const char *alt_os_name)
7347c478bd9Sstevel@tonic-gate {
7357c478bd9Sstevel@tonic-gate Ent_desc *enp;
7367c478bd9Sstevel@tonic-gate Sg_desc *sgp;
737cce0e03bSab196087 Os_desc *osp;
73857ef7aa9SRod Evans Aliste idx1, iidx;
739cc7efc4fSrie int os_ndx;
7407c478bd9Sstevel@tonic-gate Shdr *shdr = isp->is_shdr;
7417c478bd9Sstevel@tonic-gate Xword shflagmask, shflags = shdr->sh_flags;
7427c478bd9Sstevel@tonic-gate Ifl_desc *ifl = isp->is_file;
7430e233487SRod Evans char *oname, *sname;
7440e233487SRod Evans uint_t onamehash;
745d444b03eSAli Bahrami Boolean is_ehframe = (isp->is_flags & FLG_IS_EHFRAME) != 0;
7467c478bd9Sstevel@tonic-gate
7470bc07c75Srie /*
7480bc07c75Srie * Define any sections that must be thought of as referenced. These
74908278a5eSRod Evans * sections may not be referenced externally in a manner ld(1) can
7500bc07c75Srie * discover, but they must be retained (ie. not removed by -zignore).
7510bc07c75Srie */
7520bc07c75Srie static const Msg RefSecs[] = {
7530bc07c75Srie MSG_SCN_INIT, /* MSG_ORIG(MSG_SCN_INIT) */
7540bc07c75Srie MSG_SCN_FINI, /* MSG_ORIG(MSG_SCN_FINI) */
7550bc07c75Srie MSG_SCN_EX_RANGES, /* MSG_ORIG(MSG_SCN_EX_RANGES) */
7560bc07c75Srie MSG_SCN_EX_SHARED, /* MSG_ORIG(MSG_SCN_EX_SHARED) */
7570bc07c75Srie MSG_SCN_CTORS, /* MSG_ORIG(MSG_SCN_CTORS) */
7580bc07c75Srie MSG_SCN_DTORS, /* MSG_ORIG(MSG_SCN_DTORS) */
7590bc07c75Srie MSG_SCN_EHFRAME, /* MSG_ORIG(MSG_SCN_EHFRAME) */
7600bc07c75Srie MSG_SCN_EHFRAME_HDR, /* MSG_ORIG(MSG_SCN_EHFRAME_HDR) */
7610bc07c75Srie MSG_SCN_JCR, /* MSG_ORIG(MSG_SCN_JCR) */
762*9f9b7953SRichard Lowe MSG_SCN_INITARRAY, /* MSG_ORIG(MSG_SCN_INITARRAY) */
763*9f9b7953SRichard Lowe MSG_SCN_FINIARRAY, /* MSG_ORIG(MSG_SCN_FINIARRAY) */
764*9f9b7953SRichard Lowe MSG_SCN_PREINITARRAY, /* MSG_ORIG(MSG_SCN_PREINITARRAY) */
7650bc07c75Srie 0
7660bc07c75Srie };
7670bc07c75Srie
7685aefb655Srie DBG_CALL(Dbg_sec_in(ofl->ofl_lml, isp));
7697c478bd9Sstevel@tonic-gate
7700e233487SRod Evans /*
77108278a5eSRod Evans * If this section identifies group members, or this section indicates
7720e233487SRod Evans * that it is a member of a group, determine whether the section is
7730e233487SRod Evans * still required.
7740e233487SRod Evans */
7757c478bd9Sstevel@tonic-gate if ((shflags & SHF_GROUP) || (shdr->sh_type == SHT_GROUP)) {
776cc7efc4fSrie Group_desc *gdesc;
777cc7efc4fSrie
7780e233487SRod Evans if ((gdesc = ld_get_group(ofl, isp)) != NULL) {
7795aefb655Srie DBG_CALL(Dbg_sec_group(ofl->ofl_lml, isp, gdesc));
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate /*
7820e233487SRod Evans * If this group has been replaced by another group,
7830e233487SRod Evans * then this section needs to be discarded.
7847c478bd9Sstevel@tonic-gate */
7850e233487SRod Evans if (gdesc->gd_oisc) {
7867c478bd9Sstevel@tonic-gate isp->is_flags |= FLG_IS_DISCARD;
7870e233487SRod Evans
788d2ef9fe9Sab196087 /*
789d2ef9fe9Sab196087 * Since we're discarding the section, we
790d2ef9fe9Sab196087 * can skip assigning it to an output section.
791d2ef9fe9Sab196087 * The exception is that if the user
792d2ef9fe9Sab196087 * specifies -z relaxreloc, then
793d2ef9fe9Sab196087 * we need to assign the output section so
794d2ef9fe9Sab196087 * that the sloppy relocation logic will have
795d2ef9fe9Sab196087 * the information necessary to do its work.
796d2ef9fe9Sab196087 */
797d2ef9fe9Sab196087 if (!(ofl->ofl_flags1 & FLG_OF1_RLXREL))
7986b3ba5bdSAli Bahrami return (NULL);
7997c478bd9Sstevel@tonic-gate }
800cc7efc4fSrie }
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate /*
803cc7efc4fSrie * SHT_GROUP sections can only be included into relocatable
8047c478bd9Sstevel@tonic-gate * objects.
8057c478bd9Sstevel@tonic-gate */
806cc7efc4fSrie if (shdr->sh_type == SHT_GROUP) {
807cc7efc4fSrie if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
8087c478bd9Sstevel@tonic-gate isp->is_flags |= FLG_IS_DISCARD;
8096b3ba5bdSAli Bahrami return (NULL);
8107c478bd9Sstevel@tonic-gate }
8117c478bd9Sstevel@tonic-gate }
812cc7efc4fSrie }
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate /*
815cc7efc4fSrie * Always assign SHF_TLS sections to the DATA segment (and then the
816cc7efc4fSrie * PT_TLS embedded inside of there).
8177c478bd9Sstevel@tonic-gate */
8187c478bd9Sstevel@tonic-gate if (shflags & SHF_TLS)
8197c478bd9Sstevel@tonic-gate shflags |= SHF_WRITE;
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate /*
8227c478bd9Sstevel@tonic-gate * Traverse the entrance criteria list searching for a segment that
8237c478bd9Sstevel@tonic-gate * matches the input section we have. If an entrance criterion is set
8247c478bd9Sstevel@tonic-gate * then there must be an exact match. If we complete the loop without
8257c478bd9Sstevel@tonic-gate * finding a segment, then sgp will be NULL.
8267c478bd9Sstevel@tonic-gate */
8277c478bd9Sstevel@tonic-gate sgp = NULL;
82869112eddSAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_ents, idx1, enp)) {
82969112eddSAli Bahrami
83069112eddSAli Bahrami /* Disabled segments are not available for assignment */
83169112eddSAli Bahrami if (enp->ec_segment->sg_flags & FLG_SG_DISABLED)
8327c478bd9Sstevel@tonic-gate continue;
83369112eddSAli Bahrami
83469112eddSAli Bahrami /*
83569112eddSAli Bahrami * If an entrance criteria doesn't have any of its fields
83669112eddSAli Bahrami * set, it will match any section it is tested against.
83769112eddSAli Bahrami * We set the FLG_EC_CATCHALL flag on these, primarily because
83869112eddSAli Bahrami * it helps readers of our debug output to understand what
83969112eddSAli Bahrami * the criteria means --- otherwise the user would just see
84069112eddSAli Bahrami * that every field is 0, but might not understand the
84169112eddSAli Bahrami * significance of that.
84269112eddSAli Bahrami *
84369112eddSAli Bahrami * Given that we set this flag, we can use it here as an
84469112eddSAli Bahrami * optimization to short circuit all of the tests in this
84569112eddSAli Bahrami * loop. Note however, that if we did not do this, the end
84669112eddSAli Bahrami * result would be the same --- the empty criteria will sail
84769112eddSAli Bahrami * past the following tests and reach the end of the loop.
84869112eddSAli Bahrami */
84969112eddSAli Bahrami if (enp->ec_flags & FLG_EC_CATCHALL) {
85069112eddSAli Bahrami sgp = enp->ec_segment;
85169112eddSAli Bahrami break;
85269112eddSAli Bahrami }
85369112eddSAli Bahrami
8547c478bd9Sstevel@tonic-gate if (enp->ec_type && (enp->ec_type != shdr->sh_type))
8557c478bd9Sstevel@tonic-gate continue;
8567c478bd9Sstevel@tonic-gate if (enp->ec_attrmask &&
8577c478bd9Sstevel@tonic-gate /* LINTED */
8587c478bd9Sstevel@tonic-gate (enp->ec_attrmask & enp->ec_attrbits) !=
8597c478bd9Sstevel@tonic-gate (enp->ec_attrmask & shflags))
8607c478bd9Sstevel@tonic-gate continue;
86169112eddSAli Bahrami if (enp->ec_is_name &&
86269112eddSAli Bahrami (strcmp(enp->ec_is_name, isp->is_name) != 0))
8637c478bd9Sstevel@tonic-gate continue;
8647c478bd9Sstevel@tonic-gate
86569112eddSAli Bahrami if ((alist_nitems(enp->ec_files) > 0) &&
86669112eddSAli Bahrami ((path_info == NULL) || !eval_ec_files(path_info, enp)))
8677c478bd9Sstevel@tonic-gate continue;
86869112eddSAli Bahrami
86969112eddSAli Bahrami /* All entrance criteria tests passed */
87057ef7aa9SRod Evans sgp = enp->ec_segment;
8717c478bd9Sstevel@tonic-gate break;
8727c478bd9Sstevel@tonic-gate }
8737c478bd9Sstevel@tonic-gate
87469112eddSAli Bahrami /*
87569112eddSAli Bahrami * The final entrance criteria record is a FLG_EC_CATCHALL that points
87669112eddSAli Bahrami * at the final predefined segment "extra", and this final segment is
87769112eddSAli Bahrami * tagged FLG_SG_NODISABLE. Therefore, the above loop must always find
87869112eddSAli Bahrami * a segment.
87969112eddSAli Bahrami */
88069112eddSAli Bahrami assert(sgp != NULL);
88169112eddSAli Bahrami
88269112eddSAli Bahrami /*
88369112eddSAli Bahrami * Transfer the input section sorting key from the entrance criteria
88469112eddSAli Bahrami * to the input section. A non-zero value means that the section
88569112eddSAli Bahrami * will be sorted on this key amoung the other sections that have a
88669112eddSAli Bahrami * non-zero key. These sorted sections are collectively placed at the
88769112eddSAli Bahrami * head of the output section.
88869112eddSAli Bahrami *
88969112eddSAli Bahrami * If the sort key is 0, the section is placed after the sorted
89069112eddSAli Bahrami * sections in the order they are encountered.
89169112eddSAli Bahrami */
89269112eddSAli Bahrami isp->is_ordndx = enp->ec_ordndx;
89369112eddSAli Bahrami
89469112eddSAli Bahrami /* Remember that this entrance criteria has placed a section */
89569112eddSAli Bahrami enp->ec_flags |= FLG_EC_USED;
8967c478bd9Sstevel@tonic-gate
8970e233487SRod Evans /*
8981dd9d86fSAli Bahrami * If our caller has supplied an alternative name for the output
8991dd9d86fSAli Bahrami * section, then we defer to their request. Otherwise, the default
9001dd9d86fSAli Bahrami * is to use the same name as that of the input section being placed.
9011dd9d86fSAli Bahrami *
9021dd9d86fSAli Bahrami * The COMDAT, SHT_GROUP and GNU name translations that follow have
9031dd9d86fSAli Bahrami * the potential to alter this initial name.
9040e233487SRod Evans */
9051dd9d86fSAli Bahrami oname = (char *)((alt_os_name == NULL) ? isp->is_name : alt_os_name);
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate /*
9080e233487SRod Evans * Solaris section names may follow the convention:
9090e233487SRod Evans *
9100e233487SRod Evans * section-name%symbol-name
9110e233487SRod Evans *
9120e233487SRod Evans * This convention has been used to order the layout of sections within
9130e233487SRod Evans * segments for objects built with the compilers -xF option. However,
9140e233487SRod Evans * the final object should not contain individual section headers for
9150e233487SRod Evans * all such input sections, instead the symbol name is stripped from the
9160e233487SRod Evans * name to establish the final output section name.
9170e233487SRod Evans *
9180e233487SRod Evans * This convention has also been followed for COMDAT and sections
9190e233487SRod Evans * identified though SHT_GROUP data.
9200e233487SRod Evans *
92169112eddSAli Bahrami * Strip out the % from the section name for:
92269112eddSAli Bahrami * - Non-relocatable objects
92369112eddSAli Bahrami * - Relocatable objects if input section sorting is
92469112eddSAli Bahrami * in force for the segment in question.
9257c478bd9Sstevel@tonic-gate */
9260e233487SRod Evans if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) ||
92769112eddSAli Bahrami (sgp->sg_flags & FLG_SG_IS_ORDER)) {
9280e233487SRod Evans if ((sname = strchr(isp->is_name, '%')) != NULL) {
9290e233487SRod Evans size_t size = sname - isp->is_name;
9307c478bd9Sstevel@tonic-gate
9310e233487SRod Evans if ((oname = libld_malloc(size + 1)) == NULL)
9327c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
9330e233487SRod Evans (void) strncpy(oname, isp->is_name, size);
9340e233487SRod Evans oname[size] = '\0';
935e23c41c9SAli Bahrami DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname));
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate /*
940396f90f9SRichard Lowe * When building relocatable objects, we must not redirect COMDAT
941396f90f9SRichard Lowe * section names into their outputs, such that our output object may
942396f90f9SRichard Lowe * be successfully used as an input object also requiring COMDAT
943396f90f9SRichard Lowe * processing
944396f90f9SRichard Lowe */
945396f90f9SRichard Lowe
946396f90f9SRichard Lowe /*
9470e233487SRod Evans * GNU section names may follow the convention:
9480e233487SRod Evans *
9490e233487SRod Evans * .gnu.linkonce.*
9500e233487SRod Evans *
9510e233487SRod Evans * The .gnu.linkonce is a section naming convention that indicates a
9520e233487SRod Evans * COMDAT requirement. Determine whether this section follows the GNU
9530e233487SRod Evans * pattern, and if so, determine whether this section should be
954ca4eed8bSAli Bahrami * discarded or retained. The comparison of is_name[1] with 'g'
955ca4eed8bSAli Bahrami * is an optimization to skip using strncmp() too much. This is safe,
956ca4eed8bSAli Bahrami * because we know the name is not NULL, and therefore must have
957ca4eed8bSAli Bahrami * at least one character plus a NULL termination.
9587c478bd9Sstevel@tonic-gate */
959396f90f9SRichard Lowe if ((isp->is_name == oname) && (isp->is_name[1] == 'g') &&
9600e233487SRod Evans (strncmp(MSG_ORIG(MSG_SCN_GNU_LINKONCE), isp->is_name,
9610e233487SRod Evans MSG_SCN_GNU_LINKONCE_SIZE) == 0)) {
962396f90f9SRichard Lowe if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
963396f90f9SRichard Lowe if ((oname = (char *)gnu_linkonce_sec(isp->is_name)) !=
964396f90f9SRichard Lowe isp->is_name) {
965396f90f9SRichard Lowe DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp,
966396f90f9SRichard Lowe oname));
967396f90f9SRichard Lowe }
9680e233487SRod Evans }
9690e233487SRod Evans
9700e233487SRod Evans /*
9710e233487SRod Evans * Explicitly identify this section type as COMDAT. Also,
972e64d0ff9SAli Bahrami * enable relaxed relocation processing, as this is typically
973e64d0ff9SAli Bahrami * a requirement with .gnu.linkonce sections.
9740e233487SRod Evans */
9750e233487SRod Evans isp->is_flags |= FLG_IS_COMDAT;
9760e233487SRod Evans if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0)
9770e233487SRod Evans ofl->ofl_flags1 |= FLG_OF1_RLXREL;
97869112eddSAli Bahrami DBG_CALL(Dbg_sec_gnu_comdat(ofl->ofl_lml, isp, TRUE,
97969112eddSAli Bahrami (ofl->ofl_flags1 & FLG_OF1_RLXREL) != 0));
9800e233487SRod Evans }
9810e233487SRod Evans
9820e233487SRod Evans /*
9830e233487SRod Evans * GNU section names may also follow the convention:
9840e233487SRod Evans *
9850e233487SRod Evans * section-name.symbol-name
9860e233487SRod Evans *
9870e233487SRod Evans * This convention is used when defining SHT_GROUP sections of type
9880e233487SRod Evans * COMDAT. Thus, any group processing will have discovered any group
9890e233487SRod Evans * sections, and this identification can be triggered by a pattern
9900e233487SRod Evans * match section names.
9910e233487SRod Evans */
992396f90f9SRichard Lowe if ((isp->is_name == oname) && (isp->is_flags & FLG_IS_COMDAT) &&
9930e233487SRod Evans ((sname = gnu_comdat_sym(ifl, isp)) != NULL)) {
9940e233487SRod Evans size_t size = sname - isp->is_name;
9950e233487SRod Evans
996396f90f9SRichard Lowe if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
9970e233487SRod Evans if ((oname = libld_malloc(size + 1)) == NULL)
9980e233487SRod Evans return ((Os_desc *)S_ERROR);
9990e233487SRod Evans (void) strncpy(oname, isp->is_name, size);
10000e233487SRod Evans oname[size] = '\0';
1001e23c41c9SAli Bahrami DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname));
1002396f90f9SRichard Lowe }
10030e233487SRod Evans
10040e233487SRod Evans /*
1005e64d0ff9SAli Bahrami * Enable relaxed relocation processing, as this is
1006e64d0ff9SAli Bahrami * typically a requirement with GNU COMDAT sections.
10070e233487SRod Evans */
10080e233487SRod Evans if ((ofl->ofl_flags1 & FLG_OF1_NRLXREL) == 0) {
10090e233487SRod Evans ofl->ofl_flags1 |= FLG_OF1_RLXREL;
101069112eddSAli Bahrami DBG_CALL(Dbg_sec_gnu_comdat(ofl->ofl_lml, isp,
101169112eddSAli Bahrami FALSE, TRUE));
10120e233487SRod Evans }
10130e233487SRod Evans }
10140e233487SRod Evans
10150e233487SRod Evans /*
1016ce686298SRichard Lowe * GNU section names named section-name.symbol-name which are not
1017ce686298SRichard Lowe * members of COMDAT groups are merged according to the behaviour of
1018ce686298SRichard Lowe * the GNU link-editor.
1019ce686298SRichard Lowe *
1020ce686298SRichard Lowe * See the description of gnu_split_sec().
1021ce686298SRichard Lowe */
1022ce686298SRichard Lowe if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) &&
1023ce686298SRichard Lowe (isp->is_name == oname) &&
1024ce686298SRichard Lowe ((oname = (char *)gnu_split_sec(oname)) != isp->is_name)) {
1025ce686298SRichard Lowe DBG_CALL(Dbg_sec_redirected(ofl->ofl_lml, isp, oname));
1026ce686298SRichard Lowe }
1027ce686298SRichard Lowe
1028ce686298SRichard Lowe /*
10290e233487SRod Evans * Assign a hash value now that the output section name has been
10300e233487SRod Evans * finalized.
10310e233487SRod Evans */
10320e233487SRod Evans onamehash = sgs_str_hash(oname);
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate /*
103569112eddSAli Bahrami * Determine if output section ordering is turned on. If so, return
103669112eddSAli Bahrami * the appropriate ordering index for the section. This information
103769112eddSAli Bahrami * is derived from the Sg_desc->sg_os_order list that was built
10381dd9d86fSAli Bahrami * up from the Mapfile.
103969112eddSAli Bahrami *
104069112eddSAli Bahrami * A value of 0 for os_ndx means that the section is not sorted
104169112eddSAli Bahrami * (i.e. is not found in the sg_os_order). The items in sg_os_order
104269112eddSAli Bahrami * are in the desired sort order, so adding 1 to their alist index
104369112eddSAli Bahrami * gives a suitable index for sorting.
10447c478bd9Sstevel@tonic-gate */
10450bc07c75Srie os_ndx = 0;
104669112eddSAli Bahrami if (alist_nitems(sgp->sg_os_order) > 0) {
1047cce0e03bSab196087 Sec_order *scop;
10480bc07c75Srie
104969112eddSAli Bahrami for (ALIST_TRAVERSE(sgp->sg_os_order, idx1, scop)) {
10500e233487SRod Evans if (strcmp(scop->sco_secname, oname) == 0) {
10510bc07c75Srie scop->sco_flags |= FLG_SGO_USED;
105269112eddSAli Bahrami os_ndx = idx1 + 1;
10530bc07c75Srie break;
10540bc07c75Srie }
10550bc07c75Srie }
10560bc07c75Srie }
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate /*
10591dd9d86fSAli Bahrami * Mask of section header flags to ignore when matching sections. We
10601dd9d86fSAli Bahrami * are more strict with relocatable objects, ignoring only the order
10611dd9d86fSAli Bahrami * flags, and keeping sections apart if they differ otherwise. This
10621dd9d86fSAli Bahrami * follows the policy that sections in a relative object should only
10631dd9d86fSAli Bahrami * be merged if their flags are the same, and avoids destroying
10641dd9d86fSAli Bahrami * information prematurely. For final products however, we ignore all
1065240e56feSab196087 * flags that do not prevent a merge.
10667c478bd9Sstevel@tonic-gate */
106757ef7aa9SRod Evans shflagmask =
106857ef7aa9SRod Evans (ofl->ofl_flags & FLG_OF_RELOBJ) ? ALL_SHF_ORDER : ALL_SHF_IGNORE;
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate /*
10717c478bd9Sstevel@tonic-gate * Traverse the input section list for the output section we have been
10727c478bd9Sstevel@tonic-gate * assigned. If we find a matching section simply add this new section.
10737c478bd9Sstevel@tonic-gate */
107457ef7aa9SRod Evans iidx = 0;
1075cce0e03bSab196087 for (APLIST_TRAVERSE(sgp->sg_osdescs, idx1, osp)) {
1076d444b03eSAli Bahrami Shdr *os_shdr = osp->os_shdr;
10770bc07c75Srie
1078d444b03eSAli Bahrami /*
1079d444b03eSAli Bahrami * An input section matches an output section if:
1080d444b03eSAli Bahrami * - The ident values match
1081d444b03eSAli Bahrami * - The names match
1082d444b03eSAli Bahrami * - Not a GROUP section
1083d444b03eSAli Bahrami * - Not a DTrace dof section
1084d444b03eSAli Bahrami * - Section types match
1085d444b03eSAli Bahrami * - Matching section flags, after screening out the
1086d444b03eSAli Bahrami * shflagmask flags.
1087d444b03eSAli Bahrami *
1088d444b03eSAli Bahrami * Section types are considered to match if any one of
1089d444b03eSAli Bahrami * the following are true:
1090d444b03eSAli Bahrami * - The type codes are the same
10913fc1e289SBryan Cantrill * - Both are .eh_frame sections (regardless of type code)
1092d444b03eSAli Bahrami * - The input section is COMDAT, and the output section
1093d444b03eSAli Bahrami * is SHT_PROGBITS.
1094d444b03eSAli Bahrami */
109557ef7aa9SRod Evans if ((ident == osp->os_identndx) &&
1096ba2be530Sab196087 (ident != ld_targ.t_id.id_rel) &&
10970e233487SRod Evans (onamehash == osp->os_namehash) &&
10980bc07c75Srie (shdr->sh_type != SHT_GROUP) &&
10997c478bd9Sstevel@tonic-gate (shdr->sh_type != SHT_SUNW_dof) &&
1100d444b03eSAli Bahrami ((shdr->sh_type == os_shdr->sh_type) ||
11013fc1e289SBryan Cantrill (is_ehframe && (osp->os_flags & FLG_OS_EHFRAME)) ||
11027c478bd9Sstevel@tonic-gate ((shdr->sh_type == SHT_SUNW_COMDAT) &&
1103d444b03eSAli Bahrami (os_shdr->sh_type == SHT_PROGBITS))) &&
11047c478bd9Sstevel@tonic-gate ((shflags & ~shflagmask) ==
1105d444b03eSAli Bahrami (os_shdr->sh_flags & ~shflagmask)) &&
11060e233487SRod Evans (strcmp(oname, osp->os_name) == 0)) {
11070e233487SRod Evans uintptr_t err;
11087c478bd9Sstevel@tonic-gate
11097c478bd9Sstevel@tonic-gate /*
11100e233487SRod Evans * Process any COMDAT section, keeping the first and
11110e233487SRod Evans * discarding all others.
11127c478bd9Sstevel@tonic-gate */
11130e233487SRod Evans if ((isp->is_flags & FLG_IS_COMDAT) &&
11140e233487SRod Evans ((err = add_comdat(ofl, osp, isp)) != 1))
11150e233487SRod Evans return ((Os_desc *)err);
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate /*
11187c478bd9Sstevel@tonic-gate * Set alignment
11197c478bd9Sstevel@tonic-gate */
11207c478bd9Sstevel@tonic-gate set_addralign(ofl, osp, isp);
11217c478bd9Sstevel@tonic-gate
11227c478bd9Sstevel@tonic-gate /*
1123dd94ecefSrie * If this section is a non-empty TLS section indicate
1124dd94ecefSrie * that a PT_TLS program header is required.
11257c478bd9Sstevel@tonic-gate */
1126dd94ecefSrie if ((shflags & SHF_TLS) && shdr->sh_size &&
1127dd94ecefSrie ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0))
1128dd94ecefSrie ofl->ofl_flags |= FLG_OF_TLSPHDR;
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate /*
11311dd9d86fSAli Bahrami * Insert the input section descriptor on the proper
11321dd9d86fSAli Bahrami * output section descriptor list.
11331dd9d86fSAli Bahrami *
11341dd9d86fSAli Bahrami * If this segment requires input section ordering,
11351dd9d86fSAli Bahrami * honor any mapfile specified ordering for otherwise
11361dd9d86fSAli Bahrami * unordered sections by setting the mapfile_sort
11371dd9d86fSAli Bahrami * argument of os_attach_isp() to True.
11387c478bd9Sstevel@tonic-gate */
11397c478bd9Sstevel@tonic-gate
11401dd9d86fSAli Bahrami if (os_attach_isp(ofl, osp, isp,
114169112eddSAli Bahrami (sgp->sg_flags & FLG_SG_IS_ORDER) != 0) == 0)
11427c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate /*
11457c478bd9Sstevel@tonic-gate * If this input section and file is associated to an
11467c478bd9Sstevel@tonic-gate * artificially referenced output section, make sure
1147e23c41c9SAli Bahrami * they are marked as referenced also. This ensures
1148e23c41c9SAli Bahrami * that this input section and file isn't eliminated
1149e23c41c9SAli Bahrami * when -zignore is in effect.
1150e23c41c9SAli Bahrami *
11517c478bd9Sstevel@tonic-gate * See -zignore comments when creating a new output
11527c478bd9Sstevel@tonic-gate * section below.
11537c478bd9Sstevel@tonic-gate */
11540bc07c75Srie if (((ifl &&
11550bc07c75Srie (ifl->ifl_flags & FLG_IF_IGNORE)) || DBG_ENABLED) &&
11567c478bd9Sstevel@tonic-gate (osp->os_flags & FLG_OS_SECTREF)) {
11577c478bd9Sstevel@tonic-gate isp->is_flags |= FLG_IS_SECTREF;
11587c478bd9Sstevel@tonic-gate if (ifl)
11597c478bd9Sstevel@tonic-gate ifl->ifl_flags |= FLG_IF_FILEREF;
11607c478bd9Sstevel@tonic-gate }
11617c478bd9Sstevel@tonic-gate
11625aefb655Srie DBG_CALL(Dbg_sec_added(ofl->ofl_lml, osp, sgp));
11637c478bd9Sstevel@tonic-gate return (osp);
11647c478bd9Sstevel@tonic-gate }
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate /*
11670bc07c75Srie * Do we need to worry about section ordering?
11687c478bd9Sstevel@tonic-gate */
11697c478bd9Sstevel@tonic-gate if (os_ndx) {
117057ef7aa9SRod Evans if (osp->os_ordndx) {
117157ef7aa9SRod Evans if (os_ndx < osp->os_ordndx)
11727c478bd9Sstevel@tonic-gate /* insert section here. */
11737c478bd9Sstevel@tonic-gate break;
11747c478bd9Sstevel@tonic-gate else {
117557ef7aa9SRod Evans iidx = idx1 + 1;
11767c478bd9Sstevel@tonic-gate continue;
11777c478bd9Sstevel@tonic-gate }
11787c478bd9Sstevel@tonic-gate } else {
11797c478bd9Sstevel@tonic-gate /* insert section here. */
11807c478bd9Sstevel@tonic-gate break;
11817c478bd9Sstevel@tonic-gate }
118257ef7aa9SRod Evans } else if (osp->os_ordndx) {
118357ef7aa9SRod Evans iidx = idx1 + 1;
11847c478bd9Sstevel@tonic-gate continue;
11857c478bd9Sstevel@tonic-gate }
11867c478bd9Sstevel@tonic-gate
11877c478bd9Sstevel@tonic-gate /*
11887c478bd9Sstevel@tonic-gate * If the new sections identifier is less than that of the
11897c478bd9Sstevel@tonic-gate * present input section we need to insert the new section
11907c478bd9Sstevel@tonic-gate * at this point.
11917c478bd9Sstevel@tonic-gate */
119257ef7aa9SRod Evans if (ident < osp->os_identndx)
11937c478bd9Sstevel@tonic-gate break;
11940bc07c75Srie
119557ef7aa9SRod Evans iidx = idx1 + 1;
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate
11987c478bd9Sstevel@tonic-gate /*
11997c478bd9Sstevel@tonic-gate * We are adding a new output section. Update the section header
12007c478bd9Sstevel@tonic-gate * count and associated string size.
1201e64d0ff9SAli Bahrami *
1202e64d0ff9SAli Bahrami * If the input section triggering this output section has been marked
1203e64d0ff9SAli Bahrami * for discard, and if no other non-discarded input section comes along
1204e64d0ff9SAli Bahrami * to join it, then we will over count. We cannot know if this will
1205e64d0ff9SAli Bahrami * happen or not until all input is seen. Set FLG_OF_AJDOSCNT to
1206e64d0ff9SAli Bahrami * trigger a final count readjustment.
12077c478bd9Sstevel@tonic-gate */
1208e64d0ff9SAli Bahrami if (isp->is_flags & FLG_IS_DISCARD)
1209e64d0ff9SAli Bahrami ofl->ofl_flags |= FLG_OF_ADJOSCNT;
12107c478bd9Sstevel@tonic-gate ofl->ofl_shdrcnt++;
12110e233487SRod Evans if (st_insert(ofl->ofl_shdrsttab, oname) == -1)
12127c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate /*
12157c478bd9Sstevel@tonic-gate * Create a new output section descriptor.
12167c478bd9Sstevel@tonic-gate */
12176b3ba5bdSAli Bahrami if ((osp = libld_calloc(sizeof (Os_desc), 1)) == NULL)
12187c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
12196b3ba5bdSAli Bahrami if ((osp->os_shdr = libld_calloc(sizeof (Shdr), 1)) == NULL)
12207c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate /*
12230e233487SRod Evans * Convert COMDAT section to PROGBITS as this the first section of the
12240e233487SRod Evans * output section. Save any COMDAT section for later processing, as
12250e233487SRod Evans * additional COMDAT sections that match this section need discarding.
12267c478bd9Sstevel@tonic-gate */
1227d444b03eSAli Bahrami if ((shdr->sh_type == SHT_SUNW_COMDAT) &&
1228d444b03eSAli Bahrami ((shdr = isp_convert_type(isp, SHT_PROGBITS)) == NULL))
12297c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
12300e233487SRod Evans if ((isp->is_flags & FLG_IS_COMDAT) &&
12316b3ba5bdSAli Bahrami (add_comdat(ofl, osp, isp) == S_ERROR))
12320e233487SRod Evans return ((Os_desc *)S_ERROR);
12337c478bd9Sstevel@tonic-gate
1234d444b03eSAli Bahrami if (is_ehframe) {
1235d444b03eSAli Bahrami /*
1236d444b03eSAli Bahrami * Executable or sharable objects can have at most a single
1237d444b03eSAli Bahrami * .eh_frame section. Detect attempts to create more than
1238d444b03eSAli Bahrami * one. This occurs if the input sections have incompatible
1239d444b03eSAli Bahrami * attributes.
1240d444b03eSAli Bahrami */
1241d444b03eSAli Bahrami if ((ofl->ofl_flags & FLG_OF_EHFRAME) &&
1242d444b03eSAli Bahrami !(ofl->ofl_flags & FLG_OF_RELOBJ)) {
1243d444b03eSAli Bahrami eh_frame_muldef(ofl, isp);
1244d444b03eSAli Bahrami return ((Os_desc *)S_ERROR);
1245d444b03eSAli Bahrami }
1246d444b03eSAli Bahrami ofl->ofl_flags |= FLG_OF_EHFRAME;
12473fc1e289SBryan Cantrill
12483fc1e289SBryan Cantrill /*
12493fc1e289SBryan Cantrill * For .eh_frame sections, we always set the type to be the
12503fc1e289SBryan Cantrill * type specified by the ABI. This allows .eh_frame sections
12513fc1e289SBryan Cantrill * of type SHT_PROGBITS to be correctly merged with .eh_frame
12523fc1e289SBryan Cantrill * sections of the ABI-defined type (e.g. SHT_AMD64_UNWIND),
12533fc1e289SBryan Cantrill * with the output being of the ABI-defined type.
12543fc1e289SBryan Cantrill */
12553fc1e289SBryan Cantrill osp->os_shdr->sh_type = ld_targ.t_m.m_sht_unwind;
12563fc1e289SBryan Cantrill } else {
12573fc1e289SBryan Cantrill osp->os_shdr->sh_type = shdr->sh_type;
1258d444b03eSAli Bahrami }
1259d444b03eSAli Bahrami
12607c478bd9Sstevel@tonic-gate osp->os_shdr->sh_flags = shdr->sh_flags;
12617c478bd9Sstevel@tonic-gate osp->os_shdr->sh_entsize = shdr->sh_entsize;
12620e233487SRod Evans osp->os_name = oname;
12630e233487SRod Evans osp->os_namehash = onamehash;
126457ef7aa9SRod Evans osp->os_ordndx = os_ndx;
12657c478bd9Sstevel@tonic-gate osp->os_sgdesc = sgp;
1266d444b03eSAli Bahrami if (is_ehframe)
1267d444b03eSAli Bahrami osp->os_flags |= FLG_OS_EHFRAME;
12680bc07c75Srie
12697c478bd9Sstevel@tonic-gate if (ifl && (shdr->sh_type == SHT_PROGBITS)) {
12707c478bd9Sstevel@tonic-gate /*
12714899432aSab196087 * Try to preserve the intended meaning of sh_link/sh_info.
12720bc07c75Srie * See the translate_link() in update.c.
12737c478bd9Sstevel@tonic-gate */
12747c478bd9Sstevel@tonic-gate osp->os_shdr->sh_link = shdr->sh_link;
12757c478bd9Sstevel@tonic-gate if (shdr->sh_flags & SHF_INFO_LINK)
12767c478bd9Sstevel@tonic-gate osp->os_shdr->sh_info = shdr->sh_info;
12777c478bd9Sstevel@tonic-gate }
12787c478bd9Sstevel@tonic-gate
12797c478bd9Sstevel@tonic-gate /*
12800bc07c75Srie * When -zignore is in effect, user supplied sections and files that are
12810bc07c75Srie * not referenced from other sections, are eliminated from the object
12820bc07c75Srie * being produced. Some sections, although unreferenced, are special,
12830bc07c75Srie * and must not be eliminated. Determine if this new output section is
12840bc07c75Srie * one of those special sections, and if so mark it artificially as
12850bc07c75Srie * referenced. Any input section and file associated to this output
12860bc07c75Srie * section is also be marked as referenced, and thus won't be eliminated
12877c478bd9Sstevel@tonic-gate * from the final output.
12887c478bd9Sstevel@tonic-gate */
12890bc07c75Srie if (ifl && ((ofl->ofl_flags1 & FLG_OF1_IGNPRC) || DBG_ENABLED)) {
12900bc07c75Srie const Msg *refsec;
12910bc07c75Srie
12920bc07c75Srie for (refsec = RefSecs; *refsec; refsec++) {
12930bc07c75Srie if (strcmp(osp->os_name, MSG_ORIG(*refsec)) == 0) {
12947c478bd9Sstevel@tonic-gate osp->os_flags |= FLG_OS_SECTREF;
12957c478bd9Sstevel@tonic-gate
12960bc07c75Srie if ((ifl->ifl_flags & FLG_IF_IGNORE) ||
12970bc07c75Srie DBG_ENABLED) {
12987c478bd9Sstevel@tonic-gate isp->is_flags |= FLG_IS_SECTREF;
12997c478bd9Sstevel@tonic-gate ifl->ifl_flags |= FLG_IF_FILEREF;
13007c478bd9Sstevel@tonic-gate }
13010bc07c75Srie break;
13020bc07c75Srie }
13030bc07c75Srie }
13047c478bd9Sstevel@tonic-gate }
13057c478bd9Sstevel@tonic-gate
13067c478bd9Sstevel@tonic-gate /*
130757ef7aa9SRod Evans * Sections of type SHT_GROUP are added to the ofl->ofl_osgroups list,
130857ef7aa9SRod Evans * so that they can be updated as a group later.
13097c478bd9Sstevel@tonic-gate */
131057ef7aa9SRod Evans if ((shdr->sh_type == SHT_GROUP) &&
1311c866e237SRichard Lowe ((isp->is_flags & FLG_IS_DISCARD) == 0) &&
131257ef7aa9SRod Evans (aplist_append(&ofl->ofl_osgroups, osp,
131357ef7aa9SRod Evans AL_CNT_OFL_OSGROUPS) == NULL))
13147c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate /*
1317dd94ecefSrie * If this section is a non-empty TLS section indicate that a PT_TLS
1318dd94ecefSrie * program header is required.
13197c478bd9Sstevel@tonic-gate */
1320dd94ecefSrie if ((shflags & SHF_TLS) && shdr->sh_size &&
1321dd94ecefSrie ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0))
1322dd94ecefSrie ofl->ofl_flags |= FLG_OF_TLSPHDR;
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate /*
13257c478bd9Sstevel@tonic-gate * If a non-allocatable section is going to be put into a loadable
13267c478bd9Sstevel@tonic-gate * segment then turn on the allocate bit for this section and warn the
13277c478bd9Sstevel@tonic-gate * user that we have done so. This could only happen through the use
13287c478bd9Sstevel@tonic-gate * of a mapfile.
13297c478bd9Sstevel@tonic-gate */
13300bc07c75Srie if ((sgp->sg_phdr.p_type == PT_LOAD) &&
13310bc07c75Srie ((osp->os_shdr->sh_flags & SHF_ALLOC) == 0)) {
13321007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SCN_NONALLOC),
133369112eddSAli Bahrami ofl->ofl_name, osp->os_name, sgp->sg_name);
13347c478bd9Sstevel@tonic-gate osp->os_shdr->sh_flags |= SHF_ALLOC;
13357c478bd9Sstevel@tonic-gate }
13367c478bd9Sstevel@tonic-gate
13377c478bd9Sstevel@tonic-gate /*
13387c478bd9Sstevel@tonic-gate * Retain this sections identifier for future comparisons when placing
13397c478bd9Sstevel@tonic-gate * a section (after all sections have been processed this variable will
13407c478bd9Sstevel@tonic-gate * be used to hold the sections symbol index as we don't need to retain
13417c478bd9Sstevel@tonic-gate * the identifier any more).
13427c478bd9Sstevel@tonic-gate */
134357ef7aa9SRod Evans osp->os_identndx = ident;
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate /*
134657ef7aa9SRod Evans * Set alignment.
13477c478bd9Sstevel@tonic-gate */
13487c478bd9Sstevel@tonic-gate set_addralign(ofl, osp, isp);
13497c478bd9Sstevel@tonic-gate
13501dd9d86fSAli Bahrami if (os_attach_isp(ofl, osp, isp, 0) == 0)
13517c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
13527c478bd9Sstevel@tonic-gate
13535aefb655Srie DBG_CALL(Dbg_sec_created(ofl->ofl_lml, osp, sgp));
13540bc07c75Srie
13550bc07c75Srie /*
135657ef7aa9SRod Evans * Insert the new section at the offset given by iidx. If no position
135757ef7aa9SRod Evans * for it was identified above, this will be index 0, causing the new
135857ef7aa9SRod Evans * section to be prepended to the beginning of the section list.
135957ef7aa9SRod Evans * Otherwise, it is the index following the section that was identified.
13600bc07c75Srie */
1361cce0e03bSab196087 if (aplist_insert(&sgp->sg_osdescs, osp, AL_CNT_SG_OSDESC,
136257ef7aa9SRod Evans iidx) == NULL)
13637c478bd9Sstevel@tonic-gate return ((Os_desc *)S_ERROR);
13647c478bd9Sstevel@tonic-gate return (osp);
13657c478bd9Sstevel@tonic-gate }
1366