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 */ 34ba2be530Sab196087 35ba2be530Sab196087 #define ELF_TARGET_AMD64 36ba2be530Sab196087 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 /* 459039eeafSab196087 * 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 547c478bd9Sstevel@tonic-gate /* 55d579eb63Sab196087 * Comparison routine used by qsort() for sorting of dyn[sym|tls]sort section 56d579eb63Sab196087 * indices based on the address of the symbols they reference. The 57d579eb63Sab196087 * use of the global dynsort_compare_syms variable is needed because 58d579eb63Sab196087 * we need to examine the symbols the indices reference. It is safe, because 59d579eb63Sab196087 * the linker is single threaded. 60d579eb63Sab196087 */ 61d579eb63Sab196087 Sym *dynsort_compare_syms; 62d579eb63Sab196087 63d579eb63Sab196087 static int 64d579eb63Sab196087 dynsort_compare(const void *idx1, const void *idx2) 65d579eb63Sab196087 { 66d579eb63Sab196087 Sym *s1 = dynsort_compare_syms + *((const Word *) idx1); 67d579eb63Sab196087 Sym *s2 = dynsort_compare_syms + *((const Word *) idx2); 68d579eb63Sab196087 69d579eb63Sab196087 /* 70d579eb63Sab196087 * Note: the logical computation for this is 71d579eb63Sab196087 * (st_value1 - st_value2) 72d579eb63Sab196087 * However, that is only correct if the address type is smaller 73d579eb63Sab196087 * than a pointer. Writing it this way makes it immune to the 74d579eb63Sab196087 * class (32 or 64-bit) of the linker. 75d579eb63Sab196087 */ 76d579eb63Sab196087 return ((s1->st_value < s2->st_value) ? -1 : 77d579eb63Sab196087 (s1->st_value > s2->st_value)); 78d579eb63Sab196087 } 79d579eb63Sab196087 80d579eb63Sab196087 /* 81d579eb63Sab196087 * Scan the sorted symbols, and issue warnings if there are any duplicate 82d579eb63Sab196087 * values in the list. We only do this if -zverbose is set, or we are 83d579eb63Sab196087 * running with LD_DEBUG defined 84d579eb63Sab196087 * 85d579eb63Sab196087 * entry: 86d579eb63Sab196087 * ofl - Output file descriptor 87d579eb63Sab196087 * ldynsym - Pointer to start of .SUNW_ldynsym section that the 88d579eb63Sab196087 * sort section indexes reference. 89d579eb63Sab196087 * symsort - Pointer to start of .SUNW_dynsymsort or .SUNW_dyntlssort 90d579eb63Sab196087 * section. 91d579eb63Sab196087 * n - # of indices in symsort array 92d579eb63Sab196087 * secname - Name of the symsort section. 93d579eb63Sab196087 * 94d579eb63Sab196087 * exit: 95d579eb63Sab196087 * If the symsort section contains indexes to more than one 96d579eb63Sab196087 * symbol with the same address value, a warning is issued. 97d579eb63Sab196087 */ 98d579eb63Sab196087 static void 99d579eb63Sab196087 dynsort_dupwarn(Ofl_desc *ofl, Sym *ldynsym, const char *str, 100d579eb63Sab196087 Word *symsort, Word n, const char *secname) 101d579eb63Sab196087 { 102d579eb63Sab196087 int zverbose = (ofl->ofl_flags & FLG_OF_VERBOSE) != 0; 103d579eb63Sab196087 Word ndx, cmp_ndx; 104d579eb63Sab196087 Addr addr, cmp_addr; 105d579eb63Sab196087 106d579eb63Sab196087 /* Nothing to do if -zverbose or LD_DEBUG are not active */ 107d579eb63Sab196087 if (!(zverbose || DBG_ENABLED)) 108d579eb63Sab196087 return; 109d579eb63Sab196087 110d579eb63Sab196087 cmp_ndx = 0; 111d579eb63Sab196087 cmp_addr = ldynsym[symsort[cmp_ndx]].st_value; 112d579eb63Sab196087 for (ndx = 1; ndx < n; ndx++) { 113d579eb63Sab196087 addr = ldynsym[symsort[ndx]].st_value; 114d579eb63Sab196087 if (cmp_addr == addr) { 115d579eb63Sab196087 if (zverbose) 116*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 117d579eb63Sab196087 MSG_INTL(MSG_SYM_DUPSORTADDR), secname, 118d579eb63Sab196087 str + ldynsym[symsort[cmp_ndx]].st_name, 119d579eb63Sab196087 str + ldynsym[symsort[ndx]].st_name, 120d579eb63Sab196087 EC_ADDR(addr)); 121d579eb63Sab196087 DBG_CALL(Dbg_syms_dup_sort_addr(ofl->ofl_lml, secname, 122d579eb63Sab196087 str + ldynsym[symsort[cmp_ndx]].st_name, 123d579eb63Sab196087 str + ldynsym[symsort[ndx]].st_name, 124d579eb63Sab196087 EC_ADDR(addr))); 125d579eb63Sab196087 } else { /* Not a dup. Move reference up */ 126d579eb63Sab196087 cmp_ndx = ndx; 127d579eb63Sab196087 cmp_addr = addr; 128d579eb63Sab196087 } 129d579eb63Sab196087 } 130d579eb63Sab196087 } 131d579eb63Sab196087 132d579eb63Sab196087 /* 1337c478bd9Sstevel@tonic-gate * Build and update any output symbol tables. Here we work on all the symbol 1347c478bd9Sstevel@tonic-gate * tables at once to reduce the duplication of symbol and string manipulation. 1357c478bd9Sstevel@tonic-gate * Symbols and their associated strings are copied from the read-only input 1367c478bd9Sstevel@tonic-gate * file images to the output image and their values and index's updated in the 1377c478bd9Sstevel@tonic-gate * output image. 1387c478bd9Sstevel@tonic-gate */ 1395aefb655Srie static Addr 1407c478bd9Sstevel@tonic-gate update_osym(Ofl_desc *ofl) 1417c478bd9Sstevel@tonic-gate { 142d579eb63Sab196087 /* 143d579eb63Sab196087 * There are several places in this function where we wish 144d579eb63Sab196087 * to insert a symbol index to the combined .SUNW_ldynsym/.dynsym 145d579eb63Sab196087 * symbol table into one of the two sort sections (.SUNW_dynsymsort 146d579eb63Sab196087 * or .SUNW_dyntlssort), if that symbol has the right attributes. 147d579eb63Sab196087 * This macro is used to generate the necessary code from a single 148d579eb63Sab196087 * specification. 149d579eb63Sab196087 * 150d579eb63Sab196087 * entry: 151d579eb63Sab196087 * _sdp, _sym, _type - As per DYNSORT_COUNT. See _libld.h 152d579eb63Sab196087 * _sym_ndx - Index that _sym will have in the combined 153d579eb63Sab196087 * .SUNW_ldynsym/.dynsym symbol table. 154d579eb63Sab196087 */ 155d579eb63Sab196087 #define ADD_TO_DYNSORT(_sdp, _sym, _type, _sym_ndx) \ 156d579eb63Sab196087 { \ 157d579eb63Sab196087 Word *_dynsort_arr, *_dynsort_ndx; \ 158d579eb63Sab196087 \ 159d579eb63Sab196087 if (dynsymsort_symtype[_type]) { \ 160d579eb63Sab196087 _dynsort_arr = dynsymsort; \ 161d579eb63Sab196087 _dynsort_ndx = &dynsymsort_ndx; \ 162d579eb63Sab196087 } else if (_type == STT_TLS) { \ 163d579eb63Sab196087 _dynsort_arr = dyntlssort; \ 164d579eb63Sab196087 _dynsort_ndx = &dyntlssort_ndx; \ 165d579eb63Sab196087 } else { \ 166d579eb63Sab196087 _dynsort_arr = NULL; \ 167d579eb63Sab196087 } \ 168d579eb63Sab196087 if ((_dynsort_arr != NULL) && DYNSORT_TEST_ATTR(_sdp, _sym)) \ 169d579eb63Sab196087 _dynsort_arr[(*_dynsort_ndx)++] = _sym_ndx; \ 170d579eb63Sab196087 } 171d579eb63Sab196087 1727c478bd9Sstevel@tonic-gate Sym_desc *sdp; 1737c478bd9Sstevel@tonic-gate Sym_avlnode *sav; 17457ef7aa9SRod Evans Sg_desc *sgp, *tsgp = NULL, *dsgp = NULL, *esgp = NULL; 17557ef7aa9SRod Evans Os_desc *osp, *iosp = NULL, *fosp = NULL; 17657ef7aa9SRod Evans Is_desc *isc; 1777c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 1787c478bd9Sstevel@tonic-gate Word bssndx, etext_ndx, edata_ndx = 0, end_ndx, start_ndx; 1797c478bd9Sstevel@tonic-gate Word end_abs = 0, etext_abs = 0, edata_abs; 18035450702SAli Bahrami Word tlsbssndx = 0, parexpnndx; 181ba2be530Sab196087 #if defined(_ELF64) 18254d82594Sseizo Word lbssndx = 0; 18354d82594Sseizo Addr lbssaddr = 0; 18454d82594Sseizo #endif 1857c478bd9Sstevel@tonic-gate Addr bssaddr, etext = 0, edata = 0, end = 0, start = 0; 1867c478bd9Sstevel@tonic-gate Addr tlsbssaddr = 0; 187b26cc8daSAli Bahrami Addr parexpnbase, parexpnaddr; 1887c478bd9Sstevel@tonic-gate int start_set = 0; 18957ef7aa9SRod Evans Sym _sym = {0}, *sym, *symtab = NULL; 19057ef7aa9SRod Evans Sym *dynsym = NULL, *ldynsym = NULL; 1917c478bd9Sstevel@tonic-gate Word symtab_ndx = 0; /* index into .symtab */ 192ca4eed8bSAli Bahrami Word symtab_gbl_bndx; /* .symtab ndx 1st global */ 1939039eeafSab196087 Word ldynsym_ndx = 0; /* index into .SUNW_ldynsym */ 1947c478bd9Sstevel@tonic-gate Word dynsym_ndx = 0; /* index into .dynsym */ 1957c478bd9Sstevel@tonic-gate Word scopesym_ndx = 0; /* index into scoped symbols */ 196ca4eed8bSAli Bahrami Word scopesym_bndx = 0; /* .symtab ndx 1st scoped sym */ 197635216b6SRod Evans Word ldynscopesym_ndx = 0; /* index to ldynsym scoped */ 198635216b6SRod Evans /* symbols */ 199635216b6SRod Evans Word *dynsymsort = NULL; /* SUNW_dynsymsort index */ 200635216b6SRod Evans /* vector */ 201635216b6SRod Evans Word *dyntlssort = NULL; /* SUNW_dyntlssort index */ 202635216b6SRod Evans /* vector */ 203d579eb63Sab196087 Word dynsymsort_ndx; /* index dynsymsort array */ 204d579eb63Sab196087 Word dyntlssort_ndx; /* index dyntlssort array */ 205635216b6SRod Evans Word *symndx; /* symbol index (for */ 206635216b6SRod Evans /* relocation use) */ 20757ef7aa9SRod Evans Word *symshndx = NULL; /* .symtab_shndx table */ 20857ef7aa9SRod Evans Word *dynshndx = NULL; /* .dynsym_shndx table */ 20957ef7aa9SRod Evans Word *ldynshndx = NULL; /* .SUNW_ldynsym_shndx table */ 210635216b6SRod Evans Word ldynsym_cnt = NULL; /* number of items in */ 211635216b6SRod Evans /* .SUNW_ldynsym */ 2127c478bd9Sstevel@tonic-gate Str_tbl *shstrtab; 2137c478bd9Sstevel@tonic-gate Str_tbl *strtab; 2147c478bd9Sstevel@tonic-gate Str_tbl *dynstr; 2157c478bd9Sstevel@tonic-gate Word *hashtab; /* hash table pointer */ 2167c478bd9Sstevel@tonic-gate Word *hashbkt; /* hash table bucket pointer */ 2177c478bd9Sstevel@tonic-gate Word *hashchain; /* hash table chain pointer */ 2187c478bd9Sstevel@tonic-gate Wk_desc *wkp; 21957ef7aa9SRod Evans Alist *weak = NULL; 2201d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 2217c478bd9Sstevel@tonic-gate Versym *versym; 2227c478bd9Sstevel@tonic-gate Gottable *gottable; /* used for display got debugging */ 2237c478bd9Sstevel@tonic-gate /* information */ 2247c478bd9Sstevel@tonic-gate Syminfo *syminfo; 2257c478bd9Sstevel@tonic-gate Sym_s_list *sorted_syms; /* table to hold sorted symbols */ 2267c478bd9Sstevel@tonic-gate Word ssndx; /* global index into sorted_syms */ 2277c478bd9Sstevel@tonic-gate Word scndx; /* scoped index into sorted_syms */ 228cce0e03bSab196087 size_t stoff; /* string offset */ 22957ef7aa9SRod Evans Aliste idx1; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * Initialize pointers to the symbol table entries and the symbol 2337c478bd9Sstevel@tonic-gate * table strings. Skip the first symbol entry and the first string 2347c478bd9Sstevel@tonic-gate * table byte. Note that if we are not generating any output symbol 235e64d0ff9SAli Bahrami * tables we must still generate and update internal copies so 2367c478bd9Sstevel@tonic-gate * that the relocation phase has the correct information. 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) || 2397c478bd9Sstevel@tonic-gate ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) { 2407c478bd9Sstevel@tonic-gate symtab = (Sym *)ofl->ofl_ossymtab->os_outdata->d_buf; 2417c478bd9Sstevel@tonic-gate symtab[symtab_ndx++] = _sym; 2427c478bd9Sstevel@tonic-gate if (ofl->ofl_ossymshndx) 243d840867fSab196087 symshndx = 244d840867fSab196087 (Word *)ofl->ofl_ossymshndx->os_outdata->d_buf; 2457c478bd9Sstevel@tonic-gate } 2469039eeafSab196087 if (OFL_ALLOW_DYNSYM(ofl)) { 2477c478bd9Sstevel@tonic-gate dynsym = (Sym *)ofl->ofl_osdynsym->os_outdata->d_buf; 2487c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx++] = _sym; 2497c478bd9Sstevel@tonic-gate /* 2509039eeafSab196087 * If we are also constructing a .SUNW_ldynsym section 2519039eeafSab196087 * to contain local function symbols, then set it up too. 2529039eeafSab196087 */ 2539039eeafSab196087 if (ofl->ofl_osldynsym) { 2549039eeafSab196087 ldynsym = (Sym *)ofl->ofl_osldynsym->os_outdata->d_buf; 2559039eeafSab196087 ldynsym[ldynsym_ndx++] = _sym; 256d579eb63Sab196087 ldynsym_cnt = 1 + ofl->ofl_dynlocscnt + 257d579eb63Sab196087 ofl->ofl_dynscopecnt; 258d579eb63Sab196087 259d579eb63Sab196087 /* 260d579eb63Sab196087 * If there is a SUNW_ldynsym, then there may also 261d579eb63Sab196087 * be a .SUNW_dynsymsort and/or .SUNW_dyntlssort 262d579eb63Sab196087 * sections, used to collect indices of function 263d579eb63Sab196087 * and data symbols sorted by address order. 264d579eb63Sab196087 */ 265d579eb63Sab196087 if (ofl->ofl_osdynsymsort) { /* .SUNW_dynsymsort */ 266d579eb63Sab196087 dynsymsort = (Word *) 267d579eb63Sab196087 ofl->ofl_osdynsymsort->os_outdata->d_buf; 268d579eb63Sab196087 dynsymsort_ndx = 0; 269d579eb63Sab196087 } 270d579eb63Sab196087 if (ofl->ofl_osdyntlssort) { /* .SUNW_dyntlssort */ 271d579eb63Sab196087 dyntlssort = (Word *) 272d579eb63Sab196087 ofl->ofl_osdyntlssort->os_outdata->d_buf; 273d579eb63Sab196087 dyntlssort_ndx = 0; 274d579eb63Sab196087 } 2759039eeafSab196087 } 2769039eeafSab196087 2779039eeafSab196087 /* 2787c478bd9Sstevel@tonic-gate * Initialize the hash table. 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate hashtab = (Word *)(ofl->ofl_oshash->os_outdata->d_buf); 2817c478bd9Sstevel@tonic-gate hashbkt = &hashtab[2]; 2827c478bd9Sstevel@tonic-gate hashchain = &hashtab[2 + ofl->ofl_hashbkts]; 2837c478bd9Sstevel@tonic-gate hashtab[0] = ofl->ofl_hashbkts; 284635216b6SRod Evans hashtab[1] = DYNSYM_ALL_CNT(ofl); 2857c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynshndx) 286d840867fSab196087 dynshndx = 287d840867fSab196087 (Word *)ofl->ofl_osdynshndx->os_outdata->d_buf; 2889039eeafSab196087 if (ofl->ofl_osldynshndx) 289d840867fSab196087 ldynshndx = 290d840867fSab196087 (Word *)ofl->ofl_osldynshndx->os_outdata->d_buf; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * symndx is the symbol index to be used for relocation processing. It 2957c478bd9Sstevel@tonic-gate * points to the relevant symtab's (.dynsym or .symtab) symbol ndx. 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate if (dynsym) 2987c478bd9Sstevel@tonic-gate symndx = &dynsym_ndx; 2997c478bd9Sstevel@tonic-gate else 3007c478bd9Sstevel@tonic-gate symndx = &symtab_ndx; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * If we have version definitions initialize the version symbol index 3047c478bd9Sstevel@tonic-gate * table. There is one entry for each symbol which contains the symbols 3057c478bd9Sstevel@tonic-gate * version index. 3067c478bd9Sstevel@tonic-gate */ 307090a8d9eSAli Bahrami if (!(flags & FLG_OF_NOVERSEC) && 308090a8d9eSAli Bahrami (flags & (FLG_OF_VERNEED | FLG_OF_VERDEF))) { 3097c478bd9Sstevel@tonic-gate versym = (Versym *)ofl->ofl_osversym->os_outdata->d_buf; 31028bda19cSRod Evans versym[0] = NULL; 3117c478bd9Sstevel@tonic-gate } else 31228bda19cSRod Evans versym = NULL; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * If syminfo section exists be prepared to fill it in. 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate if (ofl->ofl_ossyminfo) { 3187c478bd9Sstevel@tonic-gate syminfo = ofl->ofl_ossyminfo->os_outdata->d_buf; 3197c478bd9Sstevel@tonic-gate syminfo[0].si_flags = SYMINFO_CURRENT; 3207c478bd9Sstevel@tonic-gate } else 32128bda19cSRod Evans syminfo = NULL; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Setup our string tables. 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate shstrtab = ofl->ofl_shdrsttab; 3277c478bd9Sstevel@tonic-gate strtab = ofl->ofl_strtab; 3287c478bd9Sstevel@tonic-gate dynstr = ofl->ofl_dynstrtab; 3297c478bd9Sstevel@tonic-gate 3305aefb655Srie DBG_CALL(Dbg_syms_sec_title(ofl->ofl_lml)); 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3339039eeafSab196087 * Put output file name to the first .symtab and .SUNW_ldynsym symbol. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate if (symtab) { 3367c478bd9Sstevel@tonic-gate (void) st_setstring(strtab, ofl->ofl_name, &stoff); 3377c478bd9Sstevel@tonic-gate sym = &symtab[symtab_ndx++]; 3387c478bd9Sstevel@tonic-gate /* LINTED */ 3397c478bd9Sstevel@tonic-gate sym->st_name = stoff; 3407c478bd9Sstevel@tonic-gate sym->st_value = 0; 3417c478bd9Sstevel@tonic-gate sym->st_size = 0; 3427c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE); 3437c478bd9Sstevel@tonic-gate sym->st_other = 0; 3447c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_ABS; 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate if (versym && !dynsym) 3477c478bd9Sstevel@tonic-gate versym[1] = 0; 3487c478bd9Sstevel@tonic-gate } 349d579eb63Sab196087 if (ldynsym) { 3509039eeafSab196087 (void) st_setstring(dynstr, ofl->ofl_name, &stoff); 3519039eeafSab196087 sym = &ldynsym[ldynsym_ndx]; 3529039eeafSab196087 /* LINTED */ 3539039eeafSab196087 sym->st_name = stoff; 3549039eeafSab196087 sym->st_value = 0; 3559039eeafSab196087 sym->st_size = 0; 3569039eeafSab196087 sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE); 3579039eeafSab196087 sym->st_other = 0; 3589039eeafSab196087 sym->st_shndx = SHN_ABS; 3599039eeafSab196087 3609039eeafSab196087 /* Scoped symbols get filled in global loop below */ 3619039eeafSab196087 ldynscopesym_ndx = ldynsym_ndx + 1; 3629039eeafSab196087 ldynsym_ndx += ofl->ofl_dynscopecnt; 3639039eeafSab196087 } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * If we are to display GOT summary information, then allocate 3677c478bd9Sstevel@tonic-gate * the buffer to 'cache' the GOT symbols into now. 3687c478bd9Sstevel@tonic-gate */ 3695aefb655Srie if (DBG_ENABLED) { 370d326b23bSrie if ((ofl->ofl_gottable = gottable = 37157ef7aa9SRod Evans libld_calloc(ofl->ofl_gotcnt, sizeof (Gottable))) == NULL) 3727c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate /* 3767c478bd9Sstevel@tonic-gate * Traverse the program headers. Determine the last executable segment 3777c478bd9Sstevel@tonic-gate * and the last data segment so that we can update etext and edata. If 3787c478bd9Sstevel@tonic-gate * we have empty segments (reservations) record them for setting _end. 3797c478bd9Sstevel@tonic-gate */ 38057ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 3817c478bd9Sstevel@tonic-gate Phdr *phd = &(sgp->sg_phdr); 382cce0e03bSab196087 Os_desc *osp; 38357ef7aa9SRod Evans Aliste idx2; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate if (phd->p_type == PT_LOAD) { 3860bc07c75Srie if (sgp->sg_osdescs != NULL) { 3877c478bd9Sstevel@tonic-gate Word _flags = phd->p_flags & (PF_W | PF_R); 3880bc07c75Srie 389fdf855a7Sseizo if (_flags == PF_R) 3907c478bd9Sstevel@tonic-gate tsgp = sgp; 391fdf855a7Sseizo else if (_flags == (PF_W | PF_R)) 3927c478bd9Sstevel@tonic-gate dsgp = sgp; 3937c478bd9Sstevel@tonic-gate } else if (sgp->sg_flags & FLG_SG_EMPTY) 3947c478bd9Sstevel@tonic-gate esgp = sgp; 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * Generate a section symbol for each output section. 3997c478bd9Sstevel@tonic-gate */ 40057ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 4017c478bd9Sstevel@tonic-gate Word sectndx; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate sym = &_sym; 4047c478bd9Sstevel@tonic-gate sym->st_value = osp->os_shdr->sh_addr; 4057c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION); 4067c478bd9Sstevel@tonic-gate /* LINTED */ 4077c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn(osp->os_scn); 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate if (symtab) { 4107c478bd9Sstevel@tonic-gate if (sectndx >= SHN_LORESERVE) { 4117c478bd9Sstevel@tonic-gate symshndx[symtab_ndx] = sectndx; 4127c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_XINDEX; 4137c478bd9Sstevel@tonic-gate } else { 4147c478bd9Sstevel@tonic-gate /* LINTED */ 4157c478bd9Sstevel@tonic-gate sym->st_shndx = (Half)sectndx; 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate symtab[symtab_ndx++] = *sym; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate if (dynsym && (osp->os_flags & FLG_OS_OUTREL)) 4217c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx++] = *sym; 4227c478bd9Sstevel@tonic-gate 42357ef7aa9SRod Evans if ((dynsym == NULL) || 42457ef7aa9SRod Evans (osp->os_flags & FLG_OS_OUTREL)) { 4257c478bd9Sstevel@tonic-gate if (versym) 4267c478bd9Sstevel@tonic-gate versym[*symndx - 1] = 0; 42757ef7aa9SRod Evans osp->os_identndx = *symndx - 1; 4285aefb655Srie DBG_CALL(Dbg_syms_sec_entry(ofl->ofl_lml, 42957ef7aa9SRod Evans osp->os_identndx, sgp, osp)); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * Generate the .shstrtab for this section. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate (void) st_setstring(shstrtab, osp->os_name, &stoff); 4367c478bd9Sstevel@tonic-gate osp->os_shdr->sh_name = (Word)stoff; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * Find the section index for our special symbols. 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate if (sgp == tsgp) { 4427c478bd9Sstevel@tonic-gate /* LINTED */ 4437c478bd9Sstevel@tonic-gate etext_ndx = elf_ndxscn(osp->os_scn); 4447c478bd9Sstevel@tonic-gate } else if (dsgp == sgp) { 4457c478bd9Sstevel@tonic-gate if (osp->os_shdr->sh_type != SHT_NOBITS) { 4467c478bd9Sstevel@tonic-gate /* LINTED */ 4477c478bd9Sstevel@tonic-gate edata_ndx = elf_ndxscn(osp->os_scn); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate if (start_set == 0) { 4527c478bd9Sstevel@tonic-gate start = sgp->sg_phdr.p_vaddr; 4537c478bd9Sstevel@tonic-gate /* LINTED */ 4547c478bd9Sstevel@tonic-gate start_ndx = elf_ndxscn(osp->os_scn); 4557c478bd9Sstevel@tonic-gate start_set++; 4567c478bd9Sstevel@tonic-gate } 457c1c6f601Srie 458c1c6f601Srie /* 459c1c6f601Srie * While we're here, determine whether a .init or .fini 460c1c6f601Srie * section exist. 461c1c6f601Srie */ 46257ef7aa9SRod Evans if ((iosp == NULL) && (strcmp(osp->os_name, 463c1c6f601Srie MSG_ORIG(MSG_SCN_INIT)) == 0)) 464c1c6f601Srie iosp = osp; 46557ef7aa9SRod Evans if ((fosp == NULL) && (strcmp(osp->os_name, 466c1c6f601Srie MSG_ORIG(MSG_SCN_FINI)) == 0)) 467c1c6f601Srie fosp = osp; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate /* 4727c478bd9Sstevel@tonic-gate * Add local register symbols to the .dynsym. These are required as 4737c478bd9Sstevel@tonic-gate * DT_REGISTER .dynamic entries must have a symbol to reference. 4747c478bd9Sstevel@tonic-gate */ 4757c478bd9Sstevel@tonic-gate if (ofl->ofl_regsyms && dynsym) { 4767c478bd9Sstevel@tonic-gate int ndx; 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) { 4797c478bd9Sstevel@tonic-gate Sym_desc *rsdp; 4807c478bd9Sstevel@tonic-gate 48157ef7aa9SRod Evans if ((rsdp = ofl->ofl_regsyms[ndx]) == NULL) 4827c478bd9Sstevel@tonic-gate continue; 4837c478bd9Sstevel@tonic-gate 48408278a5eSRod Evans if (!SYM_IS_HIDDEN(rsdp) && 4857c478bd9Sstevel@tonic-gate (ELF_ST_BIND(rsdp->sd_sym->st_info) != STB_LOCAL)) 4867c478bd9Sstevel@tonic-gate continue; 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx] = *(rsdp->sd_sym); 4897c478bd9Sstevel@tonic-gate rsdp->sd_symndx = *symndx; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate if (dynsym[dynsym_ndx].st_name) { 4927c478bd9Sstevel@tonic-gate (void) st_setstring(dynstr, rsdp->sd_name, 4937c478bd9Sstevel@tonic-gate &stoff); 4947c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx].st_name = stoff; 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate dynsym_ndx++; 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* 5017c478bd9Sstevel@tonic-gate * Having traversed all the output segments, warn the user if the 5027c478bd9Sstevel@tonic-gate * traditional text or data segments don't exist. Otherwise from these 5037c478bd9Sstevel@tonic-gate * segments establish the values for `etext', `edata', `end', `END', 5047c478bd9Sstevel@tonic-gate * and `START'. 5057c478bd9Sstevel@tonic-gate */ 5067c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ)) { 5077c478bd9Sstevel@tonic-gate Sg_desc *sgp; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate if (tsgp) 5107c478bd9Sstevel@tonic-gate etext = tsgp->sg_phdr.p_vaddr + tsgp->sg_phdr.p_filesz; 5117c478bd9Sstevel@tonic-gate else { 5127c478bd9Sstevel@tonic-gate etext = (Addr)0; 5137c478bd9Sstevel@tonic-gate etext_ndx = SHN_ABS; 5147c478bd9Sstevel@tonic-gate etext_abs = 1; 5151d9df23bSab196087 if (flags & FLG_OF_VERBOSE) 516*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 5177c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_NOREADSEG)); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate if (dsgp) { 5207c478bd9Sstevel@tonic-gate edata = dsgp->sg_phdr.p_vaddr + dsgp->sg_phdr.p_filesz; 5217c478bd9Sstevel@tonic-gate } else { 5227c478bd9Sstevel@tonic-gate edata = (Addr)0; 5237c478bd9Sstevel@tonic-gate edata_ndx = SHN_ABS; 5247c478bd9Sstevel@tonic-gate edata_abs = 1; 5251d9df23bSab196087 if (flags & FLG_OF_VERBOSE) 526*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 5277c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_NORDWRSEG)); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 53057ef7aa9SRod Evans if (dsgp == NULL) { 5317c478bd9Sstevel@tonic-gate if (tsgp) 5327c478bd9Sstevel@tonic-gate sgp = tsgp; 5337c478bd9Sstevel@tonic-gate else 5347c478bd9Sstevel@tonic-gate sgp = 0; 53557ef7aa9SRod Evans } else if (tsgp == NULL) 5367c478bd9Sstevel@tonic-gate sgp = dsgp; 5377c478bd9Sstevel@tonic-gate else if (dsgp->sg_phdr.p_vaddr > tsgp->sg_phdr.p_vaddr) 5387c478bd9Sstevel@tonic-gate sgp = dsgp; 5397c478bd9Sstevel@tonic-gate else if (dsgp->sg_phdr.p_vaddr < tsgp->sg_phdr.p_vaddr) 5407c478bd9Sstevel@tonic-gate sgp = tsgp; 5417c478bd9Sstevel@tonic-gate else { 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * One of the segments must be of zero size. 5447c478bd9Sstevel@tonic-gate */ 5457c478bd9Sstevel@tonic-gate if (tsgp->sg_phdr.p_memsz) 5467c478bd9Sstevel@tonic-gate sgp = tsgp; 5477c478bd9Sstevel@tonic-gate else 5487c478bd9Sstevel@tonic-gate sgp = dsgp; 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if (esgp && (esgp->sg_phdr.p_vaddr > sgp->sg_phdr.p_vaddr)) 5527c478bd9Sstevel@tonic-gate sgp = esgp; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate if (sgp) { 5557c478bd9Sstevel@tonic-gate end = sgp->sg_phdr.p_vaddr + sgp->sg_phdr.p_memsz; 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate /* 558fdf855a7Sseizo * If the last loadable segment is a read-only segment, 559fdf855a7Sseizo * then the application which uses the symbol _end to 560fdf855a7Sseizo * find the beginning of writable heap area may cause 561fdf855a7Sseizo * segmentation violation. We adjust the value of the 562fdf855a7Sseizo * _end to skip to the next page boundary. 563fdf855a7Sseizo * 564fdf855a7Sseizo * 6401812 System interface which returs beginning 565fdf855a7Sseizo * heap would be nice. 566fdf855a7Sseizo * When the above RFE is implemented, the changes below 567fdf855a7Sseizo * could be changed in a better way. 568fdf855a7Sseizo */ 569fdf855a7Sseizo if ((sgp->sg_phdr.p_flags & PF_W) == 0) 57060758829Srie end = (Addr)S_ROUND(end, sysconf(_SC_PAGESIZE)); 571fdf855a7Sseizo 572fdf855a7Sseizo /* 5737c478bd9Sstevel@tonic-gate * If we're dealing with a memory reservation there are 5747c478bd9Sstevel@tonic-gate * no sections to establish an index for _end, so assign 5757c478bd9Sstevel@tonic-gate * it as an absolute. 5767c478bd9Sstevel@tonic-gate */ 5770bc07c75Srie if (sgp->sg_osdescs != NULL) { 5780bc07c75Srie /* 5790bc07c75Srie * Determine the last section for this segment. 5800bc07c75Srie */ 581cce0e03bSab196087 Os_desc *osp = sgp->sg_osdescs->apl_data 582cce0e03bSab196087 [sgp->sg_osdescs->apl_nitems - 1]; 583cce0e03bSab196087 5847c478bd9Sstevel@tonic-gate /* LINTED */ 585cce0e03bSab196087 end_ndx = elf_ndxscn(osp->os_scn); 5867c478bd9Sstevel@tonic-gate } else { 5877c478bd9Sstevel@tonic-gate end_ndx = SHN_ABS; 5887c478bd9Sstevel@tonic-gate end_abs = 1; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate } else { 5917c478bd9Sstevel@tonic-gate end = (Addr) 0; 5927c478bd9Sstevel@tonic-gate end_ndx = SHN_ABS; 5937c478bd9Sstevel@tonic-gate end_abs = 1; 594*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_UPD_NOSEG)); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* 5997c478bd9Sstevel@tonic-gate * Initialize the scoped symbol table entry point. This is for all 6007c478bd9Sstevel@tonic-gate * the global symbols that have been scoped to locals and will be 6017c478bd9Sstevel@tonic-gate * filled in during global symbol processing so that we don't have 6027c478bd9Sstevel@tonic-gate * to traverse the globals symbol hash array more than once. 6037c478bd9Sstevel@tonic-gate */ 6047c478bd9Sstevel@tonic-gate if (symtab) { 605ca4eed8bSAli Bahrami scopesym_bndx = symtab_ndx; 606ca4eed8bSAli Bahrami scopesym_ndx = scopesym_bndx; 6077c478bd9Sstevel@tonic-gate symtab_ndx += ofl->ofl_scopecnt; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate /* 61135450702SAli Bahrami * If expanding partially expanded symbols under '-z nopartial', 61235450702SAli Bahrami * prepare to do that. 6137c478bd9Sstevel@tonic-gate */ 61435450702SAli Bahrami if (ofl->ofl_isparexpn) { 61535450702SAli Bahrami osp = ofl->ofl_isparexpn->is_osdesc; 616b26cc8daSAli Bahrami parexpnbase = parexpnaddr = (Addr)(osp->os_shdr->sh_addr + 61735450702SAli Bahrami ofl->ofl_isparexpn->is_indata->d_off); 6187c478bd9Sstevel@tonic-gate /* LINTED */ 61935450702SAli Bahrami parexpnndx = elf_ndxscn(osp->os_scn); 62057ef7aa9SRod Evans ofl->ofl_parexpnndx = osp->os_identndx; 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * If we are generating a .symtab collect all the local symbols, 6257c478bd9Sstevel@tonic-gate * assigning a new virtual address or displacement (value). 6267c478bd9Sstevel@tonic-gate */ 62757ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_objs, idx1, ifl)) { 628635216b6SRod Evans Xword lndx, local = ifl->ifl_locscnt; 62908278a5eSRod Evans Cap_desc *cdp = ifl->ifl_caps; 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate for (lndx = 1; lndx < local; lndx++) { 6327c478bd9Sstevel@tonic-gate Gotndx *gnp; 633d579eb63Sab196087 uchar_t type; 6347c478bd9Sstevel@tonic-gate Word *_symshndx; 6359039eeafSab196087 int enter_in_symtab, enter_in_ldynsym; 6369039eeafSab196087 int update_done; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate sdp = ifl->ifl_oldndx[lndx]; 6397c478bd9Sstevel@tonic-gate sym = sdp->sd_sym; 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate /* 6427c478bd9Sstevel@tonic-gate * Assign a got offset if necessary. 6437c478bd9Sstevel@tonic-gate */ 644ba2be530Sab196087 if ((ld_targ.t_mr.mr_assign_got != NULL) && 645ba2be530Sab196087 (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR) 6467c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 647ba2be530Sab196087 6485aefb655Srie if (DBG_ENABLED) { 64957ef7aa9SRod Evans Aliste idx2; 65057ef7aa9SRod Evans 65157ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_GOTndxs, 65257ef7aa9SRod Evans idx2, gnp)) { 653d326b23bSrie gottable->gt_sym = sdp; 654d840867fSab196087 gottable->gt_gndx.gn_gotndx = 655d840867fSab196087 gnp->gn_gotndx; 656d840867fSab196087 gottable->gt_gndx.gn_addend = 657d840867fSab196087 gnp->gn_addend; 658d326b23bSrie gottable++; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate if ((type = ELF_ST_TYPE(sym->st_info)) == STT_SECTION) 6637c478bd9Sstevel@tonic-gate continue; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * Ignore any symbols that have been marked as invalid 6677c478bd9Sstevel@tonic-gate * during input processing. Providing these aren't used 6687c478bd9Sstevel@tonic-gate * for relocation they'll just be dropped from the 6697c478bd9Sstevel@tonic-gate * output image. 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_INVALID) 6727c478bd9Sstevel@tonic-gate continue; 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * If the section that this symbol was associated 6767c478bd9Sstevel@tonic-gate * with has been discarded - then we discard 6777c478bd9Sstevel@tonic-gate * the local symbol along with it. 6787c478bd9Sstevel@tonic-gate */ 6797c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_ISDISC) 6807c478bd9Sstevel@tonic-gate continue; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate /* 683ca4eed8bSAli Bahrami * If this symbol is from a different file 684ca4eed8bSAli Bahrami * than the input descriptor we are processing, 685ca4eed8bSAli Bahrami * treat it as if it has FLG_SY_ISDISC set. 686ca4eed8bSAli Bahrami * This happens when sloppy_comdat_reloc() 687ca4eed8bSAli Bahrami * replaces a symbol to a discarded comdat section 688ca4eed8bSAli Bahrami * with an equivalent symbol from a different 689ca4eed8bSAli Bahrami * file. We only want to enter such a symbol 690ca4eed8bSAli Bahrami * once --- as part of the file that actually 691ca4eed8bSAli Bahrami * supplies it. 692ca4eed8bSAli Bahrami */ 693ca4eed8bSAli Bahrami if (ifl != sdp->sd_file) 694ca4eed8bSAli Bahrami continue; 695ca4eed8bSAli Bahrami 696ca4eed8bSAli Bahrami /* 6977c478bd9Sstevel@tonic-gate * Generate an output symbol to represent this input 6987c478bd9Sstevel@tonic-gate * symbol. Even if the symbol table is to be stripped 6997c478bd9Sstevel@tonic-gate * we still need to update any local symbols that are 7007c478bd9Sstevel@tonic-gate * used during relocation. 7017c478bd9Sstevel@tonic-gate */ 7029039eeafSab196087 enter_in_symtab = symtab && 70344bac77bSrie (!(ofl->ofl_flags & FLG_OF_REDLSYM) || 70457ef7aa9SRod Evans sdp->sd_move); 7059039eeafSab196087 enter_in_ldynsym = ldynsym && sdp->sd_name && 706d579eb63Sab196087 ldynsym_symtype[type] && 70744bac77bSrie !(ofl->ofl_flags & FLG_OF_REDLSYM); 70857ef7aa9SRod Evans _symshndx = NULL; 70957ef7aa9SRod Evans 7109039eeafSab196087 if (enter_in_symtab) { 7117c478bd9Sstevel@tonic-gate if (!dynsym) 7127c478bd9Sstevel@tonic-gate sdp->sd_symndx = *symndx; 7137c478bd9Sstevel@tonic-gate symtab[symtab_ndx] = *sym; 71408278a5eSRod Evans 7157c478bd9Sstevel@tonic-gate /* 7167c478bd9Sstevel@tonic-gate * Provided this isn't an unnamed register 7177c478bd9Sstevel@tonic-gate * symbol, update its name. 7187c478bd9Sstevel@tonic-gate */ 7197c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) || 7207c478bd9Sstevel@tonic-gate symtab[symtab_ndx].st_name) { 7217c478bd9Sstevel@tonic-gate (void) st_setstring(strtab, 7227c478bd9Sstevel@tonic-gate sdp->sd_name, &stoff); 7237c478bd9Sstevel@tonic-gate symtab[symtab_ndx].st_name = stoff; 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_CLEAN; 7267c478bd9Sstevel@tonic-gate if (symshndx) 7277c478bd9Sstevel@tonic-gate _symshndx = &symshndx[symtab_ndx]; 7287c478bd9Sstevel@tonic-gate sdp->sd_sym = sym = &symtab[symtab_ndx++]; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_SPECSEC) && 7319039eeafSab196087 (sym->st_shndx == SHN_ABS) && 7329039eeafSab196087 !enter_in_ldynsym) 7337c478bd9Sstevel@tonic-gate continue; 7349039eeafSab196087 } else if (enter_in_ldynsym) { 7359039eeafSab196087 /* 7369039eeafSab196087 * Not using symtab, but we do have ldynsym 7379039eeafSab196087 * available. 7389039eeafSab196087 */ 7399039eeafSab196087 ldynsym[ldynsym_ndx] = *sym; 7409039eeafSab196087 (void) st_setstring(dynstr, sdp->sd_name, 7419039eeafSab196087 &stoff); 7429039eeafSab196087 ldynsym[ldynsym_ndx].st_name = stoff; 7439039eeafSab196087 7449039eeafSab196087 sdp->sd_flags &= ~FLG_SY_CLEAN; 7459039eeafSab196087 if (ldynshndx) 7469039eeafSab196087 _symshndx = &ldynshndx[ldynsym_ndx]; 747d579eb63Sab196087 sdp->sd_sym = sym = &ldynsym[ldynsym_ndx]; 748d579eb63Sab196087 /* Add it to sort section if it qualifies */ 749d579eb63Sab196087 ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx); 750d579eb63Sab196087 ldynsym_ndx++; 7519039eeafSab196087 } else { /* Not using symtab or ldynsym */ 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * If this symbol requires modifying to provide 7547c478bd9Sstevel@tonic-gate * for a relocation or move table update, make 7557c478bd9Sstevel@tonic-gate * a copy of it. 7567c478bd9Sstevel@tonic-gate */ 7577c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags & FLG_SY_UPREQD) && 75857ef7aa9SRod Evans !(sdp->sd_move)) 7597c478bd9Sstevel@tonic-gate continue; 7607c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_SPECSEC) && 7617c478bd9Sstevel@tonic-gate (sym->st_shndx == SHN_ABS)) 7627c478bd9Sstevel@tonic-gate continue; 7637c478bd9Sstevel@tonic-gate 7645aefb655Srie if (ld_sym_copy(sdp) == S_ERROR) 7657c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 7667c478bd9Sstevel@tonic-gate sym = sdp->sd_sym; 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate /* 7707c478bd9Sstevel@tonic-gate * Update the symbols contents if necessary. 7717c478bd9Sstevel@tonic-gate */ 7729039eeafSab196087 update_done = 0; 7737c478bd9Sstevel@tonic-gate if (type == STT_FILE) { 7747c478bd9Sstevel@tonic-gate sdp->sd_shndx = sym->st_shndx = SHN_ABS; 7757c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 7769039eeafSab196087 update_done = 1; 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate /* 7807c478bd9Sstevel@tonic-gate * If we are expanding the locally bound partially 7817c478bd9Sstevel@tonic-gate * initialized symbols, then update the address here. 7827c478bd9Sstevel@tonic-gate */ 78335450702SAli Bahrami if (ofl->ofl_isparexpn && 7849039eeafSab196087 (sdp->sd_flags & FLG_SY_PAREXPN) && !update_done) { 78535450702SAli Bahrami sym->st_shndx = parexpnndx; 78635450702SAli Bahrami sdp->sd_isc = ofl->ofl_isparexpn; 78735450702SAli Bahrami sym->st_value = parexpnaddr; 78835450702SAli Bahrami parexpnaddr += sym->st_size; 789b26cc8daSAli Bahrami if ((flags & FLG_OF_RELOBJ) == 0) 790b26cc8daSAli Bahrami sym->st_value -= parexpnbase; 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate /* 7947c478bd9Sstevel@tonic-gate * If this isn't an UNDEF symbol (ie. an input section 7957c478bd9Sstevel@tonic-gate * is associated), update the symbols value and index. 7967c478bd9Sstevel@tonic-gate */ 79708278a5eSRod Evans if (((isc = sdp->sd_isc) != NULL) && !update_done) { 7987c478bd9Sstevel@tonic-gate Word sectndx; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate osp = isc->is_osdesc; 8017c478bd9Sstevel@tonic-gate /* LINTED */ 8027c478bd9Sstevel@tonic-gate sym->st_value += 8037c478bd9Sstevel@tonic-gate (Off)_elf_getxoff(isc->is_indata); 804635216b6SRod Evans if ((flags & FLG_OF_RELOBJ) == 0) { 8057c478bd9Sstevel@tonic-gate sym->st_value += osp->os_shdr->sh_addr; 8067c478bd9Sstevel@tonic-gate /* 8077c478bd9Sstevel@tonic-gate * TLS symbols are relative to 8087c478bd9Sstevel@tonic-gate * the TLS segment. 8097c478bd9Sstevel@tonic-gate */ 810d579eb63Sab196087 if ((type == STT_TLS) && 811d579eb63Sab196087 (ofl->ofl_tlsphdr)) { 8127c478bd9Sstevel@tonic-gate sym->st_value -= 8137c478bd9Sstevel@tonic-gate ofl->ofl_tlsphdr->p_vaddr; 8147c478bd9Sstevel@tonic-gate } 8159039eeafSab196087 } 8167c478bd9Sstevel@tonic-gate /* LINTED */ 8177c478bd9Sstevel@tonic-gate if ((sdp->sd_shndx = sectndx = 8187c478bd9Sstevel@tonic-gate elf_ndxscn(osp->os_scn)) >= SHN_LORESERVE) { 8197c478bd9Sstevel@tonic-gate if (_symshndx) { 8207c478bd9Sstevel@tonic-gate *_symshndx = sectndx; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_XINDEX; 8237c478bd9Sstevel@tonic-gate } else { 8247c478bd9Sstevel@tonic-gate /* LINTED */ 8257c478bd9Sstevel@tonic-gate sym->st_shndx = sectndx; 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate } 8289039eeafSab196087 8299039eeafSab196087 /* 8309039eeafSab196087 * If entering the symbol in both the symtab and the 8319039eeafSab196087 * ldynsym, then the one in symtab needs to be 8329039eeafSab196087 * copied to ldynsym. If it is only in the ldynsym, 8339039eeafSab196087 * then the code above already set it up and we have 8349039eeafSab196087 * nothing more to do here. 8359039eeafSab196087 */ 8369039eeafSab196087 if (enter_in_symtab && enter_in_ldynsym) { 8379039eeafSab196087 ldynsym[ldynsym_ndx] = *sym; 8389039eeafSab196087 (void) st_setstring(dynstr, sdp->sd_name, 8399039eeafSab196087 &stoff); 8409039eeafSab196087 ldynsym[ldynsym_ndx].st_name = stoff; 8419039eeafSab196087 8429039eeafSab196087 if (_symshndx && ldynshndx) 8439039eeafSab196087 ldynshndx[ldynsym_ndx] = *_symshndx; 8449039eeafSab196087 845d579eb63Sab196087 /* Add it to sort section if it qualifies */ 846d579eb63Sab196087 ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx); 847d579eb63Sab196087 8489039eeafSab196087 ldynsym_ndx++; 8499039eeafSab196087 } 8507c478bd9Sstevel@tonic-gate } 85108278a5eSRod Evans 85208278a5eSRod Evans /* 85308278a5eSRod Evans * If this input file has undergone object to symbol 85408278a5eSRod Evans * capabilities conversion, supply any new capabilities symbols. 85508278a5eSRod Evans * These symbols are copies of the original global symbols, and 85608278a5eSRod Evans * follow the existing local symbols that are supplied from this 85708278a5eSRod Evans * input file (which are identified with a preceding STT_FILE). 85808278a5eSRod Evans */ 85908278a5eSRod Evans if (symtab && cdp && cdp->ca_syms) { 86008278a5eSRod Evans Aliste idx2; 86108278a5eSRod Evans Cap_sym *csp; 86208278a5eSRod Evans 86308278a5eSRod Evans for (APLIST_TRAVERSE(cdp->ca_syms, idx2, csp)) { 86408278a5eSRod Evans Is_desc *isp; 86508278a5eSRod Evans 86608278a5eSRod Evans sdp = csp->cs_sdp; 86708278a5eSRod Evans sym = sdp->sd_sym; 86808278a5eSRod Evans 86908278a5eSRod Evans if ((isp = sdp->sd_isc) != NULL) { 87008278a5eSRod Evans Os_desc *osp = isp->is_osdesc; 87108278a5eSRod Evans 87208278a5eSRod Evans /* 87308278a5eSRod Evans * Update the symbols value. 87408278a5eSRod Evans */ 87508278a5eSRod Evans /* LINTED */ 87608278a5eSRod Evans sym->st_value += 87708278a5eSRod Evans (Off)_elf_getxoff(isp->is_indata); 87808278a5eSRod Evans if ((flags & FLG_OF_RELOBJ) == 0) 87908278a5eSRod Evans sym->st_value += 88008278a5eSRod Evans osp->os_shdr->sh_addr; 88108278a5eSRod Evans 88208278a5eSRod Evans /* 88308278a5eSRod Evans * Update the symbols section index. 88408278a5eSRod Evans */ 88508278a5eSRod Evans sdp->sd_shndx = sym->st_shndx = 88608278a5eSRod Evans elf_ndxscn(osp->os_scn); 8877c478bd9Sstevel@tonic-gate } 88808278a5eSRod Evans 88908278a5eSRod Evans symtab[symtab_ndx] = *sym; 89008278a5eSRod Evans (void) st_setstring(strtab, sdp->sd_name, 89108278a5eSRod Evans &stoff); 89208278a5eSRod Evans symtab[symtab_ndx].st_name = stoff; 89308278a5eSRod Evans sdp->sd_symndx = symtab_ndx++; 89408278a5eSRod Evans } 89508278a5eSRod Evans } 89608278a5eSRod Evans } 89708278a5eSRod Evans 898ca4eed8bSAli Bahrami symtab_gbl_bndx = symtab_ndx; /* .symtab index of 1st global entry */ 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate /* 9017c478bd9Sstevel@tonic-gate * Two special symbols are `_init' and `_fini'. If these are supplied 9027c478bd9Sstevel@tonic-gate * by crti.o then they are used to represent the total concatenation of 903c1c6f601Srie * the `.init' and `.fini' sections. 904c1c6f601Srie * 905635216b6SRod Evans * Determine whether any .init or .fini sections exist. If these 906635216b6SRod Evans * sections exist and a dynamic object is being built, but no `_init' 907635216b6SRod Evans * or `_fini' symbols are found, then the user is probably building 908635216b6SRod Evans * this object directly from ld(1) rather than using a compiler driver 909635216b6SRod Evans * that provides the symbols via crt's. 910c1c6f601Srie * 911c1c6f601Srie * If the .init or .fini section exist, and their associated symbols, 912c1c6f601Srie * determine the size of the sections and updated the symbols value 913c1c6f601Srie * accordingly. 9147c478bd9Sstevel@tonic-gate */ 9155aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U), SYM_NOHASH, 0, 9167c478bd9Sstevel@tonic-gate ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc && 917c1c6f601Srie (sdp->sd_isc->is_osdesc == iosp)) { 9185aefb655Srie if (ld_sym_copy(sdp) == S_ERROR) 9197c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 92060758829Srie sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size; 92160758829Srie 922c1c6f601Srie } else if (iosp && !(flags & FLG_OF_RELOBJ)) { 923*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT), 924c1c6f601Srie MSG_ORIG(MSG_SYM_INIT_U), MSG_ORIG(MSG_SCN_INIT)); 9257c478bd9Sstevel@tonic-gate } 926c1c6f601Srie 9275aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U), SYM_NOHASH, 0, 9287c478bd9Sstevel@tonic-gate ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc && 929c1c6f601Srie (sdp->sd_isc->is_osdesc == fosp)) { 9305aefb655Srie if (ld_sym_copy(sdp) == S_ERROR) 9317c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 93260758829Srie sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size; 93360758829Srie 934c1c6f601Srie } else if (fosp && !(flags & FLG_OF_RELOBJ)) { 935*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT), 936c1c6f601Srie MSG_ORIG(MSG_SYM_FINI_U), MSG_ORIG(MSG_SCN_FINI)); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * Assign .bss information for use with updating COMMON symbols. 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate if (ofl->ofl_isbss) { 94357ef7aa9SRod Evans isc = ofl->ofl_isbss; 94457ef7aa9SRod Evans osp = isc->is_osdesc; 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate bssaddr = osp->os_shdr->sh_addr + 94757ef7aa9SRod Evans (Off)_elf_getxoff(isc->is_indata); 9487c478bd9Sstevel@tonic-gate /* LINTED */ 9497c478bd9Sstevel@tonic-gate bssndx = elf_ndxscn(osp->os_scn); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 952ba2be530Sab196087 #if defined(_ELF64) 95354d82594Sseizo /* 954ba2be530Sab196087 * For amd64 target, assign .lbss information for use 955ba2be530Sab196087 * with updating LCOMMON symbols. 95654d82594Sseizo */ 957ba2be530Sab196087 if ((ld_targ.t_m.m_mach == EM_AMD64) && ofl->ofl_islbss) { 95854d82594Sseizo osp = ofl->ofl_islbss->is_osdesc; 95954d82594Sseizo 96054d82594Sseizo lbssaddr = osp->os_shdr->sh_addr + 96154d82594Sseizo (Off)_elf_getxoff(ofl->ofl_islbss->is_indata); 96254d82594Sseizo /* LINTED */ 96354d82594Sseizo lbssndx = elf_ndxscn(osp->os_scn); 96454d82594Sseizo } 96554d82594Sseizo #endif 9667c478bd9Sstevel@tonic-gate /* 9677c478bd9Sstevel@tonic-gate * Assign .tlsbss information for use with updating COMMON symbols. 9687c478bd9Sstevel@tonic-gate */ 9697c478bd9Sstevel@tonic-gate if (ofl->ofl_istlsbss) { 9707c478bd9Sstevel@tonic-gate osp = ofl->ofl_istlsbss->is_osdesc; 9717c478bd9Sstevel@tonic-gate tlsbssaddr = osp->os_shdr->sh_addr + 9727c478bd9Sstevel@tonic-gate (Off)_elf_getxoff(ofl->ofl_istlsbss->is_indata); 9737c478bd9Sstevel@tonic-gate /* LINTED */ 9747c478bd9Sstevel@tonic-gate tlsbssndx = elf_ndxscn(osp->os_scn); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate if ((sorted_syms = libld_calloc(ofl->ofl_globcnt + 97857ef7aa9SRod Evans ofl->ofl_elimcnt + ofl->ofl_scopecnt, 97957ef7aa9SRod Evans sizeof (*sorted_syms))) == NULL) 9807c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate scndx = 0; 9837c478bd9Sstevel@tonic-gate ssndx = ofl->ofl_scopecnt + ofl->ofl_elimcnt; 9847c478bd9Sstevel@tonic-gate 985635216b6SRod Evans DBG_CALL(Dbg_syms_up_title(ofl->ofl_lml)); 986635216b6SRod Evans 9877c478bd9Sstevel@tonic-gate /* 98828bda19cSRod Evans * Traverse the internal symbol table updating global symbol information 98928bda19cSRod Evans * and allocating common. 9907c478bd9Sstevel@tonic-gate */ 9917c478bd9Sstevel@tonic-gate for (sav = avl_first(&ofl->ofl_symavl); sav; 9927c478bd9Sstevel@tonic-gate sav = AVL_NEXT(&ofl->ofl_symavl, sav)) { 9937c478bd9Sstevel@tonic-gate Sym *symptr; 9947c478bd9Sstevel@tonic-gate int local; 99554d82594Sseizo int restore; 9967c478bd9Sstevel@tonic-gate 997635216b6SRod Evans sdp = sav->sav_sdp; 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* 100060758829Srie * Ignore any symbols that have been marked as invalid during 100160758829Srie * input processing. Providing these aren't used for 100260758829Srie * relocation, they will be dropped from the output image. 10037c478bd9Sstevel@tonic-gate */ 10047c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_INVALID) { 10055aefb655Srie DBG_CALL(Dbg_syms_old(ofl, sdp)); 10065aefb655Srie DBG_CALL(Dbg_syms_ignore(ofl, sdp)); 10077c478bd9Sstevel@tonic-gate continue; 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate /* 101160758829Srie * Only needed symbols are copied to the output symbol table. 10127c478bd9Sstevel@tonic-gate */ 10137c478bd9Sstevel@tonic-gate if (sdp->sd_ref == REF_DYN_SEEN) 10147c478bd9Sstevel@tonic-gate continue; 10157c478bd9Sstevel@tonic-gate 101608278a5eSRod Evans if (SYM_IS_HIDDEN(sdp) && (flags & FLG_OF_PROCRED)) 10177c478bd9Sstevel@tonic-gate local = 1; 10187c478bd9Sstevel@tonic-gate else 10197c478bd9Sstevel@tonic-gate local = 0; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate if (local || (ofl->ofl_hashbkts == 0)) { 10227c478bd9Sstevel@tonic-gate sorted_syms[scndx++].sl_sdp = sdp; 10237c478bd9Sstevel@tonic-gate } else { 10247c478bd9Sstevel@tonic-gate sorted_syms[ssndx].sl_hval = sdp->sd_aux->sa_hash % 10257c478bd9Sstevel@tonic-gate ofl->ofl_hashbkts; 10267c478bd9Sstevel@tonic-gate sorted_syms[ssndx].sl_sdp = sdp; 10277c478bd9Sstevel@tonic-gate ssndx++; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate /* 1031c1c6f601Srie * Note - expand the COMMON symbols here because an address 1032c1c6f601Srie * must be assigned to them in the same order that space was 1033c1c6f601Srie * calculated in sym_validate(). If this ordering isn't 1034c1c6f601Srie * followed differing alignment requirements can throw us all 1035c1c6f601Srie * out of whack. 10367c478bd9Sstevel@tonic-gate * 1037c1c6f601Srie * The expanded .bss global symbol is handled here as well. 10387c478bd9Sstevel@tonic-gate * 1039c1c6f601Srie * The actual adding entries into the symbol table still occurs 1040c1c6f601Srie * below in hashbucket order. 10417c478bd9Sstevel@tonic-gate */ 10427c478bd9Sstevel@tonic-gate symptr = sdp->sd_sym; 104354d82594Sseizo restore = 0; 10447c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_PAREXPN) || 10457c478bd9Sstevel@tonic-gate ((sdp->sd_flags & FLG_SY_SPECSEC) && 10467c478bd9Sstevel@tonic-gate (sdp->sd_shndx = symptr->st_shndx) == SHN_COMMON)) { 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate /* 104935450702SAli Bahrami * An expanded symbol goes to a special .data section 105035450702SAli Bahrami * prepared for that purpose (ofl->ofl_isparexpn). 1051c1c6f601Srie * Assign COMMON allocations to .bss. 10527c478bd9Sstevel@tonic-gate * Otherwise leave it as is. 10537c478bd9Sstevel@tonic-gate */ 10547c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_PAREXPN) { 10557c478bd9Sstevel@tonic-gate restore = 1; 105635450702SAli Bahrami sdp->sd_shndx = parexpnndx; 10577c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 10587c478bd9Sstevel@tonic-gate symptr->st_value = (Xword) S_ROUND( 105935450702SAli Bahrami parexpnaddr, symptr->st_value); 106035450702SAli Bahrami parexpnaddr = symptr->st_value + 10617c478bd9Sstevel@tonic-gate symptr->st_size; 106235450702SAli Bahrami sdp->sd_isc = ofl->ofl_isparexpn; 10637c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_COMMEXP; 1064c1c6f601Srie 10657c478bd9Sstevel@tonic-gate } else if (ELF_ST_TYPE(symptr->st_info) != STT_TLS && 10667c478bd9Sstevel@tonic-gate (local || !(flags & FLG_OF_RELOBJ))) { 10677c478bd9Sstevel@tonic-gate restore = 1; 10687c478bd9Sstevel@tonic-gate sdp->sd_shndx = bssndx; 10697c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 10707c478bd9Sstevel@tonic-gate symptr->st_value = (Xword)S_ROUND(bssaddr, 10717c478bd9Sstevel@tonic-gate symptr->st_value); 10727c478bd9Sstevel@tonic-gate bssaddr = symptr->st_value + symptr->st_size; 10737c478bd9Sstevel@tonic-gate sdp->sd_isc = ofl->ofl_isbss; 10747c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_COMMEXP; 1075c1c6f601Srie 10767c478bd9Sstevel@tonic-gate } else if (ELF_ST_TYPE(symptr->st_info) == STT_TLS && 10777c478bd9Sstevel@tonic-gate (local || !(flags & FLG_OF_RELOBJ))) { 10787c478bd9Sstevel@tonic-gate restore = 1; 10797c478bd9Sstevel@tonic-gate sdp->sd_shndx = tlsbssndx; 10807c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 10817c478bd9Sstevel@tonic-gate symptr->st_value = (Xword)S_ROUND(tlsbssaddr, 10827c478bd9Sstevel@tonic-gate symptr->st_value); 10837c478bd9Sstevel@tonic-gate tlsbssaddr = symptr->st_value + symptr->st_size; 10847c478bd9Sstevel@tonic-gate sdp->sd_isc = ofl->ofl_istlsbss; 10857c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_COMMEXP; 10867c478bd9Sstevel@tonic-gate /* 1087dd94ecefSrie * TLS symbols are relative to the TLS segment. 10887c478bd9Sstevel@tonic-gate */ 10897c478bd9Sstevel@tonic-gate symptr->st_value -= ofl->ofl_tlsphdr->p_vaddr; 10907c478bd9Sstevel@tonic-gate } 1091ba2be530Sab196087 #if defined(_ELF64) 1092ba2be530Sab196087 } else if ((ld_targ.t_m.m_mach == EM_AMD64) && 1093ba2be530Sab196087 (sdp->sd_flags & FLG_SY_SPECSEC) && 109454d82594Sseizo ((sdp->sd_shndx = symptr->st_shndx) == 109554d82594Sseizo SHN_X86_64_LCOMMON) && 109654d82594Sseizo ((local || !(flags & FLG_OF_RELOBJ)))) { 109754d82594Sseizo restore = 1; 109854d82594Sseizo sdp->sd_shndx = lbssndx; 109954d82594Sseizo sdp->sd_flags &= ~FLG_SY_SPECSEC; 110054d82594Sseizo symptr->st_value = (Xword)S_ROUND(lbssaddr, 110154d82594Sseizo symptr->st_value); 110254d82594Sseizo lbssaddr = symptr->st_value + symptr->st_size; 110354d82594Sseizo sdp->sd_isc = ofl->ofl_islbss; 110454d82594Sseizo sdp->sd_flags |= FLG_SY_COMMEXP; 110554d82594Sseizo #endif 110654d82594Sseizo } 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate if (restore != 0) { 1109d579eb63Sab196087 uchar_t type, bind; 1110c1c6f601Srie 11117c478bd9Sstevel@tonic-gate /* 1112c1c6f601Srie * Make sure this COMMON symbol is returned to the same 1113c1c6f601Srie * binding as was defined in the original relocatable 11147c478bd9Sstevel@tonic-gate * object reference. 11157c478bd9Sstevel@tonic-gate */ 11167c478bd9Sstevel@tonic-gate type = ELF_ST_TYPE(symptr->st_info); 11177c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_GLOBREF) 11187c478bd9Sstevel@tonic-gate bind = STB_GLOBAL; 11197c478bd9Sstevel@tonic-gate else 11207c478bd9Sstevel@tonic-gate bind = STB_WEAK; 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate symptr->st_info = ELF_ST_INFO(bind, type); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate 112608278a5eSRod Evans /* 112708278a5eSRod Evans * If this is a dynamic object then add any local capabilities symbols. 112808278a5eSRod Evans */ 112908278a5eSRod Evans if (dynsym && ofl->ofl_capfamilies) { 113008278a5eSRod Evans Cap_avlnode *cav; 113108278a5eSRod Evans 113208278a5eSRod Evans for (cav = avl_first(ofl->ofl_capfamilies); cav; 113308278a5eSRod Evans cav = AVL_NEXT(ofl->ofl_capfamilies, cav)) { 113408278a5eSRod Evans Cap_sym *csp; 113508278a5eSRod Evans Aliste idx; 113608278a5eSRod Evans 113708278a5eSRod Evans for (APLIST_TRAVERSE(cav->cn_members, idx, csp)) { 113808278a5eSRod Evans sdp = csp->cs_sdp; 113908278a5eSRod Evans 114008278a5eSRod Evans DBG_CALL(Dbg_syms_created(ofl->ofl_lml, 114108278a5eSRod Evans sdp->sd_name)); 114208278a5eSRod Evans DBG_CALL(Dbg_syms_entered(ofl, sdp->sd_sym, 114308278a5eSRod Evans sdp)); 114408278a5eSRod Evans 114508278a5eSRod Evans dynsym[dynsym_ndx] = *sdp->sd_sym; 114608278a5eSRod Evans 114708278a5eSRod Evans (void) st_setstring(dynstr, sdp->sd_name, 114808278a5eSRod Evans &stoff); 114908278a5eSRod Evans dynsym[dynsym_ndx].st_name = stoff; 115008278a5eSRod Evans 115108278a5eSRod Evans sdp->sd_sym = &dynsym[dynsym_ndx]; 115208278a5eSRod Evans sdp->sd_symndx = dynsym_ndx; 115308278a5eSRod Evans 115408278a5eSRod Evans /* 115508278a5eSRod Evans * Indicate that this is a capabilities symbol. 115608278a5eSRod Evans * Note, that this identification only provides 115708278a5eSRod Evans * information regarding the symbol that is 115808278a5eSRod Evans * visible from elfdump(1) -y. The association 115908278a5eSRod Evans * of a symbol to its capabilities is derived 116008278a5eSRod Evans * from a .SUNW_capinfo entry. 116108278a5eSRod Evans */ 116208278a5eSRod Evans if (syminfo) { 116308278a5eSRod Evans syminfo[dynsym_ndx].si_flags |= 116408278a5eSRod Evans SYMINFO_FLG_CAP; 116508278a5eSRod Evans } 116608278a5eSRod Evans 116708278a5eSRod Evans dynsym_ndx++; 116808278a5eSRod Evans } 116908278a5eSRod Evans } 117008278a5eSRod Evans } 117108278a5eSRod Evans 11727c478bd9Sstevel@tonic-gate if (ofl->ofl_hashbkts) { 11737c478bd9Sstevel@tonic-gate qsort(sorted_syms + ofl->ofl_scopecnt + ofl->ofl_elimcnt, 11747c478bd9Sstevel@tonic-gate ofl->ofl_globcnt, sizeof (Sym_s_list), 11757c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))sym_hash_compare); 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate 11787c478bd9Sstevel@tonic-gate for (ssndx = 0; ssndx < (ofl->ofl_elimcnt + ofl->ofl_scopecnt + 11797c478bd9Sstevel@tonic-gate ofl->ofl_globcnt); ssndx++) { 11807c478bd9Sstevel@tonic-gate const char *name; 11817c478bd9Sstevel@tonic-gate Sym *sym; 11827c478bd9Sstevel@tonic-gate Sym_aux *sap; 11837c478bd9Sstevel@tonic-gate Half spec; 11849039eeafSab196087 int local = 0, dynlocal = 0, enter_in_symtab; 11857c478bd9Sstevel@tonic-gate Gotndx *gnp; 11867c478bd9Sstevel@tonic-gate Word sectndx; 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate sdp = sorted_syms[ssndx].sl_sdp; 11897c478bd9Sstevel@tonic-gate sectndx = 0; 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate if (symtab) 11927c478bd9Sstevel@tonic-gate enter_in_symtab = 1; 11937c478bd9Sstevel@tonic-gate else 11947c478bd9Sstevel@tonic-gate enter_in_symtab = 0; 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate /* 11977c478bd9Sstevel@tonic-gate * Assign a got offset if necessary. 11987c478bd9Sstevel@tonic-gate */ 1199ba2be530Sab196087 if ((ld_targ.t_mr.mr_assign_got != NULL) && 1200ba2be530Sab196087 (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR) 12017c478bd9Sstevel@tonic-gate return ((Addr)S_ERROR); 1202c1c6f601Srie 12035aefb655Srie if (DBG_ENABLED) { 120457ef7aa9SRod Evans Aliste idx2; 120557ef7aa9SRod Evans 120657ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_GOTndxs, idx2, gnp)) { 1207d326b23bSrie gottable->gt_sym = sdp; 1208d326b23bSrie gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx; 1209d326b23bSrie gottable->gt_gndx.gn_addend = gnp->gn_addend; 1210d326b23bSrie gottable++; 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate if (sdp->sd_aux && sdp->sd_aux->sa_PLTGOTndx) { 1214d326b23bSrie gottable->gt_sym = sdp; 1215d326b23bSrie gottable->gt_gndx.gn_gotndx = 12167c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_PLTGOTndx; 1217d326b23bSrie gottable++; 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * If this symbol has been marked as being reduced to local 12237c478bd9Sstevel@tonic-gate * scope then it will have to be placed in the scoped portion 12247c478bd9Sstevel@tonic-gate * of the .symtab. Retain the appropriate index for use in 12257c478bd9Sstevel@tonic-gate * version symbol indexing and relocation. 12267c478bd9Sstevel@tonic-gate */ 122708278a5eSRod Evans if (SYM_IS_HIDDEN(sdp) && (flags & FLG_OF_PROCRED)) { 12287c478bd9Sstevel@tonic-gate local = 1; 1229635216b6SRod Evans if (!(sdp->sd_flags & FLG_SY_ELIM) && !dynsym) 12307c478bd9Sstevel@tonic-gate sdp->sd_symndx = scopesym_ndx; 12317c478bd9Sstevel@tonic-gate else 12327c478bd9Sstevel@tonic-gate sdp->sd_symndx = 0; 12337c478bd9Sstevel@tonic-gate 1234635216b6SRod Evans if (sdp->sd_flags & FLG_SY_ELIM) { 12357c478bd9Sstevel@tonic-gate enter_in_symtab = 0; 12369039eeafSab196087 } else if (ldynsym && sdp->sd_sym->st_name && 1237d579eb63Sab196087 ldynsym_symtype[ 1238d579eb63Sab196087 ELF_ST_TYPE(sdp->sd_sym->st_info)]) { 12399039eeafSab196087 dynlocal = 1; 12409039eeafSab196087 } 12419039eeafSab196087 } else { 12427c478bd9Sstevel@tonic-gate sdp->sd_symndx = *symndx; 12439039eeafSab196087 } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate /* 12467c478bd9Sstevel@tonic-gate * Copy basic symbol and string information. 12477c478bd9Sstevel@tonic-gate */ 12487c478bd9Sstevel@tonic-gate name = sdp->sd_name; 12497c478bd9Sstevel@tonic-gate sap = sdp->sd_aux; 12507c478bd9Sstevel@tonic-gate 12517c478bd9Sstevel@tonic-gate /* 12527c478bd9Sstevel@tonic-gate * If we require to record version symbol indexes, update the 12537c478bd9Sstevel@tonic-gate * associated version symbol information for all defined 12547c478bd9Sstevel@tonic-gate * symbols. If a version definition is required any zero value 12557c478bd9Sstevel@tonic-gate * symbol indexes would have been flagged as undefined symbol 12567c478bd9Sstevel@tonic-gate * errors, however if we're just scoping these need to fall into 12577c478bd9Sstevel@tonic-gate * the base of global symbols. 12587c478bd9Sstevel@tonic-gate */ 12597c478bd9Sstevel@tonic-gate if (sdp->sd_symndx && versym) { 12607c478bd9Sstevel@tonic-gate Half vndx = 0; 12617c478bd9Sstevel@tonic-gate 1262090a8d9eSAli Bahrami if (sdp->sd_flags & FLG_SY_MVTOCOMM) { 12637c478bd9Sstevel@tonic-gate vndx = VER_NDX_GLOBAL; 1264090a8d9eSAli Bahrami } else if (sdp->sd_ref == REF_REL_NEED) { 12657c478bd9Sstevel@tonic-gate vndx = sap->sa_overndx; 126608278a5eSRod Evans 12677c478bd9Sstevel@tonic-gate if ((vndx == 0) && 12687c478bd9Sstevel@tonic-gate (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 126908278a5eSRod Evans if (SYM_IS_HIDDEN(sdp)) 12707c478bd9Sstevel@tonic-gate vndx = VER_NDX_LOCAL; 12717c478bd9Sstevel@tonic-gate else 12727c478bd9Sstevel@tonic-gate vndx = VER_NDX_GLOBAL; 12737c478bd9Sstevel@tonic-gate } 1274090a8d9eSAli Bahrami } else if ((sdp->sd_ref == REF_DYN_NEED) && 1275090a8d9eSAli Bahrami (sap->sa_dverndx > 0) && 1276090a8d9eSAli Bahrami (sap->sa_dverndx <= sdp->sd_file->ifl_vercnt) && 1277090a8d9eSAli Bahrami (sdp->sd_file->ifl_verndx != NULL)) { 1278090a8d9eSAli Bahrami /* Use index of verneed record */ 1279090a8d9eSAli Bahrami vndx = sdp->sd_file->ifl_verndx 1280090a8d9eSAli Bahrami [sap->sa_dverndx].vi_overndx; 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate versym[sdp->sd_symndx] = vndx; 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate /* 12867c478bd9Sstevel@tonic-gate * If we are creating the .syminfo section then set per symbol 12877c478bd9Sstevel@tonic-gate * flags here. 12887c478bd9Sstevel@tonic-gate */ 12897c478bd9Sstevel@tonic-gate if (sdp->sd_symndx && syminfo && 12907c478bd9Sstevel@tonic-gate !(sdp->sd_flags & FLG_SY_NOTAVAIL)) { 12917c478bd9Sstevel@tonic-gate int ndx = sdp->sd_symndx; 1292635216b6SRod Evans APlist **alpp = &(ofl->ofl_symdtent); 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_MVTOCOMM) 12957c478bd9Sstevel@tonic-gate /* 12967c478bd9Sstevel@tonic-gate * Identify a copy relocation symbol. 12977c478bd9Sstevel@tonic-gate */ 12987c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_COPY; 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate if (sdp->sd_ref == REF_DYN_NEED) { 13017c478bd9Sstevel@tonic-gate /* 13027c478bd9Sstevel@tonic-gate * A reference is bound to a needed dependency. 130328bda19cSRod Evans * Save the syminfo entry, so that when the 130428bda19cSRod Evans * .dynamic section has been updated, a 130528bda19cSRod Evans * DT_NEEDED entry can be associated 130628bda19cSRod Evans * (see update_osyminfo()). 13077c478bd9Sstevel@tonic-gate */ 130857ef7aa9SRod Evans if (aplist_append(alpp, sdp, 130957ef7aa9SRod Evans AL_CNT_OFL_SYMINFOSYMS) == NULL) 13107c478bd9Sstevel@tonic-gate return (0); 13117c478bd9Sstevel@tonic-gate 131228bda19cSRod Evans /* 131328bda19cSRod Evans * Flag that the symbol has a direct association 131428bda19cSRod Evans * with the external reference (this is an old 131528bda19cSRod Evans * tagging, that has no real effect by itself). 131628bda19cSRod Evans */ 13177c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT; 1318f441771bSRod Evans 1319f441771bSRod Evans /* 1320f441771bSRod Evans * Flag any lazy or deferred reference. 1321f441771bSRod Evans */ 13227c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_LAZYLD) 13237c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 13247c478bd9Sstevel@tonic-gate SYMINFO_FLG_LAZYLOAD; 1325f441771bSRod Evans if (sdp->sd_flags & FLG_SY_DEFERRED) 1326f441771bSRod Evans syminfo[ndx].si_flags |= 1327f441771bSRod Evans SYMINFO_FLG_DEFERRED; 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate /* 13307c478bd9Sstevel@tonic-gate * Enable direct symbol bindings if: 13317c478bd9Sstevel@tonic-gate * 133257ef7aa9SRod Evans * - Symbol was identified with the DIRECT 13337c478bd9Sstevel@tonic-gate * keyword in a mapfile. 13347c478bd9Sstevel@tonic-gate * 133557ef7aa9SRod Evans * - Symbol reference has been bound to a 13367c478bd9Sstevel@tonic-gate * dependency which was specified as 13377c478bd9Sstevel@tonic-gate * requiring direct bindings with -zdirect. 13387c478bd9Sstevel@tonic-gate * 133957ef7aa9SRod Evans * - All symbol references are required to 13407c478bd9Sstevel@tonic-gate * use direct bindings via -Bdirect. 13417c478bd9Sstevel@tonic-gate */ 1342635216b6SRod Evans if (sdp->sd_flags & FLG_SY_DIR) 13437c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 13447c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECTBIND; 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate } else if ((sdp->sd_flags & FLG_SY_EXTERN) && 13477c478bd9Sstevel@tonic-gate (sdp->sd_sym->st_shndx == SHN_UNDEF)) { 13487c478bd9Sstevel@tonic-gate /* 13497c478bd9Sstevel@tonic-gate * If this symbol has been explicitly defined 13507c478bd9Sstevel@tonic-gate * as external, and remains unresolved, mark 13517c478bd9Sstevel@tonic-gate * it as external. 13527c478bd9Sstevel@tonic-gate */ 13537c478bd9Sstevel@tonic-gate syminfo[ndx].si_boundto = SYMINFO_BT_EXTERN; 13547c478bd9Sstevel@tonic-gate 13559a411307Srie } else if ((sdp->sd_flags & FLG_SY_PARENT) && 13569a411307Srie (sdp->sd_sym->st_shndx == SHN_UNDEF)) { 13577c478bd9Sstevel@tonic-gate /* 13589a411307Srie * If this symbol has been explicitly defined 13599a411307Srie * to be a reference to a parent object, 13609a411307Srie * indicate whether a direct binding should be 13617c478bd9Sstevel@tonic-gate * established. 13627c478bd9Sstevel@tonic-gate */ 13637c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT; 13647c478bd9Sstevel@tonic-gate syminfo[ndx].si_boundto = SYMINFO_BT_PARENT; 1365635216b6SRod Evans if (sdp->sd_flags & FLG_SY_DIR) 13667c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 13677c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECTBIND; 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate } else if (sdp->sd_flags & FLG_SY_STDFLTR) { 13707c478bd9Sstevel@tonic-gate /* 13717c478bd9Sstevel@tonic-gate * A filter definition. Although this symbol 13727c478bd9Sstevel@tonic-gate * can only be a stub, it might be necessary to 13737c478bd9Sstevel@tonic-gate * prevent external direct bindings. 13747c478bd9Sstevel@tonic-gate */ 13757c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_FILTER; 1376635216b6SRod Evans if (sdp->sd_flags & FLG_SY_NDIR) 13777c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 13787c478bd9Sstevel@tonic-gate SYMINFO_FLG_NOEXTDIRECT; 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate } else if (sdp->sd_flags & FLG_SY_AUXFLTR) { 13817c478bd9Sstevel@tonic-gate /* 13827c478bd9Sstevel@tonic-gate * An auxiliary filter definition. By nature, 13837c478bd9Sstevel@tonic-gate * this definition is direct, in that should the 13847c478bd9Sstevel@tonic-gate * filtee lookup fail, we'll fall back to this 138508278a5eSRod Evans * object. It may still be necessary to 13867c478bd9Sstevel@tonic-gate * prevent external direct bindings. 13877c478bd9Sstevel@tonic-gate */ 13887c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= SYMINFO_FLG_AUXILIARY; 1389635216b6SRod Evans if (sdp->sd_flags & FLG_SY_NDIR) 13907c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 13917c478bd9Sstevel@tonic-gate SYMINFO_FLG_NOEXTDIRECT; 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate } else if ((sdp->sd_ref == REF_REL_NEED) && 13947c478bd9Sstevel@tonic-gate (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 13957c478bd9Sstevel@tonic-gate /* 13967c478bd9Sstevel@tonic-gate * This definition exists within the object 1397635216b6SRod Evans * being created. Provide a default boundto 1398635216b6SRod Evans * definition, which may be overridden later. 13997c478bd9Sstevel@tonic-gate */ 1400635216b6SRod Evans syminfo[ndx].si_boundto = SYMINFO_BT_NONE; 1401635216b6SRod Evans 1402635216b6SRod Evans /* 1403635216b6SRod Evans * Indicate whether it is necessary to prevent 1404635216b6SRod Evans * external direct bindings. 1405635216b6SRod Evans */ 1406635216b6SRod Evans if (sdp->sd_flags & FLG_SY_NDIR) { 14077c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14087c478bd9Sstevel@tonic-gate SYMINFO_FLG_NOEXTDIRECT; 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate /* 14129a411307Srie * Indicate that this symbol is acting as an 14139a411307Srie * individual interposer. 14149a411307Srie */ 14159a411307Srie if (sdp->sd_flags & FLG_SY_INTPOSE) { 14169a411307Srie syminfo[ndx].si_flags |= 14179a411307Srie SYMINFO_FLG_INTERPOSE; 14189a411307Srie } 14199a411307Srie 14209a411307Srie /* 1421f441771bSRod Evans * Indicate that this symbol is deferred, and 1422f441771bSRod Evans * hence should not be bound to during BIND_NOW 1423f441771bSRod Evans * relocations. 1424f441771bSRod Evans */ 1425f441771bSRod Evans if (sdp->sd_flags & FLG_SY_DEFERRED) { 1426f441771bSRod Evans syminfo[ndx].si_flags |= 1427f441771bSRod Evans SYMINFO_FLG_DEFERRED; 1428f441771bSRod Evans } 1429f441771bSRod Evans 1430f441771bSRod Evans /* 1431635216b6SRod Evans * If external bindings are allowed, indicate 1432635216b6SRod Evans * the binding, and a direct binding if 1433635216b6SRod Evans * necessary. 14347c478bd9Sstevel@tonic-gate */ 1435635216b6SRod Evans if ((sdp->sd_flags & FLG_SY_NDIR) == 0) { 14367c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14377c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECT; 14387c478bd9Sstevel@tonic-gate 1439635216b6SRod Evans if (sdp->sd_flags & FLG_SY_DIR) 14407c478bd9Sstevel@tonic-gate syminfo[ndx].si_flags |= 14417c478bd9Sstevel@tonic-gate SYMINFO_FLG_DIRECTBIND; 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate /* 1444635216b6SRod Evans * Provide a default boundto definition, 1445635216b6SRod Evans * which may be overridden later. 14467c478bd9Sstevel@tonic-gate */ 14477c478bd9Sstevel@tonic-gate syminfo[ndx].si_boundto = 14487c478bd9Sstevel@tonic-gate SYMINFO_BT_SELF; 14497c478bd9Sstevel@tonic-gate } 145008278a5eSRod Evans 145108278a5eSRod Evans /* 145208278a5eSRod Evans * Indicate that this is a capabilities symbol. 145308278a5eSRod Evans * Note, that this identification only provides 145408278a5eSRod Evans * information regarding the symbol that is 145508278a5eSRod Evans * visible from elfdump(1) -y. The association 145608278a5eSRod Evans * of a symbol to its capabilities is derived 145708278a5eSRod Evans * from a .SUNW_capinfo entry. 145808278a5eSRod Evans */ 145908278a5eSRod Evans if ((sdp->sd_flags & FLG_SY_CAP) && 146008278a5eSRod Evans ofl->ofl_oscapinfo) { 146108278a5eSRod Evans syminfo[ndx].si_flags |= 146208278a5eSRod Evans SYMINFO_FLG_CAP; 146308278a5eSRod Evans } 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate /* 14687c478bd9Sstevel@tonic-gate * Note that the `sym' value is reset to be one of the new 14697c478bd9Sstevel@tonic-gate * symbol table entries. This symbol will be updated further 14707c478bd9Sstevel@tonic-gate * depending on the type of the symbol. Process the .symtab 14717c478bd9Sstevel@tonic-gate * first, followed by the .dynsym, thus the `sym' value will 14727c478bd9Sstevel@tonic-gate * remain as the .dynsym value when the .dynsym is present. 1473c1c6f601Srie * This ensures that any versioning symbols st_name value will 14749039eeafSab196087 * be appropriate for the string table used by version 14757c478bd9Sstevel@tonic-gate * entries. 14767c478bd9Sstevel@tonic-gate */ 14777c478bd9Sstevel@tonic-gate if (enter_in_symtab) { 14787c478bd9Sstevel@tonic-gate Word _symndx; 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate if (local) 14817c478bd9Sstevel@tonic-gate _symndx = scopesym_ndx; 14827c478bd9Sstevel@tonic-gate else 14837c478bd9Sstevel@tonic-gate _symndx = symtab_ndx; 14849039eeafSab196087 14857c478bd9Sstevel@tonic-gate symtab[_symndx] = *sdp->sd_sym; 14867c478bd9Sstevel@tonic-gate sdp->sd_sym = sym = &symtab[_symndx]; 14877c478bd9Sstevel@tonic-gate (void) st_setstring(strtab, name, &stoff); 14887c478bd9Sstevel@tonic-gate sym->st_name = stoff; 14897c478bd9Sstevel@tonic-gate } 14909039eeafSab196087 if (dynlocal) { 14919039eeafSab196087 ldynsym[ldynscopesym_ndx] = *sdp->sd_sym; 14929039eeafSab196087 sdp->sd_sym = sym = &ldynsym[ldynscopesym_ndx]; 14939039eeafSab196087 (void) st_setstring(dynstr, name, &stoff); 14949039eeafSab196087 ldynsym[ldynscopesym_ndx].st_name = stoff; 1495d579eb63Sab196087 /* Add it to sort section if it qualifies */ 1496d579eb63Sab196087 ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info), 1497d579eb63Sab196087 ldynscopesym_ndx); 14989039eeafSab196087 } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate if (dynsym && !local) { 15017c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx] = *sdp->sd_sym; 150260758829Srie 15037c478bd9Sstevel@tonic-gate /* 15047c478bd9Sstevel@tonic-gate * Provided this isn't an unnamed register symbol, 150560758829Srie * update the symbols name and hash value. 15067c478bd9Sstevel@tonic-gate */ 15077c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) || 15087c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx].st_name) { 15097c478bd9Sstevel@tonic-gate (void) st_setstring(dynstr, name, &stoff); 15107c478bd9Sstevel@tonic-gate dynsym[dynsym_ndx].st_name = stoff; 151160758829Srie 15127c478bd9Sstevel@tonic-gate if (stoff) { 151308278a5eSRod Evans Word hashval, _hashndx; 151460758829Srie 151560758829Srie hashval = 151660758829Srie sap->sa_hash % ofl->ofl_hashbkts; 151760758829Srie 15187c478bd9Sstevel@tonic-gate /* LINTED */ 15197c478bd9Sstevel@tonic-gate if (_hashndx = hashbkt[hashval]) { 152060758829Srie while (hashchain[_hashndx]) { 1521d840867fSab196087 _hashndx = 1522d840867fSab196087 hashchain[_hashndx]; 152360758829Srie } 1524d840867fSab196087 hashchain[_hashndx] = 1525d840867fSab196087 sdp->sd_symndx; 15269039eeafSab196087 } else { 1527d840867fSab196087 hashbkt[hashval] = 1528d840867fSab196087 sdp->sd_symndx; 15299039eeafSab196087 } 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate sdp->sd_sym = sym = &dynsym[dynsym_ndx]; 153360758829Srie 1534d579eb63Sab196087 /* 1535d579eb63Sab196087 * Add it to sort section if it qualifies. 1536d579eb63Sab196087 * The indexes in that section are relative to the 1537d579eb63Sab196087 * the adjacent SUNW_ldynsym/dymsym pair, so we 1538d579eb63Sab196087 * add the number of items in SUNW_ldynsym to the 1539d579eb63Sab196087 * dynsym index. 1540d579eb63Sab196087 */ 1541d579eb63Sab196087 ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info), 1542d579eb63Sab196087 ldynsym_cnt + dynsym_ndx); 15437c478bd9Sstevel@tonic-gate } 154408278a5eSRod Evans 15459039eeafSab196087 if (!enter_in_symtab && (!dynsym || (local && !dynlocal))) { 15467c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags & FLG_SY_UPREQD)) 15477c478bd9Sstevel@tonic-gate continue; 15487c478bd9Sstevel@tonic-gate sym = sdp->sd_sym; 15497c478bd9Sstevel@tonic-gate } else 15507c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_CLEAN; 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate /* 15537c478bd9Sstevel@tonic-gate * If we have a weak data symbol for which we need the real 15547c478bd9Sstevel@tonic-gate * symbol also, save this processing until later. 15557c478bd9Sstevel@tonic-gate * 15567c478bd9Sstevel@tonic-gate * The exception to this is if the weak/strong have PLT's 15577c478bd9Sstevel@tonic-gate * assigned to them. In that case we don't do the post-weak 15587c478bd9Sstevel@tonic-gate * processing because the PLT's must be maintained so that we 15597c478bd9Sstevel@tonic-gate * can do 'interpositioning' on both of the symbols. 15607c478bd9Sstevel@tonic-gate */ 15617c478bd9Sstevel@tonic-gate if ((sap->sa_linkndx) && 15627c478bd9Sstevel@tonic-gate (ELF_ST_BIND(sym->st_info) == STB_WEAK) && 15637c478bd9Sstevel@tonic-gate (!sap->sa_PLTndx)) { 156457ef7aa9SRod Evans Sym_desc *_sdp; 156557ef7aa9SRod Evans 156657ef7aa9SRod Evans _sdp = sdp->sd_file->ifl_oldndx[sap->sa_linkndx]; 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate if (_sdp->sd_ref != REF_DYN_SEEN) { 156957ef7aa9SRod Evans Wk_desc wk; 15707c478bd9Sstevel@tonic-gate 15719039eeafSab196087 if (enter_in_symtab) { 157257ef7aa9SRod Evans if (local) { 157357ef7aa9SRod Evans wk.wk_symtab = 15747c478bd9Sstevel@tonic-gate &symtab[scopesym_ndx]; 15757c478bd9Sstevel@tonic-gate scopesym_ndx++; 157657ef7aa9SRod Evans } else { 157757ef7aa9SRod Evans wk.wk_symtab = 157857ef7aa9SRod Evans &symtab[symtab_ndx]; 15797c478bd9Sstevel@tonic-gate symtab_ndx++; 158057ef7aa9SRod Evans } 15813e831575SAli Bahrami } else { 15823e831575SAli Bahrami wk.wk_symtab = NULL; 158357ef7aa9SRod Evans } 15849039eeafSab196087 if (dynsym) { 15859039eeafSab196087 if (!local) { 158657ef7aa9SRod Evans wk.wk_dynsym = 158757ef7aa9SRod Evans &dynsym[dynsym_ndx]; 15887c478bd9Sstevel@tonic-gate dynsym_ndx++; 15899039eeafSab196087 } else if (dynlocal) { 159057ef7aa9SRod Evans wk.wk_dynsym = 159157ef7aa9SRod Evans &ldynsym[ldynscopesym_ndx]; 15929039eeafSab196087 ldynscopesym_ndx++; 15939039eeafSab196087 } 15943e831575SAli Bahrami } else { 15953e831575SAli Bahrami wk.wk_dynsym = NULL; 15969039eeafSab196087 } 159757ef7aa9SRod Evans wk.wk_weak = sdp; 159857ef7aa9SRod Evans wk.wk_alias = _sdp; 159957ef7aa9SRod Evans 160057ef7aa9SRod Evans if (alist_append(&weak, &wk, 160157ef7aa9SRod Evans sizeof (Wk_desc), AL_CNT_WEAK) == NULL) 160257ef7aa9SRod Evans return ((Addr)S_ERROR); 160357ef7aa9SRod Evans 16047c478bd9Sstevel@tonic-gate continue; 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16085aefb655Srie DBG_CALL(Dbg_syms_old(ofl, sdp)); 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate spec = NULL; 16117c478bd9Sstevel@tonic-gate /* 16127c478bd9Sstevel@tonic-gate * assign new symbol value. 16137c478bd9Sstevel@tonic-gate */ 16147c478bd9Sstevel@tonic-gate sectndx = sdp->sd_shndx; 16157c478bd9Sstevel@tonic-gate if (sectndx == SHN_UNDEF) { 16167c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) && 16177c478bd9Sstevel@tonic-gate (sym->st_value != 0)) { 1618*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 16195aefb655Srie MSG_INTL(MSG_SYM_NOTNULL), 16207c478bd9Sstevel@tonic-gate demangle(name), sdp->sd_file->ifl_name); 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate /* 16247c478bd9Sstevel@tonic-gate * Undefined weak global, if we are generating a static 16257c478bd9Sstevel@tonic-gate * executable, output as an absolute zero. Otherwise 16267c478bd9Sstevel@tonic-gate * leave it as is, ld.so.1 will skip symbols of this 16277c478bd9Sstevel@tonic-gate * type (this technique allows applications and 16287c478bd9Sstevel@tonic-gate * libraries to test for the existence of a symbol as an 16297c478bd9Sstevel@tonic-gate * indication of the presence or absence of certain 16307c478bd9Sstevel@tonic-gate * functionality). 16317c478bd9Sstevel@tonic-gate */ 1632635216b6SRod Evans if (OFL_IS_STATIC_EXEC(ofl) && 16337c478bd9Sstevel@tonic-gate (ELF_ST_BIND(sym->st_info) == STB_WEAK)) { 16347c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 16357c478bd9Sstevel@tonic-gate sdp->sd_shndx = sectndx = SHN_ABS; 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate } else if ((sdp->sd_flags & FLG_SY_SPECSEC) && 16387c478bd9Sstevel@tonic-gate (sectndx == SHN_COMMON)) { 16397c478bd9Sstevel@tonic-gate /* COMMONs have already been processed */ 16407c478bd9Sstevel@tonic-gate /* EMPTY */ 16417c478bd9Sstevel@tonic-gate ; 16427c478bd9Sstevel@tonic-gate } else { 16437c478bd9Sstevel@tonic-gate if ((sdp->sd_flags & FLG_SY_SPECSEC) && 16447c478bd9Sstevel@tonic-gate (sectndx == SHN_ABS)) 16457c478bd9Sstevel@tonic-gate spec = sdp->sd_aux->sa_symspec; 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate /* LINTED */ 16487c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_COMMEXP) { 16497c478bd9Sstevel@tonic-gate /* 16507c478bd9Sstevel@tonic-gate * This is (or was) a COMMON symbol which was 16517c478bd9Sstevel@tonic-gate * processed above - no processing 16527c478bd9Sstevel@tonic-gate * required here. 16537c478bd9Sstevel@tonic-gate */ 16547c478bd9Sstevel@tonic-gate ; 16557c478bd9Sstevel@tonic-gate } else if (sdp->sd_ref == REF_DYN_NEED) { 1656d579eb63Sab196087 uchar_t type, bind; 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate sectndx = SHN_UNDEF; 16597c478bd9Sstevel@tonic-gate sym->st_value = 0; 16607c478bd9Sstevel@tonic-gate sym->st_size = 0; 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate /* 16637c478bd9Sstevel@tonic-gate * Make sure this undefined symbol is returned 16647c478bd9Sstevel@tonic-gate * to the same binding as was defined in the 16657c478bd9Sstevel@tonic-gate * original relocatable object reference. 16667c478bd9Sstevel@tonic-gate */ 16677c478bd9Sstevel@tonic-gate type = ELF_ST_TYPE(sym-> st_info); 16687c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_GLOBREF) 16697c478bd9Sstevel@tonic-gate bind = STB_GLOBAL; 16707c478bd9Sstevel@tonic-gate else 16717c478bd9Sstevel@tonic-gate bind = STB_WEAK; 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, type); 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate } else if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) && 16767c478bd9Sstevel@tonic-gate (sdp->sd_ref == REF_REL_NEED)) { 16777c478bd9Sstevel@tonic-gate osp = sdp->sd_isc->is_osdesc; 16787c478bd9Sstevel@tonic-gate /* LINTED */ 16797c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn(osp->os_scn); 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate /* 16827c478bd9Sstevel@tonic-gate * In an executable, the new symbol value is the 16837c478bd9Sstevel@tonic-gate * old value (offset into defining section) plus 16847c478bd9Sstevel@tonic-gate * virtual address of defining section. In a 16857c478bd9Sstevel@tonic-gate * relocatable, the new value is the old value 16867c478bd9Sstevel@tonic-gate * plus the displacement of the section within 16877c478bd9Sstevel@tonic-gate * the file. 16887c478bd9Sstevel@tonic-gate */ 16897c478bd9Sstevel@tonic-gate /* LINTED */ 16907c478bd9Sstevel@tonic-gate sym->st_value += 16917c478bd9Sstevel@tonic-gate (Off)_elf_getxoff(sdp->sd_isc->is_indata); 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ)) { 16947c478bd9Sstevel@tonic-gate sym->st_value += osp->os_shdr->sh_addr; 16957c478bd9Sstevel@tonic-gate /* 16967c478bd9Sstevel@tonic-gate * TLS symbols are relative to 16977c478bd9Sstevel@tonic-gate * the TLS segment. 16987c478bd9Sstevel@tonic-gate */ 16997c478bd9Sstevel@tonic-gate if ((ELF_ST_TYPE(sym->st_info) == 17007c478bd9Sstevel@tonic-gate STT_TLS) && (ofl->ofl_tlsphdr)) 17017c478bd9Sstevel@tonic-gate sym->st_value -= 17027c478bd9Sstevel@tonic-gate ofl->ofl_tlsphdr->p_vaddr; 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate } 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate if (spec) { 17087c478bd9Sstevel@tonic-gate switch (spec) { 17097c478bd9Sstevel@tonic-gate case SDAUX_ID_ETEXT: 17107c478bd9Sstevel@tonic-gate sym->st_value = etext; 17117c478bd9Sstevel@tonic-gate sectndx = etext_ndx; 17127c478bd9Sstevel@tonic-gate if (etext_abs) 17137c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 17147c478bd9Sstevel@tonic-gate else 17157c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17167c478bd9Sstevel@tonic-gate break; 17177c478bd9Sstevel@tonic-gate case SDAUX_ID_EDATA: 17187c478bd9Sstevel@tonic-gate sym->st_value = edata; 17197c478bd9Sstevel@tonic-gate sectndx = edata_ndx; 17207c478bd9Sstevel@tonic-gate if (edata_abs) 17217c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 17227c478bd9Sstevel@tonic-gate else 17237c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17247c478bd9Sstevel@tonic-gate break; 17257c478bd9Sstevel@tonic-gate case SDAUX_ID_END: 17267c478bd9Sstevel@tonic-gate sym->st_value = end; 17277c478bd9Sstevel@tonic-gate sectndx = end_ndx; 17287c478bd9Sstevel@tonic-gate if (end_abs) 17297c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 17307c478bd9Sstevel@tonic-gate else 17317c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17327c478bd9Sstevel@tonic-gate break; 17337c478bd9Sstevel@tonic-gate case SDAUX_ID_START: 17347c478bd9Sstevel@tonic-gate sym->st_value = start; 17357c478bd9Sstevel@tonic-gate sectndx = start_ndx; 17367c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17377c478bd9Sstevel@tonic-gate break; 17387c478bd9Sstevel@tonic-gate case SDAUX_ID_DYN: 17397c478bd9Sstevel@tonic-gate if (flags & FLG_OF_DYNAMIC) { 17407c478bd9Sstevel@tonic-gate sym->st_value = ofl-> 17417c478bd9Sstevel@tonic-gate ofl_osdynamic->os_shdr->sh_addr; 17427c478bd9Sstevel@tonic-gate /* LINTED */ 17437c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn( 17447c478bd9Sstevel@tonic-gate ofl->ofl_osdynamic->os_scn); 17457c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate break; 17487c478bd9Sstevel@tonic-gate case SDAUX_ID_PLT: 17497c478bd9Sstevel@tonic-gate if (ofl->ofl_osplt) { 17507c478bd9Sstevel@tonic-gate sym->st_value = ofl-> 17517c478bd9Sstevel@tonic-gate ofl_osplt->os_shdr->sh_addr; 17527c478bd9Sstevel@tonic-gate /* LINTED */ 17537c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn( 17547c478bd9Sstevel@tonic-gate ofl->ofl_osplt->os_scn); 17557c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate break; 17587c478bd9Sstevel@tonic-gate case SDAUX_ID_GOT: 17597c478bd9Sstevel@tonic-gate /* 17607c478bd9Sstevel@tonic-gate * Symbol bias for negative growing tables is 17617c478bd9Sstevel@tonic-gate * stored in symbol's value during 17627c478bd9Sstevel@tonic-gate * allocate_got(). 17637c478bd9Sstevel@tonic-gate */ 17647c478bd9Sstevel@tonic-gate sym->st_value += ofl-> 17657c478bd9Sstevel@tonic-gate ofl_osgot->os_shdr->sh_addr; 17667c478bd9Sstevel@tonic-gate /* LINTED */ 17677c478bd9Sstevel@tonic-gate sectndx = elf_ndxscn(ofl-> 17687c478bd9Sstevel@tonic-gate ofl_osgot->os_scn); 17697c478bd9Sstevel@tonic-gate sdp->sd_flags &= ~FLG_SY_SPECSEC; 17707c478bd9Sstevel@tonic-gate break; 17717c478bd9Sstevel@tonic-gate default: 17727c478bd9Sstevel@tonic-gate /* NOTHING */ 17737c478bd9Sstevel@tonic-gate ; 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate } 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate /* 17787c478bd9Sstevel@tonic-gate * If a plt index has been assigned to an undefined function, 17797c478bd9Sstevel@tonic-gate * update the symbols value to the appropriate .plt address. 17807c478bd9Sstevel@tonic-gate */ 17817c478bd9Sstevel@tonic-gate if ((flags & FLG_OF_DYNAMIC) && (flags & FLG_OF_EXEC) && 17827c478bd9Sstevel@tonic-gate (sdp->sd_file) && 17837c478bd9Sstevel@tonic-gate (sdp->sd_file->ifl_ehdr->e_type == ET_DYN) && 17847c478bd9Sstevel@tonic-gate (ELF_ST_TYPE(sym->st_info) == STT_FUNC) && 17857c478bd9Sstevel@tonic-gate !(flags & FLG_OF_BFLAG)) { 17867c478bd9Sstevel@tonic-gate if (sap->sa_PLTndx) 1787ba2be530Sab196087 sym->st_value = 1788ba2be530Sab196087 (*ld_targ.t_mr.mr_calc_plt_addr)(sdp, ofl); 17897c478bd9Sstevel@tonic-gate } 17907c478bd9Sstevel@tonic-gate 17917c478bd9Sstevel@tonic-gate /* 17927c478bd9Sstevel@tonic-gate * Finish updating the symbols. 17937c478bd9Sstevel@tonic-gate */ 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate /* 17967c478bd9Sstevel@tonic-gate * Sym Update: if scoped local - set local binding 17977c478bd9Sstevel@tonic-gate */ 17987c478bd9Sstevel@tonic-gate if (local) 17997c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(STB_LOCAL, 18007c478bd9Sstevel@tonic-gate ELF_ST_TYPE(sym->st_info)); 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate /* 18037c478bd9Sstevel@tonic-gate * Sym Updated: If both the .symtab and .dynsym 18047c478bd9Sstevel@tonic-gate * are present then we've actually updated the information in 18057c478bd9Sstevel@tonic-gate * the .dynsym, therefore copy this same information to the 18067c478bd9Sstevel@tonic-gate * .symtab entry. 18077c478bd9Sstevel@tonic-gate */ 18087c478bd9Sstevel@tonic-gate sdp->sd_shndx = sectndx; 18099039eeafSab196087 if (enter_in_symtab && dynsym && (!local || dynlocal)) { 18109039eeafSab196087 Word _symndx = dynlocal ? scopesym_ndx : symtab_ndx; 18119039eeafSab196087 18129039eeafSab196087 symtab[_symndx].st_value = sym->st_value; 18139039eeafSab196087 symtab[_symndx].st_size = sym->st_size; 18149039eeafSab196087 symtab[_symndx].st_info = sym->st_info; 18159039eeafSab196087 symtab[_symndx].st_other = sym->st_other; 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate 18187c478bd9Sstevel@tonic-gate if (enter_in_symtab) { 18197c478bd9Sstevel@tonic-gate Word _symndx; 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate if (local) 18227c478bd9Sstevel@tonic-gate _symndx = scopesym_ndx++; 18237c478bd9Sstevel@tonic-gate else 18247c478bd9Sstevel@tonic-gate _symndx = symtab_ndx++; 18257c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) && 18267c478bd9Sstevel@tonic-gate (sectndx >= SHN_LORESERVE)) { 182757ef7aa9SRod Evans assert(symshndx != NULL); 18287c478bd9Sstevel@tonic-gate symshndx[_symndx] = sectndx; 18297c478bd9Sstevel@tonic-gate symtab[_symndx].st_shndx = SHN_XINDEX; 18307c478bd9Sstevel@tonic-gate } else { 18317c478bd9Sstevel@tonic-gate /* LINTED */ 18327c478bd9Sstevel@tonic-gate symtab[_symndx].st_shndx = (Half)sectndx; 18337c478bd9Sstevel@tonic-gate } 18347c478bd9Sstevel@tonic-gate } 18357c478bd9Sstevel@tonic-gate 18369039eeafSab196087 if (dynsym && (!local || dynlocal)) { 18379039eeafSab196087 /* 18389039eeafSab196087 * dynsym and ldynsym are distinct tables, so 18399039eeafSab196087 * we use indirection to access the right one 18409039eeafSab196087 * and the related extended section index array. 18419039eeafSab196087 */ 18429039eeafSab196087 Word _symndx; 18439039eeafSab196087 Sym *_dynsym; 18449039eeafSab196087 Word *_dynshndx; 18459039eeafSab196087 18469039eeafSab196087 if (!local) { 18479039eeafSab196087 _symndx = dynsym_ndx++; 18489039eeafSab196087 _dynsym = dynsym; 18499039eeafSab196087 _dynshndx = dynshndx; 18509039eeafSab196087 } else { 18519039eeafSab196087 _symndx = ldynscopesym_ndx++; 18529039eeafSab196087 _dynsym = ldynsym; 18539039eeafSab196087 _dynshndx = ldynshndx; 18549039eeafSab196087 } 18557c478bd9Sstevel@tonic-gate if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) && 18567c478bd9Sstevel@tonic-gate (sectndx >= SHN_LORESERVE)) { 185757ef7aa9SRod Evans assert(_dynshndx != NULL); 18589039eeafSab196087 _dynshndx[_symndx] = sectndx; 18599039eeafSab196087 _dynsym[_symndx].st_shndx = SHN_XINDEX; 18607c478bd9Sstevel@tonic-gate } else { 18617c478bd9Sstevel@tonic-gate /* LINTED */ 18629039eeafSab196087 _dynsym[_symndx].st_shndx = (Half)sectndx; 18637c478bd9Sstevel@tonic-gate } 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate 18665aefb655Srie DBG_CALL(Dbg_syms_new(ofl, sym, sdp)); 18677c478bd9Sstevel@tonic-gate } 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate /* 18707c478bd9Sstevel@tonic-gate * Now that all the symbols have been processed update any weak symbols 18717c478bd9Sstevel@tonic-gate * information (ie. copy all information except `st_name'). As both 18727c478bd9Sstevel@tonic-gate * symbols will be represented in the output, return the weak symbol to 18737c478bd9Sstevel@tonic-gate * its correct type. 18747c478bd9Sstevel@tonic-gate */ 187557ef7aa9SRod Evans for (ALIST_TRAVERSE(weak, idx1, wkp)) { 18767c478bd9Sstevel@tonic-gate Sym_desc *sdp, *_sdp; 18777c478bd9Sstevel@tonic-gate Sym *sym, *_sym, *__sym; 1878d579eb63Sab196087 uchar_t bind; 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate sdp = wkp->wk_weak; 18817c478bd9Sstevel@tonic-gate _sdp = wkp->wk_alias; 18823e831575SAli Bahrami _sym = __sym = _sdp->sd_sym; 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_WEAKDEF; 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate /* 18877c478bd9Sstevel@tonic-gate * If the symbol definition has been scoped then assign it to 18887c478bd9Sstevel@tonic-gate * be local, otherwise if it's from a shared object then we need 18897c478bd9Sstevel@tonic-gate * to maintain the binding of the original reference. 18907c478bd9Sstevel@tonic-gate */ 189108278a5eSRod Evans if (SYM_IS_HIDDEN(sdp)) { 18927c478bd9Sstevel@tonic-gate if (flags & FLG_OF_PROCRED) 18937c478bd9Sstevel@tonic-gate bind = STB_LOCAL; 18947c478bd9Sstevel@tonic-gate else 18957c478bd9Sstevel@tonic-gate bind = STB_WEAK; 18967c478bd9Sstevel@tonic-gate } else if ((sdp->sd_ref == REF_DYN_NEED) && 18977c478bd9Sstevel@tonic-gate (sdp->sd_flags & FLG_SY_GLOBREF)) 18987c478bd9Sstevel@tonic-gate bind = STB_GLOBAL; 18997c478bd9Sstevel@tonic-gate else 19007c478bd9Sstevel@tonic-gate bind = STB_WEAK; 19017c478bd9Sstevel@tonic-gate 19025aefb655Srie DBG_CALL(Dbg_syms_old(ofl, sdp)); 19033e831575SAli Bahrami if ((sym = wkp->wk_symtab) != NULL) { 19047c478bd9Sstevel@tonic-gate sym->st_value = _sym->st_value; 19057c478bd9Sstevel@tonic-gate sym->st_size = _sym->st_size; 19067c478bd9Sstevel@tonic-gate sym->st_other = _sym->st_other; 19077c478bd9Sstevel@tonic-gate sym->st_shndx = _sym->st_shndx; 19087c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, 19097c478bd9Sstevel@tonic-gate ELF_ST_TYPE(sym->st_info)); 19107c478bd9Sstevel@tonic-gate __sym = sym; 19117c478bd9Sstevel@tonic-gate } 19123e831575SAli Bahrami if ((sym = wkp->wk_dynsym) != NULL) { 19137c478bd9Sstevel@tonic-gate sym->st_value = _sym->st_value; 19147c478bd9Sstevel@tonic-gate sym->st_size = _sym->st_size; 19157c478bd9Sstevel@tonic-gate sym->st_other = _sym->st_other; 19167c478bd9Sstevel@tonic-gate sym->st_shndx = _sym->st_shndx; 19177c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, 19187c478bd9Sstevel@tonic-gate ELF_ST_TYPE(sym->st_info)); 19197c478bd9Sstevel@tonic-gate __sym = sym; 19207c478bd9Sstevel@tonic-gate } 19215aefb655Srie DBG_CALL(Dbg_syms_new(ofl, __sym, sdp)); 19227c478bd9Sstevel@tonic-gate } 19237c478bd9Sstevel@tonic-gate 19247c478bd9Sstevel@tonic-gate /* 19255aefb655Srie * Now display GOT debugging information if required. 19267c478bd9Sstevel@tonic-gate */ 1927ba2be530Sab196087 DBG_CALL(Dbg_got_display(ofl, 0, 0, 1928ba2be530Sab196087 ld_targ.t_m.m_got_xnumber, ld_targ.t_m.m_got_entsize)); 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate /* 19319039eeafSab196087 * Update the section headers information. sh_info is 19329039eeafSab196087 * supposed to contain the offset at which the first 19339039eeafSab196087 * global symbol resides in the symbol table, while 19349039eeafSab196087 * sh_link contains the section index of the associated 19359039eeafSab196087 * string table. 19367c478bd9Sstevel@tonic-gate */ 19377c478bd9Sstevel@tonic-gate if (symtab) { 19387c478bd9Sstevel@tonic-gate Shdr *shdr = ofl->ofl_ossymtab->os_shdr; 19397c478bd9Sstevel@tonic-gate 1940ca4eed8bSAli Bahrami shdr->sh_info = symtab_gbl_bndx; 19417c478bd9Sstevel@tonic-gate /* LINTED */ 19427c478bd9Sstevel@tonic-gate shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osstrtab->os_scn); 1943e64d0ff9SAli Bahrami if (symshndx) 1944e64d0ff9SAli Bahrami ofl->ofl_ossymshndx->os_shdr->sh_link = 19457c478bd9Sstevel@tonic-gate (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn); 1946ca4eed8bSAli Bahrami 1947ca4eed8bSAli Bahrami /* 1948ca4eed8bSAli Bahrami * Ensure that the expected number of symbols 1949ca4eed8bSAli Bahrami * were entered into the right spots: 1950ca4eed8bSAli Bahrami * - Scoped symbols in the right range 1951ca4eed8bSAli Bahrami * - Globals start at the right spot 1952ca4eed8bSAli Bahrami * (correct number of locals entered) 1953ca4eed8bSAli Bahrami * - The table is exactly filled 1954ca4eed8bSAli Bahrami * (correct number of globals entered) 1955ca4eed8bSAli Bahrami */ 1956ca4eed8bSAli Bahrami assert((scopesym_bndx + ofl->ofl_scopecnt) == scopesym_ndx); 1957635216b6SRod Evans assert(shdr->sh_info == SYMTAB_LOC_CNT(ofl)); 1958ca4eed8bSAli Bahrami assert((shdr->sh_info + ofl->ofl_globcnt) == symtab_ndx); 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate if (dynsym) { 19617c478bd9Sstevel@tonic-gate Shdr *shdr = ofl->ofl_osdynsym->os_shdr; 19627c478bd9Sstevel@tonic-gate 1963635216b6SRod Evans shdr->sh_info = DYNSYM_LOC_CNT(ofl); 19647c478bd9Sstevel@tonic-gate /* LINTED */ 19657c478bd9Sstevel@tonic-gate shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn); 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate ofl->ofl_oshash->os_shdr->sh_link = 19687c478bd9Sstevel@tonic-gate /* LINTED */ 19697c478bd9Sstevel@tonic-gate (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn); 19707c478bd9Sstevel@tonic-gate if (dynshndx) { 19717c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osdynshndx->os_shdr; 19727c478bd9Sstevel@tonic-gate shdr->sh_link = 19737c478bd9Sstevel@tonic-gate (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn); 19747c478bd9Sstevel@tonic-gate } 19757c478bd9Sstevel@tonic-gate } 19769039eeafSab196087 if (ldynsym) { 19779039eeafSab196087 Shdr *shdr = ofl->ofl_osldynsym->os_shdr; 19789039eeafSab196087 19799039eeafSab196087 /* ldynsym has no globals, so give index one past the end */ 19809039eeafSab196087 shdr->sh_info = ldynsym_ndx; 19819039eeafSab196087 19829039eeafSab196087 /* 19839039eeafSab196087 * The ldynsym and dynsym must be adjacent. The 19849039eeafSab196087 * idea is that rtld should be able to start with 19859039eeafSab196087 * the ldynsym and march straight through the end 19869039eeafSab196087 * of dynsym, seeing them as a single symbol table, 19879039eeafSab196087 * despite the fact that they are in distinct sections. 19889039eeafSab196087 * Ensure that this happened correctly. 19899039eeafSab196087 * 19909039eeafSab196087 * Note that I use ldynsym_ndx here instead of the 19919039eeafSab196087 * computation I used to set the section size 1992d579eb63Sab196087 * (found in ldynsym_cnt). The two will agree, unless 1993d579eb63Sab196087 * we somehow miscounted symbols or failed to insert them 1994d579eb63Sab196087 * all. Using ldynsym_ndx here catches that error in 1995d579eb63Sab196087 * addition to checking for adjacency. 19969039eeafSab196087 */ 19979039eeafSab196087 assert(dynsym == (ldynsym + ldynsym_ndx)); 19989039eeafSab196087 19999039eeafSab196087 20009039eeafSab196087 /* LINTED */ 20019039eeafSab196087 shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn); 20029039eeafSab196087 20039039eeafSab196087 if (ldynshndx) { 20049039eeafSab196087 shdr = ofl->ofl_osldynshndx->os_shdr; 20059039eeafSab196087 shdr->sh_link = 20069039eeafSab196087 (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn); 20079039eeafSab196087 } 2008d579eb63Sab196087 2009d579eb63Sab196087 /* 2010d579eb63Sab196087 * The presence of .SUNW_ldynsym means that there may be 2011d579eb63Sab196087 * associated sort sections, one for regular symbols 2012d579eb63Sab196087 * and the other for TLS. Each sort section needs the 2013d579eb63Sab196087 * following done: 2014d579eb63Sab196087 * - Section header link references .SUNW_ldynsym 2015d579eb63Sab196087 * - Should have received the expected # of items 2016d579eb63Sab196087 * - Sorted by increasing address 2017d579eb63Sab196087 */ 2018d579eb63Sab196087 if (ofl->ofl_osdynsymsort) { /* .SUNW_dynsymsort */ 2019d579eb63Sab196087 ofl->ofl_osdynsymsort->os_shdr->sh_link = 2020d579eb63Sab196087 (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn); 2021d579eb63Sab196087 assert(ofl->ofl_dynsymsortcnt == dynsymsort_ndx); 202260758829Srie 2023d579eb63Sab196087 if (dynsymsort_ndx > 1) { 2024d579eb63Sab196087 dynsort_compare_syms = ldynsym; 2025d579eb63Sab196087 qsort(dynsymsort, dynsymsort_ndx, 2026d579eb63Sab196087 sizeof (*dynsymsort), dynsort_compare); 2027a194faf8Srie dynsort_dupwarn(ofl, ldynsym, 2028a194faf8Srie st_getstrbuf(dynstr), 2029d579eb63Sab196087 dynsymsort, dynsymsort_ndx, 2030d579eb63Sab196087 MSG_ORIG(MSG_SCN_DYNSYMSORT)); 2031d579eb63Sab196087 } 2032d579eb63Sab196087 } 2033d579eb63Sab196087 if (ofl->ofl_osdyntlssort) { /* .SUNW_dyntlssort */ 2034d579eb63Sab196087 ofl->ofl_osdyntlssort->os_shdr->sh_link = 2035d579eb63Sab196087 (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn); 2036d579eb63Sab196087 assert(ofl->ofl_dyntlssortcnt == dyntlssort_ndx); 203760758829Srie 2038d579eb63Sab196087 if (dyntlssort_ndx > 1) { 2039d579eb63Sab196087 dynsort_compare_syms = ldynsym; 2040d579eb63Sab196087 qsort(dyntlssort, dyntlssort_ndx, 2041d579eb63Sab196087 sizeof (*dyntlssort), dynsort_compare); 2042a194faf8Srie dynsort_dupwarn(ofl, ldynsym, 2043a194faf8Srie st_getstrbuf(dynstr), 2044d579eb63Sab196087 dyntlssort, dyntlssort_ndx, 2045d579eb63Sab196087 MSG_ORIG(MSG_SCN_DYNTLSSORT)); 2046d579eb63Sab196087 } 2047d579eb63Sab196087 } 20489039eeafSab196087 } 20497c478bd9Sstevel@tonic-gate 20507c478bd9Sstevel@tonic-gate /* 20517c478bd9Sstevel@tonic-gate * Used by ld.so.1 only. 20527c478bd9Sstevel@tonic-gate */ 20537c478bd9Sstevel@tonic-gate return (etext); 2054d579eb63Sab196087 2055d579eb63Sab196087 #undef ADD_TO_DYNSORT 20567c478bd9Sstevel@tonic-gate } 20577c478bd9Sstevel@tonic-gate 20587c478bd9Sstevel@tonic-gate /* 20597c478bd9Sstevel@tonic-gate * Build the dynamic section. 20601d9df23bSab196087 * 20611d9df23bSab196087 * This routine must be maintained in parallel with make_dynamic() 20621d9df23bSab196087 * in sections.c 20637c478bd9Sstevel@tonic-gate */ 20645aefb655Srie static int 20657c478bd9Sstevel@tonic-gate update_odynamic(Ofl_desc *ofl) 20667c478bd9Sstevel@tonic-gate { 206757ef7aa9SRod Evans Aliste idx; 20687c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 20697c478bd9Sstevel@tonic-gate Sym_desc *sdp; 20707c478bd9Sstevel@tonic-gate Shdr *shdr; 20717c478bd9Sstevel@tonic-gate Dyn *_dyn = (Dyn *)ofl->ofl_osdynamic->os_outdata->d_buf; 20727c478bd9Sstevel@tonic-gate Dyn *dyn; 2073635216b6SRod Evans Os_desc *symosp, *strosp; 2074635216b6SRod Evans Str_tbl *strtbl; 2075cce0e03bSab196087 size_t stoff; 20761d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 20771d9df23bSab196087 int not_relobj = !(flags & FLG_OF_RELOBJ); 20783244bcaaSab196087 Word cnt; 20797c478bd9Sstevel@tonic-gate 20801d9df23bSab196087 /* 2081635216b6SRod Evans * Relocatable objects can be built with -r and -dy to trigger the 2082635216b6SRod Evans * creation of a .dynamic section. This model is used to create kernel 2083635216b6SRod Evans * device drivers. The .dynamic section provides a subset of userland 2084635216b6SRod Evans * .dynamic entries, typically entries such as DT_NEEDED and DT_RUNPATH. 20851d9df23bSab196087 * 2086635216b6SRod Evans * Within a dynamic object, any .dynamic string references are to the 2087635216b6SRod Evans * .dynstr table. Within a relocatable object, these strings can reside 2088635216b6SRod Evans * within the .strtab. 20891d9df23bSab196087 */ 2090635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 2091635216b6SRod Evans symosp = ofl->ofl_ossymtab; 2092635216b6SRod Evans strosp = ofl->ofl_osstrtab; 2093635216b6SRod Evans strtbl = ofl->ofl_strtab; 2094635216b6SRod Evans } else { 2095635216b6SRod Evans symosp = ofl->ofl_osdynsym; 2096635216b6SRod Evans strosp = ofl->ofl_osdynstr; 2097635216b6SRod Evans strtbl = ofl->ofl_dynstrtab; 2098635216b6SRod Evans } 2099635216b6SRod Evans 21007c478bd9Sstevel@tonic-gate /* LINTED */ 2101635216b6SRod Evans ofl->ofl_osdynamic->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn); 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate dyn = _dyn; 21047c478bd9Sstevel@tonic-gate 210557ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_sos, idx, ifl)) { 21067c478bd9Sstevel@tonic-gate if ((ifl->ifl_flags & 21077c478bd9Sstevel@tonic-gate (FLG_IF_IGNORE | FLG_IF_DEPREQD)) == FLG_IF_IGNORE) 21087c478bd9Sstevel@tonic-gate continue; 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate /* 21117c478bd9Sstevel@tonic-gate * Create and set up the DT_POSFLAG_1 entry here if required. 21127c478bd9Sstevel@tonic-gate */ 2113f441771bSRod Evans if ((ifl->ifl_flags & MSK_IF_POSFLAG1) && 2114f441771bSRod Evans (ifl->ifl_flags & FLG_IF_NEEDED) && not_relobj) { 21157c478bd9Sstevel@tonic-gate dyn->d_tag = DT_POSFLAG_1; 21167c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_LAZYLD) 21177c478bd9Sstevel@tonic-gate dyn->d_un.d_val = DF_P1_LAZYLOAD; 21187c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_GRPPRM) 21197c478bd9Sstevel@tonic-gate dyn->d_un.d_val |= DF_P1_GROUPPERM; 2120f441771bSRod Evans if (ifl->ifl_flags & FLG_IF_DEFERRED) 2121f441771bSRod Evans dyn->d_un.d_val |= DF_P1_DEFERRED; 21227c478bd9Sstevel@tonic-gate dyn++; 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR)) 21267c478bd9Sstevel@tonic-gate dyn->d_tag = DT_NEEDED; 21277c478bd9Sstevel@tonic-gate else 21287c478bd9Sstevel@tonic-gate continue; 21297c478bd9Sstevel@tonic-gate 2130635216b6SRod Evans (void) st_setstring(strtbl, ifl->ifl_soname, &stoff); 21317c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 21327c478bd9Sstevel@tonic-gate /* LINTED */ 21337c478bd9Sstevel@tonic-gate ifl->ifl_neededndx = (Half)(((uintptr_t)dyn - (uintptr_t)_dyn) / 21347c478bd9Sstevel@tonic-gate sizeof (Dyn)); 21357c478bd9Sstevel@tonic-gate dyn++; 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate 21381d9df23bSab196087 if (not_relobj) { 2139cce0e03bSab196087 if (ofl->ofl_dtsfltrs != NULL) { 21407c478bd9Sstevel@tonic-gate Dfltr_desc *dftp; 21417c478bd9Sstevel@tonic-gate 2142cce0e03bSab196087 for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, idx, dftp)) { 21437c478bd9Sstevel@tonic-gate if (dftp->dft_flag == FLG_SY_AUXFLTR) 21447c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SUNW_AUXILIARY; 21457c478bd9Sstevel@tonic-gate else 21467c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SUNW_FILTER; 21477c478bd9Sstevel@tonic-gate 2148635216b6SRod Evans (void) st_setstring(strtbl, dftp->dft_str, 21491d9df23bSab196087 &stoff); 21507c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 21517c478bd9Sstevel@tonic-gate dftp->dft_ndx = (Half)(((uintptr_t)dyn - 21527c478bd9Sstevel@tonic-gate (uintptr_t)_dyn) / sizeof (Dyn)); 21537c478bd9Sstevel@tonic-gate dyn++; 21547c478bd9Sstevel@tonic-gate } 21557c478bd9Sstevel@tonic-gate } 21565aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U), 21571d9df23bSab196087 SYM_NOHASH, 0, ofl)) != NULL) && 21581d9df23bSab196087 (sdp->sd_ref == REF_REL_NEED) && 21595b59e4caSab196087 (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 21607c478bd9Sstevel@tonic-gate dyn->d_tag = DT_INIT; 21617c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sdp->sd_sym->st_value; 21627c478bd9Sstevel@tonic-gate dyn++; 21637c478bd9Sstevel@tonic-gate } 21645aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U), 21651d9df23bSab196087 SYM_NOHASH, 0, ofl)) != NULL) && 21661d9df23bSab196087 (sdp->sd_ref == REF_REL_NEED) && 21675b59e4caSab196087 (sdp->sd_sym->st_shndx != SHN_UNDEF)) { 21687c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FINI; 21697c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sdp->sd_sym->st_value; 21707c478bd9Sstevel@tonic-gate dyn++; 21717c478bd9Sstevel@tonic-gate } 21727c478bd9Sstevel@tonic-gate if (ofl->ofl_soname) { 21737c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SONAME; 2174635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_soname, &stoff); 21757c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 21767c478bd9Sstevel@tonic-gate dyn++; 21777c478bd9Sstevel@tonic-gate } 21787c478bd9Sstevel@tonic-gate if (ofl->ofl_filtees) { 21797c478bd9Sstevel@tonic-gate if (flags & FLG_OF_AUX) { 21807c478bd9Sstevel@tonic-gate dyn->d_tag = DT_AUXILIARY; 21817c478bd9Sstevel@tonic-gate } else { 21827c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FILTER; 21837c478bd9Sstevel@tonic-gate } 2184635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_filtees, &stoff); 21857c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 21867c478bd9Sstevel@tonic-gate dyn++; 21877c478bd9Sstevel@tonic-gate } 21881d9df23bSab196087 } 21891d9df23bSab196087 21907c478bd9Sstevel@tonic-gate if (ofl->ofl_rpath) { 2191635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_rpath, &stoff); 21927c478bd9Sstevel@tonic-gate dyn->d_tag = DT_RUNPATH; 21937c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 21947c478bd9Sstevel@tonic-gate dyn++; 21957c478bd9Sstevel@tonic-gate dyn->d_tag = DT_RPATH; 21967c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 21977c478bd9Sstevel@tonic-gate dyn++; 21987c478bd9Sstevel@tonic-gate } 21991d9df23bSab196087 22001d9df23bSab196087 if (not_relobj) { 220157ef7aa9SRod Evans Aliste idx; 220294c044f4SRod Evans Sg_desc *sgp; 220357ef7aa9SRod Evans 22047c478bd9Sstevel@tonic-gate if (ofl->ofl_config) { 22057c478bd9Sstevel@tonic-gate dyn->d_tag = DT_CONFIG; 2206635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_config, &stoff); 22077c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 22087c478bd9Sstevel@tonic-gate dyn++; 22097c478bd9Sstevel@tonic-gate } 22107c478bd9Sstevel@tonic-gate if (ofl->ofl_depaudit) { 22117c478bd9Sstevel@tonic-gate dyn->d_tag = DT_DEPAUDIT; 2212635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_depaudit, &stoff); 22137c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 22147c478bd9Sstevel@tonic-gate dyn++; 22157c478bd9Sstevel@tonic-gate } 22167c478bd9Sstevel@tonic-gate if (ofl->ofl_audit) { 22177c478bd9Sstevel@tonic-gate dyn->d_tag = DT_AUDIT; 2218635216b6SRod Evans (void) st_setstring(strtbl, ofl->ofl_audit, &stoff); 22197c478bd9Sstevel@tonic-gate dyn->d_un.d_val = stoff; 22207c478bd9Sstevel@tonic-gate dyn++; 22217c478bd9Sstevel@tonic-gate } 22227c478bd9Sstevel@tonic-gate 22237c478bd9Sstevel@tonic-gate dyn->d_tag = DT_HASH; 22247c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = ofl->ofl_oshash->os_shdr->sh_addr; 22257c478bd9Sstevel@tonic-gate dyn++; 22267c478bd9Sstevel@tonic-gate 2227635216b6SRod Evans shdr = strosp->os_shdr; 22287c478bd9Sstevel@tonic-gate dyn->d_tag = DT_STRTAB; 22297c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 22307c478bd9Sstevel@tonic-gate dyn++; 22317c478bd9Sstevel@tonic-gate 22327c478bd9Sstevel@tonic-gate dyn->d_tag = DT_STRSZ; 22337c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_size; 22347c478bd9Sstevel@tonic-gate dyn++; 22357c478bd9Sstevel@tonic-gate 2236635216b6SRod Evans /* 2237635216b6SRod Evans * Note, the shdr is set and used in the ofl->ofl_osldynsym case 2238635216b6SRod Evans * that follows. 2239635216b6SRod Evans */ 2240635216b6SRod Evans shdr = symosp->os_shdr; 22417c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMTAB; 22427c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 22437c478bd9Sstevel@tonic-gate dyn++; 22447c478bd9Sstevel@tonic-gate 22457c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMENT; 22467c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_entsize; 22477c478bd9Sstevel@tonic-gate dyn++; 22487c478bd9Sstevel@tonic-gate 22499039eeafSab196087 if (ofl->ofl_osldynsym) { 2250635216b6SRod Evans Shdr *lshdr = ofl->ofl_osldynsym->os_shdr; 2251635216b6SRod Evans 22529039eeafSab196087 /* 22539039eeafSab196087 * We have arranged for the .SUNW_ldynsym data to be 22549039eeafSab196087 * immediately in front of the .dynsym data. 22559039eeafSab196087 * This means that you could start at the top 22569039eeafSab196087 * of .SUNW_ldynsym and see the data for both tables 22579039eeafSab196087 * without a break. This is the view we want to 22589039eeafSab196087 * provide for DT_SUNW_SYMTAB, which is why we 22599039eeafSab196087 * add the lengths together. 22609039eeafSab196087 */ 22619039eeafSab196087 dyn->d_tag = DT_SUNW_SYMTAB; 22629039eeafSab196087 dyn->d_un.d_ptr = lshdr->sh_addr; 22639039eeafSab196087 dyn++; 22649039eeafSab196087 22659039eeafSab196087 dyn->d_tag = DT_SUNW_SYMSZ; 22669039eeafSab196087 dyn->d_un.d_val = lshdr->sh_size + shdr->sh_size; 22679039eeafSab196087 dyn++; 22689039eeafSab196087 } 22699039eeafSab196087 2270d579eb63Sab196087 if (ofl->ofl_osdynsymsort || ofl->ofl_osdyntlssort) { 2271d579eb63Sab196087 dyn->d_tag = DT_SUNW_SORTENT; 2272d579eb63Sab196087 dyn->d_un.d_val = sizeof (Word); 2273d579eb63Sab196087 dyn++; 2274d579eb63Sab196087 } 2275d579eb63Sab196087 2276d579eb63Sab196087 if (ofl->ofl_osdynsymsort) { 2277635216b6SRod Evans shdr = ofl->ofl_osdynsymsort->os_shdr; 2278635216b6SRod Evans 2279d579eb63Sab196087 dyn->d_tag = DT_SUNW_SYMSORT; 2280635216b6SRod Evans dyn->d_un.d_ptr = shdr->sh_addr; 2281d579eb63Sab196087 dyn++; 2282d579eb63Sab196087 2283d579eb63Sab196087 dyn->d_tag = DT_SUNW_SYMSORTSZ; 2284635216b6SRod Evans dyn->d_un.d_val = shdr->sh_size; 2285d579eb63Sab196087 dyn++; 2286d579eb63Sab196087 } 2287d579eb63Sab196087 2288d579eb63Sab196087 if (ofl->ofl_osdyntlssort) { 2289635216b6SRod Evans shdr = ofl->ofl_osdyntlssort->os_shdr; 2290635216b6SRod Evans 2291d579eb63Sab196087 dyn->d_tag = DT_SUNW_TLSSORT; 2292635216b6SRod Evans dyn->d_un.d_ptr = shdr->sh_addr; 2293d579eb63Sab196087 dyn++; 2294d579eb63Sab196087 2295d579eb63Sab196087 dyn->d_tag = DT_SUNW_TLSSORTSZ; 2296635216b6SRod Evans dyn->d_un.d_val = shdr->sh_size; 2297d579eb63Sab196087 dyn++; 2298d579eb63Sab196087 } 2299d579eb63Sab196087 23007c478bd9Sstevel@tonic-gate /* 23017c478bd9Sstevel@tonic-gate * Reserve the DT_CHECKSUM entry. Its value will be filled in 23027c478bd9Sstevel@tonic-gate * after the complete image is built. 23037c478bd9Sstevel@tonic-gate */ 23047c478bd9Sstevel@tonic-gate dyn->d_tag = DT_CHECKSUM; 23057c478bd9Sstevel@tonic-gate ofl->ofl_checksum = &dyn->d_un.d_val; 23067c478bd9Sstevel@tonic-gate dyn++; 23077c478bd9Sstevel@tonic-gate 2308d840867fSab196087 /* 2309d840867fSab196087 * Versioning sections: DT_VERDEF and DT_VERNEED. 2310d840867fSab196087 * 2311d840867fSab196087 * The Solaris ld does not produce DT_VERSYM, but the GNU ld 2312d840867fSab196087 * does, in order to support their style of versioning, which 2313d840867fSab196087 * differs from ours: 2314d840867fSab196087 * 2315d840867fSab196087 * - The top bit of the 16-bit Versym index is 2316d840867fSab196087 * not part of the version, but is interpreted 2317d840867fSab196087 * as a "hidden bit". 2318d840867fSab196087 * 2319d840867fSab196087 * - External (SHN_UNDEF) symbols can have non-zero 2320d840867fSab196087 * Versym values, which specify versions in 2321d840867fSab196087 * referenced objects, via the Verneed section. 2322d840867fSab196087 * 2323d840867fSab196087 * - The vna_other field of the Vernaux structures 2324d840867fSab196087 * found in the Verneed section are not zero as 2325d840867fSab196087 * with Solaris, but instead contain the version 2326d840867fSab196087 * index to be used by Versym indices to reference 2327d840867fSab196087 * the given external version. 2328d840867fSab196087 * 2329d840867fSab196087 * The Solaris ld, rtld, and elfdump programs all interpret the 2330d840867fSab196087 * presence of DT_VERSYM as meaning that GNU versioning rules 2331d840867fSab196087 * apply to the given file. If DT_VERSYM is not present, 2332d840867fSab196087 * then Solaris versioning rules apply. If we should ever need 2333d840867fSab196087 * to change our ld so that it does issue DT_VERSYM, then 2334d840867fSab196087 * this rule for detecting GNU versioning will no longer work. 2335d840867fSab196087 * In that case, we will have to invent a way to explicitly 2336d840867fSab196087 * specify the style of versioning in use, perhaps via a 2337d840867fSab196087 * new dynamic entry named something like DT_SUNW_VERSIONSTYLE, 2338d840867fSab196087 * where the d_un.d_val value specifies which style is to be 2339d840867fSab196087 * used. 2340d840867fSab196087 */ 23417c478bd9Sstevel@tonic-gate if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) == 23427c478bd9Sstevel@tonic-gate FLG_OF_VERDEF) { 23437c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osverdef->os_shdr; 2344635216b6SRod Evans 23457c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERDEF; 23467c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 23477c478bd9Sstevel@tonic-gate dyn++; 23487c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERDEFNUM; 23497c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_info; 23507c478bd9Sstevel@tonic-gate dyn++; 23517c478bd9Sstevel@tonic-gate } 23527c478bd9Sstevel@tonic-gate if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) == 23537c478bd9Sstevel@tonic-gate FLG_OF_VERNEED) { 23547c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osverneed->os_shdr; 2355635216b6SRod Evans 23567c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERNEED; 23577c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 23587c478bd9Sstevel@tonic-gate dyn++; 23597c478bd9Sstevel@tonic-gate dyn->d_tag = DT_VERNEEDNUM; 23607c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_info; 23617c478bd9Sstevel@tonic-gate dyn++; 23627c478bd9Sstevel@tonic-gate } 2363d840867fSab196087 23641d9df23bSab196087 if ((flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt) { 2365ba2be530Sab196087 dyn->d_tag = ld_targ.t_m.m_rel_dt_count; 23667c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_relocrelcnt; 23677c478bd9Sstevel@tonic-gate dyn++; 23687c478bd9Sstevel@tonic-gate } 23697c478bd9Sstevel@tonic-gate if (flags & FLG_OF_TEXTREL) { 23707c478bd9Sstevel@tonic-gate /* 23717c478bd9Sstevel@tonic-gate * Only the presence of this entry is used in this 23727c478bd9Sstevel@tonic-gate * implementation, not the value stored. 23737c478bd9Sstevel@tonic-gate */ 23747c478bd9Sstevel@tonic-gate dyn->d_tag = DT_TEXTREL; 23757c478bd9Sstevel@tonic-gate dyn->d_un.d_val = 0; 23767c478bd9Sstevel@tonic-gate dyn++; 23777c478bd9Sstevel@tonic-gate } 23787c478bd9Sstevel@tonic-gate 23797c478bd9Sstevel@tonic-gate if (ofl->ofl_osfiniarray) { 23807c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osfiniarray->os_shdr; 23817c478bd9Sstevel@tonic-gate 23827c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FINI_ARRAY; 23837c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 23847c478bd9Sstevel@tonic-gate dyn++; 23857c478bd9Sstevel@tonic-gate 23867c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FINI_ARRAYSZ; 23877c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 23887c478bd9Sstevel@tonic-gate dyn++; 23897c478bd9Sstevel@tonic-gate } 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate if (ofl->ofl_osinitarray) { 23927c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osinitarray->os_shdr; 23937c478bd9Sstevel@tonic-gate 23947c478bd9Sstevel@tonic-gate dyn->d_tag = DT_INIT_ARRAY; 23957c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 23967c478bd9Sstevel@tonic-gate dyn++; 23977c478bd9Sstevel@tonic-gate 23987c478bd9Sstevel@tonic-gate dyn->d_tag = DT_INIT_ARRAYSZ; 23997c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 24007c478bd9Sstevel@tonic-gate dyn++; 24017c478bd9Sstevel@tonic-gate } 24027c478bd9Sstevel@tonic-gate 24037c478bd9Sstevel@tonic-gate if (ofl->ofl_ospreinitarray) { 24047c478bd9Sstevel@tonic-gate shdr = ofl->ofl_ospreinitarray->os_shdr; 24057c478bd9Sstevel@tonic-gate 24067c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PREINIT_ARRAY; 24077c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24087c478bd9Sstevel@tonic-gate dyn++; 24097c478bd9Sstevel@tonic-gate 24107c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PREINIT_ARRAYSZ; 24117c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 24127c478bd9Sstevel@tonic-gate dyn++; 24137c478bd9Sstevel@tonic-gate } 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate if (ofl->ofl_pltcnt) { 24167c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osplt->os_relosdesc->os_shdr; 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTRELSZ; 24197c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_size; 24207c478bd9Sstevel@tonic-gate dyn++; 24217c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTREL; 2422ba2be530Sab196087 dyn->d_un.d_ptr = ld_targ.t_m.m_rel_dt_type; 24237c478bd9Sstevel@tonic-gate dyn++; 24247c478bd9Sstevel@tonic-gate dyn->d_tag = DT_JMPREL; 24257c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24267c478bd9Sstevel@tonic-gate dyn++; 24277c478bd9Sstevel@tonic-gate } 24287c478bd9Sstevel@tonic-gate if (ofl->ofl_pltpad) { 24297c478bd9Sstevel@tonic-gate shdr = ofl->ofl_osplt->os_shdr; 24307c478bd9Sstevel@tonic-gate 24317c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTPAD; 243260758829Srie if (ofl->ofl_pltcnt) { 24337c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr + 2434ba2be530Sab196087 ld_targ.t_m.m_plt_reservsz + 2435ba2be530Sab196087 ofl->ofl_pltcnt * ld_targ.t_m.m_plt_entsize; 243660758829Srie } else 24377c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24387c478bd9Sstevel@tonic-gate dyn++; 24397c478bd9Sstevel@tonic-gate dyn->d_tag = DT_PLTPADSZ; 2440ba2be530Sab196087 dyn->d_un.d_val = ofl->ofl_pltpad * 2441ba2be530Sab196087 ld_targ.t_m.m_plt_entsize; 24427c478bd9Sstevel@tonic-gate dyn++; 24437c478bd9Sstevel@tonic-gate } 24447c478bd9Sstevel@tonic-gate if (ofl->ofl_relocsz) { 2445635216b6SRod Evans shdr = ofl->ofl_osrelhead->os_shdr; 2446635216b6SRod Evans 2447ba2be530Sab196087 dyn->d_tag = ld_targ.t_m.m_rel_dt_type; 2448635216b6SRod Evans dyn->d_un.d_ptr = shdr->sh_addr; 24497c478bd9Sstevel@tonic-gate dyn++; 2450ba2be530Sab196087 dyn->d_tag = ld_targ.t_m.m_rel_dt_size; 24517c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = ofl->ofl_relocsz; 24527c478bd9Sstevel@tonic-gate dyn++; 2453ba2be530Sab196087 dyn->d_tag = ld_targ.t_m.m_rel_dt_ent; 2454635216b6SRod Evans if (shdr->sh_type == SHT_REL) 24557c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sizeof (Rel); 24567c478bd9Sstevel@tonic-gate else 24577c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sizeof (Rela); 24587c478bd9Sstevel@tonic-gate dyn++; 24597c478bd9Sstevel@tonic-gate } 24607c478bd9Sstevel@tonic-gate if (ofl->ofl_ossyminfo) { 24617c478bd9Sstevel@tonic-gate shdr = ofl->ofl_ossyminfo->os_shdr; 2462635216b6SRod Evans 24637c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMINFO; 24647c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = shdr->sh_addr; 24657c478bd9Sstevel@tonic-gate dyn++; 24667c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMINSZ; 24677c478bd9Sstevel@tonic-gate dyn->d_un.d_val = shdr->sh_size; 24687c478bd9Sstevel@tonic-gate dyn++; 24697c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMINENT; 24707c478bd9Sstevel@tonic-gate dyn->d_un.d_val = sizeof (Syminfo); 24717c478bd9Sstevel@tonic-gate dyn++; 24727c478bd9Sstevel@tonic-gate } 24737c478bd9Sstevel@tonic-gate if (ofl->ofl_osmove) { 2474635216b6SRod Evans shdr = ofl->ofl_osmove->os_shdr; 24757c478bd9Sstevel@tonic-gate 247608278a5eSRod Evans dyn->d_tag = DT_MOVETAB; 247708278a5eSRod Evans dyn->d_un.d_val = shdr->sh_addr; 24787c478bd9Sstevel@tonic-gate dyn++; 24797c478bd9Sstevel@tonic-gate dyn->d_tag = DT_MOVESZ; 2480635216b6SRod Evans dyn->d_un.d_val = shdr->sh_size; 24817c478bd9Sstevel@tonic-gate dyn++; 248208278a5eSRod Evans dyn->d_tag = DT_MOVEENT; 248308278a5eSRod Evans dyn->d_un.d_val = shdr->sh_entsize; 24847c478bd9Sstevel@tonic-gate dyn++; 24857c478bd9Sstevel@tonic-gate } 24867c478bd9Sstevel@tonic-gate if (ofl->ofl_regsymcnt) { 24877c478bd9Sstevel@tonic-gate int ndx; 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) { 249057ef7aa9SRod Evans if ((sdp = ofl->ofl_regsyms[ndx]) == NULL) 24917c478bd9Sstevel@tonic-gate continue; 24927c478bd9Sstevel@tonic-gate 2493ba2be530Sab196087 dyn->d_tag = ld_targ.t_m.m_dt_register; 24947c478bd9Sstevel@tonic-gate dyn->d_un.d_val = sdp->sd_symndx; 24957c478bd9Sstevel@tonic-gate dyn++; 24967c478bd9Sstevel@tonic-gate } 24977c478bd9Sstevel@tonic-gate } 24987c478bd9Sstevel@tonic-gate 249957ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_rtldinfo, idx, sdp)) { 25007c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SUNW_RTLDINF; 25017c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = sdp->sd_sym->st_value; 25027c478bd9Sstevel@tonic-gate dyn++; 25037c478bd9Sstevel@tonic-gate } 25047c478bd9Sstevel@tonic-gate 250594c044f4SRod Evans if (((sgp = ofl->ofl_osdynamic->os_sgdesc) != NULL) && 250694c044f4SRod Evans (sgp->sg_phdr.p_flags & PF_W) && ofl->ofl_osinterp) { 25077c478bd9Sstevel@tonic-gate dyn->d_tag = DT_DEBUG; 25087c478bd9Sstevel@tonic-gate dyn->d_un.d_ptr = 0; 25097c478bd9Sstevel@tonic-gate dyn++; 25107c478bd9Sstevel@tonic-gate } 25117c478bd9Sstevel@tonic-gate 25127c478bd9Sstevel@tonic-gate if (ofl->ofl_oscap) { 25137c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SUNW_CAP; 25147c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_oscap->os_shdr->sh_addr; 25157c478bd9Sstevel@tonic-gate dyn++; 25167c478bd9Sstevel@tonic-gate } 251708278a5eSRod Evans if (ofl->ofl_oscapinfo) { 251808278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPINFO; 251908278a5eSRod Evans dyn->d_un.d_val = ofl->ofl_oscapinfo->os_shdr->sh_addr; 252008278a5eSRod Evans dyn++; 252108278a5eSRod Evans } 252208278a5eSRod Evans if (ofl->ofl_oscapchain) { 252308278a5eSRod Evans shdr = ofl->ofl_oscapchain->os_shdr; 25247c478bd9Sstevel@tonic-gate 252508278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPCHAIN; 252608278a5eSRod Evans dyn->d_un.d_val = shdr->sh_addr; 252708278a5eSRod Evans dyn++; 252808278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPCHAINSZ; 252908278a5eSRod Evans dyn->d_un.d_val = shdr->sh_size; 253008278a5eSRod Evans dyn++; 253108278a5eSRod Evans dyn->d_tag = DT_SUNW_CAPCHAINENT; 253208278a5eSRod Evans dyn->d_un.d_val = shdr->sh_entsize; 253308278a5eSRod Evans dyn++; 253408278a5eSRod Evans } 25357c478bd9Sstevel@tonic-gate if (flags & FLG_OF_SYMBOLIC) { 25367c478bd9Sstevel@tonic-gate dyn->d_tag = DT_SYMBOLIC; 25377c478bd9Sstevel@tonic-gate dyn->d_un.d_val = 0; 25387c478bd9Sstevel@tonic-gate dyn++; 25397c478bd9Sstevel@tonic-gate } 25401d9df23bSab196087 } 25411d9df23bSab196087 25427c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FLAGS; 25437c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_dtflags; 25447c478bd9Sstevel@tonic-gate dyn++; 25457c478bd9Sstevel@tonic-gate 25467c478bd9Sstevel@tonic-gate /* 25477c478bd9Sstevel@tonic-gate * If -Bdirect was specified, but some NODIRECT symbols were specified 25487c478bd9Sstevel@tonic-gate * via a mapfile, or -znodirect was used on the command line, then 25497c478bd9Sstevel@tonic-gate * clear the DF_1_DIRECT flag. The resultant object will use per-symbol 25507c478bd9Sstevel@tonic-gate * direct bindings rather than be enabled for global direct bindings. 255128bda19cSRod Evans * 255228bda19cSRod Evans * If any no-direct bindings exist within this object, set the 255328bda19cSRod Evans * DF_1_NODIRECT flag. ld(1) recognizes this flag when processing 255428bda19cSRod Evans * dependencies, and performs extra work to ensure that no direct 255528bda19cSRod Evans * bindings are established to the no-direct symbols that exist 255628bda19cSRod Evans * within these dependencies. 25577c478bd9Sstevel@tonic-gate */ 255828bda19cSRod Evans if (ofl->ofl_flags1 & FLG_OF1_NGLBDIR) 25597c478bd9Sstevel@tonic-gate ofl->ofl_dtflags_1 &= ~DF_1_DIRECT; 256028bda19cSRod Evans if (ofl->ofl_flags1 & FLG_OF1_NDIRECT) 256160758829Srie ofl->ofl_dtflags_1 |= DF_1_NODIRECT; 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate dyn->d_tag = DT_FLAGS_1; 25647c478bd9Sstevel@tonic-gate dyn->d_un.d_val = ofl->ofl_dtflags_1; 25657c478bd9Sstevel@tonic-gate dyn++; 25667c478bd9Sstevel@tonic-gate 25673244bcaaSab196087 dyn->d_tag = DT_SUNW_STRPAD; 25683244bcaaSab196087 dyn->d_un.d_val = DYNSTR_EXTRA_PAD; 25693244bcaaSab196087 dyn++; 25703244bcaaSab196087 2571ba2be530Sab196087 dyn->d_tag = DT_SUNW_LDMACH; 2572ba2be530Sab196087 dyn->d_un.d_val = ld_sunw_ldmach(); 2573ba2be530Sab196087 dyn++; 2574ba2be530Sab196087 2575ba2be530Sab196087 (*ld_targ.t_mr.mr_mach_update_odynamic)(ofl, &dyn); 25767c478bd9Sstevel@tonic-gate 25773244bcaaSab196087 for (cnt = 1 + DYNAMIC_EXTRA_ELTS; cnt--; dyn++) { 25787c478bd9Sstevel@tonic-gate dyn->d_tag = DT_NULL; 25797c478bd9Sstevel@tonic-gate dyn->d_un.d_val = 0; 25803244bcaaSab196087 } 25817c478bd9Sstevel@tonic-gate 25825b59e4caSab196087 /* 2583635216b6SRod Evans * Ensure that we wrote the right number of entries. If not, we either 2584635216b6SRod Evans * miscounted in make_dynamic(), or we did something wrong in this 2585635216b6SRod Evans * function. 25865b59e4caSab196087 */ 25875b59e4caSab196087 assert((ofl->ofl_osdynamic->os_shdr->sh_size / 25885b59e4caSab196087 ofl->ofl_osdynamic->os_shdr->sh_entsize) == 25893244bcaaSab196087 ((uintptr_t)dyn - (uintptr_t)_dyn) / sizeof (*dyn)); 25905b59e4caSab196087 25917c478bd9Sstevel@tonic-gate return (1); 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate 25947c478bd9Sstevel@tonic-gate /* 25957c478bd9Sstevel@tonic-gate * Build the version definition section 25967c478bd9Sstevel@tonic-gate */ 25975aefb655Srie static int 25987c478bd9Sstevel@tonic-gate update_overdef(Ofl_desc *ofl) 25997c478bd9Sstevel@tonic-gate { 260057ef7aa9SRod Evans Aliste idx1; 26017c478bd9Sstevel@tonic-gate Ver_desc *vdp, *_vdp; 26027c478bd9Sstevel@tonic-gate Verdef *vdf, *_vdf; 26037c478bd9Sstevel@tonic-gate int num = 0; 2604090a8d9eSAli Bahrami Os_desc *strosp; 2605635216b6SRod Evans Str_tbl *strtbl; 2606635216b6SRod Evans 2607635216b6SRod Evans /* 2608635216b6SRod Evans * Determine which string table to use. 2609635216b6SRod Evans */ 2610635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 2611635216b6SRod Evans strtbl = ofl->ofl_strtab; 2612635216b6SRod Evans strosp = ofl->ofl_osstrtab; 2613635216b6SRod Evans } else { 2614635216b6SRod Evans strtbl = ofl->ofl_dynstrtab; 2615635216b6SRod Evans strosp = ofl->ofl_osdynstr; 2616635216b6SRod Evans } 26177c478bd9Sstevel@tonic-gate 26187c478bd9Sstevel@tonic-gate /* 26197c478bd9Sstevel@tonic-gate * Traverse the version descriptors and update the version structures 26207c478bd9Sstevel@tonic-gate * to point to the dynstr name in preparation for building the version 26217c478bd9Sstevel@tonic-gate * section structure. 26227c478bd9Sstevel@tonic-gate */ 262357ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) { 26247c478bd9Sstevel@tonic-gate Sym_desc *sdp; 26257c478bd9Sstevel@tonic-gate 26267c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_BASE) { 26277c478bd9Sstevel@tonic-gate const char *name = vdp->vd_name; 2628cce0e03bSab196087 size_t stoff; 26297c478bd9Sstevel@tonic-gate 26307c478bd9Sstevel@tonic-gate /* 26317c478bd9Sstevel@tonic-gate * Create a new string table entry to represent the base 26327c478bd9Sstevel@tonic-gate * version name (there is no corresponding symbol for 26337c478bd9Sstevel@tonic-gate * this). 26347c478bd9Sstevel@tonic-gate */ 2635635216b6SRod Evans (void) st_setstring(strtbl, name, &stoff); 26367c478bd9Sstevel@tonic-gate /* LINTED */ 2637cce0e03bSab196087 vdp->vd_name = (const char *)stoff; 26387c478bd9Sstevel@tonic-gate } else { 26395aefb655Srie sdp = ld_sym_find(vdp->vd_name, vdp->vd_hash, 0, ofl); 26407c478bd9Sstevel@tonic-gate /* LINTED */ 26417c478bd9Sstevel@tonic-gate vdp->vd_name = (const char *) 26427c478bd9Sstevel@tonic-gate (uintptr_t)sdp->sd_sym->st_name; 26437c478bd9Sstevel@tonic-gate } 26447c478bd9Sstevel@tonic-gate } 26457c478bd9Sstevel@tonic-gate 26467c478bd9Sstevel@tonic-gate _vdf = vdf = (Verdef *)ofl->ofl_osverdef->os_outdata->d_buf; 26477c478bd9Sstevel@tonic-gate 26487c478bd9Sstevel@tonic-gate /* 26497c478bd9Sstevel@tonic-gate * Traverse the version descriptors and update the version section to 26507c478bd9Sstevel@tonic-gate * reflect each version and its associated dependencies. 26517c478bd9Sstevel@tonic-gate */ 265257ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) { 265357ef7aa9SRod Evans Aliste idx2; 26547c478bd9Sstevel@tonic-gate Half cnt = 1; 26557c478bd9Sstevel@tonic-gate Verdaux *vdap, *_vdap; 26567c478bd9Sstevel@tonic-gate 26577c478bd9Sstevel@tonic-gate _vdap = vdap = (Verdaux *)(vdf + 1); 26587c478bd9Sstevel@tonic-gate 26597c478bd9Sstevel@tonic-gate vdf->vd_version = VER_DEF_CURRENT; 26607c478bd9Sstevel@tonic-gate vdf->vd_flags = vdp->vd_flags & MSK_VER_USER; 26617c478bd9Sstevel@tonic-gate vdf->vd_ndx = vdp->vd_ndx; 26627c478bd9Sstevel@tonic-gate vdf->vd_hash = vdp->vd_hash; 26637c478bd9Sstevel@tonic-gate 26647c478bd9Sstevel@tonic-gate /* LINTED */ 26657c478bd9Sstevel@tonic-gate vdap->vda_name = (uintptr_t)vdp->vd_name; 26667c478bd9Sstevel@tonic-gate vdap++; 26677c478bd9Sstevel@tonic-gate /* LINTED */ 26687c478bd9Sstevel@tonic-gate _vdap->vda_next = (Word)((uintptr_t)vdap - (uintptr_t)_vdap); 26697c478bd9Sstevel@tonic-gate 26707c478bd9Sstevel@tonic-gate /* 26717c478bd9Sstevel@tonic-gate * Traverse this versions dependency list generating the 26727c478bd9Sstevel@tonic-gate * appropriate version dependency entries. 26737c478bd9Sstevel@tonic-gate */ 267457ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx2, _vdp)) { 26757c478bd9Sstevel@tonic-gate /* LINTED */ 26767c478bd9Sstevel@tonic-gate vdap->vda_name = (uintptr_t)_vdp->vd_name; 26777c478bd9Sstevel@tonic-gate _vdap = vdap; 26787c478bd9Sstevel@tonic-gate vdap++, cnt++; 26797c478bd9Sstevel@tonic-gate /* LINTED */ 26807c478bd9Sstevel@tonic-gate _vdap->vda_next = (Word)((uintptr_t)vdap - 26817c478bd9Sstevel@tonic-gate (uintptr_t)_vdap); 26827c478bd9Sstevel@tonic-gate } 26837c478bd9Sstevel@tonic-gate _vdap->vda_next = 0; 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gate /* 26867c478bd9Sstevel@tonic-gate * Record the versions auxiliary array offset and the associated 26877c478bd9Sstevel@tonic-gate * dependency count. 26887c478bd9Sstevel@tonic-gate */ 26897c478bd9Sstevel@tonic-gate /* LINTED */ 26907c478bd9Sstevel@tonic-gate vdf->vd_aux = (Word)((uintptr_t)(vdf + 1) - (uintptr_t)vdf); 26917c478bd9Sstevel@tonic-gate vdf->vd_cnt = cnt; 26927c478bd9Sstevel@tonic-gate 26937c478bd9Sstevel@tonic-gate /* 26947c478bd9Sstevel@tonic-gate * Record the next versions offset and update the version 26957c478bd9Sstevel@tonic-gate * pointer. Remember the previous version offset as the very 26967c478bd9Sstevel@tonic-gate * last structures next pointer should be null. 26977c478bd9Sstevel@tonic-gate */ 26987c478bd9Sstevel@tonic-gate _vdf = vdf; 26997c478bd9Sstevel@tonic-gate vdf = (Verdef *)vdap, num++; 27007c478bd9Sstevel@tonic-gate /* LINTED */ 27017c478bd9Sstevel@tonic-gate _vdf->vd_next = (Word)((uintptr_t)vdf - (uintptr_t)_vdf); 27027c478bd9Sstevel@tonic-gate } 27037c478bd9Sstevel@tonic-gate _vdf->vd_next = 0; 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate /* 27067c478bd9Sstevel@tonic-gate * Record the string table association with the version definition 27077c478bd9Sstevel@tonic-gate * section, and the symbol table associated with the version symbol 27087c478bd9Sstevel@tonic-gate * table (the actual contents of the version symbol table are filled 27097c478bd9Sstevel@tonic-gate * in during symbol update). 27107c478bd9Sstevel@tonic-gate */ 27117c478bd9Sstevel@tonic-gate /* LINTED */ 27127c478bd9Sstevel@tonic-gate ofl->ofl_osverdef->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn); 27137c478bd9Sstevel@tonic-gate 27147c478bd9Sstevel@tonic-gate /* 27157c478bd9Sstevel@tonic-gate * The version definition sections `info' field is used to indicate the 27167c478bd9Sstevel@tonic-gate * number of entries in this section. 27177c478bd9Sstevel@tonic-gate */ 27187c478bd9Sstevel@tonic-gate ofl->ofl_osverdef->os_shdr->sh_info = num; 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate return (1); 27217c478bd9Sstevel@tonic-gate } 27227c478bd9Sstevel@tonic-gate 27237c478bd9Sstevel@tonic-gate /* 2724090a8d9eSAli Bahrami * Finish the version symbol index section 2725090a8d9eSAli Bahrami */ 2726635216b6SRod Evans static void 2727090a8d9eSAli Bahrami update_oversym(Ofl_desc *ofl) 2728090a8d9eSAli Bahrami { 2729635216b6SRod Evans Os_desc *osp; 2730090a8d9eSAli Bahrami 2731090a8d9eSAli Bahrami /* 2732635216b6SRod Evans * Record the symbol table associated with the version symbol table. 2733635216b6SRod Evans * The contents of the version symbol table are filled in during 2734635216b6SRod Evans * symbol update. 2735090a8d9eSAli Bahrami */ 2736635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) 2737635216b6SRod Evans osp = ofl->ofl_ossymtab; 2738635216b6SRod Evans else 2739635216b6SRod Evans osp = ofl->ofl_osdynsym; 2740090a8d9eSAli Bahrami 2741090a8d9eSAli Bahrami /* LINTED */ 2742635216b6SRod Evans ofl->ofl_osversym->os_shdr->sh_link = (Word)elf_ndxscn(osp->os_scn); 2743090a8d9eSAli Bahrami } 2744090a8d9eSAli Bahrami 2745090a8d9eSAli Bahrami /* 27467c478bd9Sstevel@tonic-gate * Build the version needed section 27477c478bd9Sstevel@tonic-gate */ 27485aefb655Srie static int 27497c478bd9Sstevel@tonic-gate update_overneed(Ofl_desc *ofl) 27507c478bd9Sstevel@tonic-gate { 275157ef7aa9SRod Evans Aliste idx1; 27527c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 27537c478bd9Sstevel@tonic-gate Verneed *vnd, *_vnd; 2754635216b6SRod Evans Os_desc *strosp; 2755635216b6SRod Evans Str_tbl *strtbl; 2756090a8d9eSAli Bahrami Word num = 0; 27577c478bd9Sstevel@tonic-gate 27587c478bd9Sstevel@tonic-gate _vnd = vnd = (Verneed *)ofl->ofl_osverneed->os_outdata->d_buf; 27597c478bd9Sstevel@tonic-gate 27607c478bd9Sstevel@tonic-gate /* 2761635216b6SRod Evans * Determine which string table is appropriate. 2762635216b6SRod Evans */ 2763635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 2764635216b6SRod Evans strosp = ofl->ofl_osstrtab; 2765635216b6SRod Evans strtbl = ofl->ofl_strtab; 2766635216b6SRod Evans } else { 2767635216b6SRod Evans strosp = ofl->ofl_osdynstr; 2768635216b6SRod Evans strtbl = ofl->ofl_dynstrtab; 2769635216b6SRod Evans } 2770635216b6SRod Evans 2771635216b6SRod Evans /* 27727c478bd9Sstevel@tonic-gate * Traverse the shared object list looking for dependencies that have 27737c478bd9Sstevel@tonic-gate * versions defined within them. 27747c478bd9Sstevel@tonic-gate */ 277557ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_sos, idx1, ifl)) { 27767c478bd9Sstevel@tonic-gate Half _cnt; 2777090a8d9eSAli Bahrami Word cnt = 0; 27787c478bd9Sstevel@tonic-gate Vernaux *_vnap, *vnap; 2779cce0e03bSab196087 size_t stoff; 27807c478bd9Sstevel@tonic-gate 27817c478bd9Sstevel@tonic-gate if (!(ifl->ifl_flags & FLG_IF_VERNEED)) 27827c478bd9Sstevel@tonic-gate continue; 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate vnd->vn_version = VER_NEED_CURRENT; 27857c478bd9Sstevel@tonic-gate 2786635216b6SRod Evans (void) st_setstring(strtbl, ifl->ifl_soname, &stoff); 27877c478bd9Sstevel@tonic-gate vnd->vn_file = stoff; 27887c478bd9Sstevel@tonic-gate 27897c478bd9Sstevel@tonic-gate _vnap = vnap = (Vernaux *)(vnd + 1); 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate /* 27927c478bd9Sstevel@tonic-gate * Traverse the version index list recording 27937c478bd9Sstevel@tonic-gate * each version as a needed dependency. 27947c478bd9Sstevel@tonic-gate */ 2795090a8d9eSAli Bahrami for (_cnt = 0; _cnt <= ifl->ifl_vercnt; _cnt++) { 27967c478bd9Sstevel@tonic-gate Ver_index *vip = &ifl->ifl_verndx[_cnt]; 27977c478bd9Sstevel@tonic-gate 27987c478bd9Sstevel@tonic-gate if (vip->vi_flags & FLG_VER_REFER) { 2799635216b6SRod Evans (void) st_setstring(strtbl, vip->vi_name, 2800090a8d9eSAli Bahrami &stoff); 28017c478bd9Sstevel@tonic-gate vnap->vna_name = stoff; 280260758829Srie 28037c478bd9Sstevel@tonic-gate if (vip->vi_desc) { 2804090a8d9eSAli Bahrami vnap->vna_hash = vip->vi_desc->vd_hash; 28057c478bd9Sstevel@tonic-gate vnap->vna_flags = 28067c478bd9Sstevel@tonic-gate vip->vi_desc->vd_flags; 28077c478bd9Sstevel@tonic-gate } else { 28087c478bd9Sstevel@tonic-gate vnap->vna_hash = 0; 28097c478bd9Sstevel@tonic-gate vnap->vna_flags = 0; 28107c478bd9Sstevel@tonic-gate } 2811090a8d9eSAli Bahrami vnap->vna_other = vip->vi_overndx; 2812090a8d9eSAli Bahrami 2813090a8d9eSAli Bahrami /* 2814090a8d9eSAli Bahrami * If version A inherits version B, then 2815090a8d9eSAli Bahrami * B is implicit in A. It suffices for ld.so.1 2816090a8d9eSAli Bahrami * to verify A at runtime and skip B. The 2817090a8d9eSAli Bahrami * version normalization process sets the INFO 2818090a8d9eSAli Bahrami * flag for the versions we want ld.so.1 to 28194a8d0ea7SAli Bahrami * skip. 2820090a8d9eSAli Bahrami */ 28214a8d0ea7SAli Bahrami if (vip->vi_flags & VER_FLG_INFO) 2822090a8d9eSAli Bahrami vnap->vna_flags |= VER_FLG_INFO; 28237c478bd9Sstevel@tonic-gate 28247c478bd9Sstevel@tonic-gate _vnap = vnap; 28257c478bd9Sstevel@tonic-gate vnap++, cnt++; 28267c478bd9Sstevel@tonic-gate _vnap->vna_next = 28277c478bd9Sstevel@tonic-gate /* LINTED */ 2828090a8d9eSAli Bahrami (Word)((uintptr_t)vnap - (uintptr_t)_vnap); 28297c478bd9Sstevel@tonic-gate } 28307c478bd9Sstevel@tonic-gate } 2831090a8d9eSAli Bahrami 28327c478bd9Sstevel@tonic-gate _vnap->vna_next = 0; 28337c478bd9Sstevel@tonic-gate 28347c478bd9Sstevel@tonic-gate /* 28357c478bd9Sstevel@tonic-gate * Record the versions auxiliary array offset and 28367c478bd9Sstevel@tonic-gate * the associated dependency count. 28377c478bd9Sstevel@tonic-gate */ 28387c478bd9Sstevel@tonic-gate /* LINTED */ 28397c478bd9Sstevel@tonic-gate vnd->vn_aux = (Word)((uintptr_t)(vnd + 1) - (uintptr_t)vnd); 28407c478bd9Sstevel@tonic-gate /* LINTED */ 28417c478bd9Sstevel@tonic-gate vnd->vn_cnt = (Half)cnt; 28427c478bd9Sstevel@tonic-gate 28437c478bd9Sstevel@tonic-gate /* 28447c478bd9Sstevel@tonic-gate * Record the next versions offset and update the version 28457c478bd9Sstevel@tonic-gate * pointer. Remember the previous version offset as the very 28467c478bd9Sstevel@tonic-gate * last structures next pointer should be null. 28477c478bd9Sstevel@tonic-gate */ 28487c478bd9Sstevel@tonic-gate _vnd = vnd; 28497c478bd9Sstevel@tonic-gate vnd = (Verneed *)vnap, num++; 28507c478bd9Sstevel@tonic-gate /* LINTED */ 28517c478bd9Sstevel@tonic-gate _vnd->vn_next = (Word)((uintptr_t)vnd - (uintptr_t)_vnd); 28527c478bd9Sstevel@tonic-gate } 28537c478bd9Sstevel@tonic-gate _vnd->vn_next = 0; 28547c478bd9Sstevel@tonic-gate 28557c478bd9Sstevel@tonic-gate /* 2856635216b6SRod Evans * Use sh_link to record the associated string table section, and 2857635216b6SRod Evans * sh_info to indicate the number of entries contained in the section. 28587c478bd9Sstevel@tonic-gate */ 28597c478bd9Sstevel@tonic-gate /* LINTED */ 2860635216b6SRod Evans ofl->ofl_osverneed->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn); 28617c478bd9Sstevel@tonic-gate ofl->ofl_osverneed->os_shdr->sh_info = num; 28627c478bd9Sstevel@tonic-gate 28637c478bd9Sstevel@tonic-gate return (1); 28647c478bd9Sstevel@tonic-gate } 28657c478bd9Sstevel@tonic-gate 28667c478bd9Sstevel@tonic-gate /* 28677c478bd9Sstevel@tonic-gate * Update syminfo section. 28687c478bd9Sstevel@tonic-gate */ 28695aefb655Srie static uintptr_t 28707c478bd9Sstevel@tonic-gate update_osyminfo(Ofl_desc *ofl) 28717c478bd9Sstevel@tonic-gate { 28727c478bd9Sstevel@tonic-gate Os_desc *symosp, *infosp = ofl->ofl_ossyminfo; 28737c478bd9Sstevel@tonic-gate Syminfo *sip = infosp->os_outdata->d_buf; 28747c478bd9Sstevel@tonic-gate Shdr *shdr = infosp->os_shdr; 28757c478bd9Sstevel@tonic-gate char *strtab; 2876cce0e03bSab196087 Aliste idx; 287757ef7aa9SRod Evans Sym_desc *sdp; 28787c478bd9Sstevel@tonic-gate Sfltr_desc *sftp; 28797c478bd9Sstevel@tonic-gate 28807c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_RELOBJ) { 28817c478bd9Sstevel@tonic-gate symosp = ofl->ofl_ossymtab; 28827c478bd9Sstevel@tonic-gate strtab = ofl->ofl_osstrtab->os_outdata->d_buf; 28837c478bd9Sstevel@tonic-gate } else { 28847c478bd9Sstevel@tonic-gate symosp = ofl->ofl_osdynsym; 28857c478bd9Sstevel@tonic-gate strtab = ofl->ofl_osdynstr->os_outdata->d_buf; 28867c478bd9Sstevel@tonic-gate } 28877c478bd9Sstevel@tonic-gate 28887c478bd9Sstevel@tonic-gate /* LINTED */ 28897c478bd9Sstevel@tonic-gate infosp->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn); 28907c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynamic) 28917c478bd9Sstevel@tonic-gate infosp->os_shdr->sh_info = 28927c478bd9Sstevel@tonic-gate /* LINTED */ 28937c478bd9Sstevel@tonic-gate (Word)elf_ndxscn(ofl->ofl_osdynamic->os_scn); 28947c478bd9Sstevel@tonic-gate 28957c478bd9Sstevel@tonic-gate /* 28967c478bd9Sstevel@tonic-gate * Update any references with the index into the dynamic table. 28977c478bd9Sstevel@tonic-gate */ 2898635216b6SRod Evans for (APLIST_TRAVERSE(ofl->ofl_symdtent, idx, sdp)) 2899635216b6SRod Evans sip[sdp->sd_symndx].si_boundto = sdp->sd_file->ifl_neededndx; 29007c478bd9Sstevel@tonic-gate 29017c478bd9Sstevel@tonic-gate /* 29027c478bd9Sstevel@tonic-gate * Update any filtee references with the index into the dynamic table. 29037c478bd9Sstevel@tonic-gate */ 2904cce0e03bSab196087 for (ALIST_TRAVERSE(ofl->ofl_symfltrs, idx, sftp)) { 29057c478bd9Sstevel@tonic-gate Dfltr_desc *dftp; 29067c478bd9Sstevel@tonic-gate 2907cce0e03bSab196087 dftp = alist_item(ofl->ofl_dtsfltrs, sftp->sft_idx); 29087c478bd9Sstevel@tonic-gate sip[sftp->sft_sdp->sd_symndx].si_boundto = dftp->dft_ndx; 29097c478bd9Sstevel@tonic-gate } 29107c478bd9Sstevel@tonic-gate 29117c478bd9Sstevel@tonic-gate /* 29127c478bd9Sstevel@tonic-gate * Display debugging information about section. 29137c478bd9Sstevel@tonic-gate */ 29145aefb655Srie DBG_CALL(Dbg_syminfo_title(ofl->ofl_lml)); 29155aefb655Srie if (DBG_ENABLED) { 29165aefb655Srie Word _cnt, cnt = shdr->sh_size / shdr->sh_entsize; 29177c478bd9Sstevel@tonic-gate Sym *symtab = symosp->os_outdata->d_buf; 29187c478bd9Sstevel@tonic-gate Dyn *dyn; 29197c478bd9Sstevel@tonic-gate 29207c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynamic) 29217c478bd9Sstevel@tonic-gate dyn = ofl->ofl_osdynamic->os_outdata->d_buf; 29227c478bd9Sstevel@tonic-gate else 292357ef7aa9SRod Evans dyn = NULL; 29247c478bd9Sstevel@tonic-gate 29257c478bd9Sstevel@tonic-gate for (_cnt = 1; _cnt < cnt; _cnt++) { 29267c478bd9Sstevel@tonic-gate if (sip[_cnt].si_flags || sip[_cnt].si_boundto) 29277c478bd9Sstevel@tonic-gate /* LINTED */ 29285aefb655Srie DBG_CALL(Dbg_syminfo_entry(ofl->ofl_lml, _cnt, 29297c478bd9Sstevel@tonic-gate &sip[_cnt], &symtab[_cnt], strtab, dyn)); 29307c478bd9Sstevel@tonic-gate } 29317c478bd9Sstevel@tonic-gate } 29327c478bd9Sstevel@tonic-gate return (1); 29337c478bd9Sstevel@tonic-gate } 29347c478bd9Sstevel@tonic-gate 29357c478bd9Sstevel@tonic-gate /* 29367c478bd9Sstevel@tonic-gate * Build the output elf header. 29377c478bd9Sstevel@tonic-gate */ 29385aefb655Srie static uintptr_t 29397c478bd9Sstevel@tonic-gate update_oehdr(Ofl_desc * ofl) 29407c478bd9Sstevel@tonic-gate { 29415aefb655Srie Ehdr *ehdr = ofl->ofl_nehdr; 29427c478bd9Sstevel@tonic-gate 29437c478bd9Sstevel@tonic-gate /* 29447c478bd9Sstevel@tonic-gate * If an entry point symbol has already been established (refer 29457c478bd9Sstevel@tonic-gate * sym_validate()) simply update the elf header entry point with the 29467c478bd9Sstevel@tonic-gate * symbols value. If no entry point is defined it will have been filled 29477c478bd9Sstevel@tonic-gate * with the start address of the first section within the text segment 29487c478bd9Sstevel@tonic-gate * (refer update_outfile()). 29497c478bd9Sstevel@tonic-gate */ 29507c478bd9Sstevel@tonic-gate if (ofl->ofl_entry) 29517c478bd9Sstevel@tonic-gate ehdr->e_entry = 29527c478bd9Sstevel@tonic-gate ((Sym_desc *)(ofl->ofl_entry))->sd_sym->st_value; 29537c478bd9Sstevel@tonic-gate 295498c080d5SRod Evans ehdr->e_ident[EI_DATA] = ld_targ.t_m.m_data; 295598c080d5SRod Evans ehdr->e_version = ofl->ofl_dehdr->e_version; 295698c080d5SRod Evans 29577c478bd9Sstevel@tonic-gate /* 295898c080d5SRod Evans * When generating a relocatable object under -z symbolcap, set the 295998c080d5SRod Evans * e_machine to be generic, and remove any e_flags. Input relocatable 296098c080d5SRod Evans * objects may identify alternative e_machine (m.machplus) and e_flags 296198c080d5SRod Evans * values. However, the functions within the created output object 296298c080d5SRod Evans * are selected at runtime using the capabilities mechanism, which 296398c080d5SRod Evans * supersedes the e-machine and e_flags information. Therefore, 296498c080d5SRod Evans * e_machine and e_flag values are not propagated to the output object, 296598c080d5SRod Evans * as these values might prevent the kernel from loading the object 296698c080d5SRod Evans * before the runtime linker gets control. 296798c080d5SRod Evans */ 296898c080d5SRod Evans if (ofl->ofl_flags & FLG_OF_OTOSCAP) { 296998c080d5SRod Evans ehdr->e_machine = ld_targ.t_m.m_mach; 297098c080d5SRod Evans ehdr->e_flags = 0; 297198c080d5SRod Evans } else { 297298c080d5SRod Evans /* 297398c080d5SRod Evans * Note. it may be necessary to update the e_flags field in the 29747c478bd9Sstevel@tonic-gate * machine dependent section. 29757c478bd9Sstevel@tonic-gate */ 29765aefb655Srie ehdr->e_machine = ofl->ofl_dehdr->e_machine; 29775aefb655Srie ehdr->e_flags = ofl->ofl_dehdr->e_flags; 29785aefb655Srie 2979ba2be530Sab196087 if (ehdr->e_machine != ld_targ.t_m.m_mach) { 2980ba2be530Sab196087 if (ehdr->e_machine != ld_targ.t_m.m_machplus) 29817c478bd9Sstevel@tonic-gate return (S_ERROR); 2982ba2be530Sab196087 if ((ehdr->e_flags & ld_targ.t_m.m_flagsplus) == 0) 29837c478bd9Sstevel@tonic-gate return (S_ERROR); 29847c478bd9Sstevel@tonic-gate } 298598c080d5SRod Evans } 29867c478bd9Sstevel@tonic-gate 29877c478bd9Sstevel@tonic-gate if (ofl->ofl_flags & FLG_OF_SHAROBJ) 29887c478bd9Sstevel@tonic-gate ehdr->e_type = ET_DYN; 29897c478bd9Sstevel@tonic-gate else if (ofl->ofl_flags & FLG_OF_RELOBJ) 29907c478bd9Sstevel@tonic-gate ehdr->e_type = ET_REL; 29917c478bd9Sstevel@tonic-gate else 29927c478bd9Sstevel@tonic-gate ehdr->e_type = ET_EXEC; 29937c478bd9Sstevel@tonic-gate 29947c478bd9Sstevel@tonic-gate return (1); 29957c478bd9Sstevel@tonic-gate } 29967c478bd9Sstevel@tonic-gate 29977c478bd9Sstevel@tonic-gate /* 29987c478bd9Sstevel@tonic-gate * Perform move table expansion. 29997c478bd9Sstevel@tonic-gate */ 300057ef7aa9SRod Evans static void 300157ef7aa9SRod Evans expand_move(Ofl_desc *ofl, Sym_desc *sdp, Move *mvp) 30027c478bd9Sstevel@tonic-gate { 30037c478bd9Sstevel@tonic-gate Os_desc *osp; 300457ef7aa9SRod Evans uchar_t *taddr, *taddr0; 30057c478bd9Sstevel@tonic-gate Sxword offset; 300657ef7aa9SRod Evans Half cnt; 300757ef7aa9SRod Evans uint_t stride; 30087c478bd9Sstevel@tonic-gate 300935450702SAli Bahrami osp = ofl->ofl_isparexpn->is_osdesc; 3010b26cc8daSAli Bahrami offset = sdp->sd_sym->st_value - osp->os_shdr->sh_addr; 301157ef7aa9SRod Evans 301257ef7aa9SRod Evans taddr0 = taddr = osp->os_outdata->d_buf; 30137c478bd9Sstevel@tonic-gate taddr += offset; 301457ef7aa9SRod Evans taddr = taddr + mvp->m_poffset; 301557ef7aa9SRod Evans 301657ef7aa9SRod Evans for (cnt = 0; cnt < mvp->m_repeat; cnt++) { 30177c478bd9Sstevel@tonic-gate /* LINTED */ 301857ef7aa9SRod Evans DBG_CALL(Dbg_move_expand(ofl->ofl_lml, mvp, 30195aefb655Srie (Addr)(taddr - taddr0))); 302057ef7aa9SRod Evans stride = (uint_t)mvp->m_stride + 1; 302157ef7aa9SRod Evans 302257ef7aa9SRod Evans /* 302357ef7aa9SRod Evans * Update the target address based upon the move entry size. 302457ef7aa9SRod Evans * This size was validated in ld_process_move(). 302557ef7aa9SRod Evans */ 30267c478bd9Sstevel@tonic-gate /* LINTED */ 302757ef7aa9SRod Evans switch (ELF_M_SIZE(mvp->m_info)) { 30287c478bd9Sstevel@tonic-gate case 1: 30297c478bd9Sstevel@tonic-gate /* LINTED */ 303057ef7aa9SRod Evans *taddr = (uchar_t)mvp->m_value; 30317c478bd9Sstevel@tonic-gate taddr += stride; 30327c478bd9Sstevel@tonic-gate break; 30337c478bd9Sstevel@tonic-gate case 2: 30347c478bd9Sstevel@tonic-gate /* LINTED */ 303557ef7aa9SRod Evans *((Half *)taddr) = (Half)mvp->m_value; 30367c478bd9Sstevel@tonic-gate taddr += 2 * stride; 30377c478bd9Sstevel@tonic-gate break; 30387c478bd9Sstevel@tonic-gate case 4: 30397c478bd9Sstevel@tonic-gate /* LINTED */ 304057ef7aa9SRod Evans *((Word *)taddr) = (Word)mvp->m_value; 30417c478bd9Sstevel@tonic-gate taddr += 4 * stride; 30427c478bd9Sstevel@tonic-gate break; 30437c478bd9Sstevel@tonic-gate case 8: 30447c478bd9Sstevel@tonic-gate /* LINTED */ 304557ef7aa9SRod Evans *((u_longlong_t *)taddr) = mvp->m_value; 30467c478bd9Sstevel@tonic-gate taddr += 8 * stride; 30477c478bd9Sstevel@tonic-gate break; 30487c478bd9Sstevel@tonic-gate } 30497c478bd9Sstevel@tonic-gate } 30507c478bd9Sstevel@tonic-gate } 30517c478bd9Sstevel@tonic-gate 30527c478bd9Sstevel@tonic-gate /* 30537c478bd9Sstevel@tonic-gate * Update Move sections. 30547c478bd9Sstevel@tonic-gate */ 305557ef7aa9SRod Evans static void 30567c478bd9Sstevel@tonic-gate update_move(Ofl_desc *ofl) 30577c478bd9Sstevel@tonic-gate { 30587c478bd9Sstevel@tonic-gate Word ndx = 0; 30591d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 306057ef7aa9SRod Evans Move *omvp; 306157ef7aa9SRod Evans Aliste idx1; 306257ef7aa9SRod Evans Sym_desc *sdp; 30637c478bd9Sstevel@tonic-gate 30647c478bd9Sstevel@tonic-gate /* 30657c478bd9Sstevel@tonic-gate * Determine the index of the symbol table that will be referenced by 306657ef7aa9SRod Evans * the Move section. 30677c478bd9Sstevel@tonic-gate */ 30689039eeafSab196087 if (OFL_ALLOW_DYNSYM(ofl)) 30697c478bd9Sstevel@tonic-gate /* LINTED */ 30707c478bd9Sstevel@tonic-gate ndx = (Word) elf_ndxscn(ofl->ofl_osdynsym->os_scn); 30717c478bd9Sstevel@tonic-gate else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ)) 30727c478bd9Sstevel@tonic-gate /* LINTED */ 30737c478bd9Sstevel@tonic-gate ndx = (Word) elf_ndxscn(ofl->ofl_ossymtab->os_scn); 30747c478bd9Sstevel@tonic-gate 30757c478bd9Sstevel@tonic-gate /* 307657ef7aa9SRod Evans * Update sh_link of the Move section, and point to the new Move data. 30777c478bd9Sstevel@tonic-gate */ 30787c478bd9Sstevel@tonic-gate if (ofl->ofl_osmove) { 30797c478bd9Sstevel@tonic-gate ofl->ofl_osmove->os_shdr->sh_link = ndx; 308057ef7aa9SRod Evans omvp = (Move *)ofl->ofl_osmove->os_outdata->d_buf; 30817c478bd9Sstevel@tonic-gate } 30827c478bd9Sstevel@tonic-gate 30837c478bd9Sstevel@tonic-gate /* 30847c478bd9Sstevel@tonic-gate * Update symbol entry index 30857c478bd9Sstevel@tonic-gate */ 308657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_parsyms, idx1, sdp)) { 308757ef7aa9SRod Evans Aliste idx2; 308857ef7aa9SRod Evans Mv_desc *mdp; 30897c478bd9Sstevel@tonic-gate 30907c478bd9Sstevel@tonic-gate /* 30917c478bd9Sstevel@tonic-gate * Expand move table 30927c478bd9Sstevel@tonic-gate */ 309357ef7aa9SRod Evans if (sdp->sd_flags & FLG_SY_PAREXPN) { 309457ef7aa9SRod Evans const char *str; 30957c478bd9Sstevel@tonic-gate 30961d9df23bSab196087 if (flags & FLG_OF_STATIC) 309757ef7aa9SRod Evans str = MSG_INTL(MSG_PSYM_EXPREASON1); 30987c478bd9Sstevel@tonic-gate else if (ofl->ofl_flags1 & FLG_OF1_NOPARTI) 309957ef7aa9SRod Evans str = MSG_INTL(MSG_PSYM_EXPREASON2); 31007c478bd9Sstevel@tonic-gate else 310157ef7aa9SRod Evans str = MSG_INTL(MSG_PSYM_EXPREASON3); 310257ef7aa9SRod Evans 31035aefb655Srie DBG_CALL(Dbg_move_parexpn(ofl->ofl_lml, 310457ef7aa9SRod Evans sdp->sd_name, str)); 310557ef7aa9SRod Evans 310657ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_move, idx2, mdp)) { 31075aefb655Srie DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0, 310857ef7aa9SRod Evans mdp->md_move, sdp)); 310957ef7aa9SRod Evans expand_move(ofl, sdp, mdp->md_move); 31107c478bd9Sstevel@tonic-gate } 31117c478bd9Sstevel@tonic-gate continue; 31127c478bd9Sstevel@tonic-gate } 31137c478bd9Sstevel@tonic-gate 31147c478bd9Sstevel@tonic-gate /* 31157c478bd9Sstevel@tonic-gate * Process move table 31167c478bd9Sstevel@tonic-gate */ 311757ef7aa9SRod Evans DBG_CALL(Dbg_move_outmove(ofl->ofl_lml, sdp->sd_name)); 311857ef7aa9SRod Evans 311957ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_move, idx2, mdp)) { 312057ef7aa9SRod Evans Move *imvp; 31217c478bd9Sstevel@tonic-gate int idx = 1; 312260758829Srie Sym *sym; 312360758829Srie 312457ef7aa9SRod Evans imvp = mdp->md_move; 312560758829Srie sym = sdp->sd_sym; 31267c478bd9Sstevel@tonic-gate 312757ef7aa9SRod Evans DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 1, imvp, sdp)); 312860758829Srie 312957ef7aa9SRod Evans *omvp = *imvp; 31301d9df23bSab196087 if ((flags & FLG_OF_RELOBJ) == 0) { 313160758829Srie if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) { 313257ef7aa9SRod Evans Os_desc *osp = sdp->sd_isc->is_osdesc; 313357ef7aa9SRod Evans Word ndx = osp->os_identndx; 313460758829Srie 313557ef7aa9SRod Evans omvp->m_info = 31367c478bd9Sstevel@tonic-gate /* LINTED */ 313757ef7aa9SRod Evans ELF_M_INFO(ndx, imvp->m_info); 313860758829Srie 313960758829Srie if (ELF_ST_TYPE(sym->st_info) != 31407c478bd9Sstevel@tonic-gate STT_SECTION) { 314157ef7aa9SRod Evans omvp->m_poffset = 314257ef7aa9SRod Evans sym->st_value - 314357ef7aa9SRod Evans osp->os_shdr->sh_addr + 314457ef7aa9SRod Evans imvp->m_poffset; 31457c478bd9Sstevel@tonic-gate } 31467c478bd9Sstevel@tonic-gate } else { 314757ef7aa9SRod Evans omvp->m_info = 31487c478bd9Sstevel@tonic-gate /* LINTED */ 3149d840867fSab196087 ELF_M_INFO(sdp->sd_symndx, 315057ef7aa9SRod Evans imvp->m_info); 31517c478bd9Sstevel@tonic-gate } 31527c478bd9Sstevel@tonic-gate } else { 31537c478bd9Sstevel@tonic-gate Boolean isredloc = FALSE; 31547c478bd9Sstevel@tonic-gate 315560758829Srie if ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) && 315644bac77bSrie (ofl->ofl_flags & FLG_OF_REDLSYM)) 31577c478bd9Sstevel@tonic-gate isredloc = TRUE; 31587c478bd9Sstevel@tonic-gate 315957ef7aa9SRod Evans if (isredloc && !(sdp->sd_move)) { 316057ef7aa9SRod Evans Os_desc *osp = sdp->sd_isc->is_osdesc; 316157ef7aa9SRod Evans Word ndx = osp->os_identndx; 316260758829Srie 316357ef7aa9SRod Evans omvp->m_info = 31647c478bd9Sstevel@tonic-gate /* LINTED */ 316557ef7aa9SRod Evans ELF_M_INFO(ndx, imvp->m_info); 316657ef7aa9SRod Evans 316757ef7aa9SRod Evans omvp->m_poffset += sym->st_value; 31687c478bd9Sstevel@tonic-gate } else { 31697c478bd9Sstevel@tonic-gate if (isredloc) 31705aefb655Srie DBG_CALL(Dbg_syms_reduce(ofl, 317157ef7aa9SRod Evans DBG_SYM_REDUCE_RETAIN, 317257ef7aa9SRod Evans sdp, idx, 3173d840867fSab196087 ofl->ofl_osmove->os_name)); 31747c478bd9Sstevel@tonic-gate 317557ef7aa9SRod Evans omvp->m_info = 31767c478bd9Sstevel@tonic-gate /* LINTED */ 3177d840867fSab196087 ELF_M_INFO(sdp->sd_symndx, 317857ef7aa9SRod Evans imvp->m_info); 31797c478bd9Sstevel@tonic-gate } 31807c478bd9Sstevel@tonic-gate } 318157ef7aa9SRod Evans 318257ef7aa9SRod Evans DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0, omvp, sdp)); 318357ef7aa9SRod Evans omvp++; 31847c478bd9Sstevel@tonic-gate idx++; 31857c478bd9Sstevel@tonic-gate } 31867c478bd9Sstevel@tonic-gate } 31877c478bd9Sstevel@tonic-gate } 31887c478bd9Sstevel@tonic-gate 31897c478bd9Sstevel@tonic-gate /* 319057ef7aa9SRod Evans * Scan through the SHT_GROUP output sections. Update their sh_link/sh_info 319157ef7aa9SRod Evans * fields as well as the section contents. 31927c478bd9Sstevel@tonic-gate */ 31935aefb655Srie static uintptr_t 31947c478bd9Sstevel@tonic-gate update_ogroup(Ofl_desc *ofl) 31957c478bd9Sstevel@tonic-gate { 319657ef7aa9SRod Evans Aliste idx; 31977c478bd9Sstevel@tonic-gate Os_desc *osp; 31987c478bd9Sstevel@tonic-gate uintptr_t error = 0; 31997c478bd9Sstevel@tonic-gate 320057ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_osgroups, idx, osp)) { 32017c478bd9Sstevel@tonic-gate Is_desc *isp; 32027c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 32037c478bd9Sstevel@tonic-gate Shdr *shdr = osp->os_shdr; 32047c478bd9Sstevel@tonic-gate Sym_desc *sdp; 32057c478bd9Sstevel@tonic-gate Xword i, grpcnt; 32067c478bd9Sstevel@tonic-gate Word *gdata; 32077c478bd9Sstevel@tonic-gate 32087c478bd9Sstevel@tonic-gate /* 32097c478bd9Sstevel@tonic-gate * Since input GROUP sections always create unique 32107c478bd9Sstevel@tonic-gate * output GROUP sections - we know there is only one 32117c478bd9Sstevel@tonic-gate * item on the list. 32127c478bd9Sstevel@tonic-gate */ 32131dd9d86fSAli Bahrami isp = ld_os_first_isdesc(osp); 32147c478bd9Sstevel@tonic-gate 32157c478bd9Sstevel@tonic-gate ifl = isp->is_file; 32167c478bd9Sstevel@tonic-gate sdp = ifl->ifl_oldndx[isp->is_shdr->sh_info]; 32177c478bd9Sstevel@tonic-gate shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn); 32187c478bd9Sstevel@tonic-gate shdr->sh_info = sdp->sd_symndx; 32197c478bd9Sstevel@tonic-gate 32207c478bd9Sstevel@tonic-gate /* 32217c478bd9Sstevel@tonic-gate * Scan through the group data section and update 32227c478bd9Sstevel@tonic-gate * all of the links to new values. 32237c478bd9Sstevel@tonic-gate */ 32247c478bd9Sstevel@tonic-gate grpcnt = shdr->sh_size / shdr->sh_entsize; 32257c478bd9Sstevel@tonic-gate gdata = (Word *)osp->os_outdata->d_buf; 32260e233487SRod Evans 32277c478bd9Sstevel@tonic-gate for (i = 1; i < grpcnt; i++) { 32287c478bd9Sstevel@tonic-gate Os_desc *_osp; 32290e233487SRod Evans Is_desc *_isp = ifl->ifl_isdesc[gdata[i]]; 32307c478bd9Sstevel@tonic-gate 32317c478bd9Sstevel@tonic-gate /* 32327c478bd9Sstevel@tonic-gate * If the referenced section didn't make it to the 32337c478bd9Sstevel@tonic-gate * output file - just zero out the entry. 32347c478bd9Sstevel@tonic-gate */ 32350e233487SRod Evans if ((_osp = _isp->is_osdesc) == NULL) 32367c478bd9Sstevel@tonic-gate gdata[i] = 0; 32377c478bd9Sstevel@tonic-gate else 32387c478bd9Sstevel@tonic-gate gdata[i] = (Word)elf_ndxscn(_osp->os_scn); 32397c478bd9Sstevel@tonic-gate } 32407c478bd9Sstevel@tonic-gate } 32417c478bd9Sstevel@tonic-gate return (error); 32427c478bd9Sstevel@tonic-gate } 32437c478bd9Sstevel@tonic-gate 32445aefb655Srie static void 32453244bcaaSab196087 update_ostrtab(Os_desc *osp, Str_tbl *stp, uint_t extra) 32467c478bd9Sstevel@tonic-gate { 32477c478bd9Sstevel@tonic-gate Elf_Data *data; 32483244bcaaSab196087 324957ef7aa9SRod Evans if (osp == NULL) 32507c478bd9Sstevel@tonic-gate return; 32517c478bd9Sstevel@tonic-gate 32527c478bd9Sstevel@tonic-gate data = osp->os_outdata; 32533244bcaaSab196087 assert(data->d_size == (st_getstrtab_sz(stp) + extra)); 3254cce0e03bSab196087 (void) st_setstrbuf(stp, data->d_buf, data->d_size - extra); 32553244bcaaSab196087 /* If leaving an extra hole at the end, zero it */ 32563244bcaaSab196087 if (extra > 0) 32573244bcaaSab196087 (void) memset((char *)data->d_buf + data->d_size - extra, 32583244bcaaSab196087 0x0, extra); 32597c478bd9Sstevel@tonic-gate } 32607c478bd9Sstevel@tonic-gate 32617c478bd9Sstevel@tonic-gate /* 326208278a5eSRod Evans * Update capabilities information. 326308278a5eSRod Evans * 326408278a5eSRod Evans * If string table capabilities exist, then the associated string must be 326508278a5eSRod Evans * translated into an offset into the string table. 326608278a5eSRod Evans */ 326708278a5eSRod Evans static void 326808278a5eSRod Evans update_oscap(Ofl_desc *ofl) 326908278a5eSRod Evans { 327008278a5eSRod Evans Os_desc *strosp, *cosp; 327108278a5eSRod Evans Cap *cap; 327208278a5eSRod Evans Str_tbl *strtbl; 327308278a5eSRod Evans Capstr *capstr; 327408278a5eSRod Evans size_t stoff; 327508278a5eSRod Evans Aliste idx1; 327608278a5eSRod Evans 327708278a5eSRod Evans /* 327808278a5eSRod Evans * Determine which symbol table or string table is appropriate. 327908278a5eSRod Evans */ 328008278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl)) { 328108278a5eSRod Evans strosp = ofl->ofl_osstrtab; 328208278a5eSRod Evans strtbl = ofl->ofl_strtab; 328308278a5eSRod Evans } else { 328408278a5eSRod Evans strosp = ofl->ofl_osdynstr; 328508278a5eSRod Evans strtbl = ofl->ofl_dynstrtab; 328608278a5eSRod Evans } 328708278a5eSRod Evans 328808278a5eSRod Evans /* 328908278a5eSRod Evans * If symbol capabilities exist, set the sh_link field of the .SUNW_cap 329008278a5eSRod Evans * section to the .SUNW_capinfo section. 329108278a5eSRod Evans */ 329208278a5eSRod Evans if (ofl->ofl_oscapinfo) { 329308278a5eSRod Evans cosp = ofl->ofl_oscap; 329408278a5eSRod Evans cosp->os_shdr->sh_link = 329508278a5eSRod Evans (Word)elf_ndxscn(ofl->ofl_oscapinfo->os_scn); 329608278a5eSRod Evans } 329708278a5eSRod Evans 329808278a5eSRod Evans /* 329908278a5eSRod Evans * If there are capability strings to process, set the sh_info 330008278a5eSRod Evans * field of the .SUNW_cap section to the associated string table, and 330108278a5eSRod Evans * proceed to process any CA_SUNW_PLAT entries. 330208278a5eSRod Evans */ 330308278a5eSRod Evans if ((ofl->ofl_flags & FLG_OF_CAPSTRS) == 0) 330408278a5eSRod Evans return; 330508278a5eSRod Evans 330608278a5eSRod Evans cosp = ofl->ofl_oscap; 330708278a5eSRod Evans cosp->os_shdr->sh_info = (Word)elf_ndxscn(strosp->os_scn); 330808278a5eSRod Evans 330908278a5eSRod Evans cap = ofl->ofl_oscap->os_outdata->d_buf; 331008278a5eSRod Evans 331108278a5eSRod Evans /* 331208278a5eSRod Evans * Determine whether an object capability identifier, or object 331308278a5eSRod Evans * machine/platform capabilities exists. 331408278a5eSRod Evans */ 331508278a5eSRod Evans capstr = &ofl->ofl_ocapset.oc_id; 331608278a5eSRod Evans if (capstr->cs_str) { 331708278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, &stoff); 331808278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 331908278a5eSRod Evans } 332008278a5eSRod Evans for (ALIST_TRAVERSE(ofl->ofl_ocapset.oc_plat.cl_val, idx1, capstr)) { 332108278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, &stoff); 332208278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 332308278a5eSRod Evans } 332408278a5eSRod Evans for (ALIST_TRAVERSE(ofl->ofl_ocapset.oc_mach.cl_val, idx1, capstr)) { 332508278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, &stoff); 332608278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 332708278a5eSRod Evans } 332808278a5eSRod Evans 332908278a5eSRod Evans /* 333008278a5eSRod Evans * Determine any symbol capability identifiers, or machine/platform 333108278a5eSRod Evans * capabilities. 333208278a5eSRod Evans */ 333308278a5eSRod Evans if (ofl->ofl_capgroups) { 333408278a5eSRod Evans Cap_group *cgp; 333508278a5eSRod Evans 333608278a5eSRod Evans for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) { 333708278a5eSRod Evans Objcapset *ocapset = &cgp->cg_set; 333808278a5eSRod Evans Aliste idx2; 333908278a5eSRod Evans 334008278a5eSRod Evans capstr = &ocapset->oc_id; 334108278a5eSRod Evans if (capstr->cs_str) { 334208278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, 334308278a5eSRod Evans &stoff); 334408278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 334508278a5eSRod Evans } 334608278a5eSRod Evans for (ALIST_TRAVERSE(ocapset->oc_plat.cl_val, idx2, 334708278a5eSRod Evans capstr)) { 334808278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, 334908278a5eSRod Evans &stoff); 335008278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 335108278a5eSRod Evans } 335208278a5eSRod Evans for (ALIST_TRAVERSE(ocapset->oc_mach.cl_val, idx2, 335308278a5eSRod Evans capstr)) { 335408278a5eSRod Evans (void) st_setstring(strtbl, capstr->cs_str, 335508278a5eSRod Evans &stoff); 335608278a5eSRod Evans cap[capstr->cs_ndx].c_un.c_ptr = stoff; 335708278a5eSRod Evans } 335808278a5eSRod Evans } 335908278a5eSRod Evans } 336008278a5eSRod Evans } 336108278a5eSRod Evans 336208278a5eSRod Evans /* 336308278a5eSRod Evans * Update the .SUNW_capinfo, and possibly the .SUNW_capchain sections. 336408278a5eSRod Evans */ 336508278a5eSRod Evans static void 336608278a5eSRod Evans update_oscapinfo(Ofl_desc *ofl) 336708278a5eSRod Evans { 336808278a5eSRod Evans Os_desc *symosp, *ciosp, *ccosp = NULL; 336908278a5eSRod Evans Capinfo *ocapinfo; 337008278a5eSRod Evans Capchain *ocapchain; 337108278a5eSRod Evans Cap_avlnode *cav; 337208278a5eSRod Evans Word chainndx = 0; 337308278a5eSRod Evans 337408278a5eSRod Evans /* 337508278a5eSRod Evans * Determine which symbol table is appropriate. 337608278a5eSRod Evans */ 337708278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl)) 337808278a5eSRod Evans symosp = ofl->ofl_ossymtab; 337908278a5eSRod Evans else 338008278a5eSRod Evans symosp = ofl->ofl_osdynsym; 338108278a5eSRod Evans 338208278a5eSRod Evans /* 338308278a5eSRod Evans * Update the .SUNW_capinfo sh_link to point to the appropriate symbol 338408278a5eSRod Evans * table section. If we're creating a dynamic object, the 338508278a5eSRod Evans * .SUNW_capinfo sh_info is updated to point to the .SUNW_capchain 338608278a5eSRod Evans * section. 338708278a5eSRod Evans */ 338808278a5eSRod Evans ciosp = ofl->ofl_oscapinfo; 338908278a5eSRod Evans ciosp->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn); 339008278a5eSRod Evans 339108278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl) == 0) { 339208278a5eSRod Evans ccosp = ofl->ofl_oscapchain; 339308278a5eSRod Evans ciosp->os_shdr->sh_info = (Word)elf_ndxscn(ccosp->os_scn); 339408278a5eSRod Evans } 339508278a5eSRod Evans 339608278a5eSRod Evans /* 339708278a5eSRod Evans * Establish the data for each section. The first element of each 339808278a5eSRod Evans * section defines the section's version number. 339908278a5eSRod Evans */ 340008278a5eSRod Evans ocapinfo = ciosp->os_outdata->d_buf; 340108278a5eSRod Evans ocapinfo[0] = CAPINFO_CURRENT; 340208278a5eSRod Evans if (ccosp) { 340308278a5eSRod Evans ocapchain = ccosp->os_outdata->d_buf; 340408278a5eSRod Evans ocapchain[chainndx++] = CAPCHAIN_CURRENT; 340508278a5eSRod Evans } 340608278a5eSRod Evans 340708278a5eSRod Evans /* 340808278a5eSRod Evans * Traverse all capabilities families. Each member has a .SUNW_capinfo 340908278a5eSRod Evans * assignment. The .SUNW_capinfo entry differs for relocatable objects 341008278a5eSRod Evans * and dynamic objects. 341108278a5eSRod Evans * 341208278a5eSRod Evans * Relocatable objects: 341308278a5eSRod Evans * ELF_C_GROUP ELF_C_SYM 341408278a5eSRod Evans * 341508278a5eSRod Evans * Family lead: CAPINFO_SUNW_GLOB lead symbol index 341608278a5eSRod Evans * Family lead alias: CAPINFO_SUNW_GLOB lead symbol index 341708278a5eSRod Evans * Family member: .SUNW_cap index lead symbol index 341808278a5eSRod Evans * 341908278a5eSRod Evans * Dynamic objects: 342008278a5eSRod Evans * ELF_C_GROUP ELF_C_SYM 342108278a5eSRod Evans * 342208278a5eSRod Evans * Family lead: CAPINFO_SUNW_GLOB .SUNW_capchain index 342308278a5eSRod Evans * Family lead alias: CAPINFO_SUNW_GLOB .SUNW_capchain index 342408278a5eSRod Evans * Family member: .SUNW_cap index lead symbol index 342508278a5eSRod Evans * 342608278a5eSRod Evans * The ELF_C_GROUP field identifies a capabilities symbol. Lead 342708278a5eSRod Evans * capability symbols, and lead capability aliases are identified by 342808278a5eSRod Evans * a CAPINFO_SUNW_GLOB group identifier. For family members, the 342908278a5eSRod Evans * ELF_C_GROUP provides an index to the associate capabilities group 343008278a5eSRod Evans * (i.e, an index into the SUNW_cap section that defines a group). 343108278a5eSRod Evans * 343208278a5eSRod Evans * For relocatable objects, the ELF_C_SYM field identifies the lead 343308278a5eSRod Evans * capability symbol. For the lead symbol itself, the .SUNW_capinfo 343408278a5eSRod Evans * index is the same as the ELF_C_SYM value. For lead alias symbols, 343508278a5eSRod Evans * the .SUNW_capinfo index differs from the ELF_C_SYM value. This 343608278a5eSRod Evans * differentiation of CAPINFO_SUNW_GLOB symbols allows ld(1) to 343708278a5eSRod Evans * identify, and propagate lead alias symbols. For example, the lead 343808278a5eSRod Evans * capability symbol memcpy() would have the ELF_C_SYM for memcpy(), 343908278a5eSRod Evans * and the lead alias _memcpy() would also have the ELF_C_SYM for 344008278a5eSRod Evans * memcpy(). 344108278a5eSRod Evans * 344208278a5eSRod Evans * For dynamic objects, both a lead capability symbol, and alias symbol 344308278a5eSRod Evans * would have a ELF_C_SYM value that represents the same capability 344408278a5eSRod Evans * chain index. The capability chain allows ld.so.1 to traverse a 344508278a5eSRod Evans * family chain for a given lead symbol, and select the most appropriate 344608278a5eSRod Evans * family member. The .SUNW_capchain array contains a series of symbol 344708278a5eSRod Evans * indexes for each family member: 344808278a5eSRod Evans * 344908278a5eSRod Evans * chaincap[n] chaincap[n + 1] chaincap[n + 2] chaincap[n + x] 345008278a5eSRod Evans * foo() ndx foo%x() ndx foo%y() ndx 0 345108278a5eSRod Evans * 345208278a5eSRod Evans * For family members, the ELF_C_SYM value associates the capability 345308278a5eSRod Evans * members with their family lead symbol. This association, although 345408278a5eSRod Evans * unused within a dynamic object, allows ld(1) to identify, and 345508278a5eSRod Evans * propagate family members when processing relocatable objects. 345608278a5eSRod Evans */ 345708278a5eSRod Evans for (cav = avl_first(ofl->ofl_capfamilies); cav; 345808278a5eSRod Evans cav = AVL_NEXT(ofl->ofl_capfamilies, cav)) { 345908278a5eSRod Evans Cap_sym *csp; 346008278a5eSRod Evans Aliste idx; 346108278a5eSRod Evans Sym_desc *asdp, *lsdp = cav->cn_symavlnode.sav_sdp; 346208278a5eSRod Evans 346308278a5eSRod Evans if (ccosp) { 346408278a5eSRod Evans /* 346508278a5eSRod Evans * For a dynamic object, identify this lead symbol, and 346608278a5eSRod Evans * point it to the head of a capability chain. Set the 346708278a5eSRod Evans * head of the capability chain to the same lead symbol. 346808278a5eSRod Evans */ 346908278a5eSRod Evans ocapinfo[lsdp->sd_symndx] = 347008278a5eSRod Evans ELF_C_INFO(chainndx, CAPINFO_SUNW_GLOB); 347108278a5eSRod Evans ocapchain[chainndx] = lsdp->sd_symndx; 347208278a5eSRod Evans } else { 347308278a5eSRod Evans /* 347408278a5eSRod Evans * For a relocatable object, identify this lead symbol, 347508278a5eSRod Evans * and set the lead symbol index to itself. 347608278a5eSRod Evans */ 347708278a5eSRod Evans ocapinfo[lsdp->sd_symndx] = 347808278a5eSRod Evans ELF_C_INFO(lsdp->sd_symndx, CAPINFO_SUNW_GLOB); 347908278a5eSRod Evans } 348008278a5eSRod Evans 348108278a5eSRod Evans /* 348208278a5eSRod Evans * Gather any lead symbol aliases. 348308278a5eSRod Evans */ 348408278a5eSRod Evans for (APLIST_TRAVERSE(cav->cn_aliases, idx, asdp)) { 348508278a5eSRod Evans if (ccosp) { 348608278a5eSRod Evans /* 348708278a5eSRod Evans * For a dynamic object, identify this lead 348808278a5eSRod Evans * alias symbol, and point it to the same 348908278a5eSRod Evans * capability chain index as the lead symbol. 349008278a5eSRod Evans */ 349108278a5eSRod Evans ocapinfo[asdp->sd_symndx] = 349208278a5eSRod Evans ELF_C_INFO(chainndx, CAPINFO_SUNW_GLOB); 349308278a5eSRod Evans } else { 349408278a5eSRod Evans /* 349508278a5eSRod Evans * For a relocatable object, identify this lead 349608278a5eSRod Evans * alias symbol, and set the lead symbol index 349708278a5eSRod Evans * to the lead symbol. 349808278a5eSRod Evans */ 349908278a5eSRod Evans ocapinfo[asdp->sd_symndx] = 350008278a5eSRod Evans ELF_C_INFO(lsdp->sd_symndx, 350108278a5eSRod Evans CAPINFO_SUNW_GLOB); 350208278a5eSRod Evans } 350308278a5eSRod Evans } 350408278a5eSRod Evans 350508278a5eSRod Evans chainndx++; 350608278a5eSRod Evans 350708278a5eSRod Evans /* 350808278a5eSRod Evans * Gather the family members. 350908278a5eSRod Evans */ 351008278a5eSRod Evans for (APLIST_TRAVERSE(cav->cn_members, idx, csp)) { 351108278a5eSRod Evans Sym_desc *msdp = csp->cs_sdp; 351208278a5eSRod Evans 351308278a5eSRod Evans /* 351408278a5eSRod Evans * Identify the members capability group, and the lead 351508278a5eSRod Evans * symbol of the family this symbol is a member of. 351608278a5eSRod Evans */ 351708278a5eSRod Evans ocapinfo[msdp->sd_symndx] = 351808278a5eSRod Evans ELF_C_INFO(lsdp->sd_symndx, csp->cs_group->cg_ndx); 351908278a5eSRod Evans if (ccosp) { 352008278a5eSRod Evans /* 352108278a5eSRod Evans * For a dynamic object, set the next capability 352208278a5eSRod Evans * chain to point to this family member. 352308278a5eSRod Evans */ 352408278a5eSRod Evans ocapchain[chainndx++] = msdp->sd_symndx; 352508278a5eSRod Evans } 352608278a5eSRod Evans } 352708278a5eSRod Evans 352808278a5eSRod Evans /* 352908278a5eSRod Evans * Any chain of family members is terminated with a 0 element. 353008278a5eSRod Evans */ 353108278a5eSRod Evans if (ccosp) 353208278a5eSRod Evans ocapchain[chainndx++] = 0; 353308278a5eSRod Evans } 353408278a5eSRod Evans } 353508278a5eSRod Evans 353608278a5eSRod Evans /* 35377c478bd9Sstevel@tonic-gate * Translate the shdr->sh_{link, info} from its input section value to that 35387c478bd9Sstevel@tonic-gate * of the corresponding shdr->sh_{link, info} output section value. 35397c478bd9Sstevel@tonic-gate */ 35405aefb655Srie static Word 35415aefb655Srie translate_link(Ofl_desc *ofl, Os_desc *osp, Word link, const char *msg) 35427c478bd9Sstevel@tonic-gate { 35437c478bd9Sstevel@tonic-gate Is_desc *isp; 35447c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 35457c478bd9Sstevel@tonic-gate 35467c478bd9Sstevel@tonic-gate /* 35477c478bd9Sstevel@tonic-gate * Don't translate the special section numbers. 35487c478bd9Sstevel@tonic-gate */ 35497c478bd9Sstevel@tonic-gate if (link >= SHN_LORESERVE) 35507c478bd9Sstevel@tonic-gate return (link); 35517c478bd9Sstevel@tonic-gate 35527c478bd9Sstevel@tonic-gate /* 35537c478bd9Sstevel@tonic-gate * Does this output section translate back to an input file. If not 35547c478bd9Sstevel@tonic-gate * then there is no translation to do. In this case we will assume that 35557c478bd9Sstevel@tonic-gate * if sh_link has a value, it's the right value. 35567c478bd9Sstevel@tonic-gate */ 35571dd9d86fSAli Bahrami isp = ld_os_first_isdesc(osp); 35587c478bd9Sstevel@tonic-gate if ((ifl = isp->is_file) == NULL) 35597c478bd9Sstevel@tonic-gate return (link); 35607c478bd9Sstevel@tonic-gate 35617c478bd9Sstevel@tonic-gate /* 35627c478bd9Sstevel@tonic-gate * Sanity check to make sure that the sh_{link, info} value 35637c478bd9Sstevel@tonic-gate * is within range for the input file. 35647c478bd9Sstevel@tonic-gate */ 35657c478bd9Sstevel@tonic-gate if (link >= ifl->ifl_shnum) { 3566*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, msg, ifl->ifl_name, 35674a8d0ea7SAli Bahrami EC_WORD(isp->is_scnndx), isp->is_name, EC_XWORD(link)); 35687c478bd9Sstevel@tonic-gate return (link); 35697c478bd9Sstevel@tonic-gate } 35707c478bd9Sstevel@tonic-gate 35717c478bd9Sstevel@tonic-gate /* 35727c478bd9Sstevel@tonic-gate * Follow the link to the input section. 35737c478bd9Sstevel@tonic-gate */ 357457ef7aa9SRod Evans if ((isp = ifl->ifl_isdesc[link]) == NULL) 35757c478bd9Sstevel@tonic-gate return (0); 357657ef7aa9SRod Evans if ((osp = isp->is_osdesc) == NULL) 35777c478bd9Sstevel@tonic-gate return (0); 35787c478bd9Sstevel@tonic-gate 35797c478bd9Sstevel@tonic-gate /* LINTED */ 35807c478bd9Sstevel@tonic-gate return ((Word)elf_ndxscn(osp->os_scn)); 35817c478bd9Sstevel@tonic-gate } 35827c478bd9Sstevel@tonic-gate 35837c478bd9Sstevel@tonic-gate /* 35847c478bd9Sstevel@tonic-gate * Having created all of the necessary sections, segments, and associated 35857c478bd9Sstevel@tonic-gate * headers, fill in the program headers and update any other data in the 35867c478bd9Sstevel@tonic-gate * output image. Some general rules: 35877c478bd9Sstevel@tonic-gate * 358857ef7aa9SRod Evans * - If an interpreter is required always generate a PT_PHDR entry as 35897c478bd9Sstevel@tonic-gate * well. It is this entry that triggers the kernel into passing the 359070d3e49eSrie * interpreter an aux vector instead of just a file descriptor. 35917c478bd9Sstevel@tonic-gate * 359257ef7aa9SRod Evans * - When generating an image that will be interpreted (ie. a dynamic 35937c478bd9Sstevel@tonic-gate * executable, a shared object, or a static executable that has been 359470d3e49eSrie * provided with an interpreter - weird, but possible), make the initial 35957c478bd9Sstevel@tonic-gate * loadable segment include both the ehdr and phdr[]. Both of these 359670d3e49eSrie * tables are used by the interpreter therefore it seems more intuitive 35977c478bd9Sstevel@tonic-gate * to explicitly defined them as part of the mapped image rather than 359870d3e49eSrie * relying on page rounding by the interpreter to allow their access. 35997c478bd9Sstevel@tonic-gate * 360057ef7aa9SRod Evans * - When generating a static image that does not require an interpreter 36017c478bd9Sstevel@tonic-gate * have the first loadable segment indicate the address of the first 36027c478bd9Sstevel@tonic-gate * .section as the start address (things like /kernel/unix and ufsboot 36037c478bd9Sstevel@tonic-gate * expect this behavior). 36047c478bd9Sstevel@tonic-gate */ 36057c478bd9Sstevel@tonic-gate uintptr_t 36065aefb655Srie ld_update_outfile(Ofl_desc *ofl) 36077c478bd9Sstevel@tonic-gate { 3608bb3b4f6cSRod Evans Addr size, etext, vaddr; 360957ef7aa9SRod Evans Sg_desc *sgp; 361057ef7aa9SRod Evans Sg_desc *dtracesgp = NULL, *capsgp = NULL, *intpsgp = NULL; 3611cce0e03bSab196087 Os_desc *osp; 361257ef7aa9SRod Evans int phdrndx = 0, segndx = -1, secndx, intppndx, intpsndx; 3613d1827f25Srie int dtracepndx, dtracesndx, cappndx, capsndx; 36145aefb655Srie Ehdr *ehdr = ofl->ofl_nehdr; 36157c478bd9Sstevel@tonic-gate Shdr *hshdr; 361657ef7aa9SRod Evans Phdr *_phdr = NULL; 3617d1827f25Srie Word phdrsz = (ehdr->e_phnum * ehdr->e_phentsize), shscnndx; 36181d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags; 36191d9df23bSab196087 Word ehdrsz = ehdr->e_ehsize; 36207c478bd9Sstevel@tonic-gate Boolean nobits; 36217c478bd9Sstevel@tonic-gate Off offset; 362257ef7aa9SRod Evans Aliste idx1; 36237c478bd9Sstevel@tonic-gate 36247c478bd9Sstevel@tonic-gate /* 3625bb3b4f6cSRod Evans * Initialize the starting address for the first segment. Executables 3626bb3b4f6cSRod Evans * have different starting addresses depending upon the target ABI, 3627bb3b4f6cSRod Evans * where as shared objects have a starting address of 0. If this is 3628bb3b4f6cSRod Evans * a 64-bit executable that is being constructed to run in a restricted 3629bb3b4f6cSRod Evans * address space, use an alternative origin that will provide more free 3630bb3b4f6cSRod Evans * address space for the the eventual process. 3631bb3b4f6cSRod Evans */ 3632bb3b4f6cSRod Evans if (ofl->ofl_flags & FLG_OF_EXEC) { 3633bb3b4f6cSRod Evans #if defined(_ELF64) 363408278a5eSRod Evans if (ofl->ofl_ocapset.oc_sf_1.cm_val & SF1_SUNW_ADDR32) 3635bb3b4f6cSRod Evans vaddr = ld_targ.t_m.m_segm_aorigin; 3636bb3b4f6cSRod Evans else 3637bb3b4f6cSRod Evans #endif 3638bb3b4f6cSRod Evans vaddr = ld_targ.t_m.m_segm_origin; 3639bb3b4f6cSRod Evans } else 3640bb3b4f6cSRod Evans vaddr = 0; 3641bb3b4f6cSRod Evans 3642bb3b4f6cSRod Evans /* 36437c478bd9Sstevel@tonic-gate * Loop through the segment descriptors and pick out what we need. 36447c478bd9Sstevel@tonic-gate */ 36455aefb655Srie DBG_CALL(Dbg_seg_title(ofl->ofl_lml)); 364657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 36477c478bd9Sstevel@tonic-gate Phdr *phdr = &(sgp->sg_phdr); 36487c478bd9Sstevel@tonic-gate Xword p_align; 364957ef7aa9SRod Evans Aliste idx2; 365069112eddSAli Bahrami Sym_desc *sdp; 36517c478bd9Sstevel@tonic-gate 36527c478bd9Sstevel@tonic-gate segndx++; 36537c478bd9Sstevel@tonic-gate 36547c478bd9Sstevel@tonic-gate /* 36557c478bd9Sstevel@tonic-gate * If an interpreter is required generate a PT_INTERP and 36567c478bd9Sstevel@tonic-gate * PT_PHDR program header entry. The PT_PHDR entry describes 36577c478bd9Sstevel@tonic-gate * the program header table itself. This information will be 36587c478bd9Sstevel@tonic-gate * passed via the aux vector to the interpreter (ld.so.1). 36597c478bd9Sstevel@tonic-gate * The program header array is actually part of the first 36607c478bd9Sstevel@tonic-gate * loadable segment (and the PT_PHDR entry is the first entry), 36617c478bd9Sstevel@tonic-gate * therefore its virtual address isn't known until the first 36627c478bd9Sstevel@tonic-gate * loadable segment is processed. 36637c478bd9Sstevel@tonic-gate */ 36647c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_PHDR) { 36657c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) { 36667c478bd9Sstevel@tonic-gate phdr->p_offset = ehdr->e_phoff; 36677c478bd9Sstevel@tonic-gate phdr->p_filesz = phdr->p_memsz = phdrsz; 3668d1827f25Srie 36695aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 36707c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 36717c478bd9Sstevel@tonic-gate } 36727c478bd9Sstevel@tonic-gate continue; 36737c478bd9Sstevel@tonic-gate } 36747c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_INTERP) { 36757c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) { 367657ef7aa9SRod Evans intpsgp = sgp; 367757ef7aa9SRod Evans intpsndx = segndx; 367857ef7aa9SRod Evans intppndx = phdrndx++; 36797c478bd9Sstevel@tonic-gate } 36807c478bd9Sstevel@tonic-gate continue; 36817c478bd9Sstevel@tonic-gate } 36827c478bd9Sstevel@tonic-gate 36837c478bd9Sstevel@tonic-gate /* 3684d1827f25Srie * If we are creating a PT_SUNWDTRACE segment, remember where 3685d1827f25Srie * the program header is. The header values are assigned after 3686d1827f25Srie * update_osym() has completed and the symbol table addresses 368728bda19cSRod Evans * have been updated. 36887c478bd9Sstevel@tonic-gate */ 36897c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_SUNWDTRACE) { 369028bda19cSRod Evans if (ofl->ofl_dtracesym && 36917c478bd9Sstevel@tonic-gate ((flags & FLG_OF_RELOBJ) == 0)) { 3692d1827f25Srie dtracesgp = sgp; 3693d1827f25Srie dtracesndx = segndx; 3694d1827f25Srie dtracepndx = phdrndx++; 36957c478bd9Sstevel@tonic-gate } 36967c478bd9Sstevel@tonic-gate continue; 36977c478bd9Sstevel@tonic-gate } 36987c478bd9Sstevel@tonic-gate 36997c478bd9Sstevel@tonic-gate /* 37007c478bd9Sstevel@tonic-gate * If a hardware/software capabilities section is required, 37017c478bd9Sstevel@tonic-gate * generate the PT_SUNWCAP header. Note, as this comes before 37027c478bd9Sstevel@tonic-gate * the first loadable segment, we don't yet know its real 37037c478bd9Sstevel@tonic-gate * virtual address. This is updated later. 37047c478bd9Sstevel@tonic-gate */ 37057c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_SUNWCAP) { 370608278a5eSRod Evans if (ofl->ofl_oscap && (ofl->ofl_flags & FLG_OF_PTCAP) && 370708278a5eSRod Evans ((flags & FLG_OF_RELOBJ) == 0)) { 3708d1827f25Srie capsgp = sgp; 3709d1827f25Srie capsndx = segndx; 3710d1827f25Srie cappndx = phdrndx++; 37117c478bd9Sstevel@tonic-gate } 37127c478bd9Sstevel@tonic-gate continue; 37137c478bd9Sstevel@tonic-gate } 37147c478bd9Sstevel@tonic-gate 37157c478bd9Sstevel@tonic-gate /* 37167c478bd9Sstevel@tonic-gate * As the dynamic program header occurs after the loadable 37177c478bd9Sstevel@tonic-gate * headers in the segment descriptor table, all the address 37187c478bd9Sstevel@tonic-gate * information for the .dynamic output section will have been 37197c478bd9Sstevel@tonic-gate * figured out by now. 37207c478bd9Sstevel@tonic-gate */ 37217c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_DYNAMIC) { 37229039eeafSab196087 if (OFL_ALLOW_DYNSYM(ofl)) { 37237c478bd9Sstevel@tonic-gate Shdr *shdr = ofl->ofl_osdynamic->os_shdr; 37247c478bd9Sstevel@tonic-gate 37257c478bd9Sstevel@tonic-gate phdr->p_vaddr = shdr->sh_addr; 37267c478bd9Sstevel@tonic-gate phdr->p_offset = shdr->sh_offset; 37277c478bd9Sstevel@tonic-gate phdr->p_filesz = shdr->sh_size; 3728ba2be530Sab196087 phdr->p_flags = ld_targ.t_m.m_dataseg_perm; 3729d1827f25Srie 37305aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 37317c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 37327c478bd9Sstevel@tonic-gate } 37337c478bd9Sstevel@tonic-gate continue; 37347c478bd9Sstevel@tonic-gate } 3735d1827f25Srie 3736d1827f25Srie /* 37377e16fca0SAli Bahrami * As the unwind (.eh_frame_hdr) program header occurs after 37387e16fca0SAli Bahrami * the loadable headers in the segment descriptor table, all 37397e16fca0SAli Bahrami * the address information for the .eh_frame output section 37407e16fca0SAli Bahrami * will have been figured out by now. 3741d1827f25Srie */ 37427e16fca0SAli Bahrami if (phdr->p_type == PT_SUNW_UNWIND) { 37437c478bd9Sstevel@tonic-gate Shdr *shdr; 3744d1827f25Srie 37457e16fca0SAli Bahrami if (ofl->ofl_unwindhdr == NULL) 37467c478bd9Sstevel@tonic-gate continue; 3747d1827f25Srie 37487c478bd9Sstevel@tonic-gate shdr = ofl->ofl_unwindhdr->os_shdr; 37497c478bd9Sstevel@tonic-gate 37507c478bd9Sstevel@tonic-gate phdr->p_flags = PF_R; 37517c478bd9Sstevel@tonic-gate phdr->p_vaddr = shdr->sh_addr; 37527c478bd9Sstevel@tonic-gate phdr->p_memsz = shdr->sh_size; 37537c478bd9Sstevel@tonic-gate phdr->p_filesz = shdr->sh_size; 37547c478bd9Sstevel@tonic-gate phdr->p_offset = shdr->sh_offset; 37557c478bd9Sstevel@tonic-gate phdr->p_align = shdr->sh_addralign; 37567c478bd9Sstevel@tonic-gate phdr->p_paddr = 0; 37577c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 37587c478bd9Sstevel@tonic-gate continue; 37597c478bd9Sstevel@tonic-gate } 37607e16fca0SAli Bahrami 3761d1827f25Srie /* 376269112eddSAli Bahrami * The sunwstack program is used to convey non-default 376369112eddSAli Bahrami * flags for the process stack. Only emit it if it would 376469112eddSAli Bahrami * change the default. 376569112eddSAli Bahrami */ 376669112eddSAli Bahrami if (phdr->p_type == PT_SUNWSTACK) { 3767a1926ac7SAli Bahrami if (((flags & FLG_OF_RELOBJ) == 0) && 3768a1926ac7SAli Bahrami ((sgp->sg_flags & FLG_SG_DISABLED) == 0)) 376969112eddSAli Bahrami ofl->ofl_phdr[phdrndx++] = *phdr; 377069112eddSAli Bahrami continue; 377169112eddSAli Bahrami } 377269112eddSAli Bahrami 377369112eddSAli Bahrami /* 3774d1827f25Srie * As the TLS program header occurs after the loadable 3775d1827f25Srie * headers in the segment descriptor table, all the address 3776d1827f25Srie * information for the .tls output section will have been 3777d1827f25Srie * figured out by now. 3778d1827f25Srie */ 37797c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_TLS) { 3780dd94ecefSrie Os_desc *tlsosp; 378108278a5eSRod Evans Shdr *lastfileshdr = NULL; 378208278a5eSRod Evans Shdr *firstshdr = NULL, *lastshdr; 378357ef7aa9SRod Evans Aliste idx; 37847c478bd9Sstevel@tonic-gate 378557ef7aa9SRod Evans if (ofl->ofl_ostlsseg == NULL) 37867c478bd9Sstevel@tonic-gate continue; 3787dd94ecefSrie 3788f79d60b6Srie /* 378908278a5eSRod Evans * Scan the output sections that have contributed TLS. 3790f79d60b6Srie * Remember the first and last so as to determine the 3791f79d60b6Srie * TLS memory size requirement. Remember the last 379208278a5eSRod Evans * progbits section to determine the TLS data 379308278a5eSRod Evans * contribution, which determines the TLS program 379408278a5eSRod Evans * header filesz. 3795f79d60b6Srie */ 379657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_ostlsseg, idx, tlsosp)) { 3797dd94ecefSrie Shdr *tlsshdr = tlsosp->os_shdr; 3798dd94ecefSrie 379957ef7aa9SRod Evans if (firstshdr == NULL) 3800f79d60b6Srie firstshdr = tlsshdr; 3801f79d60b6Srie if (tlsshdr->sh_type != SHT_NOBITS) 3802f79d60b6Srie lastfileshdr = tlsshdr; 3803f79d60b6Srie lastshdr = tlsshdr; 3804dd94ecefSrie } 3805dd94ecefSrie 38067c478bd9Sstevel@tonic-gate phdr->p_flags = PF_R | PF_W; 38077c478bd9Sstevel@tonic-gate phdr->p_vaddr = firstshdr->sh_addr; 38087c478bd9Sstevel@tonic-gate phdr->p_offset = firstshdr->sh_offset; 3809dd94ecefSrie phdr->p_align = firstshdr->sh_addralign; 3810f79d60b6Srie 381108278a5eSRod Evans /* 381208278a5eSRod Evans * Determine the initialized TLS data size. This 381308278a5eSRod Evans * address range is from the start of the TLS segment 381408278a5eSRod Evans * to the end of the last piece of initialized data. 381508278a5eSRod Evans */ 3816f79d60b6Srie if (lastfileshdr) 3817f79d60b6Srie phdr->p_filesz = lastfileshdr->sh_offset + 3818f79d60b6Srie lastfileshdr->sh_size - phdr->p_offset; 3819f79d60b6Srie else 3820f79d60b6Srie phdr->p_filesz = 0; 3821f79d60b6Srie 382208278a5eSRod Evans /* 382308278a5eSRod Evans * Determine the total TLS memory size. This includes 382408278a5eSRod Evans * all TLS data and TLS uninitialized data. This 382508278a5eSRod Evans * address range is from the start of the TLS segment 382608278a5eSRod Evans * to the memory address of the last piece of 382708278a5eSRod Evans * uninitialized data. 382808278a5eSRod Evans */ 382908278a5eSRod Evans phdr->p_memsz = lastshdr->sh_addr + 383008278a5eSRod Evans lastshdr->sh_size - phdr->p_vaddr; 3831dd94ecefSrie 38325aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 3833d1827f25Srie ofl->ofl_phdr[phdrndx] = *phdr; 3834d1827f25Srie ofl->ofl_tlsphdr = &ofl->ofl_phdr[phdrndx++]; 38357c478bd9Sstevel@tonic-gate continue; 38367c478bd9Sstevel@tonic-gate } 38377c478bd9Sstevel@tonic-gate 38387c478bd9Sstevel@tonic-gate /* 38397c478bd9Sstevel@tonic-gate * If this is an empty segment declaration, it will occur after 3840d1827f25Srie * all other loadable segments. As empty segments can be 384108278a5eSRod Evans * defined with fixed addresses, make sure that no loadable 3842d1827f25Srie * segments overlap. This might occur as the object evolves 3843d1827f25Srie * and the loadable segments grow, thus encroaching upon an 3844d1827f25Srie * existing segment reservation. 3845d1827f25Srie * 3846d1827f25Srie * Segments are only created for dynamic objects, thus this 3847d1827f25Srie * checking can be skipped when building a relocatable object. 38487c478bd9Sstevel@tonic-gate */ 38491d9df23bSab196087 if (!(flags & FLG_OF_RELOBJ) && 38507c478bd9Sstevel@tonic-gate (sgp->sg_flags & FLG_SG_EMPTY)) { 38517c478bd9Sstevel@tonic-gate int i; 38527c478bd9Sstevel@tonic-gate Addr v_e; 38537c478bd9Sstevel@tonic-gate 38547c478bd9Sstevel@tonic-gate vaddr = phdr->p_vaddr; 38557c478bd9Sstevel@tonic-gate phdr->p_memsz = sgp->sg_length; 38565aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 38577c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 38587c478bd9Sstevel@tonic-gate 38597c478bd9Sstevel@tonic-gate if (phdr->p_type != PT_LOAD) 38607c478bd9Sstevel@tonic-gate continue; 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate v_e = vaddr + phdr->p_memsz; 3863d1827f25Srie 38647c478bd9Sstevel@tonic-gate /* 38657c478bd9Sstevel@tonic-gate * Check overlaps 38667c478bd9Sstevel@tonic-gate */ 38677c478bd9Sstevel@tonic-gate for (i = 0; i < phdrndx - 1; i++) { 38687c478bd9Sstevel@tonic-gate Addr p_s = (ofl->ofl_phdr[i]).p_vaddr; 38697c478bd9Sstevel@tonic-gate Addr p_e; 38707c478bd9Sstevel@tonic-gate 38717c478bd9Sstevel@tonic-gate if ((ofl->ofl_phdr[i]).p_type != PT_LOAD) 38727c478bd9Sstevel@tonic-gate continue; 38737c478bd9Sstevel@tonic-gate 38747c478bd9Sstevel@tonic-gate p_e = p_s + (ofl->ofl_phdr[i]).p_memsz; 38757c478bd9Sstevel@tonic-gate if (((p_s <= vaddr) && (p_e > vaddr)) || 38767c478bd9Sstevel@tonic-gate ((vaddr <= p_s) && (v_e > p_s))) 3877*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 38787c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_SEGOVERLAP), 38795aefb655Srie ofl->ofl_name, EC_ADDR(p_e), 38805aefb655Srie sgp->sg_name, EC_ADDR(vaddr)); 38817c478bd9Sstevel@tonic-gate } 38827c478bd9Sstevel@tonic-gate continue; 38837c478bd9Sstevel@tonic-gate } 38847c478bd9Sstevel@tonic-gate 38857c478bd9Sstevel@tonic-gate /* 38867c478bd9Sstevel@tonic-gate * Having processed any of the special program headers any 38877c478bd9Sstevel@tonic-gate * remaining headers will be built to express individual 38887c478bd9Sstevel@tonic-gate * segments. Segments are only built if they have output 38897c478bd9Sstevel@tonic-gate * section descriptors associated with them (ie. some form of 38907c478bd9Sstevel@tonic-gate * input section has been matched to this segment). 38917c478bd9Sstevel@tonic-gate */ 38920bc07c75Srie if (sgp->sg_osdescs == NULL) 38937c478bd9Sstevel@tonic-gate continue; 38947c478bd9Sstevel@tonic-gate 38957c478bd9Sstevel@tonic-gate /* 38967c478bd9Sstevel@tonic-gate * Determine the segments offset and size from the section 38977c478bd9Sstevel@tonic-gate * information provided from elf_update(). 38987c478bd9Sstevel@tonic-gate * Allow for multiple NOBITS sections. 38997c478bd9Sstevel@tonic-gate */ 3900cce0e03bSab196087 osp = sgp->sg_osdescs->apl_data[0]; 390154d82594Sseizo hshdr = osp->os_shdr; 39027c478bd9Sstevel@tonic-gate 39037c478bd9Sstevel@tonic-gate phdr->p_filesz = 0; 39047c478bd9Sstevel@tonic-gate phdr->p_memsz = 0; 39057c478bd9Sstevel@tonic-gate phdr->p_offset = offset = hshdr->sh_offset; 39060bc07c75Srie 390754d82594Sseizo nobits = ((hshdr->sh_type == SHT_NOBITS) && 390854d82594Sseizo ((sgp->sg_flags & FLG_SG_PHREQ) == 0)); 39090bc07c75Srie 391057ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 3911cce0e03bSab196087 Shdr *shdr = osp->os_shdr; 39127c478bd9Sstevel@tonic-gate 39137c478bd9Sstevel@tonic-gate p_align = 0; 39147c478bd9Sstevel@tonic-gate if (shdr->sh_addralign > p_align) 39157c478bd9Sstevel@tonic-gate p_align = shdr->sh_addralign; 39160bc07c75Srie 39177c478bd9Sstevel@tonic-gate offset = (Off)S_ROUND(offset, shdr->sh_addralign); 39187c478bd9Sstevel@tonic-gate offset += shdr->sh_size; 39190bc07c75Srie 39207c478bd9Sstevel@tonic-gate if (shdr->sh_type != SHT_NOBITS) { 39217c478bd9Sstevel@tonic-gate if (nobits) { 3922*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, 39237c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_NOBITS)); 39247c478bd9Sstevel@tonic-gate return (S_ERROR); 39257c478bd9Sstevel@tonic-gate } 39267c478bd9Sstevel@tonic-gate phdr->p_filesz = offset - phdr->p_offset; 392754d82594Sseizo } else if ((sgp->sg_flags & FLG_SG_PHREQ) == 0) 39287c478bd9Sstevel@tonic-gate nobits = TRUE; 39297c478bd9Sstevel@tonic-gate } 39307c478bd9Sstevel@tonic-gate phdr->p_memsz = offset - hshdr->sh_offset; 39317c478bd9Sstevel@tonic-gate 39327c478bd9Sstevel@tonic-gate /* 39337c478bd9Sstevel@tonic-gate * If this is the first loadable segment of a dynamic object, 393470d3e49eSrie * or an interpreter has been specified (a static object built 393570d3e49eSrie * with an interpreter will still be given a PT_HDR entry), then 39367c478bd9Sstevel@tonic-gate * compensate for the elf header and program header array. Both 39377c478bd9Sstevel@tonic-gate * of these are actually part of the loadable segment as they 393870d3e49eSrie * may be inspected by the interpreter. Adjust the segments 39397c478bd9Sstevel@tonic-gate * size and offset accordingly. 39407c478bd9Sstevel@tonic-gate */ 394157ef7aa9SRod Evans if ((_phdr == NULL) && (phdr->p_type == PT_LOAD) && 39427c478bd9Sstevel@tonic-gate ((ofl->ofl_osinterp) || (flags & FLG_OF_DYNAMIC)) && 39434899432aSab196087 (!(ofl->ofl_dtflags_1 & DF_1_NOHDR))) { 39447c478bd9Sstevel@tonic-gate size = (Addr)S_ROUND((phdrsz + ehdrsz), 39457c478bd9Sstevel@tonic-gate hshdr->sh_addralign); 39467c478bd9Sstevel@tonic-gate phdr->p_offset -= size; 39477c478bd9Sstevel@tonic-gate phdr->p_filesz += size; 39487c478bd9Sstevel@tonic-gate phdr->p_memsz += size; 39497c478bd9Sstevel@tonic-gate } 39507c478bd9Sstevel@tonic-gate 39517c478bd9Sstevel@tonic-gate /* 395269112eddSAli Bahrami * If segment size symbols are required (specified via a 395369112eddSAli Bahrami * mapfile) update their value. 39547c478bd9Sstevel@tonic-gate */ 395569112eddSAli Bahrami for (APLIST_TRAVERSE(sgp->sg_sizesym, idx2, sdp)) 395669112eddSAli Bahrami sdp->sd_sym->st_value = phdr->p_memsz; 39577c478bd9Sstevel@tonic-gate 39587c478bd9Sstevel@tonic-gate /* 39597c478bd9Sstevel@tonic-gate * If no file content has been assigned to this segment (it 39607c478bd9Sstevel@tonic-gate * only contains no-bits sections), then reset the offset for 39617c478bd9Sstevel@tonic-gate * consistency. 39627c478bd9Sstevel@tonic-gate */ 39637c478bd9Sstevel@tonic-gate if (phdr->p_filesz == 0) 39647c478bd9Sstevel@tonic-gate phdr->p_offset = 0; 39657c478bd9Sstevel@tonic-gate 39667c478bd9Sstevel@tonic-gate /* 39677c478bd9Sstevel@tonic-gate * If a virtual address has been specified for this segment 396869112eddSAli Bahrami * from a mapfile use it and make sure the previous segment 396969112eddSAli Bahrami * does not run into this segment. 39707c478bd9Sstevel@tonic-gate */ 397135450702SAli Bahrami if (phdr->p_type == PT_LOAD) { 397269112eddSAli Bahrami if ((sgp->sg_flags & FLG_SG_P_VADDR)) { 39737c478bd9Sstevel@tonic-gate if (_phdr && (vaddr > phdr->p_vaddr) && 39747c478bd9Sstevel@tonic-gate (phdr->p_type == PT_LOAD)) 3975*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 39767c478bd9Sstevel@tonic-gate MSG_INTL(MSG_UPD_SEGOVERLAP), 39777c478bd9Sstevel@tonic-gate ofl->ofl_name, EC_ADDR(vaddr), 39787c478bd9Sstevel@tonic-gate sgp->sg_name, 39797c478bd9Sstevel@tonic-gate EC_ADDR(phdr->p_vaddr)); 39807c478bd9Sstevel@tonic-gate vaddr = phdr->p_vaddr; 39817c478bd9Sstevel@tonic-gate phdr->p_align = 0; 39827c478bd9Sstevel@tonic-gate } else { 39837c478bd9Sstevel@tonic-gate vaddr = phdr->p_vaddr = 39847c478bd9Sstevel@tonic-gate (Addr)S_ROUND(vaddr, phdr->p_align); 39857c478bd9Sstevel@tonic-gate } 39867c478bd9Sstevel@tonic-gate } 39877c478bd9Sstevel@tonic-gate 39887c478bd9Sstevel@tonic-gate /* 39897c478bd9Sstevel@tonic-gate * Adjust the address offset and p_align if needed. 39907c478bd9Sstevel@tonic-gate */ 399169112eddSAli Bahrami if (((sgp->sg_flags & FLG_SG_P_VADDR) == 0) && 39923906e0c2Srie ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0)) { 39937c478bd9Sstevel@tonic-gate if (phdr->p_align != 0) 39947c478bd9Sstevel@tonic-gate vaddr += phdr->p_offset % phdr->p_align; 39957c478bd9Sstevel@tonic-gate else 39967c478bd9Sstevel@tonic-gate vaddr += phdr->p_offset; 39977c478bd9Sstevel@tonic-gate phdr->p_vaddr = vaddr; 39987c478bd9Sstevel@tonic-gate } 39997c478bd9Sstevel@tonic-gate 40007c478bd9Sstevel@tonic-gate /* 40017c478bd9Sstevel@tonic-gate * If an interpreter is required set the virtual address of the 40027c478bd9Sstevel@tonic-gate * PT_PHDR program header now that we know the virtual address 40037c478bd9Sstevel@tonic-gate * of the loadable segment that contains it. Update the 40047c478bd9Sstevel@tonic-gate * PT_SUNWCAP header similarly. 40057c478bd9Sstevel@tonic-gate */ 400657ef7aa9SRod Evans if ((_phdr == NULL) && (phdr->p_type == PT_LOAD)) { 40077c478bd9Sstevel@tonic-gate _phdr = phdr; 40087c478bd9Sstevel@tonic-gate 4009d1827f25Srie if ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0) { 40107c478bd9Sstevel@tonic-gate if (ofl->ofl_osinterp) 40117c478bd9Sstevel@tonic-gate ofl->ofl_phdr[0].p_vaddr = 40127c478bd9Sstevel@tonic-gate vaddr + ehdrsz; 40137c478bd9Sstevel@tonic-gate 40147c478bd9Sstevel@tonic-gate /* 40157c478bd9Sstevel@tonic-gate * Finally, if we're creating a dynamic object 401670d3e49eSrie * (or a static object in which an interpreter 40177c478bd9Sstevel@tonic-gate * is specified) update the vaddr to reflect 40187c478bd9Sstevel@tonic-gate * the address of the first section within this 40197c478bd9Sstevel@tonic-gate * segment. 40207c478bd9Sstevel@tonic-gate */ 40217c478bd9Sstevel@tonic-gate if ((ofl->ofl_osinterp) || 40227c478bd9Sstevel@tonic-gate (flags & FLG_OF_DYNAMIC)) 40237c478bd9Sstevel@tonic-gate vaddr += size; 40247c478bd9Sstevel@tonic-gate } else { 40257c478bd9Sstevel@tonic-gate /* 4026d1827f25Srie * If the DF_1_NOHDR flag was set, and an 4027d1827f25Srie * interpreter is being generated, the PT_PHDR 40287c478bd9Sstevel@tonic-gate * will not be part of any loadable segment. 40297c478bd9Sstevel@tonic-gate */ 4030d1827f25Srie if (ofl->ofl_osinterp) { 40317c478bd9Sstevel@tonic-gate ofl->ofl_phdr[0].p_vaddr = 0; 40327c478bd9Sstevel@tonic-gate ofl->ofl_phdr[0].p_memsz = 0; 40337c478bd9Sstevel@tonic-gate ofl->ofl_phdr[0].p_flags = 0; 40347c478bd9Sstevel@tonic-gate } 40357c478bd9Sstevel@tonic-gate } 4036d1827f25Srie } 40377c478bd9Sstevel@tonic-gate 40387c478bd9Sstevel@tonic-gate /* 4039c1c6f601Srie * Ensure the ELF entry point defaults to zero. Typically, this 4040c1c6f601Srie * value is overridden in update_oehdr() to one of the standard 4041c1c6f601Srie * entry points. Historically, this default was set to the 4042c1c6f601Srie * address of first executable section, but this has since been 4043c1c6f601Srie * found to be more confusing than it is helpful. 40447c478bd9Sstevel@tonic-gate */ 4045c1c6f601Srie ehdr->e_entry = 0; 40467c478bd9Sstevel@tonic-gate 40475aefb655Srie DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp)); 40487c478bd9Sstevel@tonic-gate 40497c478bd9Sstevel@tonic-gate /* 40507c478bd9Sstevel@tonic-gate * Traverse the output section descriptors for this segment so 40517c478bd9Sstevel@tonic-gate * that we can update the section headers addresses. We've 40527c478bd9Sstevel@tonic-gate * calculated the virtual address of the initial section within 40537c478bd9Sstevel@tonic-gate * this segment, so each successive section can be calculated 40547c478bd9Sstevel@tonic-gate * based on their offsets from each other. 40557c478bd9Sstevel@tonic-gate */ 40567c478bd9Sstevel@tonic-gate secndx = 0; 40577c478bd9Sstevel@tonic-gate hshdr = 0; 405857ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 4059cce0e03bSab196087 Shdr *shdr = osp->os_shdr; 40607c478bd9Sstevel@tonic-gate 40617c478bd9Sstevel@tonic-gate if (shdr->sh_link) 406260758829Srie shdr->sh_link = translate_link(ofl, osp, 406360758829Srie shdr->sh_link, MSG_INTL(MSG_FIL_INVSHLINK)); 40647c478bd9Sstevel@tonic-gate 40657c478bd9Sstevel@tonic-gate if (shdr->sh_info && (shdr->sh_flags & SHF_INFO_LINK)) 406660758829Srie shdr->sh_info = translate_link(ofl, osp, 406760758829Srie shdr->sh_info, MSG_INTL(MSG_FIL_INVSHINFO)); 40687c478bd9Sstevel@tonic-gate 40697c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ) && 407035450702SAli Bahrami (phdr->p_type == PT_LOAD)) { 40717c478bd9Sstevel@tonic-gate if (hshdr) 40727c478bd9Sstevel@tonic-gate vaddr += (shdr->sh_offset - 40737c478bd9Sstevel@tonic-gate hshdr->sh_offset); 40747c478bd9Sstevel@tonic-gate 40757c478bd9Sstevel@tonic-gate shdr->sh_addr = vaddr; 40767c478bd9Sstevel@tonic-gate hshdr = shdr; 40777c478bd9Sstevel@tonic-gate } 40787c478bd9Sstevel@tonic-gate 40797c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_seg_os(ofl, osp, secndx)); 40807c478bd9Sstevel@tonic-gate secndx++; 40817c478bd9Sstevel@tonic-gate } 40827c478bd9Sstevel@tonic-gate 40837c478bd9Sstevel@tonic-gate /* 40847c478bd9Sstevel@tonic-gate * Establish the virtual address of the end of the last section 40857c478bd9Sstevel@tonic-gate * in this segment so that the next segments offset can be 40867c478bd9Sstevel@tonic-gate * calculated from this. 40877c478bd9Sstevel@tonic-gate */ 40887c478bd9Sstevel@tonic-gate if (hshdr) 40897c478bd9Sstevel@tonic-gate vaddr += hshdr->sh_size; 40907c478bd9Sstevel@tonic-gate 40917c478bd9Sstevel@tonic-gate /* 40927c478bd9Sstevel@tonic-gate * Output sections for this segment complete. Adjust the 40937c478bd9Sstevel@tonic-gate * virtual offset for the last sections size, and make sure we 40947c478bd9Sstevel@tonic-gate * haven't exceeded any maximum segment length specification. 40957c478bd9Sstevel@tonic-gate */ 40967c478bd9Sstevel@tonic-gate if ((sgp->sg_length != 0) && (sgp->sg_length < phdr->p_memsz)) { 4097*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_UPD_LARGSIZE), 4098*1007fd6fSAli Bahrami ofl->ofl_name, sgp->sg_name, 4099*1007fd6fSAli Bahrami EC_XWORD(phdr->p_memsz), EC_XWORD(sgp->sg_length)); 41007c478bd9Sstevel@tonic-gate return (S_ERROR); 41017c478bd9Sstevel@tonic-gate } 41027c478bd9Sstevel@tonic-gate 41037c478bd9Sstevel@tonic-gate if (phdr->p_type == PT_NOTE) { 41047c478bd9Sstevel@tonic-gate phdr->p_vaddr = 0; 41057c478bd9Sstevel@tonic-gate phdr->p_paddr = 0; 41067c478bd9Sstevel@tonic-gate phdr->p_align = 0; 41077c478bd9Sstevel@tonic-gate phdr->p_memsz = 0; 41087c478bd9Sstevel@tonic-gate } 4109d1827f25Srie 41107c478bd9Sstevel@tonic-gate if ((phdr->p_type != PT_NULL) && !(flags & FLG_OF_RELOBJ)) 41117c478bd9Sstevel@tonic-gate ofl->ofl_phdr[phdrndx++] = *phdr; 41127c478bd9Sstevel@tonic-gate } 41137c478bd9Sstevel@tonic-gate 41147c478bd9Sstevel@tonic-gate /* 41157c478bd9Sstevel@tonic-gate * Update any new output sections. When building the initial output 41167c478bd9Sstevel@tonic-gate * image, a number of sections were created but left uninitialized (eg. 41177c478bd9Sstevel@tonic-gate * .dynsym, .dynstr, .symtab, .symtab, etc.). Here we update these 41187c478bd9Sstevel@tonic-gate * sections with the appropriate data. Other sections may still be 41197c478bd9Sstevel@tonic-gate * modified via reloc_process(). 41207c478bd9Sstevel@tonic-gate * 412170d3e49eSrie * Copy the interpreter name into the .interp section. 41227c478bd9Sstevel@tonic-gate */ 41237c478bd9Sstevel@tonic-gate if (ofl->ofl_interp) 41247c478bd9Sstevel@tonic-gate (void) strcpy((char *)ofl->ofl_osinterp->os_outdata->d_buf, 41257c478bd9Sstevel@tonic-gate ofl->ofl_interp); 41267c478bd9Sstevel@tonic-gate 41277c478bd9Sstevel@tonic-gate /* 41287c478bd9Sstevel@tonic-gate * Update the .shstrtab, .strtab and .dynstr sections. 41297c478bd9Sstevel@tonic-gate */ 41303244bcaaSab196087 update_ostrtab(ofl->ofl_osshstrtab, ofl->ofl_shdrsttab, 0); 41313244bcaaSab196087 update_ostrtab(ofl->ofl_osstrtab, ofl->ofl_strtab, 0); 41323244bcaaSab196087 update_ostrtab(ofl->ofl_osdynstr, ofl->ofl_dynstrtab, DYNSTR_EXTRA_PAD); 41337c478bd9Sstevel@tonic-gate 41347c478bd9Sstevel@tonic-gate /* 41357c478bd9Sstevel@tonic-gate * Build any output symbol tables, the symbols information is copied 41367c478bd9Sstevel@tonic-gate * and updated into the new output image. 41377c478bd9Sstevel@tonic-gate */ 41387c478bd9Sstevel@tonic-gate if ((etext = update_osym(ofl)) == (Addr)S_ERROR) 41397c478bd9Sstevel@tonic-gate return (S_ERROR); 41407c478bd9Sstevel@tonic-gate 41417c478bd9Sstevel@tonic-gate /* 414257ef7aa9SRod Evans * If we have an PT_INTERP phdr, update it now from the associated 414357ef7aa9SRod Evans * section information. 414457ef7aa9SRod Evans */ 414557ef7aa9SRod Evans if (intpsgp) { 414657ef7aa9SRod Evans Phdr *phdr = &(intpsgp->sg_phdr); 414757ef7aa9SRod Evans Shdr *shdr = ofl->ofl_osinterp->os_shdr; 414857ef7aa9SRod Evans 414957ef7aa9SRod Evans phdr->p_vaddr = shdr->sh_addr; 415057ef7aa9SRod Evans phdr->p_offset = shdr->sh_offset; 415157ef7aa9SRod Evans phdr->p_memsz = phdr->p_filesz = shdr->sh_size; 415257ef7aa9SRod Evans phdr->p_flags = PF_R; 415357ef7aa9SRod Evans 415457ef7aa9SRod Evans DBG_CALL(Dbg_seg_entry(ofl, intpsndx, intpsgp)); 415557ef7aa9SRod Evans ofl->ofl_phdr[intppndx] = *phdr; 415657ef7aa9SRod Evans } 415757ef7aa9SRod Evans 415857ef7aa9SRod Evans /* 41597c478bd9Sstevel@tonic-gate * If we have a PT_SUNWDTRACE phdr, update it now with the address of 41607c478bd9Sstevel@tonic-gate * the symbol. It's only now been updated via update_sym(). 41617c478bd9Sstevel@tonic-gate */ 4162635216b6SRod Evans if (dtracesgp) { 4163d1827f25Srie Phdr *aphdr, *phdr = &(dtracesgp->sg_phdr); 41647c478bd9Sstevel@tonic-gate Sym_desc *sdp = ofl->ofl_dtracesym; 41657c478bd9Sstevel@tonic-gate 4166d1827f25Srie phdr->p_vaddr = sdp->sd_sym->st_value; 4167d1827f25Srie phdr->p_memsz = sdp->sd_sym->st_size; 41687c478bd9Sstevel@tonic-gate 41697c478bd9Sstevel@tonic-gate /* 417008278a5eSRod Evans * Take permissions from the segment that the symbol is 417108278a5eSRod Evans * associated with. 41727c478bd9Sstevel@tonic-gate */ 4173d1827f25Srie aphdr = &sdp->sd_isc->is_osdesc->os_sgdesc->sg_phdr; 4174d1827f25Srie assert(aphdr); 4175d1827f25Srie phdr->p_flags = aphdr->p_flags; 4176d1827f25Srie 4177d1827f25Srie DBG_CALL(Dbg_seg_entry(ofl, dtracesndx, dtracesgp)); 4178d1827f25Srie ofl->ofl_phdr[dtracepndx] = *phdr; 4179d1827f25Srie } 4180d1827f25Srie 4181d1827f25Srie /* 4182d1827f25Srie * If we have a PT_SUNWCAP phdr, update it now from the associated 4183d1827f25Srie * section information. 4184d1827f25Srie */ 4185635216b6SRod Evans if (capsgp) { 4186d1827f25Srie Phdr *phdr = &(capsgp->sg_phdr); 4187d1827f25Srie Shdr *shdr = ofl->ofl_oscap->os_shdr; 4188d1827f25Srie 4189d1827f25Srie phdr->p_vaddr = shdr->sh_addr; 4190d1827f25Srie phdr->p_offset = shdr->sh_offset; 419157ef7aa9SRod Evans phdr->p_memsz = phdr->p_filesz = shdr->sh_size; 4192d1827f25Srie phdr->p_flags = PF_R; 4193d1827f25Srie 4194d1827f25Srie DBG_CALL(Dbg_seg_entry(ofl, capsndx, capsgp)); 4195d1827f25Srie ofl->ofl_phdr[cappndx] = *phdr; 41967c478bd9Sstevel@tonic-gate } 41977c478bd9Sstevel@tonic-gate 41987c478bd9Sstevel@tonic-gate /* 41997c478bd9Sstevel@tonic-gate * Update the GROUP sections. 42007c478bd9Sstevel@tonic-gate */ 42017c478bd9Sstevel@tonic-gate if (update_ogroup(ofl) == S_ERROR) 42027c478bd9Sstevel@tonic-gate return (S_ERROR); 42037c478bd9Sstevel@tonic-gate 42047c478bd9Sstevel@tonic-gate /* 42057c478bd9Sstevel@tonic-gate * Update Move Table. 42067c478bd9Sstevel@tonic-gate */ 420757ef7aa9SRod Evans if (ofl->ofl_osmove || ofl->ofl_isparexpn) 420857ef7aa9SRod Evans update_move(ofl); 42097c478bd9Sstevel@tonic-gate 42107c478bd9Sstevel@tonic-gate /* 42117c478bd9Sstevel@tonic-gate * Build any output headers, version information, dynamic structure and 42127c478bd9Sstevel@tonic-gate * syminfo structure. 42137c478bd9Sstevel@tonic-gate */ 42147c478bd9Sstevel@tonic-gate if (update_oehdr(ofl) == S_ERROR) 42157c478bd9Sstevel@tonic-gate return (S_ERROR); 4216090a8d9eSAli Bahrami if (!(flags & FLG_OF_NOVERSEC)) { 4217090a8d9eSAli Bahrami if ((flags & FLG_OF_VERDEF) && 4218090a8d9eSAli Bahrami (update_overdef(ofl) == S_ERROR)) 42197c478bd9Sstevel@tonic-gate return (S_ERROR); 4220090a8d9eSAli Bahrami if ((flags & FLG_OF_VERNEED) && 4221090a8d9eSAli Bahrami (update_overneed(ofl) == S_ERROR)) 42227c478bd9Sstevel@tonic-gate return (S_ERROR); 4223635216b6SRod Evans if (flags & (FLG_OF_VERNEED | FLG_OF_VERDEF)) 4224635216b6SRod Evans update_oversym(ofl); 4225090a8d9eSAli Bahrami } 42267c478bd9Sstevel@tonic-gate if (flags & FLG_OF_DYNAMIC) { 42277c478bd9Sstevel@tonic-gate if (update_odynamic(ofl) == S_ERROR) 42287c478bd9Sstevel@tonic-gate return (S_ERROR); 4229635216b6SRod Evans } 4230635216b6SRod Evans if (ofl->ofl_ossyminfo) { 42317c478bd9Sstevel@tonic-gate if (update_osyminfo(ofl) == S_ERROR) 42327c478bd9Sstevel@tonic-gate return (S_ERROR); 42337c478bd9Sstevel@tonic-gate } 42347c478bd9Sstevel@tonic-gate 42357c478bd9Sstevel@tonic-gate /* 423608278a5eSRod Evans * Update capabilities information if required. 423708278a5eSRod Evans */ 423808278a5eSRod Evans if (ofl->ofl_oscap) 423908278a5eSRod Evans update_oscap(ofl); 424008278a5eSRod Evans if (ofl->ofl_oscapinfo) 424108278a5eSRod Evans update_oscapinfo(ofl); 424208278a5eSRod Evans 424308278a5eSRod Evans /* 4244635216b6SRod Evans * Sanity test: the first and last data byte of a string table 42451da7e599SAli Bahrami * must be NULL. 42461da7e599SAli Bahrami */ 42471da7e599SAli Bahrami assert((ofl->ofl_osshstrtab == NULL) || 42481da7e599SAli Bahrami (*((char *)ofl->ofl_osshstrtab->os_outdata->d_buf) == '\0')); 42491da7e599SAli Bahrami assert((ofl->ofl_osshstrtab == NULL) || 42501da7e599SAli Bahrami (*(((char *)ofl->ofl_osshstrtab->os_outdata->d_buf) + 42511da7e599SAli Bahrami ofl->ofl_osshstrtab->os_outdata->d_size - 1) == '\0')); 42521da7e599SAli Bahrami 42531da7e599SAli Bahrami assert((ofl->ofl_osstrtab == NULL) || 42541da7e599SAli Bahrami (*((char *)ofl->ofl_osstrtab->os_outdata->d_buf) == '\0')); 42551da7e599SAli Bahrami assert((ofl->ofl_osstrtab == NULL) || 42561da7e599SAli Bahrami (*(((char *)ofl->ofl_osstrtab->os_outdata->d_buf) + 42571da7e599SAli Bahrami ofl->ofl_osstrtab->os_outdata->d_size - 1) == '\0')); 42581da7e599SAli Bahrami 42591da7e599SAli Bahrami assert((ofl->ofl_osdynstr == NULL) || 42601da7e599SAli Bahrami (*((char *)ofl->ofl_osdynstr->os_outdata->d_buf) == '\0')); 42611da7e599SAli Bahrami assert((ofl->ofl_osdynstr == NULL) || 42621da7e599SAli Bahrami (*(((char *)ofl->ofl_osdynstr->os_outdata->d_buf) + 42631da7e599SAli Bahrami ofl->ofl_osdynstr->os_outdata->d_size - DYNSTR_EXTRA_PAD - 1) == 42641da7e599SAli Bahrami '\0')); 42651da7e599SAli Bahrami 42661da7e599SAli Bahrami /* 42677c478bd9Sstevel@tonic-gate * Emit Strtab diagnostics. 42687c478bd9Sstevel@tonic-gate */ 42695aefb655Srie DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osshstrtab, 42705aefb655Srie ofl->ofl_shdrsttab)); 42715aefb655Srie DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osstrtab, 42725aefb655Srie ofl->ofl_strtab)); 42735aefb655Srie DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osdynstr, 42745aefb655Srie ofl->ofl_dynstrtab)); 42757c478bd9Sstevel@tonic-gate 42767c478bd9Sstevel@tonic-gate /* 42777c478bd9Sstevel@tonic-gate * Initialize the section headers string table index within the elf 42787c478bd9Sstevel@tonic-gate * header. 42797c478bd9Sstevel@tonic-gate */ 42807c478bd9Sstevel@tonic-gate /* LINTED */ 42817c478bd9Sstevel@tonic-gate if ((shscnndx = elf_ndxscn(ofl->ofl_osshstrtab->os_scn)) < 42827c478bd9Sstevel@tonic-gate SHN_LORESERVE) { 42835aefb655Srie ofl->ofl_nehdr->e_shstrndx = 42847c478bd9Sstevel@tonic-gate /* LINTED */ 42857c478bd9Sstevel@tonic-gate (Half)shscnndx; 42867c478bd9Sstevel@tonic-gate } else { 42877c478bd9Sstevel@tonic-gate /* 42887c478bd9Sstevel@tonic-gate * If the STRTAB section index doesn't fit into 42897c478bd9Sstevel@tonic-gate * e_shstrndx, then we store it in 'shdr[0].st_link'. 42907c478bd9Sstevel@tonic-gate */ 42917c478bd9Sstevel@tonic-gate Elf_Scn *scn; 42927c478bd9Sstevel@tonic-gate Shdr *shdr0; 42935aefb655Srie 42947c478bd9Sstevel@tonic-gate if ((scn = elf_getscn(ofl->ofl_elf, 0)) == NULL) { 4295*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETSCN), 4296*1007fd6fSAli Bahrami ofl->ofl_name); 42977c478bd9Sstevel@tonic-gate return (S_ERROR); 42987c478bd9Sstevel@tonic-gate } 42997c478bd9Sstevel@tonic-gate if ((shdr0 = elf_getshdr(scn)) == NULL) { 4300*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETSHDR), 4301*1007fd6fSAli Bahrami ofl->ofl_name); 43027c478bd9Sstevel@tonic-gate return (S_ERROR); 43037c478bd9Sstevel@tonic-gate } 43045aefb655Srie ofl->ofl_nehdr->e_shstrndx = SHN_XINDEX; 43057c478bd9Sstevel@tonic-gate shdr0->sh_link = shscnndx; 43067c478bd9Sstevel@tonic-gate } 43077c478bd9Sstevel@tonic-gate 43087c478bd9Sstevel@tonic-gate return ((uintptr_t)etext); 43097c478bd9Sstevel@tonic-gate } 4310