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