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 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 * 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 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 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 * 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 * 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 * 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 * 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 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 * 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 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 * 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*afcdab23SRichard Lowe MSG_SCN_INITARRAY, /* MSG_ORIG(MSG_SCN_INITARRAY) */ 763*afcdab23SRichard Lowe MSG_SCN_FINIARRAY, /* MSG_ORIG(MSG_SCN_FINIARRAY) */ 764*afcdab23SRichard 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