17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 247c478bd9Sstevel@tonic-gate * All Rights Reserved 257c478bd9Sstevel@tonic-gate * 26f441771bSRod Evans * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Update the new output file image, perform virtual address, offset and 317c478bd9Sstevel@tonic-gate * displacement calculations on the program headers and sections headers, 327c478bd9Sstevel@tonic-gate * and generate any new output section information. 337c478bd9Sstevel@tonic-gate */ 34ba2be530Sab 35ba2be530Sab #define ELF_TARGET_AMD64 36ba2be530Sab 377c478bd9Sstevel@tonic-gate #include <stdio.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 39fdf855a7Sseizo #include <unistd.h> 405aefb655Srie #include <debug.h> 417c478bd9Sstevel@tonic-gate #include "msg.h" 427c478bd9Sstevel@tonic-gate #include "_libld.h" 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* 459039eeafSab * Comparison routine used by qsort() for sorting of the global symbol list 467c478bd9Sstevel@tonic-gate * based off of the hashbuckets the symbol will eventually be deposited in. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate static int 497c478bd9Sstevel@tonic-gate sym_hash_compare(Sym_s_list * s1, Sym_s_list * s2) 507c478bd9Sstevel@tonic-gate { 517c478bd9Sstevel@tonic-gate return (s1->sl_hval - s2->sl_hval); 527c478bd9Sstevel@tonic-gate } 537c478bd9Sstevel@tonic-gate 54d579eb63Sab /* 55d579eb63Sab * Comparison routine used by qsort() for sorting of dyn[sym|tls]sort section 56d579eb63Sab * indices based on the address of the symbols they reference. The 57d579eb63Sab * use of the global dynsort_compare_syms variable is needed because 58d579eb63Sab * we need to examine the symbols the indices reference. It is safe, because 59d579eb63Sab * the linker is single threaded. 60d579eb63Sab */ 61ae940584SToomas Soome static Sym *dynsort_compare_syms; 62d579eb63Sab 63d579eb63Sab static int 64d579eb63Sab dynsort_compare(const void *idx1, const void *idx2) 65d579eb63Sab { 66d579eb63Sab Sym *s1 = dynsort_compare_syms + *((const Word *) idx1); 67d579eb63Sab Sym *s2 = dynsort_compare_syms + *((const Word *) idx2); 68d579eb63Sab 69d579eb63Sab /* 70d579eb63Sab * Note: the logical computation for this is 71d579eb63Sab * (st_value1 - st_value2) 72d579eb63Sab * However, that is only correct if the address type is smaller 73d579eb63Sab * than a pointer. Writing it this way makes it immune to the 74d579eb63Sab * class (32 or 64-bit) of the linker. 75d579eb63Sab */ 76d579eb63Sab return ((s1->st_value < s2->st_value) ? -1 : 77d579eb63Sab (s1->st_value > s2->st_value)); 78d579eb63Sab } 79d579eb63Sab 80d579eb63Sab /* 81d579eb63Sab * Scan the sorted symbols, and issue warnings if there are any duplicate 82d579eb63Sab * values in the list. We only do this if -zverbose is set, or we are 83d579eb63Sab * running with LD_DEBUG defined 84d579eb63Sab * 85d579eb63Sab * entry: 86d579eb63Sab * ofl - Output file descriptor 87d579eb63Sab * ldynsym - Pointer to start of .SUNW_ldynsym section that the 88d579eb63Sab * sort section indexes reference. 89d579eb63Sab * symsort - Pointer to start of .SUNW_dynsymsort or .SUNW_dyntlssort 90d579eb63Sab * section. 91d579eb63Sab * n - # of indices in symsort array 92d579eb63Sab * secname - Name of the symsort section. 93d579eb63Sab * 94d579eb63Sab * exit: 95d579eb63Sab * If the symsort section contains indexes to more than one 96d579eb63Sab * symbol with the same address value, a warning is issued. 97d579eb63Sab */ 98d579eb63Sab static void 99d579eb63Sab dynsort_dupwarn(Ofl_desc *ofl, Sym *ldynsym, const char *str, 100d579eb63Sab Word *symsort, Word n, const char *secname) 101d579eb63Sab { 102d579eb63Sab int zverbose = (ofl->ofl_flags & FLG_OF_VERBOSE) != 0; 103d579eb63Sab Word ndx, cmp_ndx; 104d579eb63Sab Addr addr, cmp_addr; 105d579eb63Sab 106d579eb63Sab /* Nothing to do if -zverbose or LD_DEBUG are not active */ 107d579eb63Sab if (!(zverbose || DBG_ENABLED)) 108d579eb63Sab return; 109d579eb63Sab 110d579eb63Sab cmp_ndx = 0; 111d579eb63Sab cmp_addr = ldynsym[symsort[cmp_ndx]].st_value; 112d579eb63Sab for (ndx = 1; ndx < n; ndx++) { 113d579eb63Sab addr = ldynsym[symsort[ndx]].st_value; 114d579eb63Sab if (cmp_addr == addr) { 115d579eb63Sab if (zverbose) 1161007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 117d579eb63Sab MSG_INTL(MSG_SYM_DUPSORTADDR), secname, 118d579eb63Sab str + ldynsym[symsort[cmp_ndx]].st_name, 119d579eb63Sab str + ldynsym[symsort[ndx]].st_name, 120d579eb63Sab EC_ADDR(addr)); 121d579eb63Sab DBG_CALL(Dbg_syms_dup_sort_addr(ofl->ofl_lml, secname, 122d579eb63Sab str + ldynsym[symsort[cmp_ndx]].st_name, 123d579eb63Sab str + ldynsym[symsort[ndx]].st_name, 124d579eb63Sab EC_ADDR(addr))); 125d579eb63Sab } else { /* Not a dup. Move reference up */ 126d579eb63Sab cmp_ndx = ndx; 127d579eb63Sab cmp_addr = addr; 128d579eb63Sab } 129d579eb63Sab } 130d579eb63Sab } 131d579eb63Sab 1328222814eSRichard Lowe static inline Boolean 1338222814eSRichard Lowe ass_enabled(Ass_desc *ma, uint_t ass) 1348222814eSRichard Lowe { 1358222814eSRichard Lowe return ((ma->ass_enabled & ass) != 0); 1368222814eSRichard Lowe } 1378222814eSRichard Lowe 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Build and update any output symbol tables. Here we work on all the symbol 1407c478bd9Sstevel@tonic-gate * tables at once to reduce the duplication of symbol and string manipulation. 1417c478bd9Sstevel@tonic-gate * Symbols and their associated strings are copied from the read-only input 1427c478bd9Sstevel@tonic-gate * file images to the output image and their values and index's updated in the 1437c478bd9Sstevel@tonic-gate * output image. 1447c478bd9Sstevel@tonic-gate */ 1455aefb655Srie static Addr 1467c478bd9Sstevel@tonic-gate update_osym(Ofl_desc *ofl) 1477c478bd9Sstevel@tonic-gate { 148d579eb63Sab /* 149d579eb63Sab * There are several places in this function where we wish 150d579eb63Sab * to insert a symbol index to the combined .SUNW_ldynsym/.dynsym 151d579eb63Sab * symbol table into one of the two sort sections (.SUNW_dynsymsort 152d579eb63Sab * or .SUNW_dyntlssort), if that symbol has the right attributes. 153d579eb63Sab * This macro is used to generate the necessary code from a single 154d579eb63Sab * specification. 155d579eb63Sab * 156d579eb63Sab * entry: 157d579eb63Sab * _sdp, _sym, _type - As per DYNSORT_COUNT. See _libld.h 158d579eb63Sab * _sym_ndx - Index that _sym will have in the combined 159d579eb63Sab * .SUNW_ldynsym/.dynsym symbol table. 160d579eb63Sab */ 161d579eb63Sab #define ADD_TO_DYNSORT(_sdp, _sym, _type, _sym_ndx) \ 162d579eb63Sab { \ 163d579eb63Sab Word *_dynsort_arr, *_dynsort_ndx; \ 164d579eb63Sab \ 165d579eb63Sab if (dynsymsort_symtype[_type]) { \ 166d579eb63Sab _dynsort_arr = dynsymsort; \ 167d579eb63Sab _dynsort_ndx = &dynsymsort_ndx; \ 168d579eb63Sab } else if (_type == STT_TLS) { \ 169d579eb63Sab _dynsort_arr = dyntlssort; \ 170d579eb63Sab _dynsort_ndx = &dyntlssort_ndx; \ 171d579eb63Sab } else { \ 172d579eb63Sab _dynsort_arr = NULL; \ 173d579eb63Sab } \ 174d579eb63Sab if ((_dynsort_arr != NULL) && DYNSORT_TEST_ATTR(_sdp, _sym)) \ 17508278a5eSRod Evans _dynsort_arr[(*_dynsort_ndx)++] = _sym_ndx; \ 176d579eb63Sab } 177d579eb63Sab 1787c478bd9Sstevel@tonic-gate Sym_desc *sdp; 1797c478bd9Sstevel@tonic-gate Sym_avlnode *sav; 18057ef7aa9SRod Evans Sg_desc *sgp, *tsgp = NULL, *dsgp = NULL, *esgp = NULL; 18157ef7aa9SRod Evans Os_desc *osp, *iosp = NULL, *fosp = NULL; 18257ef7aa9SRod Evans Is_desc *isc; 1837c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 1847c478bd9Sstevel@tonic-gate Word bssndx, etext_ndx, edata_ndx = 0, end_ndx, start_ndx; 1857c478bd9Sstevel@tonic-gate Word end_abs = 0, etext_abs = 0, edata_abs; 18635450702SAli Bahrami Word tlsbssndx = 0, parexpnndx; 187ba2be530Sab #if defined(_ELF64) 18854d82594Sseizo Word lbssndx = 0; 18954d82594Sseizo Addr lbssaddr = 0; 19054d82594Sseizo #endif 1917c478bd9Sstevel@tonic-gate Addr bssaddr, etext = 0, edata = 0, end = 0, start = 0; 1927c478bd9Sstevel@tonic-gate Addr tlsbssaddr = 0; 193c524b4feSRichard Lowe Addr parexpnbase, parexpnaddr; 1947c478bd9Sstevel@tonic-gate int start_set = 0; 19557ef7aa9SRod Evans Sym _sym = {0}, *sym, *symtab = NULL; 19657ef7aa9SRod Evans Sym *dynsym = NULL, *ldynsym = NULL; 197635216b6SRod Evans Word symtab_ndx = 0; /* index into .symtab */ 198ca4eed8bSAli Bahrami Word symtab_gbl_bndx; /* .symtab ndx 1st global */ 1999039eeafSab Word ldynsym_ndx = 0; /* index into .SUNW_ldynsym */ 2009039eeafSab Word dynsym_ndx = 0; /* index into .dynsym */ 201635216b6SRod Evans Word scopesym_ndx = 0; /* index into scoped symbols */ 202ca4eed8bSAli Bahrami Word scopesym_bndx = 0; /* .symtab ndx 1st scoped sym */ 203635216b6SRod Evans Word ldynscopesym_ndx = 0; /* index to ldynsym scoped */ 204635216b6SRod Evans /* symbols */ 205635216b6SRod Evans Word *dynsymsort = NULL; /* SUNW_dynsymsort index */ 206635216b6SRod Evans /* vector */ 207635216b6SRod Evans Word *dyntlssort = NULL; /* SUNW_dyntlssort index */ 208635216b6SRod Evans /* vector */ 209d579eb63Sab Word dynsymsort_ndx; /* index dynsymsort array */ 210d579eb63Sab Word dyntlssort_ndx; /* index dyntlssort array */ 211635216b6SRod Evans Word *symndx; /* symbol index (for */ 212635216b6SRod Evans /* relocation use) */ 21357ef7aa9SRod Evans Word *symshndx = NULL; /* .symtab_shndx table */ 21457ef7aa9SRod Evans Word *dynshndx = NULL; /* .dynsym_shndx table */ 21557ef7aa9SRod Evans Word *ldynshndx = NULL; /* .SUNW_ldynsym_shndx table */ 216fb8f92baSToomas Soome Word ldynsym_cnt = 0; /* number of items in */ 217635216b6SRod Evans /* .SUNW_ldynsym */ 2187c478bd9Sstevel@tonic-gate Str_tbl *shstrtab; 2197c478bd9Sstevel@tonic-gate Str_tbl *strtab; 2207c478bd9Sstevel@tonic-gate Str_tbl *dynstr; 2217c478bd9Sstevel@tonic-gate Word *hashtab; /* hash table pointer */ 2227c478bd9Sstevel@tonic-gate Word *hashbkt; /* hash table bucket pointer */ 2237c478bd9Sstevel@tonic-gate Word *hashchain; /* hash table chain pointer */ 2247c478bd9Sstevel@tonic-gate Wk_desc *wkp; 22557ef7aa9SRod Evans Alist *weak = NULL; 2261d9df23bSab ofl_flag_t flags = ofl->ofl_flags; 2277c478bd9Sstevel@tonic-gate Versym *versym; 2287c478bd9Sstevel@tonic-gate Gottable *gottable; /* used for display got debugging */ 2297c478bd9Sstevel@tonic-gate /* information */ 2307c478bd9Sstevel@tonic-gate Syminfo *syminfo; 2317c478bd9Sstevel@tonic-gate Sym_s_list *sorted_syms; /* table to hold sorted symbols */ 2327c478bd9Sstevel@tonic-gate Word ssndx; /* global index into sorted_syms */ 2337c478bd9Sstevel@tonic-gate Word scndx; /* scoped index into sorted_syms */ 234cce0e03bSab size_t stoff; /* string offset */ 23557ef7aa9SRod Evans Aliste idx1; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * Initialize pointers to the symbol table entries and the symbol 2397c478bd9Sstevel@tonic-gate * table strings. Skip the first symbol entry and the first string 2407c478bd9Sstevel@tonic-gate * table byte. Note that if we are not generating any output symbol 241e64d0ff9SAli Bahrami * tables we must still generate and update internal copies so 2427c478bd9Sstevel@tonic-gate * that the relocation phase has the correct information. 2437c478bd9Sstevel@tonic-gate */ 2447c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) || 2457c478bd9Sstevel@tonic-gate ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) { 2467c478bd9Sstevel@tonic-gate symtab = (Sym *)ofl->ofl_ossymtab->os_outdata->d_buf; 2477c478bd9Sstevel@tonic-gate symtab[symtab_ndx++] = _sym; 2487c478bd9Sstevel@tonic-gate if (ofl->ofl_ossymshndx) 249d840867fSab symshndx = 250d840867fSab (Word *)ofl->ofl_ossymshndx->os_outdata->d_buf; 2517c478bd9Sstevel@tonic-gate } 2529039eeafSab if (OFL_ALLOW_DYNSYM(ofl)) { 2537c478bd9Sstevel@tonic-gate dynsym = (Sym *)ofl->ofl_osdynsym->os_outdata->d_buf; 2547c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx++] = _sym; 2559039eeafSab /* 2569039eeafSab * If we are also constructing a .SUNW_ldynsym section 2579039eeafSab * to contain local function symbols, then set it up too. 2589039eeafSab */ 2599039eeafSab if (ofl->ofl_osldynsym) { 2609039eeafSab ldynsym = (Sym *)ofl->ofl_osldynsym->os_outdata->d_buf; 2619039eeafSab ldynsym[ldynsym_ndx++] = _sym; 262d579eb63Sab ldynsym_cnt = 1 + ofl->ofl_dynlocscnt + 263d579eb63Sab ofl->ofl_dynscopecnt; 264d579eb63Sab 265d579eb63Sab /* 266d579eb63Sab * If there is a SUNW_ldynsym, then there may also 267d579eb63Sab * be a .SUNW_dynsymsort and/or .SUNW_dyntlssort 268d579eb63Sab * sections, used to collect indices of function 269d579eb63Sab * and data symbols sorted by address order. 270d579eb63Sab */ 271d579eb63Sab if (ofl->ofl_osdynsymsort) { /* .SUNW_dynsymsort */ 272d579eb63Sab dynsymsort = (Word *) 273d579eb63Sab ofl->ofl_osdynsymsort->os_outdata->d_buf; 274d579eb63Sab dynsymsort_ndx = 0; 275d579eb63Sab } 276d579eb63Sab if (ofl->ofl_osdyntlssort) { /* .SUNW_dyntlssort */ 277d579eb63Sab dyntlssort = (Word *) 278d579eb63Sab ofl->ofl_osdyntlssort->os_outdata->d_buf; 279d579eb63Sab dyntlssort_ndx = 0; 280d579eb63Sab } 2819039eeafSab } 2829039eeafSab 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * Initialize the hash table. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate hashtab = (Word *)(ofl->ofl_oshash->os_outdata->d_buf); 2877c478bd9Sstevel@tonic-gate hashbkt = &hashtab[2]; 2887c478bd9Sstevel@tonic-gate hashchain = &hashtab[2 + ofl->ofl_hashbkts]; 2897c478bd9Sstevel@tonic-gate hashtab[0] = ofl->ofl_hashbkts; 290635216b6SRod Evans hashtab[1] = DYNSYM_ALL_CNT(ofl); 2917c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynshndx) 292d840867fSab dynshndx = 293d840867fSab (Word *)ofl->ofl_osdynshndx->os_outdata->d_buf; 2949039eeafSab if (ofl->ofl_osldynshndx) 295d840867fSab ldynshndx = 296d840867fSab (Word *)ofl->ofl_osldynshndx->os_outdata->d_buf; 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* 3007c478bd9Sstevel@tonic-gate * symndx is the symbol index to be used for relocation processing. It 3017c478bd9Sstevel@tonic-gate * points to the relevant symtab's (.dynsym or .symtab) symbol ndx. 3027c478bd9Sstevel@tonic-gate */ 3037c478bd9Sstevel@tonic-gate if (dynsym) 3047c478bd9Sstevel@tonic-gate symndx = &dynsym_ndx; 3057c478bd9Sstevel@tonic-gate else 3067c478bd9Sstevel@tonic-gate symndx = &symtab_ndx; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* 3097c478bd9Sstevel@tonic-gate * If we have version definitions initialize the version symbol index 3107c478bd9Sstevel@tonic-gate * table. There is one entry for each symbol which contains the symbols 3117c478bd9Sstevel@tonic-gate * version index. 3127c478bd9Sstevel@tonic-gate */ 313090a8d9eSAli Bahrami if (!(flags & FLG_OF_NOVERSEC) && 314090a8d9eSAli Bahrami (flags & (FLG_OF_VERNEED | FLG_OF_VERDEF))) { 3157c478bd9Sstevel@tonic-gate versym = (Versym *)ofl->ofl_osversym->os_outdata->d_buf; 316fb8f92baSToomas Soome versym[0] = 0; 3177c478bd9Sstevel@tonic-gate } else 31828bda19cSRod Evans versym = NULL; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * If syminfo section exists be prepared to fill it in. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate if (ofl->ofl_ossyminfo) { 3247c478bd9Sstevel@tonic-gate syminfo = ofl->ofl_ossyminfo->os_outdata->d_buf; 3257c478bd9Sstevel@tonic-gate syminfo[0].si_flags = SYMINFO_CURRENT; 3267c478bd9Sstevel@tonic-gate } else 32728bda19cSRod Evans syminfo = NULL; 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * Setup our string tables. 3317c478bd9Sstevel@tonic-gate */ 3327c478bd9Sstevel@tonic-gate shstrtab = ofl->ofl_shdrsttab; 3337c478bd9Sstevel@tonic-gate strtab = ofl->ofl_strtab; 3347c478bd9Sstevel@tonic-gate dynstr = ofl->ofl_dynstrtab; 3357c478bd9Sstevel@tonic-gate 3365aefb655Srie DBG_CALL(Dbg_syms_sec_title(ofl->ofl_lml)); 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* 3399039eeafSab * Put output file name to the first .symtab and .SUNW_ldynsym symbol. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate if (symtab) { 3427c478bd9Sstevel@tonic-gate (void) st_setstring(strtab, ofl->ofl_name, &stoff); 3437c478bd9Sstevel@tonic-gate sym = &symtab[symtab_ndx++]; 3447c478bd9Sstevel@tonic-gate /* LINTED */ 3457c478bd9Sstevel@tonic-gate sym->st_name = stoff; 3467c478bd9Sstevel@tonic-gate sym->st_value = 0; 3477c478bd9Sstevel@tonic-gate sym->st_size = 0; 3487c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE); 3497c478bd9Sstevel@tonic-gate sym->st_other = 0; 3507c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_ABS; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate if (versym && !dynsym) 3537c478bd9Sstevel@tonic-gate versym[1] = 0; 3547c478bd9Sstevel@tonic-gate } 355d579eb63Sab if (ldynsym) { 3569039eeafSab (void) st_setstring(dynstr, ofl->ofl_name, &stoff); 3579039eeafSab sym = &ldynsym[ldynsym_ndx]; 3589039eeafSab /* LINTED */ 3599039eeafSab sym->st_name = stoff; 3609039eeafSab sym->st_value = 0; 3619039eeafSab sym->st_size = 0; 3629039eeafSab sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE); 3639039eeafSab sym->st_other = 0; 3649039eeafSab sym->st_shndx = SHN_ABS; 3659039eeafSab 3669039eeafSab /* Scoped symbols get filled in global loop below */ 3679039eeafSab ldynscopesym_ndx = ldynsym_ndx + 1; 3689039eeafSab ldynsym_ndx += ofl->ofl_dynscopecnt; 3699039eeafSab } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * If we are to display GOT summary information, then allocate 3737c478bd9Sstevel@tonic-gate * the buffer to 'cache' the GOT symbols into now. 3747c478bd9Sstevel@tonic-gate */ 3755aefb655Srie if (DBG_ENABLED) { 376d326b23bSrie if ((ofl->ofl_gottable = gottable = 37757ef7aa9SRod Evans libld_calloc(ofl->ofl_gotcnt, sizeof (Gottable))) == NULL) 37808278a5eSRod Evans return ((Addr)S_ERROR); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * Traverse the program headers. Determine the last executable segment 3837c478bd9Sstevel@tonic-gate * and the last data segment so that we can update etext and edata. If 3847c478bd9Sstevel@tonic-gate * we have empty segments (reservations) record them for setting _end. 3857c478bd9Sstevel@tonic-gate */ 38657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 3870bc07c75Srie Phdr *phd = &(sgp->sg_phdr); 388cce0e03bSab Os_desc *osp; 38957ef7aa9SRod Evans Aliste idx2; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if (phd->p_type == PT_LOAD) { 392*8b891ae8SRichard Lowe if (aplist_nitems(sgp->sg_osdescs) != 0) { 393d840867fSab Word _flags = phd->p_flags & (PF_W | PF_R); 3940bc07c75Srie 395d840867fSab if (_flags == PF_R) 396d840867fSab tsgp = sgp; 397d840867fSab else if (_flags == (PF_W | PF_R)) 398d840867fSab dsgp = sgp; 3997c478bd9Sstevel@tonic-gate } else if (sgp->sg_flags & FLG_SG_EMPTY) 400d840867fSab esgp = sgp; 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* 4047c478bd9Sstevel@tonic-gate * Generate a section symbol for each output section. 4057c478bd9Sstevel@tonic-gate */ 40657ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 4077c478bd9Sstevel@tonic-gate Word sectndx; 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate sym = &_sym; 4107c478bd9Sstevel@tonic-gate sym->st_value = osp->os_shdr->sh_addr; 4117c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION); 4127c478bd9Sstevel@tonic-gate /* LINTED */ 4137c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn(osp->os_scn); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (symtab) { 4167c478bd9Sstevel@tonic-gate if (sectndx >= SHN_LORESERVE) { 4177c478bd9Sstevel@tonic-gate symshndx[symtab_ndx] = sectndx; 4187c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_XINDEX; 4197c478bd9Sstevel@tonic-gate } else { 4207c478bd9Sstevel@tonic-gate /* LINTED */ 4217c478bd9Sstevel@tonic-gate sym->st_shndx = (Half)sectndx; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate symtab[symtab_ndx++] = *sym; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate if (dynsym && (osp->os_flags & FLG_OS_OUTREL)) 4277c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx++] = *sym; 4287c478bd9Sstevel@tonic-gate 42957ef7aa9SRod Evans if ((dynsym == NULL) || 43057ef7aa9SRod Evans (osp->os_flags & FLG_OS_OUTREL)) { 4317c478bd9Sstevel@tonic-gate if (versym) 4327c478bd9Sstevel@tonic-gate versym[*symndx - 1] = 0; 43357ef7aa9SRod Evans osp->os_identndx = *symndx - 1; 4345aefb655Srie DBG_CALL(Dbg_syms_sec_entry(ofl->ofl_lml, 43557ef7aa9SRod Evans osp->os_identndx, sgp, osp)); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * Generate the .shstrtab for this section. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate (void) st_setstring(shstrtab, osp->os_name, &stoff); 4427c478bd9Sstevel@tonic-gate osp->os_shdr->sh_name = (Word)stoff; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * Find the section index for our special symbols. 4467c478bd9Sstevel@tonic-gate */ 4477c478bd9Sstevel@tonic-gate if (sgp == tsgp) { 4487c478bd9Sstevel@tonic-gate /* LINTED */ 4497c478bd9Sstevel@tonic-gate etext_ndx = elf_ndxscn(osp->os_scn); 4507c478bd9Sstevel@tonic-gate } else if (dsgp == sgp) { 4517c478bd9Sstevel@tonic-gate if (osp->os_shdr->sh_type != SHT_NOBITS) { 4527c478bd9Sstevel@tonic-gate /* LINTED */ 4537c478bd9Sstevel@tonic-gate edata_ndx = elf_ndxscn(osp->os_scn); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (start_set == 0) { 4587c478bd9Sstevel@tonic-gate start = sgp->sg_phdr.p_vaddr; 4597c478bd9Sstevel@tonic-gate /* LINTED */ 4607c478bd9Sstevel@tonic-gate start_ndx = elf_ndxscn(osp->os_scn); 4617c478bd9Sstevel@tonic-gate start_set++; 4627c478bd9Sstevel@tonic-gate } 463c1c6f601Srie 464c1c6f601Srie /* 465c1c6f601Srie * While we're here, determine whether a .init or .fini 466c1c6f601Srie * section exist. 467c1c6f601Srie */ 46857ef7aa9SRod Evans if ((iosp == NULL) && (strcmp(osp->os_name, 469c1c6f601Srie MSG_ORIG(MSG_SCN_INIT)) == 0)) 470c1c6f601Srie iosp = osp; 47157ef7aa9SRod Evans if ((fosp == NULL) && (strcmp(osp->os_name, 472c1c6f601Srie MSG_ORIG(MSG_SCN_FINI)) == 0)) 473c1c6f601Srie fosp = osp; 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * Add local register symbols to the .dynsym. These are required as 4797c478bd9Sstevel@tonic-gate * DT_REGISTER .dynamic entries must have a symbol to reference. 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate if (ofl->ofl_regsyms && dynsym) { 4827c478bd9Sstevel@tonic-gate int ndx; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) { 48557ef7aa9SRod Evans Sym_desc *rsdp; 4867c478bd9Sstevel@tonic-gate 48757ef7aa9SRod Evans if ((rsdp = ofl->ofl_regsyms[ndx]) == NULL) 4887c478bd9Sstevel@tonic-gate continue; 4897c478bd9Sstevel@tonic-gate 49008278a5eSRod Evans if (!SYM_IS_HIDDEN(rsdp) && 4917c478bd9Sstevel@tonic-gate (ELF_ST_BIND(rsdp->sd_sym->st_info) != STB_LOCAL)) 4927c478bd9Sstevel@tonic-gate continue; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx] = *(rsdp->sd_sym); 4957c478bd9Sstevel@tonic-gate rsdp->sd_symndx = *symndx; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate if (dynsym[dynsym_ndx].st_name) { 4987c478bd9Sstevel@tonic-gate (void) st_setstring(dynstr, rsdp->sd_name, 4997c478bd9Sstevel@tonic-gate &stoff); 5007c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx].st_name = stoff; 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate dynsym_ndx++; 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate /* 5077c478bd9Sstevel@tonic-gate * Having traversed all the output segments, warn the user if the 5087c478bd9Sstevel@tonic-gate * traditional text or data segments don't exist. Otherwise from these 5097c478bd9Sstevel@tonic-gate * segments establish the values for `etext', `edata', `end', `END', 5107c478bd9Sstevel@tonic-gate * and `START'. 5117c478bd9Sstevel@tonic-gate */ 5127c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ)) { 51357ef7aa9SRod Evans Sg_desc *sgp; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate if (tsgp) 5167c478bd9Sstevel@tonic-gate etext = tsgp->sg_phdr.p_vaddr + tsgp->sg_phdr.p_filesz; 5177c478bd9Sstevel@tonic-gate else { 5187c478bd9Sstevel@tonic-gate etext = (Addr)0; 5197c478bd9Sstevel@tonic-gate etext_ndx = SHN_ABS; 5207c478bd9Sstevel@tonic-gate etext_abs = 1; 5211d9df23bSab if (flags & FLG_OF_VERBOSE) 5221007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 5237c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_NOREADSEG)); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate if (dsgp) { 5267c478bd9Sstevel@tonic-gate edata = dsgp->sg_phdr.p_vaddr + dsgp->sg_phdr.p_filesz; 5277c478bd9Sstevel@tonic-gate } else { 5287c478bd9Sstevel@tonic-gate edata = (Addr)0; 5297c478bd9Sstevel@tonic-gate edata_ndx = SHN_ABS; 5307c478bd9Sstevel@tonic-gate edata_abs = 1; 5311d9df23bSab if (flags & FLG_OF_VERBOSE) 5321007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 5337c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_NORDWRSEG)); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 53657ef7aa9SRod Evans if (dsgp == NULL) { 5377c478bd9Sstevel@tonic-gate if (tsgp) 5387c478bd9Sstevel@tonic-gate sgp = tsgp; 5397c478bd9Sstevel@tonic-gate else 5407c478bd9Sstevel@tonic-gate sgp = 0; 54157ef7aa9SRod Evans } else if (tsgp == NULL) 5427c478bd9Sstevel@tonic-gate sgp = dsgp; 5437c478bd9Sstevel@tonic-gate else if (dsgp->sg_phdr.p_vaddr > tsgp->sg_phdr.p_vaddr) 5447c478bd9Sstevel@tonic-gate sgp = dsgp; 5457c478bd9Sstevel@tonic-gate else if (dsgp->sg_phdr.p_vaddr < tsgp->sg_phdr.p_vaddr) 5467c478bd9Sstevel@tonic-gate sgp = tsgp; 5477c478bd9Sstevel@tonic-gate else { 5487c478bd9Sstevel@tonic-gate /* 5497c478bd9Sstevel@tonic-gate * One of the segments must be of zero size. 5507c478bd9Sstevel@tonic-gate */ 5517c478bd9Sstevel@tonic-gate if (tsgp->sg_phdr.p_memsz) 5527c478bd9Sstevel@tonic-gate sgp = tsgp; 5537c478bd9Sstevel@tonic-gate else 5547c478bd9Sstevel@tonic-gate sgp = dsgp; 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate if (esgp && (esgp->sg_phdr.p_vaddr > sgp->sg_phdr.p_vaddr)) 5587c478bd9Sstevel@tonic-gate sgp = esgp; 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate if (sgp) { 5617c478bd9Sstevel@tonic-gate end = sgp->sg_phdr.p_vaddr + sgp->sg_phdr.p_memsz; 5627c478bd9Sstevel@tonic-gate 563fdf855a7Sseizo /* 564fdf855a7Sseizo * If the last loadable segment is a read-only segment, 565fdf855a7Sseizo * then the application which uses the symbol _end to 566fdf855a7Sseizo * find the beginning of writable heap area may cause 567fdf855a7Sseizo * segmentation violation. We adjust the value of the 568fdf855a7Sseizo * _end to skip to the next page boundary. 569fdf855a7Sseizo * 570fdf855a7Sseizo * 6401812 System interface which returs beginning 571fdf855a7Sseizo * heap would be nice. 572fdf855a7Sseizo * When the above RFE is implemented, the changes below 573fdf855a7Sseizo * could be changed in a better way. 574fdf855a7Sseizo */ 575fdf855a7Sseizo if ((sgp->sg_phdr.p_flags & PF_W) == 0) 57660758829Srie end = (Addr)S_ROUND(end, sysconf(_SC_PAGESIZE)); 577fdf855a7Sseizo 5787c478bd9Sstevel@tonic-gate /* 5797c478bd9Sstevel@tonic-gate * If we're dealing with a memory reservation there are 5807c478bd9Sstevel@tonic-gate * no sections to establish an index for _end, so assign 5817c478bd9Sstevel@tonic-gate * it as an absolute. 5827c478bd9Sstevel@tonic-gate */ 583*8b891ae8SRichard Lowe if (aplist_nitems(sgp->sg_osdescs) != 0) { 5840bc07c75Srie /* 5850bc07c75Srie * Determine the last section for this segment. 5860bc07c75Srie */ 587cce0e03bSab Os_desc *osp = sgp->sg_osdescs->apl_data 588cce0e03bSab [sgp->sg_osdescs->apl_nitems - 1]; 589cce0e03bSab 5900bc07c75Srie /* LINTED */ 591cce0e03bSab end_ndx = elf_ndxscn(osp->os_scn); 5927c478bd9Sstevel@tonic-gate } else { 5937c478bd9Sstevel@tonic-gate end_ndx = SHN_ABS; 5947c478bd9Sstevel@tonic-gate end_abs = 1; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate } else { 5977c478bd9Sstevel@tonic-gate end = (Addr) 0; 5987c478bd9Sstevel@tonic-gate end_ndx = SHN_ABS; 5997c478bd9Sstevel@tonic-gate end_abs = 1; 6001007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_UPD_NOSEG)); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate /* 6057c478bd9Sstevel@tonic-gate * Initialize the scoped symbol table entry point. This is for all 6067c478bd9Sstevel@tonic-gate * the global symbols that have been scoped to locals and will be 6077c478bd9Sstevel@tonic-gate * filled in during global symbol processing so that we don't have 6087c478bd9Sstevel@tonic-gate * to traverse the globals symbol hash array more than once. 6097c478bd9Sstevel@tonic-gate */ 6107c478bd9Sstevel@tonic-gate if (symtab) { 611ca4eed8bSAli Bahrami scopesym_bndx = symtab_ndx; 612ca4eed8bSAli Bahrami scopesym_ndx = scopesym_bndx; 6137c478bd9Sstevel@tonic-gate symtab_ndx += ofl->ofl_scopecnt; 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate /* 61735450702SAli Bahrami * If expanding partially expanded symbols under '-z nopartial', 61835450702SAli Bahrami * prepare to do that. 6197c478bd9Sstevel@tonic-gate */ 62035450702SAli Bahrami if (ofl->ofl_isparexpn) { 62135450702SAli Bahrami osp = ofl->ofl_isparexpn->is_osdesc; 622b26cc8daSAli Bahrami parexpnbase = parexpnaddr = (Addr)(osp->os_shdr->sh_addr + 62335450702SAli Bahrami ofl->ofl_isparexpn->is_indata->d_off); 6247c478bd9Sstevel@tonic-gate /* LINTED */ 62535450702SAli Bahrami parexpnndx = elf_ndxscn(osp->os_scn); 62657ef7aa9SRod Evans ofl->ofl_parexpnndx = osp->os_identndx; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate /* 6307c478bd9Sstevel@tonic-gate * If we are generating a .symtab collect all the local symbols, 6317c478bd9Sstevel@tonic-gate * assigning a new virtual address or displacement (value). 6327c478bd9Sstevel@tonic-gate */ 63357ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_objs, idx1, ifl)) { 63408278a5eSRod Evans Xword lndx, local = ifl->ifl_locscnt; 63508278a5eSRod Evans Cap_desc *cdp = ifl->ifl_caps; 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate for (lndx = 1; lndx < local; lndx++) { 6387c478bd9Sstevel@tonic-gate Gotndx *gnp; 639d579eb63Sab uchar_t type; 6407c478bd9Sstevel@tonic-gate Word *_symshndx; 6419039eeafSab int enter_in_symtab, enter_in_ldynsym; 6429039eeafSab int update_done; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate sdp = ifl->ifl_oldndx[lndx]; 6457c478bd9Sstevel@tonic-gate sym = sdp->sd_sym; 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate /* 6487c478bd9Sstevel@tonic-gate * Assign a got offset if necessary. 6497c478bd9Sstevel@tonic-gate */ 650ba2be530Sab if ((ld_targ.t_mr.mr_assign_got != NULL) && 651ba2be530Sab (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR) 6527c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 653ba2be530Sab 6545aefb655Srie if (DBG_ENABLED) { 65557ef7aa9SRod Evans Aliste idx2; 65657ef7aa9SRod Evans 65757ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_GOTndxs, 65857ef7aa9SRod Evans idx2, gnp)) { 659d840867fSab gottable->gt_sym = sdp; 660d840867fSab gottable->gt_gndx.gn_gotndx = 661d840867fSab gnp->gn_gotndx; 662d840867fSab gottable->gt_gndx.gn_addend = 663d840867fSab gnp->gn_addend; 664d840867fSab gottable++; 665d840867fSab } 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate if ((type = ELF_ST_TYPE(sym->st_info)) == STT_SECTION) 6697c478bd9Sstevel@tonic-gate continue; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * Ignore any symbols that have been marked as invalid 6737c478bd9Sstevel@tonic-gate * during input processing. Providing these aren't used 6747c478bd9Sstevel@tonic-gate * for relocation they'll just be dropped from the 6757c478bd9Sstevel@tonic-gate * output image. 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_INVALID) 6787c478bd9Sstevel@tonic-gate continue; 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate /* 6817c478bd9Sstevel@tonic-gate * If the section that this symbol was associated 6827c478bd9Sstevel@tonic-gate * with has been discarded - then we discard 6837c478bd9Sstevel@tonic-gate * the local symbol along with it. 6847c478bd9Sstevel@tonic-gate */ 6857c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_ISDISC) 6867c478bd9Sstevel@tonic-gate continue; 6877c478bd9Sstevel@tonic-gate 688ca4eed8bSAli Bahrami /* 689ca4eed8bSAli Bahrami * If this symbol is from a different file 690ca4eed8bSAli Bahrami * than the input descriptor we are processing, 691ca4eed8bSAli Bahrami * treat it as if it has FLG_SY_ISDISC set. 692ca4eed8bSAli Bahrami * This happens when sloppy_comdat_reloc() 693ca4eed8bSAli Bahrami * replaces a symbol to a discarded comdat section 694ca4eed8bSAli Bahrami * with an equivalent symbol from a different 695ca4eed8bSAli Bahrami * file. We only want to enter such a symbol 696ca4eed8bSAli Bahrami * once --- as part of the file that actually 697ca4eed8bSAli Bahrami * supplies it. 698ca4eed8bSAli Bahrami */ 699ca4eed8bSAli Bahrami if (ifl != sdp->sd_file) 700ca4eed8bSAli Bahrami continue; 701ca4eed8bSAli Bahrami 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * Generate an output symbol to represent this input 7047c478bd9Sstevel@tonic-gate * symbol. Even if the symbol table is to be stripped 7057c478bd9Sstevel@tonic-gate * we still need to update any local symbols that are 7067c478bd9Sstevel@tonic-gate * used during relocation. 7077c478bd9Sstevel@tonic-gate */ 7089039eeafSab enter_in_symtab = symtab && 70944bac77bSrie (!(ofl->ofl_flags & FLG_OF_REDLSYM) || 71057ef7aa9SRod Evans sdp->sd_move); 711f980a4bbSRichard Lowe enter_in_ldynsym = ldynsym && 712f980a4bbSRichard Lowe ((sym->st_name != 0) || (type == STT_FILE)) && 713d579eb63Sab ldynsym_symtype[type] && 71444bac77bSrie !(ofl->ofl_flags & FLG_OF_REDLSYM); 715f980a4bbSRichard Lowe 71657ef7aa9SRod Evans _symshndx = NULL; 71757ef7aa9SRod Evans 7189039eeafSab if (enter_in_symtab) { 7197c478bd9Sstevel@tonic-gate if (!dynsym) 7207c478bd9Sstevel@tonic-gate sdp->sd_symndx = *symndx; 7217c478bd9Sstevel@tonic-gate symtab[symtab_ndx] = *sym; 72208278a5eSRod Evans 7237c478bd9Sstevel@tonic-gate /* 7247c478bd9Sstevel@tonic-gate * Provided this isn't an unnamed register 7257c478bd9Sstevel@tonic-gate * symbol, update its name. 7267c478bd9Sstevel@tonic-gate */ 7277c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) || 7287c478bd9Sstevel@tonic-gate symtab[symtab_ndx].st_name) { 7297c478bd9Sstevel@tonic-gate (void) st_setstring(strtab, 7307c478bd9Sstevel@tonic-gate sdp->sd_name, &stoff); 7317c478bd9Sstevel@tonic-gate symtab[symtab_ndx].st_name = stoff; 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_CLEAN; 7347c478bd9Sstevel@tonic-gate if (symshndx) 7357c478bd9Sstevel@tonic-gate _symshndx = &symshndx[symtab_ndx]; 7367c478bd9Sstevel@tonic-gate sdp->sd_sym = sym = &symtab[symtab_ndx++]; 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_SPECSEC) && 7399039eeafSab (sym->st_shndx == SHN_ABS) && 7409039eeafSab !enter_in_ldynsym) 7417c478bd9Sstevel@tonic-gate continue; 7429039eeafSab } else if (enter_in_ldynsym) { 7439039eeafSab /* 7449039eeafSab * Not using symtab, but we do have ldynsym 7459039eeafSab * available. 7469039eeafSab */ 7479039eeafSab ldynsym[ldynsym_ndx] = *sym; 7489039eeafSab (void) st_setstring(dynstr, sdp->sd_name, 749d840867fSab &stoff); 7509039eeafSab ldynsym[ldynsym_ndx].st_name = stoff; 7519039eeafSab 7529039eeafSab sdp->sd_flags &= ~FLG_SY_CLEAN; 7539039eeafSab if (ldynshndx) 7549039eeafSab _symshndx = &ldynshndx[ldynsym_ndx]; 755d579eb63Sab sdp->sd_sym = sym = &ldynsym[ldynsym_ndx]; 756d579eb63Sab /* Add it to sort section if it qualifies */ 757d579eb63Sab ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx); 758d579eb63Sab ldynsym_ndx++; 7599039eeafSab } else { /* Not using symtab or ldynsym */ 7607c478bd9Sstevel@tonic-gate /* 7617c478bd9Sstevel@tonic-gate * If this symbol requires modifying to provide 7627c478bd9Sstevel@tonic-gate * for a relocation or move table update, make 7637c478bd9Sstevel@tonic-gate * a copy of it. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags & FLG_SY_UPREQD) && 76657ef7aa9SRod Evans !(sdp->sd_move)) 7677c478bd9Sstevel@tonic-gate continue; 7687c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_SPECSEC) && 7697c478bd9Sstevel@tonic-gate (sym->st_shndx == SHN_ABS)) 7707c478bd9Sstevel@tonic-gate continue; 7717c478bd9Sstevel@tonic-gate 7725aefb655Srie if (ld_sym_copy(sdp) == S_ERROR) 7737c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 7747c478bd9Sstevel@tonic-gate sym = sdp->sd_sym; 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * Update the symbols contents if necessary. 7797c478bd9Sstevel@tonic-gate */ 7809039eeafSab update_done = 0; 7817c478bd9Sstevel@tonic-gate if (type == STT_FILE) { 7827c478bd9Sstevel@tonic-gate sdp->sd_shndx = sym->st_shndx = SHN_ABS; 7837c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 7849039eeafSab update_done = 1; 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate /* 7887c478bd9Sstevel@tonic-gate * If we are expanding the locally bound partially 7897c478bd9Sstevel@tonic-gate * initialized symbols, then update the address here. 7907c478bd9Sstevel@tonic-gate */ 79135450702SAli Bahrami if (ofl->ofl_isparexpn && 7929039eeafSab (sdp->sd_flags & FLG_SY_PAREXPN) && !update_done) { 79335450702SAli Bahrami sym->st_shndx = parexpnndx; 79435450702SAli Bahrami sdp->sd_isc = ofl->ofl_isparexpn; 795b26cc8daSAli Bahrami sym->st_value = parexpnaddr; 79635450702SAli Bahrami parexpnaddr += sym->st_size; 797b26cc8daSAli Bahrami if ((flags & FLG_OF_RELOBJ) == 0) 798b26cc8daSAli Bahrami sym->st_value -= parexpnbase; 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate /* 8027c478bd9Sstevel@tonic-gate * If this isn't an UNDEF symbol (ie. an input section 8037c478bd9Sstevel@tonic-gate * is associated), update the symbols value and index. 8047c478bd9Sstevel@tonic-gate */ 80508278a5eSRod Evans if (((isc = sdp->sd_isc) != NULL) && !update_done) { 8067c478bd9Sstevel@tonic-gate Word sectndx; 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate osp = isc->is_osdesc; 8097c478bd9Sstevel@tonic-gate /* LINTED */ 8107c478bd9Sstevel@tonic-gate sym->st_value += 8117c478bd9Sstevel@tonic-gate (Off)_elf_getxoff(isc->is_indata); 812635216b6SRod Evans if ((flags & FLG_OF_RELOBJ) == 0) { 8137c478bd9Sstevel@tonic-gate sym->st_value += osp->os_shdr->sh_addr; 8147c478bd9Sstevel@tonic-gate /* 8157c478bd9Sstevel@tonic-gate * TLS symbols are relative to 8167c478bd9Sstevel@tonic-gate * the TLS segment. 8177c478bd9Sstevel@tonic-gate */ 818d579eb63Sab if ((type == STT_TLS) && 819d579eb63Sab (ofl->ofl_tlsphdr)) { 8207c478bd9Sstevel@tonic-gate sym->st_value -= 8217c478bd9Sstevel@tonic-gate ofl->ofl_tlsphdr->p_vaddr; 8229039eeafSab } 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate /* LINTED */ 8257c478bd9Sstevel@tonic-gate if ((sdp->sd_shndx = sectndx = 8267c478bd9Sstevel@tonic-gate elf_ndxscn(osp->os_scn)) >= SHN_LORESERVE) { 8277c478bd9Sstevel@tonic-gate if (_symshndx) { 8287c478bd9Sstevel@tonic-gate *_symshndx = sectndx; 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_XINDEX; 8317c478bd9Sstevel@tonic-gate } else { 8327c478bd9Sstevel@tonic-gate /* LINTED */ 8337c478bd9Sstevel@tonic-gate sym->st_shndx = sectndx; 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate } 8369039eeafSab 8379039eeafSab /* 8389039eeafSab * If entering the symbol in both the symtab and the 8399039eeafSab * ldynsym, then the one in symtab needs to be 8409039eeafSab * copied to ldynsym. If it is only in the ldynsym, 8419039eeafSab * then the code above already set it up and we have 8429039eeafSab * nothing more to do here. 8439039eeafSab */ 8449039eeafSab if (enter_in_symtab && enter_in_ldynsym) { 8459039eeafSab ldynsym[ldynsym_ndx] = *sym; 8469039eeafSab (void) st_setstring(dynstr, sdp->sd_name, 847d840867fSab &stoff); 8489039eeafSab ldynsym[ldynsym_ndx].st_name = stoff; 8499039eeafSab 8509039eeafSab if (_symshndx && ldynshndx) 8519039eeafSab ldynshndx[ldynsym_ndx] = *_symshndx; 8529039eeafSab 853d579eb63Sab /* Add it to sort section if it qualifies */ 854d579eb63Sab ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx); 855d579eb63Sab 8569039eeafSab ldynsym_ndx++; 8579039eeafSab } 8587c478bd9Sstevel@tonic-gate } 85908278a5eSRod Evans 86008278a5eSRod Evans /* 86108278a5eSRod Evans * If this input file has undergone object to symbol 86208278a5eSRod Evans * capabilities conversion, supply any new capabilities symbols. 86308278a5eSRod Evans * These symbols are copies of the original global symbols, and 86408278a5eSRod Evans * follow the existing local symbols that are supplied from this 86508278a5eSRod Evans * input file (which are identified with a preceding STT_FILE). 86608278a5eSRod Evans */ 86708278a5eSRod Evans if (symtab && cdp && cdp->ca_syms) { 86808278a5eSRod Evans Aliste idx2; 86908278a5eSRod Evans Cap_sym *csp; 87008278a5eSRod Evans 87108278a5eSRod Evans for (APLIST_TRAVERSE(cdp->ca_syms, idx2, csp)) { 87208278a5eSRod Evans Is_desc *isp; 87308278a5eSRod Evans 87408278a5eSRod Evans sdp = csp->cs_sdp; 87508278a5eSRod Evans sym = sdp->sd_sym; 87608278a5eSRod Evans 87708278a5eSRod Evans if ((isp = sdp->sd_isc) != NULL) { 87808278a5eSRod Evans Os_desc *osp = isp->is_osdesc; 87908278a5eSRod Evans 88008278a5eSRod Evans /* 88108278a5eSRod Evans * Update the symbols value. 88208278a5eSRod Evans */ 88308278a5eSRod Evans /* LINTED */ 88408278a5eSRod Evans sym->st_value += 88508278a5eSRod Evans (Off)_elf_getxoff(isp->is_indata); 88608278a5eSRod Evans if ((flags & FLG_OF_RELOBJ) == 0) 88708278a5eSRod Evans sym->st_value += 88808278a5eSRod Evans osp->os_shdr->sh_addr; 88908278a5eSRod Evans 89008278a5eSRod Evans /* 89108278a5eSRod Evans * Update the symbols section index. 89208278a5eSRod Evans */ 89308278a5eSRod Evans sdp->sd_shndx = sym->st_shndx = 89408278a5eSRod Evans elf_ndxscn(osp->os_scn); 89508278a5eSRod Evans } 89608278a5eSRod Evans 89708278a5eSRod Evans symtab[symtab_ndx] = *sym; 89808278a5eSRod Evans (void) st_setstring(strtab, sdp->sd_name, 89908278a5eSRod Evans &stoff); 90008278a5eSRod Evans symtab[symtab_ndx].st_name = stoff; 90108278a5eSRod Evans sdp->sd_symndx = symtab_ndx++; 90208278a5eSRod Evans } 90308278a5eSRod Evans } 9047c478bd9Sstevel@tonic-gate } 90508278a5eSRod Evans 906ca4eed8bSAli Bahrami symtab_gbl_bndx = symtab_ndx; /* .symtab index of 1st global entry */ 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate /* 9097c478bd9Sstevel@tonic-gate * Two special symbols are `_init' and `_fini'. If these are supplied 9107c478bd9Sstevel@tonic-gate * by crti.o then they are used to represent the total concatenation of 911c1c6f601Srie * the `.init' and `.fini' sections. 912c1c6f601Srie * 913635216b6SRod Evans * Determine whether any .init or .fini sections exist. If these 914635216b6SRod Evans * sections exist and a dynamic object is being built, but no `_init' 915635216b6SRod Evans * or `_fini' symbols are found, then the user is probably building 916635216b6SRod Evans * this object directly from ld(1) rather than using a compiler driver 917635216b6SRod Evans * that provides the symbols via crt's. 918c1c6f601Srie * 919c1c6f601Srie * If the .init or .fini section exist, and their associated symbols, 920c1c6f601Srie * determine the size of the sections and updated the symbols value 921c1c6f601Srie * accordingly. 9227c478bd9Sstevel@tonic-gate */ 9235aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U), SYM_NOHASH, 0, 9247c478bd9Sstevel@tonic-gate ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc && 925c1c6f601Srie (sdp->sd_isc->is_osdesc == iosp)) { 9265aefb655Srie if (ld_sym_copy(sdp) == S_ERROR) 9277c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 92860758829Srie sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size; 92960758829Srie 930c1c6f601Srie } else if (iosp && !(flags & FLG_OF_RELOBJ)) { 9311007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT), 932c1c6f601Srie MSG_ORIG(MSG_SYM_INIT_U), MSG_ORIG(MSG_SCN_INIT)); 9337c478bd9Sstevel@tonic-gate } 934c1c6f601Srie 9355aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U), SYM_NOHASH, 0, 9367c478bd9Sstevel@tonic-gate ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc && 937c1c6f601Srie (sdp->sd_isc->is_osdesc == fosp)) { 9385aefb655Srie if (ld_sym_copy(sdp) == S_ERROR) 9397c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 94060758829Srie sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size; 94160758829Srie 942c1c6f601Srie } else if (fosp && !(flags & FLG_OF_RELOBJ)) { 9431007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT), 944c1c6f601Srie MSG_ORIG(MSG_SYM_FINI_U), MSG_ORIG(MSG_SCN_FINI)); 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate /* 9487c478bd9Sstevel@tonic-gate * Assign .bss information for use with updating COMMON symbols. 9497c478bd9Sstevel@tonic-gate */ 9507c478bd9Sstevel@tonic-gate if (ofl->ofl_isbss) { 95157ef7aa9SRod Evans isc = ofl->ofl_isbss; 95257ef7aa9SRod Evans osp = isc->is_osdesc; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate bssaddr = osp->os_shdr->sh_addr + 95557ef7aa9SRod Evans (Off)_elf_getxoff(isc->is_indata); 9567c478bd9Sstevel@tonic-gate /* LINTED */ 9577c478bd9Sstevel@tonic-gate bssndx = elf_ndxscn(osp->os_scn); 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 960ba2be530Sab #if defined(_ELF64) 96154d82594Sseizo /* 962ba2be530Sab * For amd64 target, assign .lbss information for use 963ba2be530Sab * with updating LCOMMON symbols. 96454d82594Sseizo */ 965ba2be530Sab if ((ld_targ.t_m.m_mach == EM_AMD64) && ofl->ofl_islbss) { 96654d82594Sseizo osp = ofl->ofl_islbss->is_osdesc; 96754d82594Sseizo 96854d82594Sseizo lbssaddr = osp->os_shdr->sh_addr + 969d840867fSab (Off)_elf_getxoff(ofl->ofl_islbss->is_indata); 97054d82594Sseizo /* LINTED */ 97154d82594Sseizo lbssndx = elf_ndxscn(osp->os_scn); 97254d82594Sseizo } 97354d82594Sseizo #endif 9747c478bd9Sstevel@tonic-gate /* 9757c478bd9Sstevel@tonic-gate * Assign .tlsbss information for use with updating COMMON symbols. 9767c478bd9Sstevel@tonic-gate */ 9777c478bd9Sstevel@tonic-gate if (ofl->ofl_istlsbss) { 9787c478bd9Sstevel@tonic-gate osp = ofl->ofl_istlsbss->is_osdesc; 9797c478bd9Sstevel@tonic-gate tlsbssaddr = osp->os_shdr->sh_addr + 980d840867fSab (Off)_elf_getxoff(ofl->ofl_istlsbss->is_indata); 9817c478bd9Sstevel@tonic-gate /* LINTED */ 9827c478bd9Sstevel@tonic-gate tlsbssndx = elf_ndxscn(osp->os_scn); 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate 9857c478bd9Sstevel@tonic-gate if ((sorted_syms = libld_calloc(ofl->ofl_globcnt + 98657ef7aa9SRod Evans ofl->ofl_elimcnt + ofl->ofl_scopecnt, 98757ef7aa9SRod Evans sizeof (*sorted_syms))) == NULL) 9887c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate scndx = 0; 9917c478bd9Sstevel@tonic-gate ssndx = ofl->ofl_scopecnt + ofl->ofl_elimcnt; 9927c478bd9Sstevel@tonic-gate 993635216b6SRod Evans DBG_CALL(Dbg_syms_up_title(ofl->ofl_lml)); 994635216b6SRod Evans 9957c478bd9Sstevel@tonic-gate /* 99628bda19cSRod Evans * Traverse the internal symbol table updating global symbol information 99728bda19cSRod Evans * and allocating common. 9987c478bd9Sstevel@tonic-gate */ 9997c478bd9Sstevel@tonic-gate for (sav = avl_first(&ofl->ofl_symavl); sav; 10007c478bd9Sstevel@tonic-gate sav = AVL_NEXT(&ofl->ofl_symavl, sav)) { 100157ef7aa9SRod Evans Sym *symptr; 10027c478bd9Sstevel@tonic-gate int local; 100354d82594Sseizo int restore; 10047c478bd9Sstevel@tonic-gate 1005635216b6SRod Evans sdp = sav->sav_sdp; 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate /* 100860758829Srie * Ignore any symbols that have been marked as invalid during 100960758829Srie * input processing. Providing these aren't used for 101060758829Srie * relocation, they will be dropped from the output image. 10117c478bd9Sstevel@tonic-gate */ 10127c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_INVALID) { 10135aefb655Srie DBG_CALL(Dbg_syms_old(ofl, sdp)); 10145aefb655Srie DBG_CALL(Dbg_syms_ignore(ofl, sdp)); 10157c478bd9Sstevel@tonic-gate continue; 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate /* 101960758829Srie * Only needed symbols are copied to the output symbol table. 10207c478bd9Sstevel@tonic-gate */ 10217c478bd9Sstevel@tonic-gate if (sdp->sd_ref == REF_DYN_SEEN) 10227c478bd9Sstevel@tonic-gate continue; 10237c478bd9Sstevel@tonic-gate 1024c524b4feSRichard Lowe if (ld_sym_reducable(ofl, sdp)) 10257c478bd9Sstevel@tonic-gate local = 1; 10267c478bd9Sstevel@tonic-gate else 10277c478bd9Sstevel@tonic-gate local = 0; 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate if (local || (ofl->ofl_hashbkts == 0)) { 10307c478bd9Sstevel@tonic-gate sorted_syms[scndx++].sl_sdp = sdp; 10317c478bd9Sstevel@tonic-gate } else { 10327c478bd9Sstevel@tonic-gate sorted_syms[ssndx].sl_hval = sdp->sd_aux->sa_hash % 10337c478bd9Sstevel@tonic-gate ofl->ofl_hashbkts; 10347c478bd9Sstevel@tonic-gate sorted_syms[ssndx].sl_sdp = sdp; 10357c478bd9Sstevel@tonic-gate ssndx++; 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate /* 1039c1c6f601Srie * Note - expand the COMMON symbols here because an address 1040c1c6f601Srie * must be assigned to them in the same order that space was 1041c1c6f601Srie * calculated in sym_validate(). If this ordering isn't 1042c1c6f601Srie * followed differing alignment requirements can throw us all 1043c1c6f601Srie * out of whack. 10447c478bd9Sstevel@tonic-gate * 1045c1c6f601Srie * The expanded .bss global symbol is handled here as well. 10467c478bd9Sstevel@tonic-gate * 1047c1c6f601Srie * The actual adding entries into the symbol table still occurs 1048c1c6f601Srie * below in hashbucket order. 10497c478bd9Sstevel@tonic-gate */ 10507c478bd9Sstevel@tonic-gate symptr = sdp->sd_sym; 105154d82594Sseizo restore = 0; 10527c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_PAREXPN) || 10537c478bd9Sstevel@tonic-gate ((sdp->sd_flags & FLG_SY_SPECSEC) && 10547c478bd9Sstevel@tonic-gate (sdp->sd_shndx = symptr->st_shndx) == SHN_COMMON)) { 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* 105735450702SAli Bahrami * An expanded symbol goes to a special .data section 105835450702SAli Bahrami * prepared for that purpose (ofl->ofl_isparexpn). 1059c1c6f601Srie * Assign COMMON allocations to .bss. 10607c478bd9Sstevel@tonic-gate * Otherwise leave it as is. 10617c478bd9Sstevel@tonic-gate */ 10627c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_PAREXPN) { 10637c478bd9Sstevel@tonic-gate restore = 1; 106435450702SAli Bahrami sdp->sd_shndx = parexpnndx; 10657c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 10667c478bd9Sstevel@tonic-gate symptr->st_value = (Xword) S_ROUND( 106735450702SAli Bahrami parexpnaddr, symptr->st_value); 106835450702SAli Bahrami parexpnaddr = symptr->st_value + 1069d840867fSab symptr->st_size; 107035450702SAli Bahrami sdp->sd_isc = ofl->ofl_isparexpn; 10717c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_COMMEXP; 1072c1c6f601Srie 10737c478bd9Sstevel@tonic-gate } else if (ELF_ST_TYPE(symptr->st_info) != STT_TLS && 10747c478bd9Sstevel@tonic-gate (local || !(flags & FLG_OF_RELOBJ))) { 10757c478bd9Sstevel@tonic-gate restore = 1; 10767c478bd9Sstevel@tonic-gate sdp->sd_shndx = bssndx; 10777c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 107860758829Srie symptr->st_value = (Xword)S_ROUND(bssaddr, 1079d840867fSab symptr->st_value); 10807c478bd9Sstevel@tonic-gate bssaddr = symptr->st_value + symptr->st_size; 10817c478bd9Sstevel@tonic-gate sdp->sd_isc = ofl->ofl_isbss; 10827c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_COMMEXP; 1083c1c6f601Srie 10847c478bd9Sstevel@tonic-gate } else if (ELF_ST_TYPE(symptr->st_info) == STT_TLS && 10857c478bd9Sstevel@tonic-gate (local || !(flags & FLG_OF_RELOBJ))) { 10867c478bd9Sstevel@tonic-gate restore = 1; 10877c478bd9Sstevel@tonic-gate sdp->sd_shndx = tlsbssndx; 10887c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 10897c478bd9Sstevel@tonic-gate symptr->st_value = (Xword)S_ROUND(tlsbssaddr, 1090d840867fSab symptr->st_value); 10917c478bd9Sstevel@tonic-gate tlsbssaddr = symptr->st_value + symptr->st_size; 10927c478bd9Sstevel@tonic-gate sdp->sd_isc = ofl->ofl_istlsbss; 10937c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_COMMEXP; 10947c478bd9Sstevel@tonic-gate /* 1095dd94ecefSrie * TLS symbols are relative to the TLS segment. 10967c478bd9Sstevel@tonic-gate */ 10977c478bd9Sstevel@tonic-gate symptr->st_value -= ofl->ofl_tlsphdr->p_vaddr; 10987c478bd9Sstevel@tonic-gate } 1099ba2be530Sab #if defined(_ELF64) 1100ba2be530Sab } else if ((ld_targ.t_m.m_mach == EM_AMD64) && 1101ba2be530Sab (sdp->sd_flags & FLG_SY_SPECSEC) && 110254d82594Sseizo ((sdp->sd_shndx = symptr->st_shndx) == 110354d82594Sseizo SHN_X86_64_LCOMMON) && 110454d82594Sseizo ((local || !(flags & FLG_OF_RELOBJ)))) { 110554d82594Sseizo restore = 1; 110654d82594Sseizo sdp->sd_shndx = lbssndx; 110754d82594Sseizo sdp->sd_flags &= ~FLG_SY_SPECSEC; 110860758829Srie symptr->st_value = (Xword)S_ROUND(lbssaddr, 1109d840867fSab symptr->st_value); 111054d82594Sseizo lbssaddr = symptr->st_value + symptr->st_size; 111154d82594Sseizo sdp->sd_isc = ofl->ofl_islbss; 111254d82594Sseizo sdp->sd_flags |= FLG_SY_COMMEXP; 111354d82594Sseizo #endif 111454d82594Sseizo } 11157c478bd9Sstevel@tonic-gate 111654d82594Sseizo if (restore != 0) { 1117d579eb63Sab uchar_t type, bind; 1118c1c6f601Srie 111954d82594Sseizo /* 1120c1c6f601Srie * Make sure this COMMON symbol is returned to the same 1121c1c6f601Srie * binding as was defined in the original relocatable 112254d82594Sseizo * object reference. 112354d82594Sseizo */ 112454d82594Sseizo type = ELF_ST_TYPE(symptr->st_info); 112554d82594Sseizo if (sdp->sd_flags & FLG_SY_GLOBREF) 112654d82594Sseizo bind = STB_GLOBAL; 112754d82594Sseizo else 112854d82594Sseizo bind = STB_WEAK; 11297c478bd9Sstevel@tonic-gate 113054d82594Sseizo symptr->st_info = ELF_ST_INFO(bind, type); 11317c478bd9Sstevel@tonic-gate } 11328222814eSRichard Lowe 11338222814eSRichard Lowe #define IS_DATA_SYMBOL(x) ((ELF_ST_TYPE(x->st_info) == STT_OBJECT) || \ 11348222814eSRichard Lowe (ELF_ST_TYPE(x->st_info) == STT_COMMON) || \ 11358222814eSRichard Lowe (ELF_ST_TYPE(x->st_info) == STT_TLS)) 11368222814eSRichard Lowe 11378222814eSRichard Lowe /* 11388222814eSRichard Lowe * Filter symbols, special symbols, and those that will be reduced aren't 11398222814eSRichard Lowe * worth guidance 11408222814eSRichard Lowe */ 11418222814eSRichard Lowe #define IS_BORING_SYMBOL(x) (x->sd_flags & (FLG_SY_REDUCED|FLG_SY_STDFLTR| \ 11428222814eSRichard Lowe FLG_SY_SPECSEC|FLG_SY_HIDDEN|FLG_SY_ELIM|FLG_SY_IGNORE)) 11438222814eSRichard Lowe 11448222814eSRichard Lowe /* Local symbols and unresolved weaks aren't useful to guide on */ 11458222814eSRichard Lowe #define IS_BORING_SCOPE(x) ((ELF_ST_BIND(x->st_info) == STB_LOCAL) || \ 11468222814eSRichard Lowe ((ELF_ST_BIND(x->st_info) == STB_WEAK) && \ 11478222814eSRichard Lowe (x->st_shndx == SHN_UNDEF))) 11488222814eSRichard Lowe 11498222814eSRichard Lowe /* Symbol has the assertions recommended for global data */ 11508222814eSRichard Lowe #define HAS_NEEDED_ASSERTS(x) ((x->sd_ass != NULL) && \ 11518222814eSRichard Lowe (ass_enabled(x->sd_ass, SYM_ASSERT_SIZE) || \ 11528222814eSRichard Lowe ass_enabled(x->sd_ass, SYM_ASSERT_ALIAS))) 11538222814eSRichard Lowe 11548222814eSRichard Lowe /* 11558222814eSRichard Lowe * If we're building a shared object and a mapfile is 11568222814eSRichard Lowe * specified, issue guidance if any symbol mentioned in the 11578222814eSRichard Lowe * mapfile is a global data symbol with no asserted size. 11588222814eSRichard Lowe * 11598222814eSRichard Lowe * This is somewhat heuristic to maximize the chance of 11608222814eSRichard Lowe * -zguidance users seeing our good advice without us being 11618222814eSRichard Lowe * annoying (eg. we don't guide when things like 11628222814eSRichard Lowe * mapfile.noex* are the only mapfiles) 11638222814eSRichard Lowe */ 11648222814eSRichard Lowe if (OFL_GUIDANCE(ofl, FLG_OFG_NO_ASSERTS) && 11658222814eSRichard Lowe (aplist_nitems(ofl->ofl_maps) > 0) && /* mapfile used */ 11668222814eSRichard Lowe (ofl->ofl_flags & FLG_OF_SHAROBJ) && /* building .so */ 11678222814eSRichard Lowe (ofl->ofl_flags & FLG_OF_VERDEF) && /* versions/reduce */ 11688222814eSRichard Lowe (sdp->sd_ref == REF_REL_NEED) && /* symbol in .o */ 11698222814eSRichard Lowe IS_DATA_SYMBOL(sdp->sd_sym) && 11708222814eSRichard Lowe !IS_BORING_SCOPE(sdp->sd_sym) && 11718222814eSRichard Lowe !IS_BORING_SYMBOL(sdp) && 11728222814eSRichard Lowe !HAS_NEEDED_ASSERTS(sdp)) { 11738222814eSRichard Lowe ld_eprintf(ofl, ERR_GUIDANCE, 11748222814eSRichard Lowe MSG_INTL(MSG_GUIDE_ASSERT_SIZE), 11758222814eSRichard Lowe sdp->sd_name, (Lword)sdp->sd_sym->st_size); 11768222814eSRichard Lowe } 11777c478bd9Sstevel@tonic-gate } 11787c478bd9Sstevel@tonic-gate 117908278a5eSRod Evans /* 118008278a5eSRod Evans * If this is a dynamic object then add any local capabilities symbols. 118108278a5eSRod Evans */ 118208278a5eSRod Evans if (dynsym && ofl->ofl_capfamilies) { 118308278a5eSRod Evans Cap_avlnode *cav; 118408278a5eSRod Evans 118508278a5eSRod Evans for (cav = avl_first(ofl->ofl_capfamilies); cav; 118608278a5eSRod Evans cav = AVL_NEXT(ofl->ofl_capfamilies, cav)) { 118708278a5eSRod Evans Cap_sym *csp; 118808278a5eSRod Evans Aliste idx; 118908278a5eSRod Evans 119008278a5eSRod Evans for (APLIST_TRAVERSE(cav->cn_members, idx, csp)) { 119108278a5eSRod Evans sdp = csp->cs_sdp; 119208278a5eSRod Evans 119308278a5eSRod Evans DBG_CALL(Dbg_syms_created(ofl->ofl_lml, 119408278a5eSRod Evans sdp->sd_name)); 119508278a5eSRod Evans DBG_CALL(Dbg_syms_entered(ofl, sdp->sd_sym, 119608278a5eSRod Evans sdp)); 119708278a5eSRod Evans 119808278a5eSRod Evans dynsym[dynsym_ndx] = *sdp->sd_sym; 119908278a5eSRod Evans 120008278a5eSRod Evans (void) st_setstring(dynstr, sdp->sd_name, 120108278a5eSRod Evans &stoff); 120208278a5eSRod Evans dynsym[dynsym_ndx].st_name = stoff; 120308278a5eSRod Evans 120408278a5eSRod Evans sdp->sd_sym = &dynsym[dynsym_ndx]; 120508278a5eSRod Evans sdp->sd_symndx = dynsym_ndx; 120608278a5eSRod Evans 120708278a5eSRod Evans /* 120808278a5eSRod Evans * Indicate that this is a capabilities symbol. 120908278a5eSRod Evans * Note, that this identification only provides 121008278a5eSRod Evans * information regarding the symbol that is 121108278a5eSRod Evans * visible from elfdump(1) -y. The association 121208278a5eSRod Evans * of a symbol to its capabilities is derived 121308278a5eSRod Evans * from a .SUNW_capinfo entry. 121408278a5eSRod Evans */ 121508278a5eSRod Evans if (syminfo) { 121608278a5eSRod Evans syminfo[dynsym_ndx].si_flags |= 121708278a5eSRod Evans SYMINFO_FLG_CAP; 121808278a5eSRod Evans } 121908278a5eSRod Evans 122008278a5eSRod Evans dynsym_ndx++; 122108278a5eSRod Evans } 122208278a5eSRod Evans } 122308278a5eSRod Evans } 122408278a5eSRod Evans 12257c478bd9Sstevel@tonic-gate if (ofl->ofl_hashbkts) { 12267c478bd9Sstevel@tonic-gate qsort(sorted_syms + ofl->ofl_scopecnt + ofl->ofl_elimcnt, 12277c478bd9Sstevel@tonic-gate ofl->ofl_globcnt, sizeof (Sym_s_list), 12287c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))sym_hash_compare); 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate 12317c478bd9Sstevel@tonic-gate for (ssndx = 0; ssndx < (ofl->ofl_elimcnt + ofl->ofl_scopecnt + 12327c478bd9Sstevel@tonic-gate ofl->ofl_globcnt); ssndx++) { 12337c478bd9Sstevel@tonic-gate const char *name; 12347c478bd9Sstevel@tonic-gate Sym *sym; 12357c478bd9Sstevel@tonic-gate Sym_aux *sap; 12367c478bd9Sstevel@tonic-gate Half spec; 12379039eeafSab int local = 0, dynlocal = 0, enter_in_symtab; 12387c478bd9Sstevel@tonic-gate Gotndx *gnp; 12397c478bd9Sstevel@tonic-gate Word sectndx; 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate sdp = sorted_syms[ssndx].sl_sdp; 12427c478bd9Sstevel@tonic-gate sectndx = 0; 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate if (symtab) 12457c478bd9Sstevel@tonic-gate enter_in_symtab = 1; 12467c478bd9Sstevel@tonic-gate else 12477c478bd9Sstevel@tonic-gate enter_in_symtab = 0; 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate /* 12507c478bd9Sstevel@tonic-gate * Assign a got offset if necessary. 12517c478bd9Sstevel@tonic-gate */ 1252ba2be530Sab if ((ld_targ.t_mr.mr_assign_got != NULL) && 1253ba2be530Sab (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR) 12547c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 1255c1c6f601Srie 12565aefb655Srie if (DBG_ENABLED) { 125757ef7aa9SRod Evans Aliste idx2; 125857ef7aa9SRod Evans 125957ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_GOTndxs, idx2, gnp)) { 1260d326b23bSrie gottable->gt_sym = sdp; 1261d326b23bSrie gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx; 1262d326b23bSrie gottable->gt_gndx.gn_addend = gnp->gn_addend; 1263d326b23bSrie gottable++; 12647c478bd9Sstevel@tonic-gate } 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate if (sdp->sd_aux && sdp->sd_aux->sa_PLTGOTndx) { 1267d326b23bSrie gottable->gt_sym = sdp; 1268d326b23bSrie gottable->gt_gndx.gn_gotndx = 12697c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_PLTGOTndx; 1270d326b23bSrie gottable++; 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate } 12737c478bd9Sstevel@tonic-gate 12747c478bd9Sstevel@tonic-gate /* 12757c478bd9Sstevel@tonic-gate * If this symbol has been marked as being reduced to local 12767c478bd9Sstevel@tonic-gate * scope then it will have to be placed in the scoped portion 12777c478bd9Sstevel@tonic-gate * of the .symtab. Retain the appropriate index for use in 12787c478bd9Sstevel@tonic-gate * version symbol indexing and relocation. 12797c478bd9Sstevel@tonic-gate */ 1280c524b4feSRichard Lowe if (ld_sym_reducable(ofl, sdp)) { 12817c478bd9Sstevel@tonic-gate local = 1; 1282635216b6SRod Evans if (!(sdp->sd_flags & FLG_SY_ELIM) && !dynsym) 12837c478bd9Sstevel@tonic-gate sdp->sd_symndx = scopesym_ndx; 12847c478bd9Sstevel@tonic-gate else 12857c478bd9Sstevel@tonic-gate sdp->sd_symndx = 0; 12867c478bd9Sstevel@tonic-gate 1287635216b6SRod Evans if (sdp->sd_flags & FLG_SY_ELIM) { 12887c478bd9Sstevel@tonic-gate enter_in_symtab = 0; 12899039eeafSab } else if (ldynsym && sdp->sd_sym->st_name && 1290d579eb63Sab ldynsym_symtype[ 1291d579eb63Sab ELF_ST_TYPE(sdp->sd_sym->st_info)]) { 12929039eeafSab dynlocal = 1; 12939039eeafSab } 12949039eeafSab } else { 12957c478bd9Sstevel@tonic-gate sdp->sd_symndx = *symndx; 12969039eeafSab } 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate /* 12997c478bd9Sstevel@tonic-gate * Copy basic symbol and string information. 13007c478bd9Sstevel@tonic-gate */ 13017c478bd9Sstevel@tonic-gate name = sdp->sd_name; 13027c478bd9Sstevel@tonic-gate sap = sdp->sd_aux; 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate /* 13057c478bd9Sstevel@tonic-gate * If we require to record version symbol indexes, update the 13067c478bd9Sstevel@tonic-gate * associated version symbol information for all defined 13077c478bd9Sstevel@tonic-gate * symbols. If a version definition is required any zero value 13087c478bd9Sstevel@tonic-gate * symbol indexes would have been flagged as undefined symbol 13097c478bd9Sstevel@tonic-gate * errors, however if we're just scoping these need to fall into 13107c478bd9Sstevel@tonic-gate * the base of global symbols. 13117c478bd9Sstevel@tonic-gate */ 13127c478bd9Sstevel@tonic-gate if (sdp->sd_symndx && versym) { 13137c478bd9Sstevel@tonic-gate Half vndx = 0; 13147c478bd9Sstevel@tonic-gate 1315090a8d9eSAli Bahrami if (sdp->sd_flags & FLG_SY_MVTOCOMM) { 13167c478bd9Sstevel@tonic-gate vndx = VER_NDX_GLOBAL; 1317090a8d9eSAli Bahrami } else if (sdp->sd_ref == REF_REL_NEED) { 13187c478bd9Sstevel@tonic-gate vndx = sap->sa_overndx; 131908278a5eSRod Evans 13207c478bd9Sstevel@tonic-gate if ((vndx == 0) && 13217c478bd9Sstevel@tonic-gate (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 132208278a5eSRod Evans if (SYM_IS_HIDDEN(sdp)) 13237c478bd9Sstevel@tonic-gate vndx = VER_NDX_LOCAL; 13247c478bd9Sstevel@tonic-gate else 13257c478bd9Sstevel@tonic-gate vndx = VER_NDX_GLOBAL; 13267c478bd9Sstevel@tonic-gate } 1327090a8d9eSAli Bahrami } else if ((sdp->sd_ref == REF_DYN_NEED) && 1328090a8d9eSAli Bahrami (sap->sa_dverndx > 0) && 1329090a8d9eSAli Bahrami (sap->sa_dverndx <= sdp->sd_file->ifl_vercnt) && 1330090a8d9eSAli Bahrami (sdp->sd_file->ifl_verndx != NULL)) { 1331090a8d9eSAli Bahrami /* Use index of verneed record */ 1332090a8d9eSAli Bahrami vndx = sdp->sd_file->ifl_verndx 1333090a8d9eSAli Bahrami [sap->sa_dverndx].vi_overndx; 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate versym[sdp->sd_symndx] = vndx; 13367c478bd9Sstevel@tonic-gate } 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate /* 13397c478bd9Sstevel@tonic-gate * If we are creating the .syminfo section then set per symbol 13407c478bd9Sstevel@tonic-gate * flags here. 13417c478bd9Sstevel@tonic-gate */ 13427c478bd9Sstevel@tonic-gate if (sdp->sd_symndx && syminfo && 13437c478bd9Sstevel@tonic-gate !(sdp->sd_flags & FLG_SY_NOTAVAIL)) { 13447c478bd9Sstevel@tonic-gate int ndx = sdp->sd_symndx; 1345635216b6SRod Evans APlist **alpp = &(ofl->ofl_symdtent); 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_MVTOCOMM) 13487c478bd9Sstevel@tonic-gate /* 13497c478bd9Sstevel@tonic-gate * Identify a copy relocation symbol. 13507c478bd9Sstevel@tonic-gate */ 13517c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_COPY; 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (sdp->sd_ref == REF_DYN_NEED) { 13547c478bd9Sstevel@tonic-gate /* 13557c478bd9Sstevel@tonic-gate * A reference is bound to a needed dependency. 135628bda19cSRod Evans * Save the syminfo entry, so that when the 135728bda19cSRod Evans * .dynamic section has been updated, a 135828bda19cSRod Evans * DT_NEEDED entry can be associated 135928bda19cSRod Evans * (see update_osyminfo()). 13607c478bd9Sstevel@tonic-gate */ 136157ef7aa9SRod Evans if (aplist_append(alpp, sdp, 136257ef7aa9SRod Evans AL_CNT_OFL_SYMINFOSYMS) == NULL) 13637c478bd9Sstevel@tonic-gate return (0); 13647c478bd9Sstevel@tonic-gate 136528bda19cSRod Evans /* 136628bda19cSRod Evans * Flag that the symbol has a direct association 136728bda19cSRod Evans * with the external reference (this is an old 136828bda19cSRod Evans * tagging, that has no real effect by itself). 136928bda19cSRod Evans */ 13707c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT; 1371f441771bSRod Evans 1372f441771bSRod Evans /* 1373f441771bSRod Evans * Flag any lazy or deferred reference. 1374f441771bSRod Evans */ 13757c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_LAZYLD) 13767c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 13777c478bd9Sstevel@tonic-gate SYMINFO_FLG_LAZYLOAD; 1378f441771bSRod Evans if (sdp->sd_flags & FLG_SY_DEFERRED) 1379f441771bSRod Evans syminfo[ndx].si_flags |= 1380f441771bSRod Evans SYMINFO_FLG_DEFERRED; 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate /* 13837c478bd9Sstevel@tonic-gate * Enable direct symbol bindings if: 13847c478bd9Sstevel@tonic-gate * 138557ef7aa9SRod Evans * - Symbol was identified with the DIRECT 13867c478bd9Sstevel@tonic-gate * keyword in a mapfile. 13877c478bd9Sstevel@tonic-gate * 138857ef7aa9SRod Evans * - Symbol reference has been bound to a 1389c524b4feSRichard Lowe * dependency which was specified as 13907c478bd9Sstevel@tonic-gate * requiring direct bindings with -zdirect. 13917c478bd9Sstevel@tonic-gate * 139257ef7aa9SRod Evans * - All symbol references are required to 13937c478bd9Sstevel@tonic-gate * use direct bindings via -Bdirect. 13947c478bd9Sstevel@tonic-gate */ 1395635216b6SRod Evans if (sdp->sd_flags & FLG_SY_DIR) 13967c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 13977c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECTBIND; 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate } else if ((sdp->sd_flags & FLG_SY_EXTERN) && 14007c478bd9Sstevel@tonic-gate (sdp->sd_sym->st_shndx == SHN_UNDEF)) { 14017c478bd9Sstevel@tonic-gate /* 14027c478bd9Sstevel@tonic-gate * If this symbol has been explicitly defined 14037c478bd9Sstevel@tonic-gate * as external, and remains unresolved, mark 14047c478bd9Sstevel@tonic-gate * it as external. 14057c478bd9Sstevel@tonic-gate */ 14067c478bd9Sstevel@tonic-gate syminfo[ndx].si_boundto = SYMINFO_BT_EXTERN; 14077c478bd9Sstevel@tonic-gate 14089a411307Srie } else if ((sdp->sd_flags & FLG_SY_PARENT) && 14099a411307Srie (sdp->sd_sym->st_shndx == SHN_UNDEF)) { 14107c478bd9Sstevel@tonic-gate /* 14119a411307Srie * If this symbol has been explicitly defined 14129a411307Srie * to be a reference to a parent object, 14139a411307Srie * indicate whether a direct binding should be 14147c478bd9Sstevel@tonic-gate * established. 14157c478bd9Sstevel@tonic-gate */ 14167c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT; 14177c478bd9Sstevel@tonic-gate syminfo[ndx].si_boundto = SYMINFO_BT_PARENT; 1418635216b6SRod Evans if (sdp->sd_flags & FLG_SY_DIR) 14197c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14207c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECTBIND; 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate } else if (sdp->sd_flags & FLG_SY_STDFLTR) { 14237c478bd9Sstevel@tonic-gate /* 14247c478bd9Sstevel@tonic-gate * A filter definition. Although this symbol 14257c478bd9Sstevel@tonic-gate * can only be a stub, it might be necessary to 14267c478bd9Sstevel@tonic-gate * prevent external direct bindings. 14277c478bd9Sstevel@tonic-gate */ 14287c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_FILTER; 1429635216b6SRod Evans if (sdp->sd_flags & FLG_SY_NDIR) 14307c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14317c478bd9Sstevel@tonic-gate SYMINFO_FLG_NOEXTDIRECT; 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate } else if (sdp->sd_flags & FLG_SY_AUXFLTR) { 14347c478bd9Sstevel@tonic-gate /* 14357c478bd9Sstevel@tonic-gate * An auxiliary filter definition. By nature, 14367c478bd9Sstevel@tonic-gate * this definition is direct, in that should the 14377c478bd9Sstevel@tonic-gate * filtee lookup fail, we'll fall back to this 143808278a5eSRod Evans * object. It may still be necessary to 14397c478bd9Sstevel@tonic-gate * prevent external direct bindings. 14407c478bd9Sstevel@tonic-gate */ 14417c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_AUXILIARY; 1442635216b6SRod Evans if (sdp->sd_flags & FLG_SY_NDIR) 14437c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14447c478bd9Sstevel@tonic-gate SYMINFO_FLG_NOEXTDIRECT; 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate } else if ((sdp->sd_ref == REF_REL_NEED) && 14477c478bd9Sstevel@tonic-gate (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 14487c478bd9Sstevel@tonic-gate /* 14497c478bd9Sstevel@tonic-gate * This definition exists within the object 1450635216b6SRod Evans * being created. Provide a default boundto 1451635216b6SRod Evans * definition, which may be overridden later. 14527c478bd9Sstevel@tonic-gate */ 1453635216b6SRod Evans syminfo[ndx].si_boundto = SYMINFO_BT_NONE; 1454635216b6SRod Evans 1455635216b6SRod Evans /* 1456635216b6SRod Evans * Indicate whether it is necessary to prevent 1457635216b6SRod Evans * external direct bindings. 1458635216b6SRod Evans */ 1459635216b6SRod Evans if (sdp->sd_flags & FLG_SY_NDIR) { 14607c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14617c478bd9Sstevel@tonic-gate SYMINFO_FLG_NOEXTDIRECT; 14627c478bd9Sstevel@tonic-gate } 14637c478bd9Sstevel@tonic-gate 14649a411307Srie /* 14659a411307Srie * Indicate that this symbol is acting as an 14669a411307Srie * individual interposer. 14679a411307Srie */ 14689a411307Srie if (sdp->sd_flags & FLG_SY_INTPOSE) { 14699a411307Srie syminfo[ndx].si_flags |= 14709a411307Srie SYMINFO_FLG_INTERPOSE; 14719a411307Srie } 14729a411307Srie 1473f441771bSRod Evans /* 1474f441771bSRod Evans * Indicate that this symbol is deferred, and 1475f441771bSRod Evans * hence should not be bound to during BIND_NOW 1476f441771bSRod Evans * relocations. 1477f441771bSRod Evans */ 1478f441771bSRod Evans if (sdp->sd_flags & FLG_SY_DEFERRED) { 1479f441771bSRod Evans syminfo[ndx].si_flags |= 1480f441771bSRod Evans SYMINFO_FLG_DEFERRED; 1481f441771bSRod Evans } 1482f441771bSRod Evans 14837c478bd9Sstevel@tonic-gate /* 1484635216b6SRod Evans * If external bindings are allowed, indicate 1485635216b6SRod Evans * the binding, and a direct binding if 1486635216b6SRod Evans * necessary. 14877c478bd9Sstevel@tonic-gate */ 1488635216b6SRod Evans if ((sdp->sd_flags & FLG_SY_NDIR) == 0) { 14897c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14907c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECT; 14917c478bd9Sstevel@tonic-gate 1492635216b6SRod Evans if (sdp->sd_flags & FLG_SY_DIR) 14937c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14947c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECTBIND; 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate /* 1497635216b6SRod Evans * Provide a default boundto definition, 1498635216b6SRod Evans * which may be overridden later. 14997c478bd9Sstevel@tonic-gate */ 1500635216b6SRod Evans syminfo[ndx].si_boundto = 1501635216b6SRod Evans SYMINFO_BT_SELF; 15027c478bd9Sstevel@tonic-gate } 150308278a5eSRod Evans 150408278a5eSRod Evans /* 150508278a5eSRod Evans * Indicate that this is a capabilities symbol. 150608278a5eSRod Evans * Note, that this identification only provides 150708278a5eSRod Evans * information regarding the symbol that is 150808278a5eSRod Evans * visible from elfdump(1) -y. The association 150908278a5eSRod Evans * of a symbol to its capabilities is derived 151008278a5eSRod Evans * from a .SUNW_capinfo entry. 151108278a5eSRod Evans */ 151208278a5eSRod Evans if ((sdp->sd_flags & FLG_SY_CAP) && 151308278a5eSRod Evans ofl->ofl_oscapinfo) { 151408278a5eSRod Evans syminfo[ndx].si_flags |= 151508278a5eSRod Evans SYMINFO_FLG_CAP; 151608278a5eSRod Evans } 15177c478bd9Sstevel@tonic-gate } 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate /* 15217c478bd9Sstevel@tonic-gate * Note that the `sym' value is reset to be one of the new 15227c478bd9Sstevel@tonic-gate * symbol table entries. This symbol will be updated further 15237c478bd9Sstevel@tonic-gate * depending on the type of the symbol. Process the .symtab 15247c478bd9Sstevel@tonic-gate * first, followed by the .dynsym, thus the `sym' value will 15257c478bd9Sstevel@tonic-gate * remain as the .dynsym value when the .dynsym is present. 1526c1c6f601Srie * This ensures that any versioning symbols st_name value will 15279039eeafSab * be appropriate for the string table used by version 15287c478bd9Sstevel@tonic-gate * entries. 15297c478bd9Sstevel@tonic-gate */ 15307c478bd9Sstevel@tonic-gate if (enter_in_symtab) { 15317c478bd9Sstevel@tonic-gate Word _symndx; 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if (local) 15347c478bd9Sstevel@tonic-gate _symndx = scopesym_ndx; 15357c478bd9Sstevel@tonic-gate else 15367c478bd9Sstevel@tonic-gate _symndx = symtab_ndx; 15379039eeafSab 15387c478bd9Sstevel@tonic-gate symtab[_symndx] = *sdp->sd_sym; 15397c478bd9Sstevel@tonic-gate sdp->sd_sym = sym = &symtab[_symndx]; 15407c478bd9Sstevel@tonic-gate (void) st_setstring(strtab, name, &stoff); 15417c478bd9Sstevel@tonic-gate sym->st_name = stoff; 15427c478bd9Sstevel@tonic-gate } 15439039eeafSab if (dynlocal) { 15449039eeafSab ldynsym[ldynscopesym_ndx] = *sdp->sd_sym; 15459039eeafSab sdp->sd_sym = sym = &ldynsym[ldynscopesym_ndx]; 15469039eeafSab (void) st_setstring(dynstr, name, &stoff); 15479039eeafSab ldynsym[ldynscopesym_ndx].st_name = stoff; 1548d579eb63Sab /* Add it to sort section if it qualifies */ 1549d579eb63Sab ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info), 1550d579eb63Sab ldynscopesym_ndx); 15519039eeafSab } 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate if (dynsym && !local) { 15547c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx] = *sdp->sd_sym; 155560758829Srie 15567c478bd9Sstevel@tonic-gate /* 15577c478bd9Sstevel@tonic-gate * Provided this isn't an unnamed register symbol, 155860758829Srie * update the symbols name and hash value. 15597c478bd9Sstevel@tonic-gate */ 15607c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) || 15617c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx].st_name) { 1562d840867fSab (void) st_setstring(dynstr, name, &stoff); 1563d840867fSab dynsym[dynsym_ndx].st_name = stoff; 156460758829Srie 1565d840867fSab if (stoff) { 156608278a5eSRod Evans Word hashval, _hashndx; 156760758829Srie 156860758829Srie hashval = 156960758829Srie sap->sa_hash % ofl->ofl_hashbkts; 157060758829Srie 1571d840867fSab /* LINTED */ 1572d840867fSab if (_hashndx = hashbkt[hashval]) { 157360758829Srie while (hashchain[_hashndx]) { 1574d840867fSab _hashndx = 1575d840867fSab hashchain[_hashndx]; 157660758829Srie } 1577d840867fSab hashchain[_hashndx] = 1578d840867fSab sdp->sd_symndx; 1579d840867fSab } else { 1580d840867fSab hashbkt[hashval] = 1581d840867fSab sdp->sd_symndx; 1582d840867fSab } 15837c478bd9Sstevel@tonic-gate } 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate sdp->sd_sym = sym = &dynsym[dynsym_ndx]; 158660758829Srie 1587d579eb63Sab /* 1588d579eb63Sab * Add it to sort section if it qualifies. 1589d579eb63Sab * The indexes in that section are relative to the 1590d579eb63Sab * the adjacent SUNW_ldynsym/dymsym pair, so we 1591d579eb63Sab * add the number of items in SUNW_ldynsym to the 1592d579eb63Sab * dynsym index. 1593d579eb63Sab */ 1594d579eb63Sab ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info), 1595d579eb63Sab ldynsym_cnt + dynsym_ndx); 15967c478bd9Sstevel@tonic-gate } 159708278a5eSRod Evans 15989039eeafSab if (!enter_in_symtab && (!dynsym || (local && !dynlocal))) { 15997c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags & FLG_SY_UPREQD)) 16007c478bd9Sstevel@tonic-gate continue; 16017c478bd9Sstevel@tonic-gate sym = sdp->sd_sym; 16027c478bd9Sstevel@tonic-gate } else 16037c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_CLEAN; 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate /* 16067c478bd9Sstevel@tonic-gate * If we have a weak data symbol for which we need the real 16077c478bd9Sstevel@tonic-gate * symbol also, save this processing until later. 16087c478bd9Sstevel@tonic-gate * 16097c478bd9Sstevel@tonic-gate * The exception to this is if the weak/strong have PLT's 16107c478bd9Sstevel@tonic-gate * assigned to them. In that case we don't do the post-weak 16117c478bd9Sstevel@tonic-gate * processing because the PLT's must be maintained so that we 16127c478bd9Sstevel@tonic-gate * can do 'interpositioning' on both of the symbols. 16137c478bd9Sstevel@tonic-gate */ 16147c478bd9Sstevel@tonic-gate if ((sap->sa_linkndx) && 16157c478bd9Sstevel@tonic-gate (ELF_ST_BIND(sym->st_info) == STB_WEAK) && 16167c478bd9Sstevel@tonic-gate (!sap->sa_PLTndx)) { 161757ef7aa9SRod Evans Sym_desc *_sdp; 161857ef7aa9SRod Evans 161957ef7aa9SRod Evans _sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx]; 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate if (_sdp->sd_ref != REF_DYN_SEEN) { 162257ef7aa9SRod Evans Wk_desc wk; 16237c478bd9Sstevel@tonic-gate 16249039eeafSab if (enter_in_symtab) { 162557ef7aa9SRod Evans if (local) { 162657ef7aa9SRod Evans wk.wk_symtab = 16277c478bd9Sstevel@tonic-gate &symtab[scopesym_ndx]; 162857ef7aa9SRod Evans scopesym_ndx++; 162957ef7aa9SRod Evans } else { 163057ef7aa9SRod Evans wk.wk_symtab = 16317c478bd9Sstevel@tonic-gate &symtab[symtab_ndx]; 163257ef7aa9SRod Evans symtab_ndx++; 163357ef7aa9SRod Evans } 16343e831575SAli Bahrami } else { 16353e831575SAli Bahrami wk.wk_symtab = NULL; 16369039eeafSab } 16379039eeafSab if (dynsym) { 16389039eeafSab if (!local) { 163957ef7aa9SRod Evans wk.wk_dynsym = 16409039eeafSab &dynsym[dynsym_ndx]; 164157ef7aa9SRod Evans dynsym_ndx++; 16429039eeafSab } else if (dynlocal) { 164357ef7aa9SRod Evans wk.wk_dynsym = 16449039eeafSab &ldynsym[ldynscopesym_ndx]; 164557ef7aa9SRod Evans ldynscopesym_ndx++; 16469039eeafSab } 16473e831575SAli Bahrami } else { 16483e831575SAli Bahrami wk.wk_dynsym = NULL; 16499039eeafSab } 165057ef7aa9SRod Evans wk.wk_weak = sdp; 165157ef7aa9SRod Evans wk.wk_alias = _sdp; 16527c478bd9Sstevel@tonic-gate 165357ef7aa9SRod Evans if (alist_append(&weak, &wk, 165457ef7aa9SRod Evans sizeof (Wk_desc), AL_CNT_WEAK) == NULL) 16557c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate continue; 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate } 16607c478bd9Sstevel@tonic-gate 16615aefb655Srie DBG_CALL(Dbg_syms_old(ofl, sdp)); 16627c478bd9Sstevel@tonic-gate 1663fb8f92baSToomas Soome spec = 0; 16647c478bd9Sstevel@tonic-gate /* 16657c478bd9Sstevel@tonic-gate * assign new symbol value. 16667c478bd9Sstevel@tonic-gate */ 16677c478bd9Sstevel@tonic-gate sectndx = sdp->sd_shndx; 16687c478bd9Sstevel@tonic-gate if (sectndx == SHN_UNDEF) { 16697c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) && 16707c478bd9Sstevel@tonic-gate (sym->st_value != 0)) { 16711007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 16725aefb655Srie MSG_INTL(MSG_SYM_NOTNULL), 16737c478bd9Sstevel@tonic-gate demangle(name), sdp->sd_file->ifl_name); 16747c478bd9Sstevel@tonic-gate } 16757c478bd9Sstevel@tonic-gate 16767c478bd9Sstevel@tonic-gate /* 16777c478bd9Sstevel@tonic-gate * Undefined weak global, if we are generating a static 16787c478bd9Sstevel@tonic-gate * executable, output as an absolute zero. Otherwise 16797c478bd9Sstevel@tonic-gate * leave it as is, ld.so.1 will skip symbols of this 16807c478bd9Sstevel@tonic-gate * type (this technique allows applications and 16817c478bd9Sstevel@tonic-gate * libraries to test for the existence of a symbol as an 16827c478bd9Sstevel@tonic-gate * indication of the presence or absence of certain 16837c478bd9Sstevel@tonic-gate * functionality). 16847c478bd9Sstevel@tonic-gate */ 1685635216b6SRod Evans if (OFL_IS_STATIC_EXEC(ofl) && 16867c478bd9Sstevel@tonic-gate (ELF_ST_BIND(sym->st_info) == STB_WEAK)) { 16877c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 16887c478bd9Sstevel@tonic-gate sdp->sd_shndx = sectndx = SHN_ABS; 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate } else if ((sdp->sd_flags & FLG_SY_SPECSEC) && 16917c478bd9Sstevel@tonic-gate (sectndx == SHN_COMMON)) { 16927c478bd9Sstevel@tonic-gate /* COMMONs have already been processed */ 16937c478bd9Sstevel@tonic-gate /* EMPTY */ 16947c478bd9Sstevel@tonic-gate ; 16957c478bd9Sstevel@tonic-gate } else { 16967c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_SPECSEC) && 16977c478bd9Sstevel@tonic-gate (sectndx == SHN_ABS)) 16987c478bd9Sstevel@tonic-gate spec = sdp->sd_aux->sa_symspec; 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate /* LINTED */ 17017c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_COMMEXP) { 17027c478bd9Sstevel@tonic-gate /* 17037c478bd9Sstevel@tonic-gate * This is (or was) a COMMON symbol which was 17047c478bd9Sstevel@tonic-gate * processed above - no processing 17057c478bd9Sstevel@tonic-gate * required here. 17067c478bd9Sstevel@tonic-gate */ 17077c478bd9Sstevel@tonic-gate ; 17087c478bd9Sstevel@tonic-gate } else if (sdp->sd_ref == REF_DYN_NEED) { 1709d579eb63Sab uchar_t type, bind; 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate sectndx = SHN_UNDEF; 17127c478bd9Sstevel@tonic-gate sym->st_value = 0; 17137c478bd9Sstevel@tonic-gate sym->st_size = 0; 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate /* 17167c478bd9Sstevel@tonic-gate * Make sure this undefined symbol is returned 17177c478bd9Sstevel@tonic-gate * to the same binding as was defined in the 17187c478bd9Sstevel@tonic-gate * original relocatable object reference. 17197c478bd9Sstevel@tonic-gate */ 17207c478bd9Sstevel@tonic-gate type = ELF_ST_TYPE(sym-> st_info); 17217c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_GLOBREF) 17227c478bd9Sstevel@tonic-gate bind = STB_GLOBAL; 17237c478bd9Sstevel@tonic-gate else 17247c478bd9Sstevel@tonic-gate bind = STB_WEAK; 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, type); 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate } else if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) && 17297c478bd9Sstevel@tonic-gate (sdp->sd_ref == REF_REL_NEED)) { 17307c478bd9Sstevel@tonic-gate osp = sdp->sd_isc->is_osdesc; 17317c478bd9Sstevel@tonic-gate /* LINTED */ 17327c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn(osp->os_scn); 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate /* 17357c478bd9Sstevel@tonic-gate * In an executable, the new symbol value is the 17367c478bd9Sstevel@tonic-gate * old value (offset into defining section) plus 17377c478bd9Sstevel@tonic-gate * virtual address of defining section. In a 17387c478bd9Sstevel@tonic-gate * relocatable, the new value is the old value 17397c478bd9Sstevel@tonic-gate * plus the displacement of the section within 17407c478bd9Sstevel@tonic-gate * the file. 17417c478bd9Sstevel@tonic-gate */ 17427c478bd9Sstevel@tonic-gate /* LINTED */ 17437c478bd9Sstevel@tonic-gate sym->st_value += 17447c478bd9Sstevel@tonic-gate (Off)_elf_getxoff(sdp->sd_isc->is_indata); 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ)) { 17477c478bd9Sstevel@tonic-gate sym->st_value += osp->os_shdr->sh_addr; 17487c478bd9Sstevel@tonic-gate /* 17497c478bd9Sstevel@tonic-gate * TLS symbols are relative to 17507c478bd9Sstevel@tonic-gate * the TLS segment. 17517c478bd9Sstevel@tonic-gate */ 17527c478bd9Sstevel@tonic-gate if ((ELF_ST_TYPE(sym->st_info) == 17537c478bd9Sstevel@tonic-gate STT_TLS) && (ofl->ofl_tlsphdr)) 17547c478bd9Sstevel@tonic-gate sym->st_value -= 17557c478bd9Sstevel@tonic-gate ofl->ofl_tlsphdr->p_vaddr; 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate } 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate if (spec) { 17617c478bd9Sstevel@tonic-gate switch (spec) { 17627c478bd9Sstevel@tonic-gate case SDAUX_ID_ETEXT: 17637c478bd9Sstevel@tonic-gate sym->st_value = etext; 17647c478bd9Sstevel@tonic-gate sectndx = etext_ndx; 17657c478bd9Sstevel@tonic-gate if (etext_abs) 17667c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 17677c478bd9Sstevel@tonic-gate else 17687c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17697c478bd9Sstevel@tonic-gate break; 17707c478bd9Sstevel@tonic-gate case SDAUX_ID_EDATA: 17717c478bd9Sstevel@tonic-gate sym->st_value = edata; 17727c478bd9Sstevel@tonic-gate sectndx = edata_ndx; 17737c478bd9Sstevel@tonic-gate if (edata_abs) 17747c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 17757c478bd9Sstevel@tonic-gate else 17767c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17777c478bd9Sstevel@tonic-gate break; 17787c478bd9Sstevel@tonic-gate case SDAUX_ID_END: 17797c478bd9Sstevel@tonic-gate sym->st_value = end; 17807c478bd9Sstevel@tonic-gate sectndx = end_ndx; 17817c478bd9Sstevel@tonic-gate if (end_abs) 17827c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 17837c478bd9Sstevel@tonic-gate else 17847c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17857c478bd9Sstevel@tonic-gate break; 17867c478bd9Sstevel@tonic-gate case SDAUX_ID_START: 17877c478bd9Sstevel@tonic-gate sym->st_value = start; 17887c478bd9Sstevel@tonic-gate sectndx = start_ndx; 17897c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17907c478bd9Sstevel@tonic-gate break; 17917c478bd9Sstevel@tonic-gate case SDAUX_ID_DYN: 17927c478bd9Sstevel@tonic-gate if (flags & FLG_OF_DYNAMIC) { 17937c478bd9Sstevel@tonic-gate sym->st_value = ofl-> 17947c478bd9Sstevel@tonic-gate ofl_osdynamic->os_shdr->sh_addr; 17957c478bd9Sstevel@tonic-gate /* LINTED */ 17967c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn( 17977c478bd9Sstevel@tonic-gate ofl->ofl_osdynamic->os_scn); 17987c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate break; 18017c478bd9Sstevel@tonic-gate case SDAUX_ID_PLT: 18027c478bd9Sstevel@tonic-gate if (ofl->ofl_osplt) { 18037c478bd9Sstevel@tonic-gate sym->st_value = ofl-> 18047c478bd9Sstevel@tonic-gate ofl_osplt->os_shdr->sh_addr; 18057c478bd9Sstevel@tonic-gate /* LINTED */ 18067c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn( 18077c478bd9Sstevel@tonic-gate ofl->ofl_osplt->os_scn); 18087c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 18097c478bd9Sstevel@tonic-gate } 18107c478bd9Sstevel@tonic-gate break; 18117c478bd9Sstevel@tonic-gate case SDAUX_ID_GOT: 18127c478bd9Sstevel@tonic-gate /* 18137c478bd9Sstevel@tonic-gate * Symbol bias for negative growing tables is 18147c478bd9Sstevel@tonic-gate * stored in symbol's value during 18157c478bd9Sstevel@tonic-gate * allocate_got(). 18167c478bd9Sstevel@tonic-gate */ 18177c478bd9Sstevel@tonic-gate sym->st_value += ofl-> 18187c478bd9Sstevel@tonic-gate ofl_osgot->os_shdr->sh_addr; 18197c478bd9Sstevel@tonic-gate /* LINTED */ 18207c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn(ofl-> 18217c478bd9Sstevel@tonic-gate ofl_osgot->os_scn); 18227c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 18237c478bd9Sstevel@tonic-gate break; 1824b6a0e2cdSRichard Lowe case SDAUX_ID_SECBOUND_START: 1825b6a0e2cdSRichard Lowe sym->st_value = sap->sa_boundsec-> 1826b6a0e2cdSRichard Lowe os_shdr->sh_addr; 1827b6a0e2cdSRichard Lowe sectndx = elf_ndxscn(sap->sa_boundsec->os_scn); 1828b6a0e2cdSRichard Lowe sdp->sd_flags &= ~FLG_SY_SPECSEC; 1829b6a0e2cdSRichard Lowe break; 1830b6a0e2cdSRichard Lowe case SDAUX_ID_SECBOUND_STOP: 1831b6a0e2cdSRichard Lowe sym->st_value = sap->sa_boundsec-> 1832b6a0e2cdSRichard Lowe os_shdr->sh_addr + 1833b6a0e2cdSRichard Lowe sap->sa_boundsec->os_shdr->sh_size; 1834b6a0e2cdSRichard Lowe sectndx = elf_ndxscn(sap->sa_boundsec->os_scn); 1835b6a0e2cdSRichard Lowe sdp->sd_flags &= ~FLG_SY_SPECSEC; 1836b6a0e2cdSRichard Lowe break; 18377c478bd9Sstevel@tonic-gate default: 18387c478bd9Sstevel@tonic-gate /* NOTHING */ 18397c478bd9Sstevel@tonic-gate ; 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate /* 18447c478bd9Sstevel@tonic-gate * If a plt index has been assigned to an undefined function, 18457c478bd9Sstevel@tonic-gate * update the symbols value to the appropriate .plt address. 18467c478bd9Sstevel@tonic-gate */ 18477c478bd9Sstevel@tonic-gate if ((flags & FLG_OF_DYNAMIC) && (flags & FLG_OF_EXEC) && 18487c478bd9Sstevel@tonic-gate (sdp->sd_file) && 18497c478bd9Sstevel@tonic-gate (sdp->sd_file->ifl_ehdr->e_type == ET_DYN) && 18507c478bd9Sstevel@tonic-gate (ELF_ST_TYPE(sym->st_info) == STT_FUNC) && 18517c478bd9Sstevel@tonic-gate !(flags & FLG_OF_BFLAG)) { 18527c478bd9Sstevel@tonic-gate if (sap->sa_PLTndx) 1853ba2be530Sab sym->st_value = 1854ba2be530Sab (*ld_targ.t_mr.mr_calc_plt_addr)(sdp, ofl); 18557c478bd9Sstevel@tonic-gate } 18567c478bd9Sstevel@tonic-gate 18577c478bd9Sstevel@tonic-gate /* 18587c478bd9Sstevel@tonic-gate * Finish updating the symbols. 18597c478bd9Sstevel@tonic-gate */ 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate /* 18627c478bd9Sstevel@tonic-gate * Sym Update: if scoped local - set local binding 18637c478bd9Sstevel@tonic-gate */ 18647c478bd9Sstevel@tonic-gate if (local) 18657c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(STB_LOCAL, 18667c478bd9Sstevel@tonic-gate ELF_ST_TYPE(sym->st_info)); 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate /* 18697c478bd9Sstevel@tonic-gate * Sym Updated: If both the .symtab and .dynsym 18707c478bd9Sstevel@tonic-gate * are present then we've actually updated the information in 18717c478bd9Sstevel@tonic-gate * the .dynsym, therefore copy this same information to the 18727c478bd9Sstevel@tonic-gate * .symtab entry. 18737c478bd9Sstevel@tonic-gate */ 18747c478bd9Sstevel@tonic-gate sdp->sd_shndx = sectndx; 18759039eeafSab if (enter_in_symtab && dynsym && (!local || dynlocal)) { 18769039eeafSab Word _symndx = dynlocal ? scopesym_ndx : symtab_ndx; 18779039eeafSab 18789039eeafSab symtab[_symndx].st_value = sym->st_value; 18799039eeafSab symtab[_symndx].st_size = sym->st_size; 18809039eeafSab symtab[_symndx].st_info = sym->st_info; 18819039eeafSab symtab[_symndx].st_other = sym->st_other; 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate if (enter_in_symtab) { 18857c478bd9Sstevel@tonic-gate Word _symndx; 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate if (local) 18887c478bd9Sstevel@tonic-gate _symndx = scopesym_ndx++; 18897c478bd9Sstevel@tonic-gate else 18907c478bd9Sstevel@tonic-gate _symndx = symtab_ndx++; 18917c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) && 18927c478bd9Sstevel@tonic-gate (sectndx >= SHN_LORESERVE)) { 189357ef7aa9SRod Evans assert(symshndx != NULL); 18947c478bd9Sstevel@tonic-gate symshndx[_symndx] = sectndx; 18957c478bd9Sstevel@tonic-gate symtab[_symndx].st_shndx = SHN_XINDEX; 18967c478bd9Sstevel@tonic-gate } else { 18977c478bd9Sstevel@tonic-gate /* LINTED */ 18987c478bd9Sstevel@tonic-gate symtab[_symndx].st_shndx = (Half)sectndx; 18997c478bd9Sstevel@tonic-gate } 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate 19029039eeafSab if (dynsym && (!local || dynlocal)) { 19039039eeafSab /* 19049039eeafSab * dynsym and ldynsym are distinct tables, so 19059039eeafSab * we use indirection to access the right one 19069039eeafSab * and the related extended section index array. 19079039eeafSab */ 19089039eeafSab Word _symndx; 19099039eeafSab Sym *_dynsym; 19109039eeafSab Word *_dynshndx; 19119039eeafSab 19129039eeafSab if (!local) { 19139039eeafSab _symndx = dynsym_ndx++; 19149039eeafSab _dynsym = dynsym; 19159039eeafSab _dynshndx = dynshndx; 19169039eeafSab } else { 19179039eeafSab _symndx = ldynscopesym_ndx++; 19189039eeafSab _dynsym = ldynsym; 19199039eeafSab _dynshndx = ldynshndx; 19209039eeafSab } 19217c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) && 19227c478bd9Sstevel@tonic-gate (sectndx >= SHN_LORESERVE)) { 192357ef7aa9SRod Evans assert(_dynshndx != NULL); 19249039eeafSab _dynshndx[_symndx] = sectndx; 19259039eeafSab _dynsym[_symndx].st_shndx = SHN_XINDEX; 19267c478bd9Sstevel@tonic-gate } else { 19277c478bd9Sstevel@tonic-gate /* LINTED */ 19289039eeafSab _dynsym[_symndx].st_shndx = (Half)sectndx; 19297c478bd9Sstevel@tonic-gate } 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19325aefb655Srie DBG_CALL(Dbg_syms_new(ofl, sym, sdp)); 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate /* 19367c478bd9Sstevel@tonic-gate * Now that all the symbols have been processed update any weak symbols 19377c478bd9Sstevel@tonic-gate * information (ie. copy all information except `st_name'). As both 19387c478bd9Sstevel@tonic-gate * symbols will be represented in the output, return the weak symbol to 19397c478bd9Sstevel@tonic-gate * its correct type. 19407c478bd9Sstevel@tonic-gate */ 194157ef7aa9SRod Evans for (ALIST_TRAVERSE(weak, idx1, wkp)) { 194257ef7aa9SRod Evans Sym_desc *sdp, *_sdp; 194357ef7aa9SRod Evans Sym *sym, *_sym, *__sym; 1944d579eb63Sab uchar_t bind; 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate sdp = wkp->wk_weak; 19477c478bd9Sstevel@tonic-gate _sdp = wkp->wk_alias; 19483e831575SAli Bahrami _sym = __sym = _sdp->sd_sym; 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_WEAKDEF; 19517c478bd9Sstevel@tonic-gate 19527c478bd9Sstevel@tonic-gate /* 19537c478bd9Sstevel@tonic-gate * If the symbol definition has been scoped then assign it to 19547c478bd9Sstevel@tonic-gate * be local, otherwise if it's from a shared object then we need 19557c478bd9Sstevel@tonic-gate * to maintain the binding of the original reference. 19567c478bd9Sstevel@tonic-gate */ 195708278a5eSRod Evans if (SYM_IS_HIDDEN(sdp)) { 1958c524b4feSRichard Lowe if (ld_sym_reducable(ofl, sdp)) 19597c478bd9Sstevel@tonic-gate bind = STB_LOCAL; 19607c478bd9Sstevel@tonic-gate else 19617c478bd9Sstevel@tonic-gate bind = STB_WEAK; 19627c478bd9Sstevel@tonic-gate } else if ((sdp->sd_ref == REF_DYN_NEED) && 19637c478bd9Sstevel@tonic-gate (sdp->sd_flags & FLG_SY_GLOBREF)) 19647c478bd9Sstevel@tonic-gate bind = STB_GLOBAL; 19657c478bd9Sstevel@tonic-gate else 19667c478bd9Sstevel@tonic-gate bind = STB_WEAK; 19677c478bd9Sstevel@tonic-gate 19685aefb655Srie DBG_CALL(Dbg_syms_old(ofl, sdp)); 19693e831575SAli Bahrami if ((sym = wkp->wk_symtab) != NULL) { 19707c478bd9Sstevel@tonic-gate sym->st_value = _sym->st_value; 19717c478bd9Sstevel@tonic-gate sym->st_size = _sym->st_size; 19727c478bd9Sstevel@tonic-gate sym->st_other = _sym->st_other; 19737c478bd9Sstevel@tonic-gate sym->st_shndx = _sym->st_shndx; 19747c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, 19757c478bd9Sstevel@tonic-gate ELF_ST_TYPE(sym->st_info)); 19767c478bd9Sstevel@tonic-gate __sym = sym; 19777c478bd9Sstevel@tonic-gate } 19783e831575SAli Bahrami if ((sym = wkp->wk_dynsym) != NULL) { 19797c478bd9Sstevel@tonic-gate sym->st_value = _sym->st_value; 19807c478bd9Sstevel@tonic-gate sym->st_size = _sym->st_size; 19817c478bd9Sstevel@tonic-gate sym->st_other = _sym->st_other; 19827c478bd9Sstevel@tonic-gate sym->st_shndx = _sym->st_shndx; 19837c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, 19847c478bd9Sstevel@tonic-gate ELF_ST_TYPE(sym->st_info)); 19857c478bd9Sstevel@tonic-gate __sym = sym; 19867c478bd9Sstevel@tonic-gate } 19875aefb655Srie DBG_CALL(Dbg_syms_new(ofl, __sym, sdp)); 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate 19907c478bd9Sstevel@tonic-gate /* 19915aefb655Srie * Now display GOT debugging information if required. 19927c478bd9Sstevel@tonic-gate */ 1993ba2be530Sab DBG_CALL(Dbg_got_display(ofl, 0, 0, 1994ba2be530Sab ld_targ.t_m.m_got_xnumber, ld_targ.t_m.m_got_entsize)); 19957c478bd9Sstevel@tonic-gate 19967c478bd9Sstevel@tonic-gate /* 19979039eeafSab * Update the section headers information. sh_info is 19989039eeafSab * supposed to contain the offset at which the first 19999039eeafSab * global symbol resides in the symbol table, while 20009039eeafSab * sh_link contains the section index of the associated 20019039eeafSab * string table. 20027c478bd9Sstevel@tonic-gate */ 20037c478bd9Sstevel@tonic-gate if (symtab) { 200460758829Srie Shdr *shdr = ofl->ofl_ossymtab->os_shdr; 20057c478bd9Sstevel@tonic-gate 2006ca4eed8bSAli Bahrami shdr->sh_info = symtab_gbl_bndx; 20077c478bd9Sstevel@tonic-gate /* LINTED */ 20087c478bd9Sstevel@tonic-gate shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osstrtab->os_scn); 2009e64d0ff9SAli Bahrami if (symshndx) 2010e64d0ff9SAli Bahrami ofl->ofl_ossymshndx->os_shdr->sh_link = 2011d840867fSab (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn); 2012ca4eed8bSAli Bahrami 2013ca4eed8bSAli Bahrami /* 2014ca4eed8bSAli Bahrami * Ensure that the expected number of symbols 2015ca4eed8bSAli Bahrami * were entered into the right spots: 2016ca4eed8bSAli Bahrami * - Scoped symbols in the right range 2017ca4eed8bSAli Bahrami * - Globals start at the right spot 2018ca4eed8bSAli Bahrami * (correct number of locals entered) 2019ca4eed8bSAli Bahrami * - The table is exactly filled 2020ca4eed8bSAli Bahrami * (correct number of globals entered) 2021ca4eed8bSAli Bahrami */ 2022ca4eed8bSAli Bahrami assert((scopesym_bndx + ofl->ofl_scopecnt) == scopesym_ndx); 2023635216b6SRod Evans assert(shdr->sh_info == SYMTAB_LOC_CNT(ofl)); 2024ca4eed8bSAli Bahrami assert((shdr->sh_info + ofl->ofl_globcnt) == symtab_ndx); 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate if (dynsym) { 202760758829Srie Shdr *shdr = ofl->ofl_osdynsym->os_shdr; 20287c478bd9Sstevel@tonic-gate 2029635216b6SRod Evans shdr->sh_info = DYNSYM_LOC_CNT(ofl); 20307c478bd9Sstevel@tonic-gate /* LINTED */ 20317c478bd9Sstevel@tonic-gate shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn); 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate ofl->ofl_oshash->os_shdr->sh_link = 20347c478bd9Sstevel@tonic-gate /* LINTED */ 20357c478bd9Sstevel@tonic-gate (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn); 20367c478bd9Sstevel@tonic-gate if (dynshndx) { 20377c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osdynshndx->os_shdr; 20387c478bd9Sstevel@tonic-gate shdr->sh_link = 2039d840867fSab (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn); 20407c478bd9Sstevel@tonic-gate } 20417c478bd9Sstevel@tonic-gate } 20429039eeafSab if (ldynsym) { 204360758829Srie Shdr *shdr = ofl->ofl_osldynsym->os_shdr; 20449039eeafSab 20459039eeafSab /* ldynsym has no globals, so give index one past the end */ 20469039eeafSab shdr->sh_info = ldynsym_ndx; 20479039eeafSab 20489039eeafSab /* 20499039eeafSab * The ldynsym and dynsym must be adjacent. The 20509039eeafSab * idea is that rtld should be able to start with 20519039eeafSab * the ldynsym and march straight through the end 20529039eeafSab * of dynsym, seeing them as a single symbol table, 20539039eeafSab * despite the fact that they are in distinct sections. 20549039eeafSab * Ensure that this happened correctly. 20559039eeafSab * 20569039eeafSab * Note that I use ldynsym_ndx here instead of the 20579039eeafSab * computation I used to set the section size 2058d579eb63Sab * (found in ldynsym_cnt). The two will agree, unless 2059d579eb63Sab * we somehow miscounted symbols or failed to insert them 2060d579eb63Sab * all. Using ldynsym_ndx here catches that error in 2061d579eb63Sab * addition to checking for adjacency. 20629039eeafSab */ 20639039eeafSab assert(dynsym == (ldynsym + ldynsym_ndx)); 20649039eeafSab 20659039eeafSab 20669039eeafSab /* LINTED */ 20679039eeafSab shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn); 20689039eeafSab 20699039eeafSab if (ldynshndx) { 20709039eeafSab shdr = ofl->ofl_osldynshndx->os_shdr; 20719039eeafSab shdr->sh_link = 2072d840867fSab (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn); 20739039eeafSab } 2074d579eb63Sab 2075d579eb63Sab /* 2076d579eb63Sab * The presence of .SUNW_ldynsym means that there may be 2077d579eb63Sab * associated sort sections, one for regular symbols 2078d579eb63Sab * and the other for TLS. Each sort section needs the 2079d579eb63Sab * following done: 2080d579eb63Sab * - Section header link references .SUNW_ldynsym 2081d579eb63Sab * - Should have received the expected # of items 2082d579eb63Sab * - Sorted by increasing address 2083d579eb63Sab */ 2084d579eb63Sab if (ofl->ofl_osdynsymsort) { /* .SUNW_dynsymsort */ 2085d579eb63Sab ofl->ofl_osdynsymsort->os_shdr->sh_link = 2086d579eb63Sab (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn); 2087d579eb63Sab assert(ofl->ofl_dynsymsortcnt == dynsymsort_ndx); 208860758829Srie 2089d579eb63Sab if (dynsymsort_ndx > 1) { 2090d579eb63Sab dynsort_compare_syms = ldynsym; 2091d579eb63Sab qsort(dynsymsort, dynsymsort_ndx, 2092d579eb63Sab sizeof (*dynsymsort), dynsort_compare); 2093a194faf8Srie dynsort_dupwarn(ofl, ldynsym, 2094a194faf8Srie st_getstrbuf(dynstr), 2095d579eb63Sab dynsymsort, dynsymsort_ndx, 2096d579eb63Sab MSG_ORIG(MSG_SCN_DYNSYMSORT)); 2097d579eb63Sab } 2098d579eb63Sab } 2099d579eb63Sab if (ofl->ofl_osdyntlssort) { /* .SUNW_dyntlssort */ 2100d579eb63Sab ofl->ofl_osdyntlssort->os_shdr->sh_link = 2101d579eb63Sab (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn); 2102d579eb63Sab assert(ofl->ofl_dyntlssortcnt == dyntlssort_ndx); 210360758829Srie 2104d579eb63Sab if (dyntlssort_ndx > 1) { 2105d579eb63Sab dynsort_compare_syms = ldynsym; 2106d579eb63Sab qsort(dyntlssort, dyntlssort_ndx, 2107d579eb63Sab sizeof (*dyntlssort), dynsort_compare); 2108a194faf8Srie dynsort_dupwarn(ofl, ldynsym, 2109a194faf8Srie st_getstrbuf(dynstr), 2110d579eb63Sab dyntlssort, dyntlssort_ndx, 2111d579eb63Sab MSG_ORIG(MSG_SCN_DYNTLSSORT)); 2112d579eb63Sab } 2113d579eb63Sab } 21149039eeafSab } 21157c478bd9Sstevel@tonic-gate 21167c478bd9Sstevel@tonic-gate /* 21177c478bd9Sstevel@tonic-gate * Used by ld.so.1 only. 21187c478bd9Sstevel@tonic-gate */ 21197c478bd9Sstevel@tonic-gate return (etext); 2120d579eb63Sab 2121d579eb63Sab #undef ADD_TO_DYNSORT 21227c478bd9Sstevel@tonic-gate } 21237c478bd9Sstevel@tonic-gate 21247c478bd9Sstevel@tonic-gate /* 21257c478bd9Sstevel@tonic-gate * Build the dynamic section. 21261d9df23bSab * 21271d9df23bSab * This routine must be maintained in parallel with make_dynamic() 21281d9df23bSab * in sections.c 21297c478bd9Sstevel@tonic-gate */ 21305aefb655Srie static int 21317c478bd9Sstevel@tonic-gate update_odynamic(Ofl_desc *ofl) 21327c478bd9Sstevel@tonic-gate { 213357ef7aa9SRod Evans Aliste idx; 21347c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 21357c478bd9Sstevel@tonic-gate Sym_desc *sdp; 21367c478bd9Sstevel@tonic-gate Shdr *shdr; 21377c478bd9Sstevel@tonic-gate Dyn *_dyn = (Dyn *)ofl->ofl_osdynamic->os_outdata->d_buf; 21387c478bd9Sstevel@tonic-gate Dyn *dyn; 2139635216b6SRod Evans Os_desc *symosp, *strosp; 2140635216b6SRod Evans Str_tbl *strtbl; 2141cce0e03bSab size_t stoff; 21421d9df23bSab ofl_flag_t flags = ofl->ofl_flags; 21431d9df23bSab int not_relobj = !(flags & FLG_OF_RELOBJ); 21443244bcaaSab Word cnt; 21457c478bd9Sstevel@tonic-gate 21461d9df23bSab /* 2147635216b6SRod Evans * Relocatable objects can be built with -r and -dy to trigger the 2148635216b6SRod Evans * creation of a .dynamic section. This model is used to create kernel 2149635216b6SRod Evans * device drivers. The .dynamic section provides a subset of userland 2150635216b6SRod Evans * .dynamic entries, typically entries such as DT_NEEDED and DT_RUNPATH. 21511d9df23bSab * 2152635216b6SRod Evans * Within a dynamic object, any .dynamic string references are to the 2153635216b6SRod Evans * .dynstr table. Within a relocatable object, these strings can reside 2154635216b6SRod Evans * within the .strtab. 21551d9df23bSab */ 2156635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 2157635216b6SRod Evans symosp = ofl->ofl_ossymtab; 2158635216b6SRod Evans strosp = ofl->ofl_osstrtab; 2159635216b6SRod Evans strtbl = ofl->ofl_strtab; 2160635216b6SRod Evans } else { 2161635216b6SRod Evans symosp = ofl->ofl_osdynsym; 2162635216b6SRod Evans strosp = ofl->ofl_osdynstr; 2163635216b6SRod Evans strtbl = ofl->ofl_dynstrtab; 2164635216b6SRod Evans } 2165635216b6SRod Evans 2166635216b6SRod Evans /* LINTED */ 2167635216b6SRod Evans ofl->ofl_osdynamic->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn); 21687c478bd9Sstevel@tonic-gate 21697c478bd9Sstevel@tonic-gate dyn = _dyn; 21707c478bd9Sstevel@tonic-gate 217157ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_sos, idx, ifl)) { 21727c478bd9Sstevel@tonic-gate if ((ifl->ifl_flags & 21737c478bd9Sstevel@tonic-gate (FLG_IF_IGNORE | FLG_IF_DEPREQD)) == FLG_IF_IGNORE) 21747c478bd9Sstevel@tonic-gate continue; 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate /* 21777c478bd9Sstevel@tonic-gate * Create and set up the DT_POSFLAG_1 entry here if required. 21787c478bd9Sstevel@tonic-gate */ 2179f441771bSRod Evans if ((ifl->ifl_flags & MSK_IF_POSFLAG1) && 2180f441771bSRod Evans (ifl->ifl_flags & FLG_IF_NEEDED) && not_relobj) { 21817c478bd9Sstevel@tonic-gate dyn->d_tag = DT_POSFLAG_1; 21827c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_LAZYLD) 21837c478bd9Sstevel@tonic-gate dyn->d_un.d_val = DF_P1_LAZYLOAD; 21847c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_GRPPRM) 21857c478bd9Sstevel@tonic-gate dyn->d_un.d_val |= DF_P1_GROUPPERM; 2186f441771bSRod Evans if (ifl->ifl_flags & FLG_IF_DEFERRED) 2187f441771bSRod Evans dyn->d_un.d_val |= DF_P1_DEFERRED; 21887c478bd9Sstevel@tonic-gate dyn++; 21897c478bd9Sstevel@tonic-gate } 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR)) 21927c478bd9Sstevel@tonic-gate dyn->d_tag = DT_NEEDED; 21937c478bd9Sstevel@tonic-gate else 21947c478bd9Sstevel@tonic-gate continue; 21957c478bd9Sstevel@tonic-gate 2196635216b6SRod Evans (void) st_setstring(strtbl, ifl->ifl_soname, &stoff); 21977c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 21987c478bd9Sstevel@tonic-gate /* LINTED */ 21997c478bd9Sstevel@tonic-gate ifl->ifl_neededndx = (Half)(((uintptr_t)dyn - (uintptr_t)_dyn) / 22007c478bd9Sstevel@tonic-gate sizeof (Dyn)); 22017c478bd9Sstevel@tonic-gate dyn++; 22027c478bd9Sstevel@tonic-gate } 22037c478bd9Sstevel@tonic-gate 22041d9df23bSab if (not_relobj) { 22051d9df23bSab if (ofl->ofl_dtsfltrs != NULL) { 22061d9df23bSab Dfltr_desc *dftp; 22077c478bd9Sstevel@tonic-gate 22081d9df23bSab for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, idx, dftp)) { 22091d9df23bSab if (dftp->dft_flag == FLG_SY_AUXFLTR) 22101d9df23bSab dyn->d_tag = DT_SUNW_AUXILIARY; 22111d9df23bSab else 22121d9df23bSab dyn->d_tag = DT_SUNW_FILTER; 22137c478bd9Sstevel@tonic-gate 2214635216b6SRod Evans (void) st_setstring(strtbl, dftp->dft_str, 22151d9df23bSab &stoff); 22161d9df23bSab dyn->d_un.d_val = stoff; 22171d9df23bSab dftp->dft_ndx = (Half)(((uintptr_t)dyn - 22181d9df23bSab (uintptr_t)_dyn) / sizeof (Dyn)); 22191d9df23bSab dyn++; 22201d9df23bSab } 22211d9df23bSab } 22221d9df23bSab if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U), 22231d9df23bSab SYM_NOHASH, 0, ofl)) != NULL) && 22241d9df23bSab (sdp->sd_ref == REF_REL_NEED) && 22251d9df23bSab (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 22261d9df23bSab dyn->d_tag = DT_INIT; 22271d9df23bSab dyn->d_un.d_ptr = sdp->sd_sym->st_value; 22281d9df23bSab dyn++; 22291d9df23bSab } 22301d9df23bSab if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U), 22311d9df23bSab SYM_NOHASH, 0, ofl)) != NULL) && 22321d9df23bSab (sdp->sd_ref == REF_REL_NEED) && 22331d9df23bSab (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 22341d9df23bSab dyn->d_tag = DT_FINI; 22351d9df23bSab dyn->d_un.d_ptr = sdp->sd_sym->st_value; 22361d9df23bSab dyn++; 22371d9df23bSab } 22381d9df23bSab if (ofl->ofl_soname) { 22391d9df23bSab dyn->d_tag = DT_SONAME; 2240635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_soname, &stoff); 22417c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 22427c478bd9Sstevel@tonic-gate dyn++; 22437c478bd9Sstevel@tonic-gate } 22441d9df23bSab if (ofl->ofl_filtees) { 22451d9df23bSab if (flags & FLG_OF_AUX) { 22461d9df23bSab dyn->d_tag = DT_AUXILIARY; 22471d9df23bSab } else { 22481d9df23bSab dyn->d_tag = DT_FILTER; 22491d9df23bSab } 2250635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_filtees, &stoff); 22511d9df23bSab dyn->d_un.d_val = stoff; 22521d9df23bSab dyn++; 22537c478bd9Sstevel@tonic-gate } 22547c478bd9Sstevel@tonic-gate } 22551d9df23bSab 22567c478bd9Sstevel@tonic-gate if (ofl->ofl_rpath) { 2257635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_rpath, &stoff); 22587c478bd9Sstevel@tonic-gate dyn->d_tag = DT_RUNPATH; 22597c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 22607c478bd9Sstevel@tonic-gate dyn++; 22617c478bd9Sstevel@tonic-gate dyn->d_tag = DT_RPATH; 22627c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 22637c478bd9Sstevel@tonic-gate dyn++; 22647c478bd9Sstevel@tonic-gate } 22657c478bd9Sstevel@tonic-gate 22661d9df23bSab if (not_relobj) { 226757ef7aa9SRod Evans Aliste idx; 226894c044f4SRod Evans Sg_desc *sgp; 226957ef7aa9SRod Evans 22701d9df23bSab if (ofl->ofl_config) { 22711d9df23bSab dyn->d_tag = DT_CONFIG; 2272635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_config, &stoff); 22731d9df23bSab dyn->d_un.d_val = stoff; 22741d9df23bSab dyn++; 22751d9df23bSab } 22761d9df23bSab if (ofl->ofl_depaudit) { 22771d9df23bSab dyn->d_tag = DT_DEPAUDIT; 2278635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_depaudit, &stoff); 22791d9df23bSab dyn->d_un.d_val = stoff; 22801d9df23bSab dyn++; 22811d9df23bSab } 22821d9df23bSab if (ofl->ofl_audit) { 22831d9df23bSab dyn->d_tag = DT_AUDIT; 2284635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_audit, &stoff); 22851d9df23bSab dyn->d_un.d_val = stoff; 22861d9df23bSab dyn++; 22871d9df23bSab } 22887c478bd9Sstevel@tonic-gate 22897c478bd9Sstevel@tonic-gate dyn->d_tag = DT_HASH; 22907c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = ofl->ofl_oshash->os_shdr->sh_addr; 22917c478bd9Sstevel@tonic-gate dyn++; 22927c478bd9Sstevel@tonic-gate 2293635216b6SRod Evans shdr = strosp->os_shdr; 22947c478bd9Sstevel@tonic-gate dyn->d_tag = DT_STRTAB; 22957c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 22967c478bd9Sstevel@tonic-gate dyn++; 22977c478bd9Sstevel@tonic-gate 22987c478bd9Sstevel@tonic-gate dyn->d_tag = DT_STRSZ; 22997c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_size; 23007c478bd9Sstevel@tonic-gate dyn++; 23017c478bd9Sstevel@tonic-gate 2302635216b6SRod Evans /* 2303635216b6SRod Evans * Note, the shdr is set and used in the ofl->ofl_osldynsym case 2304635216b6SRod Evans * that follows. 2305635216b6SRod Evans */ 2306635216b6SRod Evans shdr = symosp->os_shdr; 23077c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMTAB; 23087c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 23097c478bd9Sstevel@tonic-gate dyn++; 23107c478bd9Sstevel@tonic-gate 23117c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMENT; 23127c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_entsize; 23137c478bd9Sstevel@tonic-gate dyn++; 23147c478bd9Sstevel@tonic-gate 23159039eeafSab if (ofl->ofl_osldynsym) { 2316635216b6SRod Evans Shdr *lshdr = ofl->ofl_osldynsym->os_shdr; 2317635216b6SRod Evans 23189039eeafSab /* 23199039eeafSab * We have arranged for the .SUNW_ldynsym data to be 23209039eeafSab * immediately in front of the .dynsym data. 23219039eeafSab * This means that you could start at the top 23229039eeafSab * of .SUNW_ldynsym and see the data for both tables 23239039eeafSab * without a break. This is the view we want to 23249039eeafSab * provide for DT_SUNW_SYMTAB, which is why we 23259039eeafSab * add the lengths together. 23269039eeafSab */ 23279039eeafSab dyn->d_tag = DT_SUNW_SYMTAB; 23289039eeafSab dyn->d_un.d_ptr = lshdr->sh_addr; 23299039eeafSab dyn++; 23309039eeafSab 23319039eeafSab dyn->d_tag = DT_SUNW_SYMSZ; 23329039eeafSab dyn->d_un.d_val = lshdr->sh_size + shdr->sh_size; 23339039eeafSab dyn++; 23349039eeafSab } 23359039eeafSab 2336d579eb63Sab if (ofl->ofl_osdynsymsort || ofl->ofl_osdyntlssort) { 2337d579eb63Sab dyn->d_tag = DT_SUNW_SORTENT; 2338d579eb63Sab dyn->d_un.d_val = sizeof (Word); 2339d579eb63Sab dyn++; 2340d579eb63Sab } 2341d579eb63Sab 2342d579eb63Sab if (ofl->ofl_osdynsymsort) { 2343635216b6SRod Evans shdr = ofl->ofl_osdynsymsort->os_shdr; 2344635216b6SRod Evans 2345d579eb63Sab dyn->d_tag = DT_SUNW_SYMSORT; 2346635216b6SRod Evans dyn->d_un.d_ptr = shdr->sh_addr; 2347d579eb63Sab dyn++; 2348d579eb63Sab 2349d579eb63Sab dyn->d_tag = DT_SUNW_SYMSORTSZ; 2350635216b6SRod Evans dyn->d_un.d_val = shdr->sh_size; 2351d579eb63Sab dyn++; 2352d579eb63Sab } 2353d579eb63Sab 2354d579eb63Sab if (ofl->ofl_osdyntlssort) { 2355635216b6SRod Evans shdr = ofl->ofl_osdyntlssort->os_shdr; 2356635216b6SRod Evans 2357d579eb63Sab dyn->d_tag = DT_SUNW_TLSSORT; 2358635216b6SRod Evans dyn->d_un.d_ptr = shdr->sh_addr; 2359d579eb63Sab dyn++; 2360d579eb63Sab 2361d579eb63Sab dyn->d_tag = DT_SUNW_TLSSORTSZ; 2362635216b6SRod Evans dyn->d_un.d_val = shdr->sh_size; 2363d579eb63Sab dyn++; 2364d579eb63Sab } 2365d579eb63Sab 23667c478bd9Sstevel@tonic-gate /* 23677c478bd9Sstevel@tonic-gate * Reserve the DT_CHECKSUM entry. Its value will be filled in 23687c478bd9Sstevel@tonic-gate * after the complete image is built. 23697c478bd9Sstevel@tonic-gate */ 23707c478bd9Sstevel@tonic-gate dyn->d_tag = DT_CHECKSUM; 23717c478bd9Sstevel@tonic-gate ofl->ofl_checksum = &dyn->d_un.d_val; 23727c478bd9Sstevel@tonic-gate dyn++; 23737c478bd9Sstevel@tonic-gate 2374d840867fSab /* 2375d840867fSab * Versioning sections: DT_VERDEF and DT_VERNEED. 2376d840867fSab * 2377d840867fSab * The Solaris ld does not produce DT_VERSYM, but the GNU ld 2378d840867fSab * does, in order to support their style of versioning, which 2379d840867fSab * differs from ours: 2380d840867fSab * 2381d840867fSab * - The top bit of the 16-bit Versym index is 2382d840867fSab * not part of the version, but is interpreted 2383d840867fSab * as a "hidden bit". 2384d840867fSab * 2385d840867fSab * - External (SHN_UNDEF) symbols can have non-zero 2386d840867fSab * Versym values, which specify versions in 2387d840867fSab * referenced objects, via the Verneed section. 2388d840867fSab * 2389d840867fSab * - The vna_other field of the Vernaux structures 2390d840867fSab * found in the Verneed section are not zero as 2391d840867fSab * with Solaris, but instead contain the version 2392d840867fSab * index to be used by Versym indices to reference 2393d840867fSab * the given external version. 2394d840867fSab * 2395d840867fSab * The Solaris ld, rtld, and elfdump programs all interpret the 2396d840867fSab * presence of DT_VERSYM as meaning that GNU versioning rules 2397d840867fSab * apply to the given file. If DT_VERSYM is not present, 2398d840867fSab * then Solaris versioning rules apply. If we should ever need 2399d840867fSab * to change our ld so that it does issue DT_VERSYM, then 2400d840867fSab * this rule for detecting GNU versioning will no longer work. 2401d840867fSab * In that case, we will have to invent a way to explicitly 2402d840867fSab * specify the style of versioning in use, perhaps via a 2403d840867fSab * new dynamic entry named something like DT_SUNW_VERSIONSTYLE, 2404d840867fSab * where the d_un.d_val value specifies which style is to be 2405d840867fSab * used. 2406d840867fSab */ 24077c478bd9Sstevel@tonic-gate if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) == 24087c478bd9Sstevel@tonic-gate FLG_OF_VERDEF) { 24097c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osverdef->os_shdr; 2410635216b6SRod Evans 24117c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERDEF; 24127c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24137c478bd9Sstevel@tonic-gate dyn++; 24147c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERDEFNUM; 24157c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_info; 24167c478bd9Sstevel@tonic-gate dyn++; 24177c478bd9Sstevel@tonic-gate } 24187c478bd9Sstevel@tonic-gate if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) == 24197c478bd9Sstevel@tonic-gate FLG_OF_VERNEED) { 24207c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osverneed->os_shdr; 2421635216b6SRod Evans 24227c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERNEED; 24237c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24247c478bd9Sstevel@tonic-gate dyn++; 24257c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERNEEDNUM; 24267c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_info; 24277c478bd9Sstevel@tonic-gate dyn++; 24287c478bd9Sstevel@tonic-gate } 2429d840867fSab 24301d9df23bSab if ((flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt) { 2431ba2be530Sab dyn->d_tag = ld_targ.t_m.m_rel_dt_count; 24327c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_relocrelcnt; 24337c478bd9Sstevel@tonic-gate dyn++; 24347c478bd9Sstevel@tonic-gate } 24357c478bd9Sstevel@tonic-gate if (flags & FLG_OF_TEXTREL) { 24367c478bd9Sstevel@tonic-gate /* 24377c478bd9Sstevel@tonic-gate * Only the presence of this entry is used in this 24387c478bd9Sstevel@tonic-gate * implementation, not the value stored. 24397c478bd9Sstevel@tonic-gate */ 24407c478bd9Sstevel@tonic-gate dyn->d_tag = DT_TEXTREL; 24417c478bd9Sstevel@tonic-gate dyn->d_un.d_val = 0; 24427c478bd9Sstevel@tonic-gate dyn++; 24437c478bd9Sstevel@tonic-gate } 24447c478bd9Sstevel@tonic-gate 24457c478bd9Sstevel@tonic-gate if (ofl->ofl_osfiniarray) { 24467c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osfiniarray->os_shdr; 24477c478bd9Sstevel@tonic-gate 24487c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FINI_ARRAY; 24497c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24507c478bd9Sstevel@tonic-gate dyn++; 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FINI_ARRAYSZ; 24537c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 24547c478bd9Sstevel@tonic-gate dyn++; 24557c478bd9Sstevel@tonic-gate } 24567c478bd9Sstevel@tonic-gate 24577c478bd9Sstevel@tonic-gate if (ofl->ofl_osinitarray) { 24587c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osinitarray->os_shdr; 24597c478bd9Sstevel@tonic-gate 24607c478bd9Sstevel@tonic-gate dyn->d_tag = DT_INIT_ARRAY; 24617c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24627c478bd9Sstevel@tonic-gate dyn++; 24637c478bd9Sstevel@tonic-gate 24647c478bd9Sstevel@tonic-gate dyn->d_tag = DT_INIT_ARRAYSZ; 24657c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 24667c478bd9Sstevel@tonic-gate dyn++; 24677c478bd9Sstevel@tonic-gate } 24687c478bd9Sstevel@tonic-gate 24697c478bd9Sstevel@tonic-gate if (ofl->ofl_ospreinitarray) { 24707c478bd9Sstevel@tonic-gate shdr = ofl->ofl_ospreinitarray->os_shdr; 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PREINIT_ARRAY; 24737c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24747c478bd9Sstevel@tonic-gate dyn++; 24757c478bd9Sstevel@tonic-gate 24767c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PREINIT_ARRAYSZ; 24777c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 24787c478bd9Sstevel@tonic-gate dyn++; 24797c478bd9Sstevel@tonic-gate } 24807c478bd9Sstevel@tonic-gate 24817c478bd9Sstevel@tonic-gate if (ofl->ofl_pltcnt) { 2482635216b6SRod Evans shdr = ofl->ofl_osplt->os_relosdesc->os_shdr; 24837c478bd9Sstevel@tonic-gate 24847c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTRELSZ; 24857c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_size; 24867c478bd9Sstevel@tonic-gate dyn++; 24877c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTREL; 2488ba2be530Sab dyn->d_un.d_ptr = ld_targ.t_m.m_rel_dt_type; 24897c478bd9Sstevel@tonic-gate dyn++; 24907c478bd9Sstevel@tonic-gate dyn->d_tag = DT_JMPREL; 24917c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24927c478bd9Sstevel@tonic-gate dyn++; 24937c478bd9Sstevel@tonic-gate } 24947c478bd9Sstevel@tonic-gate if (ofl->ofl_pltpad) { 2495635216b6SRod Evans shdr = ofl->ofl_osplt->os_shdr; 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTPAD; 249860758829Srie if (ofl->ofl_pltcnt) { 24997c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr + 2500ba2be530Sab ld_targ.t_m.m_plt_reservsz + 2501ba2be530Sab ofl->ofl_pltcnt * ld_targ.t_m.m_plt_entsize; 250260758829Srie } else 25037c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 25047c478bd9Sstevel@tonic-gate dyn++; 25057c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTPADSZ; 2506ba2be530Sab dyn->d_un.d_val = ofl->ofl_pltpad * 2507ba2be530Sab ld_targ.t_m.m_plt_entsize; 25087c478bd9Sstevel@tonic-gate dyn++; 25097c478bd9Sstevel@tonic-gate } 25107c478bd9Sstevel@tonic-gate if (ofl->ofl_relocsz) { 2511635216b6SRod Evans shdr = ofl->ofl_osrelhead->os_shdr; 2512635216b6SRod Evans 2513ba2be530Sab dyn->d_tag = ld_targ.t_m.m_rel_dt_type; 2514635216b6SRod Evans dyn->d_un.d_ptr = shdr->sh_addr; 25157c478bd9Sstevel@tonic-gate dyn++; 2516ba2be530Sab dyn->d_tag = ld_targ.t_m.m_rel_dt_size; 25177c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = ofl->ofl_relocsz; 25187c478bd9Sstevel@tonic-gate dyn++; 2519ba2be530Sab dyn->d_tag = ld_targ.t_m.m_rel_dt_ent; 2520635216b6SRod Evans if (shdr->sh_type == SHT_REL) 25217c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sizeof (Rel); 25227c478bd9Sstevel@tonic-gate else 25237c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sizeof (Rela); 25247c478bd9Sstevel@tonic-gate dyn++; 25257c478bd9Sstevel@tonic-gate } 25267c478bd9Sstevel@tonic-gate if (ofl->ofl_ossyminfo) { 25277c478bd9Sstevel@tonic-gate shdr = ofl->ofl_ossyminfo->os_shdr; 2528635216b6SRod Evans 25297c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMINFO; 25307c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 25317c478bd9Sstevel@tonic-gate dyn++; 25327c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMINSZ; 25337c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 25347c478bd9Sstevel@tonic-gate dyn++; 25357c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMINENT; 25367c478bd9Sstevel@tonic-gate dyn->d_un.d_val = sizeof (Syminfo); 25377c478bd9Sstevel@tonic-gate dyn++; 25387c478bd9Sstevel@tonic-gate } 25397c478bd9Sstevel@tonic-gate if (ofl->ofl_osmove) { 2540635216b6SRod Evans shdr = ofl->ofl_osmove->os_shdr; 25417c478bd9Sstevel@tonic-gate 254208278a5eSRod Evans dyn->d_tag = DT_MOVETAB; 254308278a5eSRod Evans dyn->d_un.d_val = shdr->sh_addr; 25447c478bd9Sstevel@tonic-gate dyn++; 25457c478bd9Sstevel@tonic-gate dyn->d_tag = DT_MOVESZ; 2546635216b6SRod Evans dyn->d_un.d_val = shdr->sh_size; 25477c478bd9Sstevel@tonic-gate dyn++; 254808278a5eSRod Evans dyn->d_tag = DT_MOVEENT; 254908278a5eSRod Evans dyn->d_un.d_val = shdr->sh_entsize; 25507c478bd9Sstevel@tonic-gate dyn++; 25517c478bd9Sstevel@tonic-gate } 25527c478bd9Sstevel@tonic-gate if (ofl->ofl_regsymcnt) { 25537c478bd9Sstevel@tonic-gate int ndx; 25547c478bd9Sstevel@tonic-gate 25557c478bd9Sstevel@tonic-gate for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) { 255657ef7aa9SRod Evans if ((sdp = ofl->ofl_regsyms[ndx]) == NULL) 25577c478bd9Sstevel@tonic-gate continue; 25587c478bd9Sstevel@tonic-gate 2559ba2be530Sab dyn->d_tag = ld_targ.t_m.m_dt_register; 25607c478bd9Sstevel@tonic-gate dyn->d_un.d_val = sdp->sd_symndx; 25617c478bd9Sstevel@tonic-gate dyn++; 25627c478bd9Sstevel@tonic-gate } 25637c478bd9Sstevel@tonic-gate } 25647c478bd9Sstevel@tonic-gate 256557ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_rtldinfo, idx, sdp)) { 25667c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SUNW_RTLDINF; 25677c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sdp->sd_sym->st_value; 25687c478bd9Sstevel@tonic-gate dyn++; 25697c478bd9Sstevel@tonic-gate } 25707c478bd9Sstevel@tonic-gate 257194c044f4SRod Evans if (((sgp = ofl->ofl_osdynamic->os_sgdesc) != NULL) && 257294c044f4SRod Evans (sgp->sg_phdr.p_flags & PF_W) && ofl->ofl_osinterp) { 257394c044f4SRod Evans dyn->d_tag = DT_DEBUG; 257494c044f4SRod Evans dyn->d_un.d_ptr = 0; 25757c478bd9Sstevel@tonic-gate dyn++; 25767c478bd9Sstevel@tonic-gate } 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate if (ofl->ofl_oscap) { 25797c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SUNW_CAP; 25807c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_oscap->os_shdr->sh_addr; 25817c478bd9Sstevel@tonic-gate dyn++; 25827c478bd9Sstevel@tonic-gate } 258308278a5eSRod Evans if (ofl->ofl_oscapinfo) { 258408278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPINFO; 258508278a5eSRod Evans dyn->d_un.d_val = ofl->ofl_oscapinfo->os_shdr->sh_addr; 258608278a5eSRod Evans dyn++; 258708278a5eSRod Evans } 258808278a5eSRod Evans if (ofl->ofl_oscapchain) { 258908278a5eSRod Evans shdr = ofl->ofl_oscapchain->os_shdr; 25907c478bd9Sstevel@tonic-gate 259108278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPCHAIN; 259208278a5eSRod Evans dyn->d_un.d_val = shdr->sh_addr; 259308278a5eSRod Evans dyn++; 259408278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPCHAINSZ; 259508278a5eSRod Evans dyn->d_un.d_val = shdr->sh_size; 259608278a5eSRod Evans dyn++; 259708278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPCHAINENT; 259808278a5eSRod Evans dyn->d_un.d_val = shdr->sh_entsize; 259908278a5eSRod Evans dyn++; 260008278a5eSRod Evans } 2601d2a70789SRichard Lowe 2602d2a70789SRichard Lowe if (ofl->ofl_aslr != 0) { 2603d2a70789SRichard Lowe dyn->d_tag = DT_SUNW_ASLR; 2604d2a70789SRichard Lowe dyn->d_un.d_val = (ofl->ofl_aslr == 1); 2605d2a70789SRichard Lowe dyn++; 2606d2a70789SRichard Lowe } 2607d2a70789SRichard Lowe 26081d9df23bSab if (flags & FLG_OF_SYMBOLIC) { 26091d9df23bSab dyn->d_tag = DT_SYMBOLIC; 26101d9df23bSab dyn->d_un.d_val = 0; 26111d9df23bSab dyn++; 26121d9df23bSab } 26137c478bd9Sstevel@tonic-gate } 26141d9df23bSab 26157c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FLAGS; 26167c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_dtflags; 26177c478bd9Sstevel@tonic-gate dyn++; 26187c478bd9Sstevel@tonic-gate 26197c478bd9Sstevel@tonic-gate /* 26207c478bd9Sstevel@tonic-gate * If -Bdirect was specified, but some NODIRECT symbols were specified 26217c478bd9Sstevel@tonic-gate * via a mapfile, or -znodirect was used on the command line, then 26227c478bd9Sstevel@tonic-gate * clear the DF_1_DIRECT flag. The resultant object will use per-symbol 26237c478bd9Sstevel@tonic-gate * direct bindings rather than be enabled for global direct bindings. 262428bda19cSRod Evans * 262528bda19cSRod Evans * If any no-direct bindings exist within this object, set the 262628bda19cSRod Evans * DF_1_NODIRECT flag. ld(1) recognizes this flag when processing 262728bda19cSRod Evans * dependencies, and performs extra work to ensure that no direct 262828bda19cSRod Evans * bindings are established to the no-direct symbols that exist 262928bda19cSRod Evans * within these dependencies. 26307c478bd9Sstevel@tonic-gate */ 263128bda19cSRod Evans if (ofl->ofl_flags1 & FLG_OF1_NGLBDIR) 26327c478bd9Sstevel@tonic-gate ofl->ofl_dtflags_1 &= ~DF_1_DIRECT; 263328bda19cSRod Evans if (ofl->ofl_flags1 & FLG_OF1_NDIRECT) 263460758829Srie ofl->ofl_dtflags_1 |= DF_1_NODIRECT; 26357c478bd9Sstevel@tonic-gate 26367c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FLAGS_1; 26377c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_dtflags_1; 26387c478bd9Sstevel@tonic-gate dyn++; 26397c478bd9Sstevel@tonic-gate 26403244bcaaSab dyn->d_tag = DT_SUNW_STRPAD; 26413244bcaaSab dyn->d_un.d_val = DYNSTR_EXTRA_PAD; 26423244bcaaSab dyn++; 26433244bcaaSab 2644ba2be530Sab dyn->d_tag = DT_SUNW_LDMACH; 2645ba2be530Sab dyn->d_un.d_val = ld_sunw_ldmach(); 2646ba2be530Sab dyn++; 2647ba2be530Sab 2648b6a0e2cdSRichard Lowe if (ofl->ofl_flags & FLG_OF_KMOD) { 2649b6a0e2cdSRichard Lowe dyn->d_tag = DT_SUNW_KMOD; 2650b6a0e2cdSRichard Lowe dyn->d_un.d_val = 1; 2651b6a0e2cdSRichard Lowe dyn++; 2652b6a0e2cdSRichard Lowe } 2653b6a0e2cdSRichard Lowe 2654ba2be530Sab (*ld_targ.t_mr.mr_mach_update_odynamic)(ofl, &dyn); 26557c478bd9Sstevel@tonic-gate 26563244bcaaSab for (cnt = 1 + DYNAMIC_EXTRA_ELTS; cnt--; dyn++) { 26573244bcaaSab dyn->d_tag = DT_NULL; 26583244bcaaSab dyn->d_un.d_val = 0; 26593244bcaaSab } 26607c478bd9Sstevel@tonic-gate 26615b59e4caSab /* 2662635216b6SRod Evans * Ensure that we wrote the right number of entries. If not, we either 2663635216b6SRod Evans * miscounted in make_dynamic(), or we did something wrong in this 2664635216b6SRod Evans * function. 26655b59e4caSab */ 26665b59e4caSab assert((ofl->ofl_osdynamic->os_shdr->sh_size / 26675b59e4caSab ofl->ofl_osdynamic->os_shdr->sh_entsize) == 26683244bcaaSab ((uintptr_t)dyn - (uintptr_t)_dyn) / sizeof (*dyn)); 26695b59e4caSab 26707c478bd9Sstevel@tonic-gate return (1); 26717c478bd9Sstevel@tonic-gate } 26727c478bd9Sstevel@tonic-gate 26737c478bd9Sstevel@tonic-gate /* 26747c478bd9Sstevel@tonic-gate * Build the version definition section 26757c478bd9Sstevel@tonic-gate */ 26765aefb655Srie static int 26777c478bd9Sstevel@tonic-gate update_overdef(Ofl_desc *ofl) 26787c478bd9Sstevel@tonic-gate { 267957ef7aa9SRod Evans Aliste idx1; 26807c478bd9Sstevel@tonic-gate Ver_desc *vdp, *_vdp; 26817c478bd9Sstevel@tonic-gate Verdef *vdf, *_vdf; 26827c478bd9Sstevel@tonic-gate int num = 0; 2683090a8d9eSAli Bahrami Os_desc *strosp; 2684635216b6SRod Evans Str_tbl *strtbl; 2685635216b6SRod Evans 2686635216b6SRod Evans /* 2687635216b6SRod Evans * Determine which string table to use. 2688635216b6SRod Evans */ 2689635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 2690635216b6SRod Evans strtbl = ofl->ofl_strtab; 2691635216b6SRod Evans strosp = ofl->ofl_osstrtab; 2692635216b6SRod Evans } else { 2693635216b6SRod Evans strtbl = ofl->ofl_dynstrtab; 2694635216b6SRod Evans strosp = ofl->ofl_osdynstr; 2695635216b6SRod Evans } 26967c478bd9Sstevel@tonic-gate 26977c478bd9Sstevel@tonic-gate /* 26987c478bd9Sstevel@tonic-gate * Traverse the version descriptors and update the version structures 26997c478bd9Sstevel@tonic-gate * to point to the dynstr name in preparation for building the version 27007c478bd9Sstevel@tonic-gate * section structure. 27017c478bd9Sstevel@tonic-gate */ 270257ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) { 270357ef7aa9SRod Evans Sym_desc *sdp; 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_BASE) { 27067c478bd9Sstevel@tonic-gate const char *name = vdp->vd_name; 2707cce0e03bSab size_t stoff; 27087c478bd9Sstevel@tonic-gate 27097c478bd9Sstevel@tonic-gate /* 27107c478bd9Sstevel@tonic-gate * Create a new string table entry to represent the base 27117c478bd9Sstevel@tonic-gate * version name (there is no corresponding symbol for 27127c478bd9Sstevel@tonic-gate * this). 27137c478bd9Sstevel@tonic-gate */ 2714635216b6SRod Evans (void) st_setstring(strtbl, name, &stoff); 2715635216b6SRod Evans /* LINTED */ 2716635216b6SRod Evans vdp->vd_name = (const char *)stoff; 27177c478bd9Sstevel@tonic-gate } else { 27185aefb655Srie sdp = ld_sym_find(vdp->vd_name, vdp->vd_hash, 0, ofl); 27197c478bd9Sstevel@tonic-gate /* LINTED */ 27207c478bd9Sstevel@tonic-gate vdp->vd_name = (const char *) 2721d840867fSab (uintptr_t)sdp->sd_sym->st_name; 27227c478bd9Sstevel@tonic-gate } 27237c478bd9Sstevel@tonic-gate } 27247c478bd9Sstevel@tonic-gate 27257c478bd9Sstevel@tonic-gate _vdf = vdf = (Verdef *)ofl->ofl_osverdef->os_outdata->d_buf; 27267c478bd9Sstevel@tonic-gate 27277c478bd9Sstevel@tonic-gate /* 27287c478bd9Sstevel@tonic-gate * Traverse the version descriptors and update the version section to 27297c478bd9Sstevel@tonic-gate * reflect each version and its associated dependencies. 27307c478bd9Sstevel@tonic-gate */ 273157ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) { 273257ef7aa9SRod Evans Aliste idx2; 27337c478bd9Sstevel@tonic-gate Half cnt = 1; 273457ef7aa9SRod Evans Verdaux *vdap, *_vdap; 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate _vdap = vdap = (Verdaux *)(vdf + 1); 27377c478bd9Sstevel@tonic-gate 27387c478bd9Sstevel@tonic-gate vdf->vd_version = VER_DEF_CURRENT; 27397c478bd9Sstevel@tonic-gate vdf->vd_flags = vdp->vd_flags & MSK_VER_USER; 27407c478bd9Sstevel@tonic-gate vdf->vd_ndx = vdp->vd_ndx; 27417c478bd9Sstevel@tonic-gate vdf->vd_hash = vdp->vd_hash; 27427c478bd9Sstevel@tonic-gate 27437c478bd9Sstevel@tonic-gate /* LINTED */ 27447c478bd9Sstevel@tonic-gate vdap->vda_name = (uintptr_t)vdp->vd_name; 27457c478bd9Sstevel@tonic-gate vdap++; 27467c478bd9Sstevel@tonic-gate /* LINTED */ 27477c478bd9Sstevel@tonic-gate _vdap->vda_next = (Word)((uintptr_t)vdap - (uintptr_t)_vdap); 27487c478bd9Sstevel@tonic-gate 27497c478bd9Sstevel@tonic-gate /* 27507c478bd9Sstevel@tonic-gate * Traverse this versions dependency list generating the 27517c478bd9Sstevel@tonic-gate * appropriate version dependency entries. 27527c478bd9Sstevel@tonic-gate */ 275357ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx2, _vdp)) { 27547c478bd9Sstevel@tonic-gate /* LINTED */ 27557c478bd9Sstevel@tonic-gate vdap->vda_name = (uintptr_t)_vdp->vd_name; 27567c478bd9Sstevel@tonic-gate _vdap = vdap; 27577c478bd9Sstevel@tonic-gate vdap++, cnt++; 27587c478bd9Sstevel@tonic-gate /* LINTED */ 27597c478bd9Sstevel@tonic-gate _vdap->vda_next = (Word)((uintptr_t)vdap - 27607c478bd9Sstevel@tonic-gate (uintptr_t)_vdap); 27617c478bd9Sstevel@tonic-gate } 27627c478bd9Sstevel@tonic-gate _vdap->vda_next = 0; 27637c478bd9Sstevel@tonic-gate 27647c478bd9Sstevel@tonic-gate /* 27657c478bd9Sstevel@tonic-gate * Record the versions auxiliary array offset and the associated 27667c478bd9Sstevel@tonic-gate * dependency count. 27677c478bd9Sstevel@tonic-gate */ 27687c478bd9Sstevel@tonic-gate /* LINTED */ 27697c478bd9Sstevel@tonic-gate vdf->vd_aux = (Word)((uintptr_t)(vdf + 1) - (uintptr_t)vdf); 27707c478bd9Sstevel@tonic-gate vdf->vd_cnt = cnt; 27717c478bd9Sstevel@tonic-gate 27727c478bd9Sstevel@tonic-gate /* 27737c478bd9Sstevel@tonic-gate * Record the next versions offset and update the version 27747c478bd9Sstevel@tonic-gate * pointer. Remember the previous version offset as the very 27757c478bd9Sstevel@tonic-gate * last structures next pointer should be null. 27767c478bd9Sstevel@tonic-gate */ 27777c478bd9Sstevel@tonic-gate _vdf = vdf; 27787c478bd9Sstevel@tonic-gate vdf = (Verdef *)vdap, num++; 27797c478bd9Sstevel@tonic-gate /* LINTED */ 27807c478bd9Sstevel@tonic-gate _vdf->vd_next = (Word)((uintptr_t)vdf - (uintptr_t)_vdf); 27817c478bd9Sstevel@tonic-gate } 27827c478bd9Sstevel@tonic-gate _vdf->vd_next = 0; 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate /* 27857c478bd9Sstevel@tonic-gate * Record the string table association with the version definition 27867c478bd9Sstevel@tonic-gate * section, and the symbol table associated with the version symbol 27877c478bd9Sstevel@tonic-gate * table (the actual contents of the version symbol table are filled 27887c478bd9Sstevel@tonic-gate * in during symbol update). 27897c478bd9Sstevel@tonic-gate */ 27907c478bd9Sstevel@tonic-gate /* LINTED */ 27917c478bd9Sstevel@tonic-gate ofl->ofl_osverdef->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn); 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate /* 27947c478bd9Sstevel@tonic-gate * The version definition sections `info' field is used to indicate the 27957c478bd9Sstevel@tonic-gate * number of entries in this section. 27967c478bd9Sstevel@tonic-gate */ 27977c478bd9Sstevel@tonic-gate ofl->ofl_osverdef->os_shdr->sh_info = num; 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate return (1); 28007c478bd9Sstevel@tonic-gate } 28017c478bd9Sstevel@tonic-gate 2802090a8d9eSAli Bahrami /* 2803090a8d9eSAli Bahrami * Finish the version symbol index section 2804090a8d9eSAli Bahrami */ 2805635216b6SRod Evans static void 2806090a8d9eSAli Bahrami update_oversym(Ofl_desc *ofl) 2807090a8d9eSAli Bahrami { 2808635216b6SRod Evans Os_desc *osp; 2809090a8d9eSAli Bahrami 2810090a8d9eSAli Bahrami /* 2811635216b6SRod Evans * Record the symbol table associated with the version symbol table. 2812635216b6SRod Evans * The contents of the version symbol table are filled in during 2813635216b6SRod Evans * symbol update. 2814090a8d9eSAli Bahrami */ 2815635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) 2816635216b6SRod Evans osp = ofl->ofl_ossymtab; 2817635216b6SRod Evans else 2818635216b6SRod Evans osp = ofl->ofl_osdynsym; 2819090a8d9eSAli Bahrami 2820090a8d9eSAli Bahrami /* LINTED */ 2821635216b6SRod Evans ofl->ofl_osversym->os_shdr->sh_link = (Word)elf_ndxscn(osp->os_scn); 2822090a8d9eSAli Bahrami } 2823090a8d9eSAli Bahrami 28247c478bd9Sstevel@tonic-gate /* 28257c478bd9Sstevel@tonic-gate * Build the version needed section 28267c478bd9Sstevel@tonic-gate */ 28275aefb655Srie static int 28287c478bd9Sstevel@tonic-gate update_overneed(Ofl_desc *ofl) 28297c478bd9Sstevel@tonic-gate { 283057ef7aa9SRod Evans Aliste idx1; 28317c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 28327c478bd9Sstevel@tonic-gate Verneed *vnd, *_vnd; 2833635216b6SRod Evans Os_desc *strosp; 2834635216b6SRod Evans Str_tbl *strtbl; 2835090a8d9eSAli Bahrami Word num = 0; 28367c478bd9Sstevel@tonic-gate 28377c478bd9Sstevel@tonic-gate _vnd = vnd = (Verneed *)ofl->ofl_osverneed->os_outdata->d_buf; 28387c478bd9Sstevel@tonic-gate 2839635216b6SRod Evans /* 2840635216b6SRod Evans * Determine which string table is appropriate. 2841635216b6SRod Evans */ 2842635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 2843635216b6SRod Evans strosp = ofl->ofl_osstrtab; 2844635216b6SRod Evans strtbl = ofl->ofl_strtab; 2845635216b6SRod Evans } else { 2846635216b6SRod Evans strosp = ofl->ofl_osdynstr; 2847635216b6SRod Evans strtbl = ofl->ofl_dynstrtab; 2848635216b6SRod Evans } 2849635216b6SRod Evans 28507c478bd9Sstevel@tonic-gate /* 28517c478bd9Sstevel@tonic-gate * Traverse the shared object list looking for dependencies that have 28527c478bd9Sstevel@tonic-gate * versions defined within them. 28537c478bd9Sstevel@tonic-gate */ 285457ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_sos, idx1, ifl)) { 28557c478bd9Sstevel@tonic-gate Half _cnt; 2856090a8d9eSAli Bahrami Word cnt = 0; 28577c478bd9Sstevel@tonic-gate Vernaux *_vnap, *vnap; 2858cce0e03bSab size_t stoff; 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate if (!(ifl->ifl_flags & FLG_IF_VERNEED)) 28617c478bd9Sstevel@tonic-gate continue; 28627c478bd9Sstevel@tonic-gate 28637c478bd9Sstevel@tonic-gate vnd->vn_version = VER_NEED_CURRENT; 28647c478bd9Sstevel@tonic-gate 2865635216b6SRod Evans (void) st_setstring(strtbl, ifl->ifl_soname, &stoff); 28667c478bd9Sstevel@tonic-gate vnd->vn_file = stoff; 28677c478bd9Sstevel@tonic-gate 28687c478bd9Sstevel@tonic-gate _vnap = vnap = (Vernaux *)(vnd + 1); 28697c478bd9Sstevel@tonic-gate 2870090a8d9eSAli Bahrami /* 2871090a8d9eSAli Bahrami * Traverse the version index list recording 2872090a8d9eSAli Bahrami * each version as a needed dependency. 2873090a8d9eSAli Bahrami */ 2874090a8d9eSAli Bahrami for (_cnt = 0; _cnt <= ifl->ifl_vercnt; _cnt++) { 2875090a8d9eSAli Bahrami Ver_index *vip = &ifl->ifl_verndx[_cnt]; 28767c478bd9Sstevel@tonic-gate 2877090a8d9eSAli Bahrami if (vip->vi_flags & FLG_VER_REFER) { 2878635216b6SRod Evans (void) st_setstring(strtbl, vip->vi_name, 2879090a8d9eSAli Bahrami &stoff); 2880090a8d9eSAli Bahrami vnap->vna_name = stoff; 2881090a8d9eSAli Bahrami 2882090a8d9eSAli Bahrami if (vip->vi_desc) { 2883090a8d9eSAli Bahrami vnap->vna_hash = vip->vi_desc->vd_hash; 2884090a8d9eSAli Bahrami vnap->vna_flags = 2885090a8d9eSAli Bahrami vip->vi_desc->vd_flags; 2886090a8d9eSAli Bahrami } else { 2887090a8d9eSAli Bahrami vnap->vna_hash = 0; 2888090a8d9eSAli Bahrami vnap->vna_flags = 0; 28897c478bd9Sstevel@tonic-gate } 2890090a8d9eSAli Bahrami vnap->vna_other = vip->vi_overndx; 2891090a8d9eSAli Bahrami 2892090a8d9eSAli Bahrami /* 2893090a8d9eSAli Bahrami * If version A inherits version B, then 2894090a8d9eSAli Bahrami * B is implicit in A. It suffices for ld.so.1 2895090a8d9eSAli Bahrami * to verify A at runtime and skip B. The 2896090a8d9eSAli Bahrami * version normalization process sets the INFO 2897090a8d9eSAli Bahrami * flag for the versions we want ld.so.1 to 28984a8d0ea7SAli Bahrami * skip. 2899090a8d9eSAli Bahrami */ 29004a8d0ea7SAli Bahrami if (vip->vi_flags & VER_FLG_INFO) 2901090a8d9eSAli Bahrami vnap->vna_flags |= VER_FLG_INFO; 2902090a8d9eSAli Bahrami 2903090a8d9eSAli Bahrami _vnap = vnap; 2904090a8d9eSAli Bahrami vnap++, cnt++; 2905090a8d9eSAli Bahrami _vnap->vna_next = 2906090a8d9eSAli Bahrami /* LINTED */ 2907090a8d9eSAli Bahrami (Word)((uintptr_t)vnap - (uintptr_t)_vnap); 29087c478bd9Sstevel@tonic-gate } 29097c478bd9Sstevel@tonic-gate } 2910090a8d9eSAli Bahrami 29117c478bd9Sstevel@tonic-gate _vnap->vna_next = 0; 29127c478bd9Sstevel@tonic-gate 29137c478bd9Sstevel@tonic-gate /* 29147c478bd9Sstevel@tonic-gate * Record the versions auxiliary array offset and 29157c478bd9Sstevel@tonic-gate * the associated dependency count. 29167c478bd9Sstevel@tonic-gate */ 29177c478bd9Sstevel@tonic-gate /* LINTED */ 29187c478bd9Sstevel@tonic-gate vnd->vn_aux = (Word)((uintptr_t)(vnd + 1) - (uintptr_t)vnd); 29197c478bd9Sstevel@tonic-gate /* LINTED */ 29207c478bd9Sstevel@tonic-gate vnd->vn_cnt = (Half)cnt; 29217c478bd9Sstevel@tonic-gate 29227c478bd9Sstevel@tonic-gate /* 29237c478bd9Sstevel@tonic-gate * Record the next versions offset and update the version 29247c478bd9Sstevel@tonic-gate * pointer. Remember the previous version offset as the very 29257c478bd9Sstevel@tonic-gate * last structures next pointer should be null. 29267c478bd9Sstevel@tonic-gate */ 29277c478bd9Sstevel@tonic-gate _vnd = vnd; 29287c478bd9Sstevel@tonic-gate vnd = (Verneed *)vnap, num++; 29297c478bd9Sstevel@tonic-gate /* LINTED */ 29307c478bd9Sstevel@tonic-gate _vnd->vn_next = (Word)((uintptr_t)vnd - (uintptr_t)_vnd); 29317c478bd9Sstevel@tonic-gate } 29327c478bd9Sstevel@tonic-gate _vnd->vn_next = 0; 29337c478bd9Sstevel@tonic-gate 29347c478bd9Sstevel@tonic-gate /* 2935635216b6SRod Evans * Use sh_link to record the associated string table section, and 2936635216b6SRod Evans * sh_info to indicate the number of entries contained in the section. 29377c478bd9Sstevel@tonic-gate */ 2938635216b6SRod Evans /* LINTED */ 2939635216b6SRod Evans ofl->ofl_osverneed->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn); 29407c478bd9Sstevel@tonic-gate ofl->ofl_osverneed->os_shdr->sh_info = num; 29417c478bd9Sstevel@tonic-gate 29427c478bd9Sstevel@tonic-gate return (1); 29437c478bd9Sstevel@tonic-gate } 29447c478bd9Sstevel@tonic-gate 29457c478bd9Sstevel@tonic-gate /* 29467c478bd9Sstevel@tonic-gate * Update syminfo section. 29477c478bd9Sstevel@tonic-gate */ 29485aefb655Srie static uintptr_t 294957ef7aa9SRod Evans update_osyminfo(Ofl_desc *ofl) 29507c478bd9Sstevel@tonic-gate { 295157ef7aa9SRod Evans Os_desc *symosp, *infosp = ofl->ofl_ossyminfo; 295257ef7aa9SRod Evans Syminfo *sip = infosp->os_outdata->d_buf; 295357ef7aa9SRod Evans Shdr *shdr = infosp->os_shdr; 29547c478bd9Sstevel@tonic-gate char *strtab; 2955cce0e03bSab Aliste idx; 295657ef7aa9SRod Evans Sym_desc *sdp; 295757ef7aa9SRod Evans Sfltr_desc *sftp; 29587c478bd9Sstevel@tonic-gate 29597c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_RELOBJ) { 29607c478bd9Sstevel@tonic-gate symosp = ofl->ofl_ossymtab; 29617c478bd9Sstevel@tonic-gate strtab = ofl->ofl_osstrtab->os_outdata->d_buf; 29627c478bd9Sstevel@tonic-gate } else { 29637c478bd9Sstevel@tonic-gate symosp = ofl->ofl_osdynsym; 29647c478bd9Sstevel@tonic-gate strtab = ofl->ofl_osdynstr->os_outdata->d_buf; 29657c478bd9Sstevel@tonic-gate } 29667c478bd9Sstevel@tonic-gate 29677c478bd9Sstevel@tonic-gate /* LINTED */ 29687c478bd9Sstevel@tonic-gate infosp->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn); 29697c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynamic) 29707c478bd9Sstevel@tonic-gate infosp->os_shdr->sh_info = 29717c478bd9Sstevel@tonic-gate /* LINTED */ 29727c478bd9Sstevel@tonic-gate (Word)elf_ndxscn(ofl->ofl_osdynamic->os_scn); 29737c478bd9Sstevel@tonic-gate 29747c478bd9Sstevel@tonic-gate /* 29757c478bd9Sstevel@tonic-gate * Update any references with the index into the dynamic table. 29767c478bd9Sstevel@tonic-gate */ 2977635216b6SRod Evans for (APLIST_TRAVERSE(ofl->ofl_symdtent, idx, sdp)) 2978635216b6SRod Evans sip[sdp->sd_symndx].si_boundto = sdp->sd_file->ifl_neededndx; 29797c478bd9Sstevel@tonic-gate 29807c478bd9Sstevel@tonic-gate /* 29817c478bd9Sstevel@tonic-gate * Update any filtee references with the index into the dynamic table. 29827c478bd9Sstevel@tonic-gate */ 2983cce0e03bSab for (ALIST_TRAVERSE(ofl->ofl_symfltrs, idx, sftp)) { 2984cce0e03bSab Dfltr_desc *dftp; 29857c478bd9Sstevel@tonic-gate 2986cce0e03bSab dftp = alist_item(ofl->ofl_dtsfltrs, sftp->sft_idx); 29877c478bd9Sstevel@tonic-gate sip[sftp->sft_sdp->sd_symndx].si_boundto = dftp->dft_ndx; 29887c478bd9Sstevel@tonic-gate } 29897c478bd9Sstevel@tonic-gate 29907c478bd9Sstevel@tonic-gate /* 29917c478bd9Sstevel@tonic-gate * Display debugging information about section. 29927c478bd9Sstevel@tonic-gate */ 29935aefb655Srie DBG_CALL(Dbg_syminfo_title(ofl->ofl_lml)); 29945aefb655Srie if (DBG_ENABLED) { 29955aefb655Srie Word _cnt, cnt = shdr->sh_size / shdr->sh_entsize; 299657ef7aa9SRod Evans Sym *symtab = symosp->os_outdata->d_buf; 299757ef7aa9SRod Evans Dyn *dyn; 29987c478bd9Sstevel@tonic-gate 29997c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynamic) 30007c478bd9Sstevel@tonic-gate dyn = ofl->ofl_osdynamic->os_outdata->d_buf; 30017c478bd9Sstevel@tonic-gate else 300257ef7aa9SRod Evans dyn = NULL; 30037c478bd9Sstevel@tonic-gate 30047c478bd9Sstevel@tonic-gate for (_cnt = 1; _cnt < cnt; _cnt++) { 30057c478bd9Sstevel@tonic-gate if (sip[_cnt].si_flags || sip[_cnt].si_boundto) 30067c478bd9Sstevel@tonic-gate /* LINTED */ 30075aefb655Srie DBG_CALL(Dbg_syminfo_entry(ofl->ofl_lml, _cnt, 30087c478bd9Sstevel@tonic-gate &sip[_cnt], &symtab[_cnt], strtab, dyn)); 30097c478bd9Sstevel@tonic-gate } 30107c478bd9Sstevel@tonic-gate } 30117c478bd9Sstevel@tonic-gate return (1); 30127c478bd9Sstevel@tonic-gate } 30137c478bd9Sstevel@tonic-gate 30147c478bd9Sstevel@tonic-gate /* 30157c478bd9Sstevel@tonic-gate * Build the output elf header. 30167c478bd9Sstevel@tonic-gate */ 30175aefb655Srie static uintptr_t 30187c478bd9Sstevel@tonic-gate update_oehdr(Ofl_desc * ofl) 30197c478bd9Sstevel@tonic-gate { 30205aefb655Srie Ehdr *ehdr = ofl->ofl_nehdr; 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate /* 30237c478bd9Sstevel@tonic-gate * If an entry point symbol has already been established (refer 30247c478bd9Sstevel@tonic-gate * sym_validate()) simply update the elf header entry point with the 30257c478bd9Sstevel@tonic-gate * symbols value. If no entry point is defined it will have been filled 30267c478bd9Sstevel@tonic-gate * with the start address of the first section within the text segment 30277c478bd9Sstevel@tonic-gate * (refer update_outfile()). 30287c478bd9Sstevel@tonic-gate */ 30297c478bd9Sstevel@tonic-gate if (ofl->ofl_entry) 30307c478bd9Sstevel@tonic-gate ehdr->e_entry = 3031d840867fSab ((Sym_desc *)(ofl->ofl_entry))->sd_sym->st_value; 30327c478bd9Sstevel@tonic-gate 3033ba2be530Sab ehdr->e_ident[EI_DATA] = ld_targ.t_m.m_data; 30345aefb655Srie ehdr->e_version = ofl->ofl_dehdr->e_version; 30355aefb655Srie 303698c080d5SRod Evans /* 303798c080d5SRod Evans * When generating a relocatable object under -z symbolcap, set the 303898c080d5SRod Evans * e_machine to be generic, and remove any e_flags. Input relocatable 303998c080d5SRod Evans * objects may identify alternative e_machine (m.machplus) and e_flags 304098c080d5SRod Evans * values. However, the functions within the created output object 304198c080d5SRod Evans * are selected at runtime using the capabilities mechanism, which 304298c080d5SRod Evans * supersedes the e-machine and e_flags information. Therefore, 304398c080d5SRod Evans * e_machine and e_flag values are not propagated to the output object, 304498c080d5SRod Evans * as these values might prevent the kernel from loading the object 304598c080d5SRod Evans * before the runtime linker gets control. 304698c080d5SRod Evans */ 304798c080d5SRod Evans if (ofl->ofl_flags & FLG_OF_OTOSCAP) { 304898c080d5SRod Evans ehdr->e_machine = ld_targ.t_m.m_mach; 304998c080d5SRod Evans ehdr->e_flags = 0; 305098c080d5SRod Evans } else { 305198c080d5SRod Evans /* 305298c080d5SRod Evans * Note. it may be necessary to update the e_flags field in the 305398c080d5SRod Evans * machine dependent section. 305498c080d5SRod Evans */ 305598c080d5SRod Evans ehdr->e_machine = ofl->ofl_dehdr->e_machine; 305698c080d5SRod Evans ehdr->e_flags = ofl->ofl_dehdr->e_flags; 305798c080d5SRod Evans 305898c080d5SRod Evans if (ehdr->e_machine != ld_targ.t_m.m_mach) { 305998c080d5SRod Evans if (ehdr->e_machine != ld_targ.t_m.m_machplus) 306098c080d5SRod Evans return (S_ERROR); 306198c080d5SRod Evans if ((ehdr->e_flags & ld_targ.t_m.m_flagsplus) == 0) 306298c080d5SRod Evans return (S_ERROR); 306398c080d5SRod Evans } 30647c478bd9Sstevel@tonic-gate } 30657c478bd9Sstevel@tonic-gate 30667c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_SHAROBJ) 30677c478bd9Sstevel@tonic-gate ehdr->e_type = ET_DYN; 30687c478bd9Sstevel@tonic-gate else if (ofl->ofl_flags & FLG_OF_RELOBJ) 30697c478bd9Sstevel@tonic-gate ehdr->e_type = ET_REL; 30707c478bd9Sstevel@tonic-gate else 30717c478bd9Sstevel@tonic-gate ehdr->e_type = ET_EXEC; 30727c478bd9Sstevel@tonic-gate 30737c478bd9Sstevel@tonic-gate return (1); 30747c478bd9Sstevel@tonic-gate } 30757c478bd9Sstevel@tonic-gate 30767c478bd9Sstevel@tonic-gate /* 30777c478bd9Sstevel@tonic-gate * Perform move table expansion. 30787c478bd9Sstevel@tonic-gate */ 307957ef7aa9SRod Evans static void 308057ef7aa9SRod Evans expand_move(Ofl_desc *ofl, Sym_desc *sdp, Move *mvp) 30817c478bd9Sstevel@tonic-gate { 30827c478bd9Sstevel@tonic-gate Os_desc *osp; 308357ef7aa9SRod Evans uchar_t *taddr, *taddr0; 30847c478bd9Sstevel@tonic-gate Sxword offset; 308557ef7aa9SRod Evans Half cnt; 308657ef7aa9SRod Evans uint_t stride; 30877c478bd9Sstevel@tonic-gate 308835450702SAli Bahrami osp = ofl->ofl_isparexpn->is_osdesc; 3089b26cc8daSAli Bahrami offset = sdp->sd_sym->st_value - osp->os_shdr->sh_addr; 309057ef7aa9SRod Evans 309157ef7aa9SRod Evans taddr0 = taddr = osp->os_outdata->d_buf; 30927c478bd9Sstevel@tonic-gate taddr += offset; 309357ef7aa9SRod Evans taddr = taddr + mvp->m_poffset; 309457ef7aa9SRod Evans 309557ef7aa9SRod Evans for (cnt = 0; cnt < mvp->m_repeat; cnt++) { 30967c478bd9Sstevel@tonic-gate /* LINTED */ 309757ef7aa9SRod Evans DBG_CALL(Dbg_move_expand(ofl->ofl_lml, mvp, 30985aefb655Srie (Addr)(taddr - taddr0))); 309957ef7aa9SRod Evans stride = (uint_t)mvp->m_stride + 1; 310057ef7aa9SRod Evans 310157ef7aa9SRod Evans /* 310257ef7aa9SRod Evans * Update the target address based upon the move entry size. 310357ef7aa9SRod Evans * This size was validated in ld_process_move(). 310457ef7aa9SRod Evans */ 31057c478bd9Sstevel@tonic-gate /* LINTED */ 310657ef7aa9SRod Evans switch (ELF_M_SIZE(mvp->m_info)) { 31077c478bd9Sstevel@tonic-gate case 1: 31087c478bd9Sstevel@tonic-gate /* LINTED */ 310957ef7aa9SRod Evans *taddr = (uchar_t)mvp->m_value; 31107c478bd9Sstevel@tonic-gate taddr += stride; 31117c478bd9Sstevel@tonic-gate break; 31127c478bd9Sstevel@tonic-gate case 2: 31137c478bd9Sstevel@tonic-gate /* LINTED */ 311457ef7aa9SRod Evans *((Half *)taddr) = (Half)mvp->m_value; 311557ef7aa9SRod Evans taddr += 2 * stride; 31167c478bd9Sstevel@tonic-gate break; 31177c478bd9Sstevel@tonic-gate case 4: 31187c478bd9Sstevel@tonic-gate /* LINTED */ 311957ef7aa9SRod Evans *((Word *)taddr) = (Word)mvp->m_value; 312057ef7aa9SRod Evans taddr += 4 * stride; 31217c478bd9Sstevel@tonic-gate break; 31227c478bd9Sstevel@tonic-gate case 8: 31237c478bd9Sstevel@tonic-gate /* LINTED */ 312457ef7aa9SRod Evans *((u_longlong_t *)taddr) = mvp->m_value; 312557ef7aa9SRod Evans taddr += 8 * stride; 31267c478bd9Sstevel@tonic-gate break; 31277c478bd9Sstevel@tonic-gate } 31287c478bd9Sstevel@tonic-gate } 31297c478bd9Sstevel@tonic-gate } 31307c478bd9Sstevel@tonic-gate 31317c478bd9Sstevel@tonic-gate /* 31327c478bd9Sstevel@tonic-gate * Update Move sections. 31337c478bd9Sstevel@tonic-gate */ 313457ef7aa9SRod Evans static void 31357c478bd9Sstevel@tonic-gate update_move(Ofl_desc *ofl) 31367c478bd9Sstevel@tonic-gate { 31377c478bd9Sstevel@tonic-gate Word ndx = 0; 31381d9df23bSab ofl_flag_t flags = ofl->ofl_flags; 313957ef7aa9SRod Evans Move *omvp; 314057ef7aa9SRod Evans Aliste idx1; 314157ef7aa9SRod Evans Sym_desc *sdp; 31427c478bd9Sstevel@tonic-gate 31437c478bd9Sstevel@tonic-gate /* 31447c478bd9Sstevel@tonic-gate * Determine the index of the symbol table that will be referenced by 314557ef7aa9SRod Evans * the Move section. 31467c478bd9Sstevel@tonic-gate */ 31479039eeafSab if (OFL_ALLOW_DYNSYM(ofl)) 31487c478bd9Sstevel@tonic-gate /* LINTED */ 31497c478bd9Sstevel@tonic-gate ndx = (Word) elf_ndxscn(ofl->ofl_osdynsym->os_scn); 31507c478bd9Sstevel@tonic-gate else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ)) 31517c478bd9Sstevel@tonic-gate /* LINTED */ 31527c478bd9Sstevel@tonic-gate ndx = (Word) elf_ndxscn(ofl->ofl_ossymtab->os_scn); 31537c478bd9Sstevel@tonic-gate 31547c478bd9Sstevel@tonic-gate /* 315557ef7aa9SRod Evans * Update sh_link of the Move section, and point to the new Move data. 31567c478bd9Sstevel@tonic-gate */ 31577c478bd9Sstevel@tonic-gate if (ofl->ofl_osmove) { 31587c478bd9Sstevel@tonic-gate ofl->ofl_osmove->os_shdr->sh_link = ndx; 315957ef7aa9SRod Evans omvp = (Move *)ofl->ofl_osmove->os_outdata->d_buf; 31607c478bd9Sstevel@tonic-gate } 31617c478bd9Sstevel@tonic-gate 31627c478bd9Sstevel@tonic-gate /* 31637c478bd9Sstevel@tonic-gate * Update symbol entry index 31647c478bd9Sstevel@tonic-gate */ 316557ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_parsyms, idx1, sdp)) { 316657ef7aa9SRod Evans Aliste idx2; 316757ef7aa9SRod Evans Mv_desc *mdp; 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate /* 31707c478bd9Sstevel@tonic-gate * Expand move table 31717c478bd9Sstevel@tonic-gate */ 317257ef7aa9SRod Evans if (sdp->sd_flags & FLG_SY_PAREXPN) { 317357ef7aa9SRod Evans const char *str; 31747c478bd9Sstevel@tonic-gate 31751d9df23bSab if (flags & FLG_OF_STATIC) 317657ef7aa9SRod Evans str = MSG_INTL(MSG_PSYM_EXPREASON1); 31777c478bd9Sstevel@tonic-gate else if (ofl->ofl_flags1 & FLG_OF1_NOPARTI) 317857ef7aa9SRod Evans str = MSG_INTL(MSG_PSYM_EXPREASON2); 31797c478bd9Sstevel@tonic-gate else 318057ef7aa9SRod Evans str = MSG_INTL(MSG_PSYM_EXPREASON3); 318157ef7aa9SRod Evans 31825aefb655Srie DBG_CALL(Dbg_move_parexpn(ofl->ofl_lml, 318357ef7aa9SRod Evans sdp->sd_name, str)); 318457ef7aa9SRod Evans 318557ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_move, idx2, mdp)) { 31865aefb655Srie DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0, 318757ef7aa9SRod Evans mdp->md_move, sdp)); 318857ef7aa9SRod Evans expand_move(ofl, sdp, mdp->md_move); 31897c478bd9Sstevel@tonic-gate } 31907c478bd9Sstevel@tonic-gate continue; 31917c478bd9Sstevel@tonic-gate } 31927c478bd9Sstevel@tonic-gate 31937c478bd9Sstevel@tonic-gate /* 31947c478bd9Sstevel@tonic-gate * Process move table 31957c478bd9Sstevel@tonic-gate */ 319657ef7aa9SRod Evans DBG_CALL(Dbg_move_outmove(ofl->ofl_lml, sdp->sd_name)); 319757ef7aa9SRod Evans 319857ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_move, idx2, mdp)) { 319957ef7aa9SRod Evans Move *imvp; 32007c478bd9Sstevel@tonic-gate int idx = 1; 320160758829Srie Sym *sym; 320260758829Srie 320357ef7aa9SRod Evans imvp = mdp->md_move; 320460758829Srie sym = sdp->sd_sym; 32057c478bd9Sstevel@tonic-gate 320657ef7aa9SRod Evans DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 1, imvp, sdp)); 320760758829Srie 320857ef7aa9SRod Evans *omvp = *imvp; 32091d9df23bSab if ((flags & FLG_OF_RELOBJ) == 0) { 321060758829Srie if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) { 321157ef7aa9SRod Evans Os_desc *osp = sdp->sd_isc->is_osdesc; 321257ef7aa9SRod Evans Word ndx = osp->os_identndx; 321360758829Srie 321457ef7aa9SRod Evans omvp->m_info = 3215d840867fSab /* LINTED */ 321657ef7aa9SRod Evans ELF_M_INFO(ndx, imvp->m_info); 321760758829Srie 321860758829Srie if (ELF_ST_TYPE(sym->st_info) != 3219d840867fSab STT_SECTION) { 322057ef7aa9SRod Evans omvp->m_poffset = 322157ef7aa9SRod Evans sym->st_value - 322257ef7aa9SRod Evans osp->os_shdr->sh_addr + 322357ef7aa9SRod Evans imvp->m_poffset; 3224d840867fSab } 32257c478bd9Sstevel@tonic-gate } else { 322657ef7aa9SRod Evans omvp->m_info = 3227d840867fSab /* LINTED */ 3228d840867fSab ELF_M_INFO(sdp->sd_symndx, 322957ef7aa9SRod Evans imvp->m_info); 32307c478bd9Sstevel@tonic-gate } 32317c478bd9Sstevel@tonic-gate } else { 3232c524b4feSRichard Lowe Boolean isredloc = FALSE; 32337c478bd9Sstevel@tonic-gate 323460758829Srie if ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) && 323544bac77bSrie (ofl->ofl_flags & FLG_OF_REDLSYM)) 32367c478bd9Sstevel@tonic-gate isredloc = TRUE; 32377c478bd9Sstevel@tonic-gate 323857ef7aa9SRod Evans if (isredloc && !(sdp->sd_move)) { 323957ef7aa9SRod Evans Os_desc *osp = sdp->sd_isc->is_osdesc; 324057ef7aa9SRod Evans Word ndx = osp->os_identndx; 324160758829Srie 324257ef7aa9SRod Evans omvp->m_info = 3243d840867fSab /* LINTED */ 324457ef7aa9SRod Evans ELF_M_INFO(ndx, imvp->m_info); 324557ef7aa9SRod Evans 324657ef7aa9SRod Evans omvp->m_poffset += sym->st_value; 32477c478bd9Sstevel@tonic-gate } else { 32487c478bd9Sstevel@tonic-gate if (isredloc) 3249d840867fSab DBG_CALL(Dbg_syms_reduce(ofl, 325057ef7aa9SRod Evans DBG_SYM_REDUCE_RETAIN, 325157ef7aa9SRod Evans sdp, idx, 3252d840867fSab ofl->ofl_osmove->os_name)); 32537c478bd9Sstevel@tonic-gate 325457ef7aa9SRod Evans omvp->m_info = 3255d840867fSab /* LINTED */ 3256d840867fSab ELF_M_INFO(sdp->sd_symndx, 325757ef7aa9SRod Evans imvp->m_info); 32587c478bd9Sstevel@tonic-gate } 32597c478bd9Sstevel@tonic-gate } 326057ef7aa9SRod Evans 326157ef7aa9SRod Evans DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0, omvp, sdp)); 326257ef7aa9SRod Evans omvp++; 32637c478bd9Sstevel@tonic-gate idx++; 32647c478bd9Sstevel@tonic-gate } 32657c478bd9Sstevel@tonic-gate } 32667c478bd9Sstevel@tonic-gate } 32677c478bd9Sstevel@tonic-gate 32687c478bd9Sstevel@tonic-gate /* 326957ef7aa9SRod Evans * Scan through the SHT_GROUP output sections. Update their sh_link/sh_info 327057ef7aa9SRod Evans * fields as well as the section contents. 32717c478bd9Sstevel@tonic-gate */ 32725aefb655Srie static uintptr_t 32730e233487SRod Evans update_ogroup(Ofl_desc *ofl) 32747c478bd9Sstevel@tonic-gate { 327557ef7aa9SRod Evans Aliste idx; 32767c478bd9Sstevel@tonic-gate Os_desc *osp; 32777c478bd9Sstevel@tonic-gate uintptr_t error = 0; 32787c478bd9Sstevel@tonic-gate 327957ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_osgroups, idx, osp)) { 32807c478bd9Sstevel@tonic-gate Is_desc *isp; 32817c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 32827c478bd9Sstevel@tonic-gate Shdr *shdr = osp->os_shdr; 32837c478bd9Sstevel@tonic-gate Sym_desc *sdp; 32847c478bd9Sstevel@tonic-gate Xword i, grpcnt; 32857c478bd9Sstevel@tonic-gate Word *gdata; 32867c478bd9Sstevel@tonic-gate 32877c478bd9Sstevel@tonic-gate /* 32887c478bd9Sstevel@tonic-gate * Since input GROUP sections always create unique 32897c478bd9Sstevel@tonic-gate * output GROUP sections - we know there is only one 32907c478bd9Sstevel@tonic-gate * item on the list. 32917c478bd9Sstevel@tonic-gate */ 32921dd9d86fSAli Bahrami isp = ld_os_first_isdesc(osp); 32937c478bd9Sstevel@tonic-gate 32947c478bd9Sstevel@tonic-gate ifl = isp->is_file; 32957c478bd9Sstevel@tonic-gate sdp = ifl->ifl_oldndx[isp->is_shdr->sh_info]; 32967c478bd9Sstevel@tonic-gate shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn); 32977c478bd9Sstevel@tonic-gate shdr->sh_info = sdp->sd_symndx; 32987c478bd9Sstevel@tonic-gate 32997c478bd9Sstevel@tonic-gate /* 33007c478bd9Sstevel@tonic-gate * Scan through the group data section and update 33017c478bd9Sstevel@tonic-gate * all of the links to new values. 33027c478bd9Sstevel@tonic-gate */ 33037c478bd9Sstevel@tonic-gate grpcnt = shdr->sh_size / shdr->sh_entsize; 33047c478bd9Sstevel@tonic-gate gdata = (Word *)osp->os_outdata->d_buf; 33057c478bd9Sstevel@tonic-gate 33060e233487SRod Evans for (i = 1; i < grpcnt; i++) { 33070e233487SRod Evans Os_desc *_osp; 33080e233487SRod Evans Is_desc *_isp = ifl->ifl_isdesc[gdata[i]]; 33097c478bd9Sstevel@tonic-gate 33107c478bd9Sstevel@tonic-gate /* 33117c478bd9Sstevel@tonic-gate * If the referenced section didn't make it to the 33127c478bd9Sstevel@tonic-gate * output file - just zero out the entry. 33137c478bd9Sstevel@tonic-gate */ 33140e233487SRod Evans if ((_osp = _isp->is_osdesc) == NULL) 33157c478bd9Sstevel@tonic-gate gdata[i] = 0; 33167c478bd9Sstevel@tonic-gate else 33177c478bd9Sstevel@tonic-gate gdata[i] = (Word)elf_ndxscn(_osp->os_scn); 33187c478bd9Sstevel@tonic-gate } 33197c478bd9Sstevel@tonic-gate } 33207c478bd9Sstevel@tonic-gate return (error); 33217c478bd9Sstevel@tonic-gate } 33227c478bd9Sstevel@tonic-gate 33235aefb655Srie static void 33243244bcaaSab update_ostrtab(Os_desc *osp, Str_tbl *stp, uint_t extra) 33257c478bd9Sstevel@tonic-gate { 33267c478bd9Sstevel@tonic-gate Elf_Data *data; 33273244bcaaSab 332857ef7aa9SRod Evans if (osp == NULL) 33297c478bd9Sstevel@tonic-gate return; 33307c478bd9Sstevel@tonic-gate 33317c478bd9Sstevel@tonic-gate data = osp->os_outdata; 33323244bcaaSab assert(data->d_size == (st_getstrtab_sz(stp) + extra)); 3333cce0e03bSab (void) st_setstrbuf(stp, data->d_buf, data->d_size - extra); 33343244bcaaSab /* If leaving an extra hole at the end, zero it */ 33353244bcaaSab if (extra > 0) 33363244bcaaSab (void) memset((char *)data->d_buf + data->d_size - extra, 33373244bcaaSab 0x0, extra); 33387c478bd9Sstevel@tonic-gate } 33397c478bd9Sstevel@tonic-gate 334008278a5eSRod Evans /* 334108278a5eSRod Evans * Update capabilities information. 334208278a5eSRod Evans * 334308278a5eSRod Evans * If string table capabilities exist, then the associated string must be 334408278a5eSRod Evans * translated into an offset into the string table. 334508278a5eSRod Evans */ 334608278a5eSRod Evans static void 334708278a5eSRod Evans update_oscap(Ofl_desc *ofl) 334808278a5eSRod Evans { 334908278a5eSRod Evans Os_desc *strosp, *cosp; 335008278a5eSRod Evans Cap *cap; 335108278a5eSRod Evans Str_tbl *strtbl; 335208278a5eSRod Evans Capstr *capstr; 335308278a5eSRod Evans size_t stoff; 335408278a5eSRod Evans Aliste idx1; 335508278a5eSRod Evans 335608278a5eSRod Evans /* 335708278a5eSRod Evans * Determine which symbol table or string table is appropriate. 335808278a5eSRod Evans */ 335908278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 336008278a5eSRod Evans strosp = ofl->ofl_osstrtab; 336108278a5eSRod Evans strtbl = ofl->ofl_strtab; 336208278a5eSRod Evans } else { 336308278a5eSRod Evans strosp = ofl->ofl_osdynstr; 336408278a5eSRod Evans strtbl = ofl->ofl_dynstrtab; 336508278a5eSRod Evans } 336608278a5eSRod Evans 336708278a5eSRod Evans /* 336808278a5eSRod Evans * If symbol capabilities exist, set the sh_link field of the .SUNW_cap 336908278a5eSRod Evans * section to the .SUNW_capinfo section. 337008278a5eSRod Evans */ 337108278a5eSRod Evans if (ofl->ofl_oscapinfo) { 337208278a5eSRod Evans cosp = ofl->ofl_oscap; 337308278a5eSRod Evans cosp->os_shdr->sh_link = 337408278a5eSRod Evans (Word)elf_ndxscn(ofl->ofl_oscapinfo->os_scn); 337508278a5eSRod Evans } 337608278a5eSRod Evans 337708278a5eSRod Evans /* 337808278a5eSRod Evans * If there are capability strings to process, set the sh_info 337908278a5eSRod Evans * field of the .SUNW_cap section to the associated string table, and 338008278a5eSRod Evans * proceed to process any CA_SUNW_PLAT entries. 338108278a5eSRod Evans */ 338208278a5eSRod Evans if ((ofl->ofl_flags & FLG_OF_CAPSTRS) == 0) 338308278a5eSRod Evans return; 338408278a5eSRod Evans 338508278a5eSRod Evans cosp = ofl->ofl_oscap; 338608278a5eSRod Evans cosp->os_shdr->sh_info = (Word)elf_ndxscn(strosp->os_scn); 338708278a5eSRod Evans 338808278a5eSRod Evans cap = ofl->ofl_oscap->os_outdata->d_buf; 338908278a5eSRod Evans 339008278a5eSRod Evans /* 339108278a5eSRod Evans * Determine whether an object capability identifier, or object 339208278a5eSRod Evans * machine/platform capabilities exists. 339308278a5eSRod Evans */ 339408278a5eSRod Evans capstr = &ofl->ofl_ocapset.oc_id; 339508278a5eSRod Evans if (capstr->cs_str) { 339608278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, &stoff); 339708278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 339808278a5eSRod Evans } 339908278a5eSRod Evans for (ALIST_TRAVERSE(ofl->ofl_ocapset.oc_plat.cl_val, idx1, capstr)) { 340008278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, &stoff); 340108278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 340208278a5eSRod Evans } 340308278a5eSRod Evans for (ALIST_TRAVERSE(ofl->ofl_ocapset.oc_mach.cl_val, idx1, capstr)) { 340408278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, &stoff); 340508278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 340608278a5eSRod Evans } 340708278a5eSRod Evans 340808278a5eSRod Evans /* 340908278a5eSRod Evans * Determine any symbol capability identifiers, or machine/platform 341008278a5eSRod Evans * capabilities. 341108278a5eSRod Evans */ 341208278a5eSRod Evans if (ofl->ofl_capgroups) { 341308278a5eSRod Evans Cap_group *cgp; 341408278a5eSRod Evans 341508278a5eSRod Evans for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) { 341608278a5eSRod Evans Objcapset *ocapset = &cgp->cg_set; 341708278a5eSRod Evans Aliste idx2; 341808278a5eSRod Evans 341908278a5eSRod Evans capstr = &ocapset->oc_id; 342008278a5eSRod Evans if (capstr->cs_str) { 342108278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, 342208278a5eSRod Evans &stoff); 342308278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 342408278a5eSRod Evans } 342508278a5eSRod Evans for (ALIST_TRAVERSE(ocapset->oc_plat.cl_val, idx2, 342608278a5eSRod Evans capstr)) { 342708278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, 342808278a5eSRod Evans &stoff); 342908278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 343008278a5eSRod Evans } 343108278a5eSRod Evans for (ALIST_TRAVERSE(ocapset->oc_mach.cl_val, idx2, 343208278a5eSRod Evans capstr)) { 343308278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, 343408278a5eSRod Evans &stoff); 343508278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 343608278a5eSRod Evans } 343708278a5eSRod Evans } 343808278a5eSRod Evans } 343908278a5eSRod Evans } 344008278a5eSRod Evans 344108278a5eSRod Evans /* 344208278a5eSRod Evans * Update the .SUNW_capinfo, and possibly the .SUNW_capchain sections. 344308278a5eSRod Evans */ 344408278a5eSRod Evans static void 344508278a5eSRod Evans update_oscapinfo(Ofl_desc *ofl) 344608278a5eSRod Evans { 344708278a5eSRod Evans Os_desc *symosp, *ciosp, *ccosp = NULL; 344808278a5eSRod Evans Capinfo *ocapinfo; 344908278a5eSRod Evans Capchain *ocapchain; 345008278a5eSRod Evans Cap_avlnode *cav; 345108278a5eSRod Evans Word chainndx = 0; 345208278a5eSRod Evans 345308278a5eSRod Evans /* 345408278a5eSRod Evans * Determine which symbol table is appropriate. 345508278a5eSRod Evans */ 345608278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl)) 345708278a5eSRod Evans symosp = ofl->ofl_ossymtab; 345808278a5eSRod Evans else 345908278a5eSRod Evans symosp = ofl->ofl_osdynsym; 346008278a5eSRod Evans 346108278a5eSRod Evans /* 346208278a5eSRod Evans * Update the .SUNW_capinfo sh_link to point to the appropriate symbol 346308278a5eSRod Evans * table section. If we're creating a dynamic object, the 346408278a5eSRod Evans * .SUNW_capinfo sh_info is updated to point to the .SUNW_capchain 346508278a5eSRod Evans * section. 346608278a5eSRod Evans */ 346708278a5eSRod Evans ciosp = ofl->ofl_oscapinfo; 346808278a5eSRod Evans ciosp->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn); 346908278a5eSRod Evans 347008278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl) == 0) { 347108278a5eSRod Evans ccosp = ofl->ofl_oscapchain; 347208278a5eSRod Evans ciosp->os_shdr->sh_info = (Word)elf_ndxscn(ccosp->os_scn); 347308278a5eSRod Evans } 347408278a5eSRod Evans 347508278a5eSRod Evans /* 347608278a5eSRod Evans * Establish the data for each section. The first element of each 347708278a5eSRod Evans * section defines the section's version number. 347808278a5eSRod Evans */ 347908278a5eSRod Evans ocapinfo = ciosp->os_outdata->d_buf; 348008278a5eSRod Evans ocapinfo[0] = CAPINFO_CURRENT; 348108278a5eSRod Evans if (ccosp) { 348208278a5eSRod Evans ocapchain = ccosp->os_outdata->d_buf; 348308278a5eSRod Evans ocapchain[chainndx++] = CAPCHAIN_CURRENT; 348408278a5eSRod Evans } 348508278a5eSRod Evans 348608278a5eSRod Evans /* 348708278a5eSRod Evans * Traverse all capabilities families. Each member has a .SUNW_capinfo 348808278a5eSRod Evans * assignment. The .SUNW_capinfo entry differs for relocatable objects 348908278a5eSRod Evans * and dynamic objects. 349008278a5eSRod Evans * 349108278a5eSRod Evans * Relocatable objects: 349208278a5eSRod Evans * ELF_C_GROUP ELF_C_SYM 349308278a5eSRod Evans * 349408278a5eSRod Evans * Family lead: CAPINFO_SUNW_GLOB lead symbol index 349508278a5eSRod Evans * Family lead alias: CAPINFO_SUNW_GLOB lead symbol index 349608278a5eSRod Evans * Family member: .SUNW_cap index lead symbol index 349708278a5eSRod Evans * 349808278a5eSRod Evans * Dynamic objects: 349908278a5eSRod Evans * ELF_C_GROUP ELF_C_SYM 350008278a5eSRod Evans * 350108278a5eSRod Evans * Family lead: CAPINFO_SUNW_GLOB .SUNW_capchain index 350208278a5eSRod Evans * Family lead alias: CAPINFO_SUNW_GLOB .SUNW_capchain index 350308278a5eSRod Evans * Family member: .SUNW_cap index lead symbol index 350408278a5eSRod Evans * 350508278a5eSRod Evans * The ELF_C_GROUP field identifies a capabilities symbol. Lead 350608278a5eSRod Evans * capability symbols, and lead capability aliases are identified by 350708278a5eSRod Evans * a CAPINFO_SUNW_GLOB group identifier. For family members, the 350808278a5eSRod Evans * ELF_C_GROUP provides an index to the associate capabilities group 350908278a5eSRod Evans * (i.e, an index into the SUNW_cap section that defines a group). 351008278a5eSRod Evans * 351108278a5eSRod Evans * For relocatable objects, the ELF_C_SYM field identifies the lead 351208278a5eSRod Evans * capability symbol. For the lead symbol itself, the .SUNW_capinfo 351308278a5eSRod Evans * index is the same as the ELF_C_SYM value. For lead alias symbols, 351408278a5eSRod Evans * the .SUNW_capinfo index differs from the ELF_C_SYM value. This 351508278a5eSRod Evans * differentiation of CAPINFO_SUNW_GLOB symbols allows ld(1) to 351608278a5eSRod Evans * identify, and propagate lead alias symbols. For example, the lead 351708278a5eSRod Evans * capability symbol memcpy() would have the ELF_C_SYM for memcpy(), 351808278a5eSRod Evans * and the lead alias _memcpy() would also have the ELF_C_SYM for 351908278a5eSRod Evans * memcpy(). 352008278a5eSRod Evans * 352108278a5eSRod Evans * For dynamic objects, both a lead capability symbol, and alias symbol 352208278a5eSRod Evans * would have a ELF_C_SYM value that represents the same capability 352308278a5eSRod Evans * chain index. The capability chain allows ld.so.1 to traverse a 352408278a5eSRod Evans * family chain for a given lead symbol, and select the most appropriate 352508278a5eSRod Evans * family member. The .SUNW_capchain array contains a series of symbol 352608278a5eSRod Evans * indexes for each family member: 352708278a5eSRod Evans * 352808278a5eSRod Evans * chaincap[n] chaincap[n + 1] chaincap[n + 2] chaincap[n + x] 352908278a5eSRod Evans * foo() ndx foo%x() ndx foo%y() ndx 0 353008278a5eSRod Evans * 353108278a5eSRod Evans * For family members, the ELF_C_SYM value associates the capability 353208278a5eSRod Evans * members with their family lead symbol. This association, although 353308278a5eSRod Evans * unused within a dynamic object, allows ld(1) to identify, and 353408278a5eSRod Evans * propagate family members when processing relocatable objects. 353508278a5eSRod Evans */ 353608278a5eSRod Evans for (cav = avl_first(ofl->ofl_capfamilies); cav; 353708278a5eSRod Evans cav = AVL_NEXT(ofl->ofl_capfamilies, cav)) { 353808278a5eSRod Evans Cap_sym *csp; 353908278a5eSRod Evans Aliste idx; 354008278a5eSRod Evans Sym_desc *asdp, *lsdp = cav->cn_symavlnode.sav_sdp; 354108278a5eSRod Evans 354208278a5eSRod Evans if (ccosp) { 354308278a5eSRod Evans /* 354408278a5eSRod Evans * For a dynamic object, identify this lead symbol, and 354508278a5eSRod Evans * point it to the head of a capability chain. Set the 354608278a5eSRod Evans * head of the capability chain to the same lead symbol. 354708278a5eSRod Evans */ 354808278a5eSRod Evans ocapinfo[lsdp->sd_symndx] = 354908278a5eSRod Evans ELF_C_INFO(chainndx, CAPINFO_SUNW_GLOB); 355008278a5eSRod Evans ocapchain[chainndx] = lsdp->sd_symndx; 355108278a5eSRod Evans } else { 355208278a5eSRod Evans /* 355308278a5eSRod Evans * For a relocatable object, identify this lead symbol, 355408278a5eSRod Evans * and set the lead symbol index to itself. 355508278a5eSRod Evans */ 355608278a5eSRod Evans ocapinfo[lsdp->sd_symndx] = 355708278a5eSRod Evans ELF_C_INFO(lsdp->sd_symndx, CAPINFO_SUNW_GLOB); 355808278a5eSRod Evans } 355908278a5eSRod Evans 356008278a5eSRod Evans /* 356108278a5eSRod Evans * Gather any lead symbol aliases. 356208278a5eSRod Evans */ 356308278a5eSRod Evans for (APLIST_TRAVERSE(cav->cn_aliases, idx, asdp)) { 356408278a5eSRod Evans if (ccosp) { 356508278a5eSRod Evans /* 356608278a5eSRod Evans * For a dynamic object, identify this lead 356708278a5eSRod Evans * alias symbol, and point it to the same 356808278a5eSRod Evans * capability chain index as the lead symbol. 356908278a5eSRod Evans */ 357008278a5eSRod Evans ocapinfo[asdp->sd_symndx] = 357108278a5eSRod Evans ELF_C_INFO(chainndx, CAPINFO_SUNW_GLOB); 357208278a5eSRod Evans } else { 357308278a5eSRod Evans /* 357408278a5eSRod Evans * For a relocatable object, identify this lead 357508278a5eSRod Evans * alias symbol, and set the lead symbol index 357608278a5eSRod Evans * to the lead symbol. 357708278a5eSRod Evans */ 357808278a5eSRod Evans ocapinfo[asdp->sd_symndx] = 357908278a5eSRod Evans ELF_C_INFO(lsdp->sd_symndx, 358008278a5eSRod Evans CAPINFO_SUNW_GLOB); 358108278a5eSRod Evans } 358208278a5eSRod Evans } 358308278a5eSRod Evans 358408278a5eSRod Evans chainndx++; 358508278a5eSRod Evans 358608278a5eSRod Evans /* 358708278a5eSRod Evans * Gather the family members. 358808278a5eSRod Evans */ 358908278a5eSRod Evans for (APLIST_TRAVERSE(cav->cn_members, idx, csp)) { 359008278a5eSRod Evans Sym_desc *msdp = csp->cs_sdp; 359108278a5eSRod Evans 359208278a5eSRod Evans /* 359308278a5eSRod Evans * Identify the members capability group, and the lead 359408278a5eSRod Evans * symbol of the family this symbol is a member of. 359508278a5eSRod Evans */ 359608278a5eSRod Evans ocapinfo[msdp->sd_symndx] = 359708278a5eSRod Evans ELF_C_INFO(lsdp->sd_symndx, csp->cs_group->cg_ndx); 359808278a5eSRod Evans if (ccosp) { 359908278a5eSRod Evans /* 360008278a5eSRod Evans * For a dynamic object, set the next capability 360108278a5eSRod Evans * chain to point to this family member. 360208278a5eSRod Evans */ 360308278a5eSRod Evans ocapchain[chainndx++] = msdp->sd_symndx; 360408278a5eSRod Evans } 360508278a5eSRod Evans } 360608278a5eSRod Evans 360708278a5eSRod Evans /* 360808278a5eSRod Evans * Any chain of family members is terminated with a 0 element. 360908278a5eSRod Evans */ 361008278a5eSRod Evans if (ccosp) 361108278a5eSRod Evans ocapchain[chainndx++] = 0; 361208278a5eSRod Evans } 361308278a5eSRod Evans } 361408278a5eSRod Evans 36157c478bd9Sstevel@tonic-gate /* 36167c478bd9Sstevel@tonic-gate * Translate the shdr->sh_{link, info} from its input section value to that 36177c478bd9Sstevel@tonic-gate * of the corresponding shdr->sh_{link, info} output section value. 36187c478bd9Sstevel@tonic-gate */ 36195aefb655Srie static Word 36205aefb655Srie translate_link(Ofl_desc *ofl, Os_desc *osp, Word link, const char *msg) 36217c478bd9Sstevel@tonic-gate { 362257ef7aa9SRod Evans Is_desc *isp; 362357ef7aa9SRod Evans Ifl_desc *ifl; 36247c478bd9Sstevel@tonic-gate 36257c478bd9Sstevel@tonic-gate /* 36267c478bd9Sstevel@tonic-gate * Don't translate the special section numbers. 36277c478bd9Sstevel@tonic-gate */ 36287c478bd9Sstevel@tonic-gate if (link >= SHN_LORESERVE) 36297c478bd9Sstevel@tonic-gate return (link); 36307c478bd9Sstevel@tonic-gate 36317c478bd9Sstevel@tonic-gate /* 36327c478bd9Sstevel@tonic-gate * Does this output section translate back to an input file. If not 36337c478bd9Sstevel@tonic-gate * then there is no translation to do. In this case we will assume that 36347c478bd9Sstevel@tonic-gate * if sh_link has a value, it's the right value. 36357c478bd9Sstevel@tonic-gate */ 36361dd9d86fSAli Bahrami isp = ld_os_first_isdesc(osp); 36377c478bd9Sstevel@tonic-gate if ((ifl = isp->is_file) == NULL) 36387c478bd9Sstevel@tonic-gate return (link); 36397c478bd9Sstevel@tonic-gate 36407c478bd9Sstevel@tonic-gate /* 36417c478bd9Sstevel@tonic-gate * Sanity check to make sure that the sh_{link, info} value 36427c478bd9Sstevel@tonic-gate * is within range for the input file. 36437c478bd9Sstevel@tonic-gate */ 36447c478bd9Sstevel@tonic-gate if (link >= ifl->ifl_shnum) { 36451007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, msg, ifl->ifl_name, 36464a8d0ea7SAli Bahrami EC_WORD(isp->is_scnndx), isp->is_name, EC_XWORD(link)); 36477c478bd9Sstevel@tonic-gate return (link); 36487c478bd9Sstevel@tonic-gate } 36497c478bd9Sstevel@tonic-gate 36507c478bd9Sstevel@tonic-gate /* 36517c478bd9Sstevel@tonic-gate * Follow the link to the input section. 36527c478bd9Sstevel@tonic-gate */ 365357ef7aa9SRod Evans if ((isp = ifl->ifl_isdesc[link]) == NULL) 36547c478bd9Sstevel@tonic-gate return (0); 365557ef7aa9SRod Evans if ((osp = isp->is_osdesc) == NULL) 36567c478bd9Sstevel@tonic-gate return (0); 36577c478bd9Sstevel@tonic-gate 36587c478bd9Sstevel@tonic-gate /* LINTED */ 36597c478bd9Sstevel@tonic-gate return ((Word)elf_ndxscn(osp->os_scn)); 36607c478bd9Sstevel@tonic-gate } 36617c478bd9Sstevel@tonic-gate 36628222814eSRichard Lowe typedef struct { 36638222814eSRichard Lowe avl_node_t aav_avl; 36648222814eSRichard Lowe Ass_desc *aav_ass; 36658222814eSRichard Lowe } Aav_node; 36668222814eSRichard Lowe 36678222814eSRichard Lowe static int 36688222814eSRichard Lowe aav_compare(const void *first, const void *second) 36698222814eSRichard Lowe { 36708222814eSRichard Lowe Sym *fs = ((Aav_node *)first)->aav_ass->ass_sdp->sd_sym; 36718222814eSRichard Lowe Sym *ss = ((Aav_node *)second)->aav_ass->ass_sdp->sd_sym; 36728222814eSRichard Lowe 36738222814eSRichard Lowe if (fs->st_value < ss->st_value) 36748222814eSRichard Lowe return (-1); 36758222814eSRichard Lowe if (fs->st_value > ss->st_value) 36768222814eSRichard Lowe return (1); 36778222814eSRichard Lowe 36788222814eSRichard Lowe if (fs->st_size < ss->st_size) 36798222814eSRichard Lowe return (-1); 36808222814eSRichard Lowe if (fs->st_size > ss->st_size) 36818222814eSRichard Lowe return (1); 36828222814eSRichard Lowe 36838222814eSRichard Lowe return (0); 36848222814eSRichard Lowe } 36858222814eSRichard Lowe 36868222814eSRichard Lowe 36878222814eSRichard Lowe /* 36888222814eSRichard Lowe * Check any assertions from mapfiles, provide guidance if there is global 36898222814eSRichard Lowe * data in a shared object that does not assert its size. 36908222814eSRichard Lowe */ 36918222814eSRichard Lowe static uintptr_t 36928222814eSRichard Lowe check_mapfile_assertions(Ofl_desc *ofl) 36938222814eSRichard Lowe { 36948222814eSRichard Lowe Ass_desc *ma; 36958222814eSRichard Lowe uintptr_t ret = 0; 36968222814eSRichard Lowe Aliste idx; 36978222814eSRichard Lowe avl_tree_t ass_avl; 36988222814eSRichard Lowe 36998222814eSRichard Lowe avl_create(&ass_avl, &aav_compare, sizeof (Aav_node), 37008222814eSRichard Lowe SGSOFFSETOF(Aav_node, aav_avl)); 37018222814eSRichard Lowe 37028222814eSRichard Lowe for (APLIST_TRAVERSE(ofl->ofl_symasserts, idx, ma)) { 37038222814eSRichard Lowe Sym_desc *sdp = ma->ass_sdp; 37048222814eSRichard Lowe Conv_inv_buf_t inv_buf, inv_buf2; 37058222814eSRichard Lowe 37068222814eSRichard Lowe /* 37078222814eSRichard Lowe * Try to insert the assertion into the tree if it's not an 37088222814eSRichard Lowe * alias assertion. If it's already present, it means we have 37098222814eSRichard Lowe * two non-alias assertions and should complain 37108222814eSRichard Lowe */ 37118222814eSRichard Lowe if (!ass_enabled(ma, SYM_ASSERT_ALIAS)) { 37128222814eSRichard Lowe Aav_node *av = libld_calloc(1, sizeof (Aav_node)); 37138222814eSRichard Lowe Aav_node *dup; 37148222814eSRichard Lowe avl_index_t where; 37158222814eSRichard Lowe 37168222814eSRichard Lowe if (av == NULL) 37178222814eSRichard Lowe return (S_ERROR); 37188222814eSRichard Lowe 37198222814eSRichard Lowe av->aav_ass = ma; 37208222814eSRichard Lowe 37218222814eSRichard Lowe if ((dup = avl_find(&ass_avl, av, &where)) != NULL) { 37228222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, 37238222814eSRichard Lowe MSG_INTL(MSG_ALIAS_NOTALIAS), 37248222814eSRichard Lowe ma->ass_file, 37257e85189aSToomas Soome EC_LINENO(ma->ass_lineno), 37268222814eSRichard Lowe ma->ass_sdp->sd_name, 37278222814eSRichard Lowe dup->aav_ass->ass_sdp->sd_name, 37288222814eSRichard Lowe dup->aav_ass->ass_file, 37297e85189aSToomas Soome EC_LINENO(dup->aav_ass->ass_lineno)); 37308222814eSRichard Lowe ret = S_ERROR; 37318222814eSRichard Lowe } else { 37328222814eSRichard Lowe avl_insert(&ass_avl, av, where); 37338222814eSRichard Lowe } 37348222814eSRichard Lowe } 37358222814eSRichard Lowe 37368222814eSRichard Lowe /* 37378222814eSRichard Lowe * All assertions can assert on binding. Other 37388222814eSRichard Lowe * assertion behaviour differs based on whether we're 37398222814eSRichard Lowe * asserting specifics, or asserting an ALIAS. In the 37408222814eSRichard Lowe * latter case, we just compare all the attributes 37418222814eSRichard Lowe * against another symbol. 37428222814eSRichard Lowe */ 37438222814eSRichard Lowe if (ass_enabled(ma, SYM_ASSERT_BIND) && 37448222814eSRichard Lowe (ma->ass_bind != ELF_ST_BIND(sdp->sd_sym->st_info))) { 37458222814eSRichard Lowe Sym *sym = sdp->sd_sym; 37468222814eSRichard Lowe 37478222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ASSFAIL_SCOPE), 37487e85189aSToomas Soome ma->ass_file, EC_LINENO(ma->ass_lineno), 37498222814eSRichard Lowe demangle(sdp->sd_name), 37508222814eSRichard Lowe conv_sym_info_bind(ma->ass_bind, CONV_FMT_ALT_CFNP, 37518222814eSRichard Lowe &inv_buf), 37528222814eSRichard Lowe conv_sym_info_bind(ELF_ST_BIND(sym->st_info), 37538222814eSRichard Lowe CONV_FMT_ALT_CFNP, &inv_buf2)); 37548222814eSRichard Lowe ret = S_ERROR; 37558222814eSRichard Lowe } 37568222814eSRichard Lowe 37578222814eSRichard Lowe if (ass_enabled(ma, SYM_ASSERT_ALIAS)) { 37588222814eSRichard Lowe Sym *rsym, *sym; 37598222814eSRichard Lowe Sym_desc *asdp; 37608222814eSRichard Lowe 37618222814eSRichard Lowe if ((asdp = ld_sym_find(ma->ass_alias, SYM_NOHASH, 37628222814eSRichard Lowe NULL, ofl)) == NULL) { 37638222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, 37648222814eSRichard Lowe MSG_INTL(MSG_ALIAS_BADSYM), 37657e85189aSToomas Soome ma->ass_file, EC_LINENO(ma->ass_lineno), 37668222814eSRichard Lowe ma->ass_alias); 37678222814eSRichard Lowe ret = S_ERROR; 37688222814eSRichard Lowe } else { 37698222814eSRichard Lowe /* 37708222814eSRichard Lowe * We forbid aliases of aliases, preferring 37718222814eSRichard Lowe * they all point to the concrete symbol. 37728222814eSRichard Lowe * This is unnecessary, but a strong 37738222814eSRichard Lowe * preference for maintainability. 37748222814eSRichard Lowe * 37758222814eSRichard Lowe * This does prevent circular references 37768222814eSRichard Lowe * however, and if this check is removed a 37778222814eSRichard Lowe * real check for such would need to be added. 37788222814eSRichard Lowe */ 37798222814eSRichard Lowe if (((asdp->sd_flags & FLG_SY_MAPASSRT) != 0) && 37808222814eSRichard Lowe ass_enabled(asdp->sd_ass, 37818222814eSRichard Lowe SYM_ASSERT_ALIAS)) { 37828222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, 37838222814eSRichard Lowe MSG_INTL(MSG_ALIAS_TOALIAS), 37847e85189aSToomas Soome ma->ass_file, 37857e85189aSToomas Soome EC_LINENO(ma->ass_lineno), 37868222814eSRichard Lowe ma->ass_alias); 37878222814eSRichard Lowe ret = S_ERROR; 37888222814eSRichard Lowe } 37898222814eSRichard Lowe 37908222814eSRichard Lowe rsym = asdp->sd_sym; 37918222814eSRichard Lowe sym = sdp->sd_sym; 37928222814eSRichard Lowe 37938222814eSRichard Lowe if ((rsym->st_value != sym->st_value) || 37948222814eSRichard Lowe (rsym->st_size != sym->st_size) || 37958222814eSRichard Lowe (ELF_ST_TYPE(rsym->st_info) != 37968222814eSRichard Lowe ELF_ST_TYPE(sym->st_info))) { 37978222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, 37988222814eSRichard Lowe MSG_INTL(MSG_ASSFAIL_ALIAS), 37997e85189aSToomas Soome ma->ass_file, 38007e85189aSToomas Soome EC_LINENO(ma->ass_lineno), 38018222814eSRichard Lowe demangle(sdp->sd_name), 38028222814eSRichard Lowe asdp->sd_name); 38038222814eSRichard Lowe ret = S_ERROR; 38048222814eSRichard Lowe } 38058222814eSRichard Lowe } 38068222814eSRichard Lowe 38078222814eSRichard Lowe /* 38088222814eSRichard Lowe * If this is an alias, none of our other checks 38098222814eSRichard Lowe * matter. 38108222814eSRichard Lowe */ 38118222814eSRichard Lowe continue; 38128222814eSRichard Lowe } 38138222814eSRichard Lowe 38148222814eSRichard Lowe /* 38158222814eSRichard Lowe * We only want to assert on the size of a _function_ if it's 38168222814eSRichard Lowe * explicitly sized, otherwise skip 38178222814eSRichard Lowe */ 38188222814eSRichard Lowe if (ass_enabled(ma, SYM_ASSERT_SIZE) && 38198222814eSRichard Lowe (ma->ass_size != sdp->sd_sym->st_size)) { 38208222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ASSFAIL_SIZE), 38217e85189aSToomas Soome ma->ass_file, EC_LINENO(ma->ass_lineno), 38228222814eSRichard Lowe demangle(sdp->sd_name), 38238222814eSRichard Lowe ma->ass_size, (Lword)sdp->sd_sym->st_size); 38248222814eSRichard Lowe ret = S_ERROR; 38258222814eSRichard Lowe } 38268222814eSRichard Lowe 38278222814eSRichard Lowe if (ass_enabled(ma, SYM_ASSERT_BITS) && (sdp->sd_isc != NULL)) { 38288222814eSRichard Lowe if ((ma->ass_bits == TRUE) && 38298222814eSRichard Lowe (sdp->sd_isc->is_shdr->sh_type == SHT_NOBITS)) { 38308222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, 38318222814eSRichard Lowe MSG_INTL(MSG_ASSFAIL_BITS), 38327e85189aSToomas Soome ma->ass_file, EC_LINENO(ma->ass_lineno), 38338222814eSRichard Lowe demangle(sdp->sd_name)); 38348222814eSRichard Lowe ret = S_ERROR; 38358222814eSRichard Lowe } 38368222814eSRichard Lowe if ((ma->ass_bits == FALSE) && 38378222814eSRichard Lowe (sdp->sd_isc->is_shdr->sh_type != SHT_NOBITS)) { 38388222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, 38398222814eSRichard Lowe MSG_INTL(MSG_ASSFAIL_NOBITS), 38407e85189aSToomas Soome ma->ass_file, EC_LINENO(ma->ass_lineno), 38418222814eSRichard Lowe demangle(sdp->sd_name)); 38428222814eSRichard Lowe ret = S_ERROR; 38438222814eSRichard Lowe } 38448222814eSRichard Lowe } 38458222814eSRichard Lowe 38468222814eSRichard Lowe if (ass_enabled(ma, SYM_ASSERT_TYPE) && 38478222814eSRichard Lowe (ma->ass_type != ELF_ST_TYPE(sdp->sd_sym->st_info))) { 38488222814eSRichard Lowe Ehdr *ehdr = sdp->sd_file->ifl_ehdr; 38498222814eSRichard Lowe 38508222814eSRichard Lowe ld_eprintf(ofl, ERR_FATAL, 38518222814eSRichard Lowe MSG_INTL(MSG_ASSFAIL_TYPE), 38527e85189aSToomas Soome ma->ass_file, EC_LINENO(ma->ass_lineno), 38538222814eSRichard Lowe demangle(sdp->sd_name), 38548222814eSRichard Lowe conv_sym_info_type(ehdr->e_machine, 38558222814eSRichard Lowe ma->ass_type, CONV_FMT_ALT_CFNP, &inv_buf), 38568222814eSRichard Lowe conv_sym_info_type(ehdr->e_machine, 38578222814eSRichard Lowe ELF_ST_TYPE(sdp->sd_sym->st_info), 38588222814eSRichard Lowe CONV_FMT_ALT_CFNP, &inv_buf2)); 38598222814eSRichard Lowe ret = S_ERROR; 38608222814eSRichard Lowe } 38618222814eSRichard Lowe } 38628222814eSRichard Lowe 38638222814eSRichard Lowe return (ret); 38648222814eSRichard Lowe } 38658222814eSRichard Lowe 38668222814eSRichard Lowe 38677c478bd9Sstevel@tonic-gate /* 38687c478bd9Sstevel@tonic-gate * Having created all of the necessary sections, segments, and associated 38697c478bd9Sstevel@tonic-gate * headers, fill in the program headers and update any other data in the 38707c478bd9Sstevel@tonic-gate * output image. Some general rules: 38717c478bd9Sstevel@tonic-gate * 387257ef7aa9SRod Evans * - If an interpreter is required always generate a PT_PHDR entry as 38737c478bd9Sstevel@tonic-gate * well. It is this entry that triggers the kernel into passing the 387470d3e49eSrie * interpreter an aux vector instead of just a file descriptor. 38757c478bd9Sstevel@tonic-gate * 387657ef7aa9SRod Evans * - When generating an image that will be interpreted (ie. a dynamic 38777c478bd9Sstevel@tonic-gate * executable, a shared object, or a static executable that has been 387870d3e49eSrie * provided with an interpreter - weird, but possible), make the initial 38797c478bd9Sstevel@tonic-gate * loadable segment include both the ehdr and phdr[]. Both of these 388070d3e49eSrie * tables are used by the interpreter therefore it seems more intuitive 38817c478bd9Sstevel@tonic-gate * to explicitly defined them as part of the mapped image rather than 388270d3e49eSrie * relying on page rounding by the interpreter to allow their access. 38837c478bd9Sstevel@tonic-gate * 388457ef7aa9SRod Evans * - When generating a static image that does not require an interpreter 38857c478bd9Sstevel@tonic-gate * have the first loadable segment indicate the address of the first 38867c478bd9Sstevel@tonic-gate * .section as the start address (things like /kernel/unix and ufsboot 38877c478bd9Sstevel@tonic-gate * expect this behavior). 38887c478bd9Sstevel@tonic-gate */ 38897c478bd9Sstevel@tonic-gate uintptr_t 38905aefb655Srie ld_update_outfile(Ofl_desc *ofl) 38917c478bd9Sstevel@tonic-gate { 3892bb3b4f6cSRod Evans Addr size, etext, vaddr; 389357ef7aa9SRod Evans Sg_desc *sgp; 389457ef7aa9SRod Evans Sg_desc *dtracesgp = NULL, *capsgp = NULL, *intpsgp = NULL; 3895cce0e03bSab Os_desc *osp; 389657ef7aa9SRod Evans int phdrndx = 0, segndx = -1, secndx, intppndx, intpsndx; 3897d1827f25Srie int dtracepndx, dtracesndx, cappndx, capsndx; 38985aefb655Srie Ehdr *ehdr = ofl->ofl_nehdr; 38997c478bd9Sstevel@tonic-gate Shdr *hshdr; 390057ef7aa9SRod Evans Phdr *_phdr = NULL; 3901d1827f25Srie Word phdrsz = (ehdr->e_phnum * ehdr->e_phentsize), shscnndx; 39021d9df23bSab ofl_flag_t flags = ofl->ofl_flags; 39031d9df23bSab Word ehdrsz = ehdr->e_ehsize; 39047c478bd9Sstevel@tonic-gate Boolean nobits; 39057c478bd9Sstevel@tonic-gate Off offset; 390657ef7aa9SRod Evans Aliste idx1; 39077c478bd9Sstevel@tonic-gate 3908bb3b4f6cSRod Evans /* 3909bb3b4f6cSRod Evans * Initialize the starting address for the first segment. Executables 3910bb3b4f6cSRod Evans * have different starting addresses depending upon the target ABI, 3911bb3b4f6cSRod Evans * where as shared objects have a starting address of 0. If this is 3912bb3b4f6cSRod Evans * a 64-bit executable that is being constructed to run in a restricted 3913bb3b4f6cSRod Evans * address space, use an alternative origin that will provide more free 3914bb3b4f6cSRod Evans * address space for the the eventual process. 3915bb3b4f6cSRod Evans */ 3916bb3b4f6cSRod Evans if (ofl->ofl_flags & FLG_OF_EXEC) { 3917bb3b4f6cSRod Evans #if defined(_ELF64) 391808278a5eSRod Evans if (ofl->ofl_ocapset.oc_sf_1.cm_val & SF1_SUNW_ADDR32) 3919bb3b4f6cSRod Evans vaddr = ld_targ.t_m.m_segm_aorigin; 3920bb3b4f6cSRod Evans else 3921bb3b4f6cSRod Evans #endif 3922bb3b4f6cSRod Evans vaddr = ld_targ.t_m.m_segm_origin; 3923bb3b4f6cSRod Evans } else 3924bb3b4f6cSRod Evans vaddr = 0; 3925bb3b4f6cSRod Evans 39267c478bd9Sstevel@tonic-gate /* 39277c478bd9Sstevel@tonic-gate * Loop through the segment descriptors and pick out what we need. 39287c478bd9Sstevel@tonic-gate */ 39295aefb655Srie DBG_CALL(Dbg_seg_title(ofl->ofl_lml)); 393057ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 393169112eddSAli Bahrami Phdr *phdr = &(sgp->sg_phdr); 3932c524b4feSRichard Lowe Xword p_align; 393369112eddSAli Bahrami Aliste idx2; 393469112eddSAli Bahrami Sym_desc *sdp; 39357c478bd9Sstevel@tonic-gate 39367c478bd9Sstevel@tonic-gate segndx++; 39377c478bd9Sstevel@tonic-gate 39387c478bd9Sstevel@tonic-gate /* 39397c478bd9Sstevel@tonic-gate * If an interpreter is required generate a PT_INTERP and 39407c478bd9Sstevel@tonic-gate * PT_PHDR program header entry. The PT_PHDR entry describes 39417c478bd9Sstevel@tonic-gate * the program header table itself. This information will be 39427c478bd9Sstevel@tonic-gate * passed via the aux vector to the interpreter (ld.so.1). 39437c478bd9Sstevel@tonic-gate * The program header array is actually part of the first 39447c478bd9Sstevel@tonic-gate * loadable segment (and the PT_PHDR entry is the first entry), 39457c478bd9Sstevel@tonic-gate * therefore its virtual address isn't known until the first 39467c478bd9Sstevel@tonic-gate * loadable segment is processed. 39477c478bd9Sstevel@tonic-gate */ 39487c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_PHDR) { 39497c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) { 39507c478bd9Sstevel@tonic-gate phdr->p_offset = ehdr->e_phoff; 39517c478bd9Sstevel@tonic-gate phdr->p_filesz = phdr->p_memsz = phdrsz; 3952d1827f25Srie 39535aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 39547c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 39557c478bd9Sstevel@tonic-gate } 39567c478bd9Sstevel@tonic-gate continue; 39577c478bd9Sstevel@tonic-gate } 39587c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_INTERP) { 39597c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) { 396057ef7aa9SRod Evans intpsgp = sgp; 396157ef7aa9SRod Evans intpsndx = segndx; 396257ef7aa9SRod Evans intppndx = phdrndx++; 39637c478bd9Sstevel@tonic-gate } 39647c478bd9Sstevel@tonic-gate continue; 39657c478bd9Sstevel@tonic-gate } 39667c478bd9Sstevel@tonic-gate 39677c478bd9Sstevel@tonic-gate /* 3968d1827f25Srie * If we are creating a PT_SUNWDTRACE segment, remember where 3969d1827f25Srie * the program header is. The header values are assigned after 3970d1827f25Srie * update_osym() has completed and the symbol table addresses 397128bda19cSRod Evans * have been updated. 39727c478bd9Sstevel@tonic-gate */ 39737c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_SUNWDTRACE) { 397428bda19cSRod Evans if (ofl->ofl_dtracesym && 39757c478bd9Sstevel@tonic-gate ((flags & FLG_OF_RELOBJ) == 0)) { 3976d1827f25Srie dtracesgp = sgp; 3977d1827f25Srie dtracesndx = segndx; 3978d1827f25Srie dtracepndx = phdrndx++; 39797c478bd9Sstevel@tonic-gate } 39807c478bd9Sstevel@tonic-gate continue; 39817c478bd9Sstevel@tonic-gate } 39827c478bd9Sstevel@tonic-gate 39837c478bd9Sstevel@tonic-gate /* 39847c478bd9Sstevel@tonic-gate * If a hardware/software capabilities section is required, 39857c478bd9Sstevel@tonic-gate * generate the PT_SUNWCAP header. Note, as this comes before 39867c478bd9Sstevel@tonic-gate * the first loadable segment, we don't yet know its real 39877c478bd9Sstevel@tonic-gate * virtual address. This is updated later. 39887c478bd9Sstevel@tonic-gate */ 39897c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_SUNWCAP) { 399008278a5eSRod Evans if (ofl->ofl_oscap && (ofl->ofl_flags & FLG_OF_PTCAP) && 399108278a5eSRod Evans ((flags & FLG_OF_RELOBJ) == 0)) { 3992d1827f25Srie capsgp = sgp; 3993d1827f25Srie capsndx = segndx; 3994d1827f25Srie cappndx = phdrndx++; 39957c478bd9Sstevel@tonic-gate } 39967c478bd9Sstevel@tonic-gate continue; 39977c478bd9Sstevel@tonic-gate } 39987c478bd9Sstevel@tonic-gate 39997c478bd9Sstevel@tonic-gate /* 40007c478bd9Sstevel@tonic-gate * As the dynamic program header occurs after the loadable 40017c478bd9Sstevel@tonic-gate * headers in the segment descriptor table, all the address 40027c478bd9Sstevel@tonic-gate * information for the .dynamic output section will have been 40037c478bd9Sstevel@tonic-gate * figured out by now. 40047c478bd9Sstevel@tonic-gate */ 40057c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_DYNAMIC) { 40069039eeafSab if (OFL_ALLOW_DYNSYM(ofl)) { 4007d1827f25Srie Shdr *shdr = ofl->ofl_osdynamic->os_shdr; 40087c478bd9Sstevel@tonic-gate 40097c478bd9Sstevel@tonic-gate phdr->p_vaddr = shdr->sh_addr; 40107c478bd9Sstevel@tonic-gate phdr->p_offset = shdr->sh_offset; 40117c478bd9Sstevel@tonic-gate phdr->p_filesz = shdr->sh_size; 4012ba2be530Sab phdr->p_flags = ld_targ.t_m.m_dataseg_perm; 4013d1827f25Srie 40145aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 40157c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 40167c478bd9Sstevel@tonic-gate } 40177c478bd9Sstevel@tonic-gate continue; 40187c478bd9Sstevel@tonic-gate } 4019d1827f25Srie 4020d1827f25Srie /* 40217e16fca0SAli Bahrami * As the unwind (.eh_frame_hdr) program header occurs after 40227e16fca0SAli Bahrami * the loadable headers in the segment descriptor table, all 40237e16fca0SAli Bahrami * the address information for the .eh_frame output section 40247e16fca0SAli Bahrami * will have been figured out by now. 4025d1827f25Srie */ 40267e16fca0SAli Bahrami if (phdr->p_type == PT_SUNW_UNWIND) { 40277c478bd9Sstevel@tonic-gate Shdr *shdr; 4028d1827f25Srie 40297e16fca0SAli Bahrami if (ofl->ofl_unwindhdr == NULL) 40307c478bd9Sstevel@tonic-gate continue; 4031d1827f25Srie 40327c478bd9Sstevel@tonic-gate shdr = ofl->ofl_unwindhdr->os_shdr; 40337c478bd9Sstevel@tonic-gate 40347c478bd9Sstevel@tonic-gate phdr->p_flags = PF_R; 40357c478bd9Sstevel@tonic-gate phdr->p_vaddr = shdr->sh_addr; 40367c478bd9Sstevel@tonic-gate phdr->p_memsz = shdr->sh_size; 40377c478bd9Sstevel@tonic-gate phdr->p_filesz = shdr->sh_size; 40387c478bd9Sstevel@tonic-gate phdr->p_offset = shdr->sh_offset; 40397c478bd9Sstevel@tonic-gate phdr->p_align = shdr->sh_addralign; 40407c478bd9Sstevel@tonic-gate phdr->p_paddr = 0; 40417c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 40427c478bd9Sstevel@tonic-gate continue; 40437c478bd9Sstevel@tonic-gate } 40447e16fca0SAli Bahrami 404569112eddSAli Bahrami /* 404669112eddSAli Bahrami * The sunwstack program is used to convey non-default 404769112eddSAli Bahrami * flags for the process stack. Only emit it if it would 404869112eddSAli Bahrami * change the default. 404969112eddSAli Bahrami */ 405069112eddSAli Bahrami if (phdr->p_type == PT_SUNWSTACK) { 4051a1926ac7SAli Bahrami if (((flags & FLG_OF_RELOBJ) == 0) && 4052a1926ac7SAli Bahrami ((sgp->sg_flags & FLG_SG_DISABLED) == 0)) 405369112eddSAli Bahrami ofl->ofl_phdr[phdrndx++] = *phdr; 405469112eddSAli Bahrami continue; 405569112eddSAli Bahrami } 405669112eddSAli Bahrami 4057d1827f25Srie /* 4058d1827f25Srie * As the TLS program header occurs after the loadable 4059d1827f25Srie * headers in the segment descriptor table, all the address 4060d1827f25Srie * information for the .tls output section will have been 4061d1827f25Srie * figured out by now. 4062d1827f25Srie */ 40637c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_TLS) { 406457ef7aa9SRod Evans Os_desc *tlsosp; 406508278a5eSRod Evans Shdr *lastfileshdr = NULL; 406608278a5eSRod Evans Shdr *firstshdr = NULL, *lastshdr; 406757ef7aa9SRod Evans Aliste idx; 40687c478bd9Sstevel@tonic-gate 406957ef7aa9SRod Evans if (ofl->ofl_ostlsseg == NULL) 40707c478bd9Sstevel@tonic-gate continue; 4071dd94ecefSrie 4072f79d60b6Srie /* 407308278a5eSRod Evans * Scan the output sections that have contributed TLS. 4074f79d60b6Srie * Remember the first and last so as to determine the 4075f79d60b6Srie * TLS memory size requirement. Remember the last 407608278a5eSRod Evans * progbits section to determine the TLS data 407708278a5eSRod Evans * contribution, which determines the TLS program 407808278a5eSRod Evans * header filesz. 4079f79d60b6Srie */ 408057ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_ostlsseg, idx, tlsosp)) { 4081dd94ecefSrie Shdr *tlsshdr = tlsosp->os_shdr; 4082dd94ecefSrie 408357ef7aa9SRod Evans if (firstshdr == NULL) 4084f79d60b6Srie firstshdr = tlsshdr; 4085f79d60b6Srie if (tlsshdr->sh_type != SHT_NOBITS) 4086f79d60b6Srie lastfileshdr = tlsshdr; 4087f79d60b6Srie lastshdr = tlsshdr; 40887c478bd9Sstevel@tonic-gate } 4089dd94ecefSrie 4090dd94ecefSrie phdr->p_flags = PF_R | PF_W; 40917c478bd9Sstevel@tonic-gate phdr->p_vaddr = firstshdr->sh_addr; 40927c478bd9Sstevel@tonic-gate phdr->p_offset = firstshdr->sh_offset; 4093dd94ecefSrie phdr->p_align = firstshdr->sh_addralign; 4094f79d60b6Srie 409508278a5eSRod Evans /* 409608278a5eSRod Evans * Determine the initialized TLS data size. This 409708278a5eSRod Evans * address range is from the start of the TLS segment 409808278a5eSRod Evans * to the end of the last piece of initialized data. 409908278a5eSRod Evans */ 4100f79d60b6Srie if (lastfileshdr) 4101f79d60b6Srie phdr->p_filesz = lastfileshdr->sh_offset + 4102f79d60b6Srie lastfileshdr->sh_size - phdr->p_offset; 4103f79d60b6Srie else 4104f79d60b6Srie phdr->p_filesz = 0; 4105f79d60b6Srie 410608278a5eSRod Evans /* 410708278a5eSRod Evans * Determine the total TLS memory size. This includes 410808278a5eSRod Evans * all TLS data and TLS uninitialized data. This 410908278a5eSRod Evans * address range is from the start of the TLS segment 411008278a5eSRod Evans * to the memory address of the last piece of 411108278a5eSRod Evans * uninitialized data. 411208278a5eSRod Evans */ 411308278a5eSRod Evans phdr->p_memsz = lastshdr->sh_addr + 411408278a5eSRod Evans lastshdr->sh_size - phdr->p_vaddr; 4115dd94ecefSrie 41165aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 4117d1827f25Srie ofl->ofl_phdr[phdrndx] = *phdr; 4118d1827f25Srie ofl->ofl_tlsphdr = &ofl->ofl_phdr[phdrndx++]; 41197c478bd9Sstevel@tonic-gate continue; 41207c478bd9Sstevel@tonic-gate } 41217c478bd9Sstevel@tonic-gate 41227c478bd9Sstevel@tonic-gate /* 41237c478bd9Sstevel@tonic-gate * If this is an empty segment declaration, it will occur after 4124d1827f25Srie * all other loadable segments. As empty segments can be 412508278a5eSRod Evans * defined with fixed addresses, make sure that no loadable 4126d1827f25Srie * segments overlap. This might occur as the object evolves 4127d1827f25Srie * and the loadable segments grow, thus encroaching upon an 4128d1827f25Srie * existing segment reservation. 4129d1827f25Srie * 4130d1827f25Srie * Segments are only created for dynamic objects, thus this 4131d1827f25Srie * checking can be skipped when building a relocatable object. 41327c478bd9Sstevel@tonic-gate */ 41331d9df23bSab if (!(flags & FLG_OF_RELOBJ) && 41347c478bd9Sstevel@tonic-gate (sgp->sg_flags & FLG_SG_EMPTY)) { 4135d1827f25Srie int i; 41367c478bd9Sstevel@tonic-gate Addr v_e; 41377c478bd9Sstevel@tonic-gate 41387c478bd9Sstevel@tonic-gate vaddr = phdr->p_vaddr; 41397c478bd9Sstevel@tonic-gate phdr->p_memsz = sgp->sg_length; 41405aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 41417c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 41427c478bd9Sstevel@tonic-gate 41437c478bd9Sstevel@tonic-gate if (phdr->p_type != PT_LOAD) 41447c478bd9Sstevel@tonic-gate continue; 41457c478bd9Sstevel@tonic-gate 41467c478bd9Sstevel@tonic-gate v_e = vaddr + phdr->p_memsz; 4147d1827f25Srie 41487c478bd9Sstevel@tonic-gate /* 41497c478bd9Sstevel@tonic-gate * Check overlaps 41507c478bd9Sstevel@tonic-gate */ 41517c478bd9Sstevel@tonic-gate for (i = 0; i < phdrndx - 1; i++) { 4152c524b4feSRichard Lowe Addr p_s = (ofl->ofl_phdr[i]).p_vaddr; 4153c524b4feSRichard Lowe Addr p_e; 41547c478bd9Sstevel@tonic-gate 41557c478bd9Sstevel@tonic-gate if ((ofl->ofl_phdr[i]).p_type != PT_LOAD) 41567c478bd9Sstevel@tonic-gate continue; 41577c478bd9Sstevel@tonic-gate 41587c478bd9Sstevel@tonic-gate p_e = p_s + (ofl->ofl_phdr[i]).p_memsz; 41597c478bd9Sstevel@tonic-gate if (((p_s <= vaddr) && (p_e > vaddr)) || 41607c478bd9Sstevel@tonic-gate ((vaddr <= p_s) && (v_e > p_s))) 41611007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 41627c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_SEGOVERLAP), 41635aefb655Srie ofl->ofl_name, EC_ADDR(p_e), 41645aefb655Srie sgp->sg_name, EC_ADDR(vaddr)); 41657c478bd9Sstevel@tonic-gate } 41667c478bd9Sstevel@tonic-gate continue; 41677c478bd9Sstevel@tonic-gate } 41687c478bd9Sstevel@tonic-gate 41697c478bd9Sstevel@tonic-gate /* 41707c478bd9Sstevel@tonic-gate * Having processed any of the special program headers any 41717c478bd9Sstevel@tonic-gate * remaining headers will be built to express individual 41727c478bd9Sstevel@tonic-gate * segments. Segments are only built if they have output 41737c478bd9Sstevel@tonic-gate * section descriptors associated with them (ie. some form of 41747c478bd9Sstevel@tonic-gate * input section has been matched to this segment). 41757c478bd9Sstevel@tonic-gate */ 4176*8b891ae8SRichard Lowe if (aplist_nitems(sgp->sg_osdescs) == 0) 41777c478bd9Sstevel@tonic-gate continue; 41787c478bd9Sstevel@tonic-gate 41797c478bd9Sstevel@tonic-gate /* 41807c478bd9Sstevel@tonic-gate * Determine the segments offset and size from the section 41817c478bd9Sstevel@tonic-gate * information provided from elf_update(). 41827c478bd9Sstevel@tonic-gate * Allow for multiple NOBITS sections. 41837c478bd9Sstevel@tonic-gate */ 4184cce0e03bSab osp = sgp->sg_osdescs->apl_data[0]; 418554d82594Sseizo hshdr = osp->os_shdr; 41867c478bd9Sstevel@tonic-gate 41877c478bd9Sstevel@tonic-gate phdr->p_filesz = 0; 41887c478bd9Sstevel@tonic-gate phdr->p_memsz = 0; 41897c478bd9Sstevel@tonic-gate phdr->p_offset = offset = hshdr->sh_offset; 41900bc07c75Srie 419154d82594Sseizo nobits = ((hshdr->sh_type == SHT_NOBITS) && 41920bc07c75Srie ((sgp->sg_flags & FLG_SG_PHREQ) == 0)); 41930bc07c75Srie 419457ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 4195cce0e03bSab Shdr *shdr = osp->os_shdr; 41967c478bd9Sstevel@tonic-gate 41977c478bd9Sstevel@tonic-gate p_align = 0; 41987c478bd9Sstevel@tonic-gate if (shdr->sh_addralign > p_align) 41997c478bd9Sstevel@tonic-gate p_align = shdr->sh_addralign; 42000bc07c75Srie 42017c478bd9Sstevel@tonic-gate offset = (Off)S_ROUND(offset, shdr->sh_addralign); 42027c478bd9Sstevel@tonic-gate offset += shdr->sh_size; 42030bc07c75Srie 42047c478bd9Sstevel@tonic-gate if (shdr->sh_type != SHT_NOBITS) { 42057c478bd9Sstevel@tonic-gate if (nobits) { 42061007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, 42077c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_NOBITS)); 42087c478bd9Sstevel@tonic-gate return (S_ERROR); 42097c478bd9Sstevel@tonic-gate } 42107c478bd9Sstevel@tonic-gate phdr->p_filesz = offset - phdr->p_offset; 421154d82594Sseizo } else if ((sgp->sg_flags & FLG_SG_PHREQ) == 0) 42127c478bd9Sstevel@tonic-gate nobits = TRUE; 42137c478bd9Sstevel@tonic-gate } 42147c478bd9Sstevel@tonic-gate phdr->p_memsz = offset - hshdr->sh_offset; 42157c478bd9Sstevel@tonic-gate 42167c478bd9Sstevel@tonic-gate /* 42177c478bd9Sstevel@tonic-gate * If this is the first loadable segment of a dynamic object, 421870d3e49eSrie * or an interpreter has been specified (a static object built 421970d3e49eSrie * with an interpreter will still be given a PT_HDR entry), then 42207c478bd9Sstevel@tonic-gate * compensate for the elf header and program header array. Both 42217c478bd9Sstevel@tonic-gate * of these are actually part of the loadable segment as they 422270d3e49eSrie * may be inspected by the interpreter. Adjust the segments 42237c478bd9Sstevel@tonic-gate * size and offset accordingly. 42247c478bd9Sstevel@tonic-gate */ 422557ef7aa9SRod Evans if ((_phdr == NULL) && (phdr->p_type == PT_LOAD) && 42267c478bd9Sstevel@tonic-gate ((ofl->ofl_osinterp) || (flags & FLG_OF_DYNAMIC)) && 42274899432aSab (!(ofl->ofl_dtflags_1 & DF_1_NOHDR))) { 42287c478bd9Sstevel@tonic-gate size = (Addr)S_ROUND((phdrsz + ehdrsz), 42297c478bd9Sstevel@tonic-gate hshdr->sh_addralign); 42307c478bd9Sstevel@tonic-gate phdr->p_offset -= size; 42317c478bd9Sstevel@tonic-gate phdr->p_filesz += size; 42327c478bd9Sstevel@tonic-gate phdr->p_memsz += size; 42337c478bd9Sstevel@tonic-gate } 42347c478bd9Sstevel@tonic-gate 42357c478bd9Sstevel@tonic-gate /* 423669112eddSAli Bahrami * If segment size symbols are required (specified via a 423769112eddSAli Bahrami * mapfile) update their value. 42387c478bd9Sstevel@tonic-gate */ 423969112eddSAli Bahrami for (APLIST_TRAVERSE(sgp->sg_sizesym, idx2, sdp)) 424069112eddSAli Bahrami sdp->sd_sym->st_value = phdr->p_memsz; 42417c478bd9Sstevel@tonic-gate 42427c478bd9Sstevel@tonic-gate /* 42437c478bd9Sstevel@tonic-gate * If no file content has been assigned to this segment (it 42447c478bd9Sstevel@tonic-gate * only contains no-bits sections), then reset the offset for 42457c478bd9Sstevel@tonic-gate * consistency. 42467c478bd9Sstevel@tonic-gate */ 42477c478bd9Sstevel@tonic-gate if (phdr->p_filesz == 0) 42487c478bd9Sstevel@tonic-gate phdr->p_offset = 0; 42497c478bd9Sstevel@tonic-gate 42507c478bd9Sstevel@tonic-gate /* 42517c478bd9Sstevel@tonic-gate * If a virtual address has been specified for this segment 425269112eddSAli Bahrami * from a mapfile use it and make sure the previous segment 425369112eddSAli Bahrami * does not run into this segment. 42547c478bd9Sstevel@tonic-gate */ 425535450702SAli Bahrami if (phdr->p_type == PT_LOAD) { 425669112eddSAli Bahrami if ((sgp->sg_flags & FLG_SG_P_VADDR)) { 42577c478bd9Sstevel@tonic-gate if (_phdr && (vaddr > phdr->p_vaddr) && 42587c478bd9Sstevel@tonic-gate (phdr->p_type == PT_LOAD)) 42591007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 42607c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_SEGOVERLAP), 42617c478bd9Sstevel@tonic-gate ofl->ofl_name, EC_ADDR(vaddr), 42627c478bd9Sstevel@tonic-gate sgp->sg_name, 42637c478bd9Sstevel@tonic-gate EC_ADDR(phdr->p_vaddr)); 42647c478bd9Sstevel@tonic-gate vaddr = phdr->p_vaddr; 42657c478bd9Sstevel@tonic-gate phdr->p_align = 0; 42667c478bd9Sstevel@tonic-gate } else { 42677c478bd9Sstevel@tonic-gate vaddr = phdr->p_vaddr = 42687c478bd9Sstevel@tonic-gate (Addr)S_ROUND(vaddr, phdr->p_align); 42697c478bd9Sstevel@tonic-gate } 42707c478bd9Sstevel@tonic-gate } 42717c478bd9Sstevel@tonic-gate 42727c478bd9Sstevel@tonic-gate /* 42737c478bd9Sstevel@tonic-gate * Adjust the address offset and p_align if needed. 42747c478bd9Sstevel@tonic-gate */ 427569112eddSAli Bahrami if (((sgp->sg_flags & FLG_SG_P_VADDR) == 0) && 42763906e0c2Srie ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0)) { 42777c478bd9Sstevel@tonic-gate if (phdr->p_align != 0) 42787c478bd9Sstevel@tonic-gate vaddr += phdr->p_offset % phdr->p_align; 42797c478bd9Sstevel@tonic-gate else 42807c478bd9Sstevel@tonic-gate vaddr += phdr->p_offset; 42817c478bd9Sstevel@tonic-gate phdr->p_vaddr = vaddr; 42827c478bd9Sstevel@tonic-gate } 42837c478bd9Sstevel@tonic-gate 42847c478bd9Sstevel@tonic-gate /* 42857c478bd9Sstevel@tonic-gate * If an interpreter is required set the virtual address of the 42867c478bd9Sstevel@tonic-gate * PT_PHDR program header now that we know the virtual address 42877c478bd9Sstevel@tonic-gate * of the loadable segment that contains it. Update the 42887c478bd9Sstevel@tonic-gate * PT_SUNWCAP header similarly. 42897c478bd9Sstevel@tonic-gate */ 429057ef7aa9SRod Evans if ((_phdr == NULL) && (phdr->p_type == PT_LOAD)) { 42917c478bd9Sstevel@tonic-gate _phdr = phdr; 42927c478bd9Sstevel@tonic-gate 4293d1827f25Srie if ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0) { 42947c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) 42957c478bd9Sstevel@tonic-gate ofl->ofl_phdr[0].p_vaddr = 42967c478bd9Sstevel@tonic-gate vaddr + ehdrsz; 42977c478bd9Sstevel@tonic-gate 42987c478bd9Sstevel@tonic-gate /* 42997c478bd9Sstevel@tonic-gate * Finally, if we're creating a dynamic object 430070d3e49eSrie * (or a static object in which an interpreter 43017c478bd9Sstevel@tonic-gate * is specified) update the vaddr to reflect 43027c478bd9Sstevel@tonic-gate * the address of the first section within this 43037c478bd9Sstevel@tonic-gate * segment. 43047c478bd9Sstevel@tonic-gate */ 43057c478bd9Sstevel@tonic-gate if ((ofl->ofl_osinterp) || 43067c478bd9Sstevel@tonic-gate (flags & FLG_OF_DYNAMIC)) 43077c478bd9Sstevel@tonic-gate vaddr += size; 43087c478bd9Sstevel@tonic-gate } else { 43097c478bd9Sstevel@tonic-gate /* 4310d1827f25Srie * If the DF_1_NOHDR flag was set, and an 4311d1827f25Srie * interpreter is being generated, the PT_PHDR 43127c478bd9Sstevel@tonic-gate * will not be part of any loadable segment. 43137c478bd9Sstevel@tonic-gate */ 4314d1827f25Srie if (ofl->ofl_osinterp) { 4315d1827f25Srie ofl->ofl_phdr[0].p_vaddr = 0; 4316d1827f25Srie ofl->ofl_phdr[0].p_memsz = 0; 4317d1827f25Srie ofl->ofl_phdr[0].p_flags = 0; 4318d1827f25Srie } 43197c478bd9Sstevel@tonic-gate } 43207c478bd9Sstevel@tonic-gate } 43217c478bd9Sstevel@tonic-gate 43227c478bd9Sstevel@tonic-gate /* 4323c1c6f601Srie * Ensure the ELF entry point defaults to zero. Typically, this 4324c1c6f601Srie * value is overridden in update_oehdr() to one of the standard 4325c1c6f601Srie * entry points. Historically, this default was set to the 4326c1c6f601Srie * address of first executable section, but this has since been 4327c1c6f601Srie * found to be more confusing than it is helpful. 43287c478bd9Sstevel@tonic-gate */ 4329c1c6f601Srie ehdr->e_entry = 0; 43307c478bd9Sstevel@tonic-gate 43315aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 43327c478bd9Sstevel@tonic-gate 43337c478bd9Sstevel@tonic-gate /* 43347c478bd9Sstevel@tonic-gate * Traverse the output section descriptors for this segment so 43357c478bd9Sstevel@tonic-gate * that we can update the section headers addresses. We've 43367c478bd9Sstevel@tonic-gate * calculated the virtual address of the initial section within 43377c478bd9Sstevel@tonic-gate * this segment, so each successive section can be calculated 43387c478bd9Sstevel@tonic-gate * based on their offsets from each other. 43397c478bd9Sstevel@tonic-gate */ 43407c478bd9Sstevel@tonic-gate secndx = 0; 43417c478bd9Sstevel@tonic-gate hshdr = 0; 434257ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 4343cce0e03bSab Shdr *shdr = osp->os_shdr; 43447c478bd9Sstevel@tonic-gate 43457c478bd9Sstevel@tonic-gate if (shdr->sh_link) 434660758829Srie shdr->sh_link = translate_link(ofl, osp, 434760758829Srie shdr->sh_link, MSG_INTL(MSG_FIL_INVSHLINK)); 43487c478bd9Sstevel@tonic-gate 43497c478bd9Sstevel@tonic-gate if (shdr->sh_info && (shdr->sh_flags & SHF_INFO_LINK)) 435060758829Srie shdr->sh_info = translate_link(ofl, osp, 435160758829Srie shdr->sh_info, MSG_INTL(MSG_FIL_INVSHINFO)); 43527c478bd9Sstevel@tonic-gate 43537c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ) && 435435450702SAli Bahrami (phdr->p_type == PT_LOAD)) { 43557c478bd9Sstevel@tonic-gate if (hshdr) 43567c478bd9Sstevel@tonic-gate vaddr += (shdr->sh_offset - 43577c478bd9Sstevel@tonic-gate hshdr->sh_offset); 43587c478bd9Sstevel@tonic-gate 43597c478bd9Sstevel@tonic-gate shdr->sh_addr = vaddr; 43607c478bd9Sstevel@tonic-gate hshdr = shdr; 43617c478bd9Sstevel@tonic-gate } 43627c478bd9Sstevel@tonic-gate 43637c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_seg_os(ofl, osp, secndx)); 43647c478bd9Sstevel@tonic-gate secndx++; 43657c478bd9Sstevel@tonic-gate } 43667c478bd9Sstevel@tonic-gate 43677c478bd9Sstevel@tonic-gate /* 43687c478bd9Sstevel@tonic-gate * Establish the virtual address of the end of the last section 43697c478bd9Sstevel@tonic-gate * in this segment so that the next segments offset can be 43707c478bd9Sstevel@tonic-gate * calculated from this. 43717c478bd9Sstevel@tonic-gate */ 43727c478bd9Sstevel@tonic-gate if (hshdr) 43737c478bd9Sstevel@tonic-gate vaddr += hshdr->sh_size; 43747c478bd9Sstevel@tonic-gate 43757c478bd9Sstevel@tonic-gate /* 43767c478bd9Sstevel@tonic-gate * Output sections for this segment complete. Adjust the 43777c478bd9Sstevel@tonic-gate * virtual offset for the last sections size, and make sure we 43787c478bd9Sstevel@tonic-gate * haven't exceeded any maximum segment length specification. 43797c478bd9Sstevel@tonic-gate */ 43807c478bd9Sstevel@tonic-gate if ((sgp->sg_length != 0) && (sgp->sg_length < phdr->p_memsz)) { 43811007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_UPD_LARGSIZE), 43821007fd6fSAli Bahrami ofl->ofl_name, sgp->sg_name, 43831007fd6fSAli Bahrami EC_XWORD(phdr->p_memsz), EC_XWORD(sgp->sg_length)); 43847c478bd9Sstevel@tonic-gate return (S_ERROR); 43857c478bd9Sstevel@tonic-gate } 43867c478bd9Sstevel@tonic-gate 43877c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_NOTE) { 43887c478bd9Sstevel@tonic-gate phdr->p_vaddr = 0; 43897c478bd9Sstevel@tonic-gate phdr->p_paddr = 0; 43907c478bd9Sstevel@tonic-gate phdr->p_align = 0; 43917c478bd9Sstevel@tonic-gate phdr->p_memsz = 0; 43927c478bd9Sstevel@tonic-gate } 4393d1827f25Srie 43947c478bd9Sstevel@tonic-gate if ((phdr->p_type != PT_NULL) && !(flags & FLG_OF_RELOBJ)) 43957c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 43967c478bd9Sstevel@tonic-gate } 43977c478bd9Sstevel@tonic-gate 43987c478bd9Sstevel@tonic-gate /* 43997c478bd9Sstevel@tonic-gate * Update any new output sections. When building the initial output 44007c478bd9Sstevel@tonic-gate * image, a number of sections were created but left uninitialized (eg. 44017c478bd9Sstevel@tonic-gate * .dynsym, .dynstr, .symtab, .symtab, etc.). Here we update these 44027c478bd9Sstevel@tonic-gate * sections with the appropriate data. Other sections may still be 44037c478bd9Sstevel@tonic-gate * modified via reloc_process(). 44047c478bd9Sstevel@tonic-gate * 440570d3e49eSrie * Copy the interpreter name into the .interp section. 44067c478bd9Sstevel@tonic-gate */ 44077c478bd9Sstevel@tonic-gate if (ofl->ofl_interp) 44087c478bd9Sstevel@tonic-gate (void) strcpy((char *)ofl->ofl_osinterp->os_outdata->d_buf, 44097c478bd9Sstevel@tonic-gate ofl->ofl_interp); 44107c478bd9Sstevel@tonic-gate 44117c478bd9Sstevel@tonic-gate /* 44127c478bd9Sstevel@tonic-gate * Update the .shstrtab, .strtab and .dynstr sections. 44137c478bd9Sstevel@tonic-gate */ 44143244bcaaSab update_ostrtab(ofl->ofl_osshstrtab, ofl->ofl_shdrsttab, 0); 44153244bcaaSab update_ostrtab(ofl->ofl_osstrtab, ofl->ofl_strtab, 0); 44163244bcaaSab update_ostrtab(ofl->ofl_osdynstr, ofl->ofl_dynstrtab, DYNSTR_EXTRA_PAD); 44177c478bd9Sstevel@tonic-gate 44187c478bd9Sstevel@tonic-gate /* 44197c478bd9Sstevel@tonic-gate * Build any output symbol tables, the symbols information is copied 44207c478bd9Sstevel@tonic-gate * and updated into the new output image. 44217c478bd9Sstevel@tonic-gate */ 44227c478bd9Sstevel@tonic-gate if ((etext = update_osym(ofl)) == (Addr)S_ERROR) 44237c478bd9Sstevel@tonic-gate return (S_ERROR); 44247c478bd9Sstevel@tonic-gate 44258222814eSRichard Lowe 44268222814eSRichard Lowe /* 44278222814eSRichard Lowe * Now the symbol tables are complete, process any mapfile 44288222814eSRichard Lowe * assertions 44298222814eSRichard Lowe */ 44308222814eSRichard Lowe if (check_mapfile_assertions(ofl) == S_ERROR) 44318222814eSRichard Lowe return (S_ERROR); 443257ef7aa9SRod Evans /* 443357ef7aa9SRod Evans * If we have an PT_INTERP phdr, update it now from the associated 443457ef7aa9SRod Evans * section information. 443557ef7aa9SRod Evans */ 443657ef7aa9SRod Evans if (intpsgp) { 443757ef7aa9SRod Evans Phdr *phdr = &(intpsgp->sg_phdr); 443857ef7aa9SRod Evans Shdr *shdr = ofl->ofl_osinterp->os_shdr; 443957ef7aa9SRod Evans 444057ef7aa9SRod Evans phdr->p_vaddr = shdr->sh_addr; 444157ef7aa9SRod Evans phdr->p_offset = shdr->sh_offset; 444257ef7aa9SRod Evans phdr->p_memsz = phdr->p_filesz = shdr->sh_size; 444357ef7aa9SRod Evans phdr->p_flags = PF_R; 444457ef7aa9SRod Evans 444557ef7aa9SRod Evans DBG_CALL(Dbg_seg_entry(ofl, intpsndx, intpsgp)); 444657ef7aa9SRod Evans ofl->ofl_phdr[intppndx] = *phdr; 444757ef7aa9SRod Evans } 444857ef7aa9SRod Evans 44497c478bd9Sstevel@tonic-gate /* 44507c478bd9Sstevel@tonic-gate * If we have a PT_SUNWDTRACE phdr, update it now with the address of 44517c478bd9Sstevel@tonic-gate * the symbol. It's only now been updated via update_sym(). 44527c478bd9Sstevel@tonic-gate */ 4453635216b6SRod Evans if (dtracesgp) { 4454d1827f25Srie Phdr *aphdr, *phdr = &(dtracesgp->sg_phdr); 44557c478bd9Sstevel@tonic-gate Sym_desc *sdp = ofl->ofl_dtracesym; 44567c478bd9Sstevel@tonic-gate 4457d1827f25Srie phdr->p_vaddr = sdp->sd_sym->st_value; 4458d1827f25Srie phdr->p_memsz = sdp->sd_sym->st_size; 44597c478bd9Sstevel@tonic-gate 44607c478bd9Sstevel@tonic-gate /* 446108278a5eSRod Evans * Take permissions from the segment that the symbol is 446208278a5eSRod Evans * associated with. 44637c478bd9Sstevel@tonic-gate */ 4464d1827f25Srie aphdr = &sdp->sd_isc->is_osdesc->os_sgdesc->sg_phdr; 4465d1827f25Srie assert(aphdr); 4466d1827f25Srie phdr->p_flags = aphdr->p_flags; 4467d1827f25Srie 4468d1827f25Srie DBG_CALL(Dbg_seg_entry(ofl, dtracesndx, dtracesgp)); 4469d1827f25Srie ofl->ofl_phdr[dtracepndx] = *phdr; 4470d1827f25Srie } 4471d1827f25Srie 4472d1827f25Srie /* 4473d1827f25Srie * If we have a PT_SUNWCAP phdr, update it now from the associated 4474d1827f25Srie * section information. 4475d1827f25Srie */ 4476635216b6SRod Evans if (capsgp) { 4477d1827f25Srie Phdr *phdr = &(capsgp->sg_phdr); 4478d1827f25Srie Shdr *shdr = ofl->ofl_oscap->os_shdr; 4479d1827f25Srie 4480d1827f25Srie phdr->p_vaddr = shdr->sh_addr; 4481d1827f25Srie phdr->p_offset = shdr->sh_offset; 448257ef7aa9SRod Evans phdr->p_memsz = phdr->p_filesz = shdr->sh_size; 4483d1827f25Srie phdr->p_flags = PF_R; 4484d1827f25Srie 4485d1827f25Srie DBG_CALL(Dbg_seg_entry(ofl, capsndx, capsgp)); 4486d1827f25Srie ofl->ofl_phdr[cappndx] = *phdr; 44877c478bd9Sstevel@tonic-gate } 44887c478bd9Sstevel@tonic-gate 44897c478bd9Sstevel@tonic-gate /* 44907c478bd9Sstevel@tonic-gate * Update the GROUP sections. 44917c478bd9Sstevel@tonic-gate */ 44927c478bd9Sstevel@tonic-gate if (update_ogroup(ofl) == S_ERROR) 44937c478bd9Sstevel@tonic-gate return (S_ERROR); 44947c478bd9Sstevel@tonic-gate 44957c478bd9Sstevel@tonic-gate /* 44967c478bd9Sstevel@tonic-gate * Update Move Table. 44977c478bd9Sstevel@tonic-gate */ 449857ef7aa9SRod Evans if (ofl->ofl_osmove || ofl->ofl_isparexpn) 449957ef7aa9SRod Evans update_move(ofl); 45007c478bd9Sstevel@tonic-gate 45017c478bd9Sstevel@tonic-gate /* 45027c478bd9Sstevel@tonic-gate * Build any output headers, version information, dynamic structure and 45037c478bd9Sstevel@tonic-gate * syminfo structure. 45047c478bd9Sstevel@tonic-gate */ 45057c478bd9Sstevel@tonic-gate if (update_oehdr(ofl) == S_ERROR) 45067c478bd9Sstevel@tonic-gate return (S_ERROR); 4507090a8d9eSAli Bahrami if (!(flags & FLG_OF_NOVERSEC)) { 4508090a8d9eSAli Bahrami if ((flags & FLG_OF_VERDEF) && 4509090a8d9eSAli Bahrami (update_overdef(ofl) == S_ERROR)) 4510090a8d9eSAli Bahrami return (S_ERROR); 4511090a8d9eSAli Bahrami if ((flags & FLG_OF_VERNEED) && 4512090a8d9eSAli Bahrami (update_overneed(ofl) == S_ERROR)) 45137c478bd9Sstevel@tonic-gate return (S_ERROR); 4514635216b6SRod Evans if (flags & (FLG_OF_VERNEED | FLG_OF_VERDEF)) 4515635216b6SRod Evans update_oversym(ofl); 4516090a8d9eSAli Bahrami } 45177c478bd9Sstevel@tonic-gate if (flags & FLG_OF_DYNAMIC) { 45187c478bd9Sstevel@tonic-gate if (update_odynamic(ofl) == S_ERROR) 45197c478bd9Sstevel@tonic-gate return (S_ERROR); 4520635216b6SRod Evans } 4521635216b6SRod Evans if (ofl->ofl_ossyminfo) { 4522635216b6SRod Evans if (update_osyminfo(ofl) == S_ERROR) 4523635216b6SRod Evans return (S_ERROR); 45247c478bd9Sstevel@tonic-gate } 45257c478bd9Sstevel@tonic-gate 452608278a5eSRod Evans /* 452708278a5eSRod Evans * Update capabilities information if required. 452808278a5eSRod Evans */ 452908278a5eSRod Evans if (ofl->ofl_oscap) 453008278a5eSRod Evans update_oscap(ofl); 453108278a5eSRod Evans if (ofl->ofl_oscapinfo) 453208278a5eSRod Evans update_oscapinfo(ofl); 453308278a5eSRod Evans 45341da7e599SAli Bahrami /* 4535635216b6SRod Evans * Sanity test: the first and last data byte of a string table 45361da7e599SAli Bahrami * must be NULL. 45371da7e599SAli Bahrami */ 45381da7e599SAli Bahrami assert((ofl->ofl_osshstrtab == NULL) || 45391da7e599SAli Bahrami (*((char *)ofl->ofl_osshstrtab->os_outdata->d_buf) == '\0')); 45401da7e599SAli Bahrami assert((ofl->ofl_osshstrtab == NULL) || 45411da7e599SAli Bahrami (*(((char *)ofl->ofl_osshstrtab->os_outdata->d_buf) + 45421da7e599SAli Bahrami ofl->ofl_osshstrtab->os_outdata->d_size - 1) == '\0')); 45431da7e599SAli Bahrami 45441da7e599SAli Bahrami assert((ofl->ofl_osstrtab == NULL) || 45451da7e599SAli Bahrami (*((char *)ofl->ofl_osstrtab->os_outdata->d_buf) == '\0')); 45461da7e599SAli Bahrami assert((ofl->ofl_osstrtab == NULL) || 45471da7e599SAli Bahrami (*(((char *)ofl->ofl_osstrtab->os_outdata->d_buf) + 45481da7e599SAli Bahrami ofl->ofl_osstrtab->os_outdata->d_size - 1) == '\0')); 45491da7e599SAli Bahrami 45501da7e599SAli Bahrami assert((ofl->ofl_osdynstr == NULL) || 45511da7e599SAli Bahrami (*((char *)ofl->ofl_osdynstr->os_outdata->d_buf) == '\0')); 45521da7e599SAli Bahrami assert((ofl->ofl_osdynstr == NULL) || 45531da7e599SAli Bahrami (*(((char *)ofl->ofl_osdynstr->os_outdata->d_buf) + 45541da7e599SAli Bahrami ofl->ofl_osdynstr->os_outdata->d_size - DYNSTR_EXTRA_PAD - 1) == 45551da7e599SAli Bahrami '\0')); 45561da7e599SAli Bahrami 45577c478bd9Sstevel@tonic-gate /* 45587c478bd9Sstevel@tonic-gate * Emit Strtab diagnostics. 45597c478bd9Sstevel@tonic-gate */ 45605aefb655Srie DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osshstrtab, 45615aefb655Srie ofl->ofl_shdrsttab)); 45625aefb655Srie DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osstrtab, 45635aefb655Srie ofl->ofl_strtab)); 45645aefb655Srie DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osdynstr, 45655aefb655Srie ofl->ofl_dynstrtab)); 45667c478bd9Sstevel@tonic-gate 45677c478bd9Sstevel@tonic-gate /* 45687c478bd9Sstevel@tonic-gate * Initialize the section headers string table index within the elf 45697c478bd9Sstevel@tonic-gate * header. 45707c478bd9Sstevel@tonic-gate */ 45717c478bd9Sstevel@tonic-gate /* LINTED */ 45727c478bd9Sstevel@tonic-gate if ((shscnndx = elf_ndxscn(ofl->ofl_osshstrtab->os_scn)) < 45737c478bd9Sstevel@tonic-gate SHN_LORESERVE) { 45745aefb655Srie ofl->ofl_nehdr->e_shstrndx = 45757c478bd9Sstevel@tonic-gate /* LINTED */ 45767c478bd9Sstevel@tonic-gate (Half)shscnndx; 45777c478bd9Sstevel@tonic-gate } else { 45787c478bd9Sstevel@tonic-gate /* 45797c478bd9Sstevel@tonic-gate * If the STRTAB section index doesn't fit into 45807c478bd9Sstevel@tonic-gate * e_shstrndx, then we store it in 'shdr[0].st_link'. 45817c478bd9Sstevel@tonic-gate */ 45827c478bd9Sstevel@tonic-gate Elf_Scn *scn; 45837c478bd9Sstevel@tonic-gate Shdr *shdr0; 45845aefb655Srie 45857c478bd9Sstevel@tonic-gate if ((scn = elf_getscn(ofl->ofl_elf, 0)) == NULL) { 45861007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETSCN), 45871007fd6fSAli Bahrami ofl->ofl_name); 45887c478bd9Sstevel@tonic-gate return (S_ERROR); 45897c478bd9Sstevel@tonic-gate } 45907c478bd9Sstevel@tonic-gate if ((shdr0 = elf_getshdr(scn)) == NULL) { 45911007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETSHDR), 45921007fd6fSAli Bahrami ofl->ofl_name); 45937c478bd9Sstevel@tonic-gate return (S_ERROR); 45947c478bd9Sstevel@tonic-gate } 45955aefb655Srie ofl->ofl_nehdr->e_shstrndx = SHN_XINDEX; 45967c478bd9Sstevel@tonic-gate shdr0->sh_link = shscnndx; 45977c478bd9Sstevel@tonic-gate } 45987c478bd9Sstevel@tonic-gate 45997c478bd9Sstevel@tonic-gate return ((uintptr_t)etext); 46007c478bd9Sstevel@tonic-gate } 4601