xref: /illumos-gate/usr/src/cmd/sgs/libld/common/update.c (revision 44bac77b)
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  *
26e38a713aSrie  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
277c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Update the new output file image, perform virtual address, offset and
337c478bd9Sstevel@tonic-gate  * displacement calculations on the program headers and sections headers,
347c478bd9Sstevel@tonic-gate  * and generate any new output section information.
357c478bd9Sstevel@tonic-gate  */
36ba2be530Sab 
37ba2be530Sab #define	ELF_TARGET_AMD64
38ba2be530Sab 
397c478bd9Sstevel@tonic-gate #include	<stdio.h>
407c478bd9Sstevel@tonic-gate #include	<string.h>
41fdf855a7Sseizo #include	<unistd.h>
425aefb655Srie #include	<debug.h>
437c478bd9Sstevel@tonic-gate #include	"msg.h"
447c478bd9Sstevel@tonic-gate #include	"_libld.h"
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
479039eeafSab  * Comparison routine used by qsort() for sorting of the global symbol list
487c478bd9Sstevel@tonic-gate  * based off of the hashbuckets the symbol will eventually be deposited in.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate static int
517c478bd9Sstevel@tonic-gate sym_hash_compare(Sym_s_list * s1, Sym_s_list * s2)
527c478bd9Sstevel@tonic-gate {
537c478bd9Sstevel@tonic-gate 	return (s1->sl_hval - s2->sl_hval);
547c478bd9Sstevel@tonic-gate }
557c478bd9Sstevel@tonic-gate 
56d579eb63Sab /*
57d579eb63Sab  * Comparison routine used by qsort() for sorting of dyn[sym|tls]sort section
58d579eb63Sab  * indices based on the address of the symbols they reference. The
59d579eb63Sab  * use of the global dynsort_compare_syms variable is needed because
60d579eb63Sab  * we need to examine the symbols the indices reference. It is safe, because
61d579eb63Sab  * the linker is single threaded.
62d579eb63Sab  */
63d579eb63Sab Sym *dynsort_compare_syms;
64d579eb63Sab 
65d579eb63Sab static int
66d579eb63Sab dynsort_compare(const void *idx1, const void *idx2)
67d579eb63Sab {
68d579eb63Sab 	Sym *s1 = dynsort_compare_syms + *((const Word *) idx1);
69d579eb63Sab 	Sym *s2 = dynsort_compare_syms + *((const Word *) idx2);
70d579eb63Sab 
71d579eb63Sab 	/*
72d579eb63Sab 	 * Note: the logical computation for this is
73d579eb63Sab 	 *	(st_value1 - st_value2)
74d579eb63Sab 	 * However, that is only correct if the address type is smaller
75d579eb63Sab 	 * than a pointer. Writing it this way makes it immune to the
76d579eb63Sab 	 * class (32 or 64-bit) of the linker.
77d579eb63Sab 	 */
78d579eb63Sab 	return ((s1->st_value < s2->st_value) ? -1 :
79d579eb63Sab 	    (s1->st_value > s2->st_value));
80d579eb63Sab }
81d579eb63Sab 
82d579eb63Sab 
83d579eb63Sab /*
84d579eb63Sab  * Scan the sorted symbols, and issue warnings if there are any duplicate
85d579eb63Sab  * values in the list. We only do this if -zverbose is set, or we are
86d579eb63Sab  * running with LD_DEBUG defined
87d579eb63Sab  *
88d579eb63Sab  * entry:
89d579eb63Sab  *	ofl - Output file descriptor
90d579eb63Sab  *	ldynsym - Pointer to start of .SUNW_ldynsym section that the
91d579eb63Sab  *		sort section indexes reference.
92d579eb63Sab  *	symsort - Pointer to start of .SUNW_dynsymsort or .SUNW_dyntlssort
93d579eb63Sab  *		section.
94d579eb63Sab  *	n - # of indices in symsort array
95d579eb63Sab  *	secname - Name of the symsort section.
96d579eb63Sab  *
97d579eb63Sab  * exit:
98d579eb63Sab  *	If the symsort section contains indexes to more than one
99d579eb63Sab  *	symbol with the same address value, a warning is issued.
100d579eb63Sab  */
101d579eb63Sab static void
102d579eb63Sab dynsort_dupwarn(Ofl_desc *ofl, Sym *ldynsym, const char *str,
103d579eb63Sab     Word *symsort, Word n, const char *secname)
104d579eb63Sab {
105d579eb63Sab 	int zverbose = (ofl->ofl_flags & FLG_OF_VERBOSE) != 0;
106d579eb63Sab 	Word ndx, cmp_ndx;
107d579eb63Sab 	Addr addr, cmp_addr;
108d579eb63Sab 
109d579eb63Sab 	/* Nothing to do if -zverbose or LD_DEBUG are not active */
110d579eb63Sab 	if (!(zverbose || DBG_ENABLED))
111d579eb63Sab 		return;
112d579eb63Sab 
113d579eb63Sab 	cmp_ndx = 0;
114d579eb63Sab 	cmp_addr = ldynsym[symsort[cmp_ndx]].st_value;
115d579eb63Sab 	for (ndx = 1; ndx < n; ndx++) {
116d579eb63Sab 		addr = ldynsym[symsort[ndx]].st_value;
117d579eb63Sab 		if (cmp_addr == addr) {
118d579eb63Sab 			if (zverbose)
119d579eb63Sab 				eprintf(ofl->ofl_lml, ERR_WARNING,
120d579eb63Sab 				    MSG_INTL(MSG_SYM_DUPSORTADDR), secname,
121d579eb63Sab 				    str + ldynsym[symsort[cmp_ndx]].st_name,
122d579eb63Sab 				    str + ldynsym[symsort[ndx]].st_name,
123d579eb63Sab 				    EC_ADDR(addr));
124d579eb63Sab 			DBG_CALL(Dbg_syms_dup_sort_addr(ofl->ofl_lml, secname,
125d579eb63Sab 			    str + ldynsym[symsort[cmp_ndx]].st_name,
126d579eb63Sab 			    str + ldynsym[symsort[ndx]].st_name,
127d579eb63Sab 			    EC_ADDR(addr)));
128d579eb63Sab 		} else {	/* Not a dup. Move reference up */
129d579eb63Sab 			cmp_ndx = ndx;
130d579eb63Sab 			cmp_addr = addr;
131d579eb63Sab 		}
132d579eb63Sab 	}
133d579eb63Sab }
134d579eb63Sab 
135d579eb63Sab 
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate  * Build and update any output symbol tables.  Here we work on all the symbol
1387c478bd9Sstevel@tonic-gate  * tables at once to reduce the duplication of symbol and string manipulation.
1397c478bd9Sstevel@tonic-gate  * Symbols and their associated strings are copied from the read-only input
1407c478bd9Sstevel@tonic-gate  * file images to the output image and their values and index's updated in the
1417c478bd9Sstevel@tonic-gate  * output image.
1427c478bd9Sstevel@tonic-gate  */
1435aefb655Srie static Addr
1447c478bd9Sstevel@tonic-gate update_osym(Ofl_desc *ofl)
1457c478bd9Sstevel@tonic-gate {
146d579eb63Sab 	/*
147d579eb63Sab 	 * There are several places in this function where we wish
148d579eb63Sab 	 * to insert a symbol index to the combined .SUNW_ldynsym/.dynsym
149d579eb63Sab 	 * symbol table into one of the two sort sections (.SUNW_dynsymsort
150d579eb63Sab 	 * or .SUNW_dyntlssort), if that symbol has the right attributes.
151d579eb63Sab 	 * This macro is used to generate the necessary code from a single
152d579eb63Sab 	 * specification.
153d579eb63Sab 	 *
154d579eb63Sab 	 * entry:
155d579eb63Sab 	 *	_sdp, _sym, _type - As per DYNSORT_COUNT. See _libld.h
156d579eb63Sab 	 *	_sym_ndx - Index that _sym will have in the combined
157d579eb63Sab 	 *		.SUNW_ldynsym/.dynsym symbol table.
158d579eb63Sab 	 */
159d579eb63Sab #define	ADD_TO_DYNSORT(_sdp, _sym, _type, _sym_ndx) \
160d579eb63Sab 	{ \
161d579eb63Sab 		Word *_dynsort_arr, *_dynsort_ndx; \
162d579eb63Sab 		\
163d579eb63Sab 		if (dynsymsort_symtype[_type]) { \
164d579eb63Sab 			_dynsort_arr = dynsymsort; \
165d579eb63Sab 			_dynsort_ndx = &dynsymsort_ndx; \
166d579eb63Sab 		} else if (_type == STT_TLS) { \
167d579eb63Sab 			_dynsort_arr = dyntlssort; \
168d579eb63Sab 			_dynsort_ndx = &dyntlssort_ndx; \
169d579eb63Sab 		} else { \
170d579eb63Sab 			_dynsort_arr = NULL; \
171d579eb63Sab 		} \
172d579eb63Sab 		if ((_dynsort_arr != NULL) && DYNSORT_TEST_ATTR(_sdp, _sym)) \
173d579eb63Sab 			_dynsort_arr[(*_dynsort_ndx)++] = _sym_ndx; \
174d579eb63Sab 	}
175d579eb63Sab 
176d579eb63Sab 
1770bc07c75Srie 	Listnode	*lnp1;
1787c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
1797c478bd9Sstevel@tonic-gate 	Sym_avlnode	*sav;
1807c478bd9Sstevel@tonic-gate 	Sg_desc		*sgp, *tsgp = 0, *dsgp = 0, *esgp = 0;
181c1c6f601Srie 	Os_desc		*osp, *iosp = 0, *fosp = 0;
1827c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
1837c478bd9Sstevel@tonic-gate 	Word		bssndx, etext_ndx, edata_ndx = 0, end_ndx, start_ndx;
1847c478bd9Sstevel@tonic-gate 	Word		end_abs = 0, etext_abs = 0, edata_abs;
1857c478bd9Sstevel@tonic-gate 	Word		tlsbssndx = 0, sunwbssndx = 0, sunwdata1ndx;
186ba2be530Sab #if	defined(_ELF64)
18754d82594Sseizo 	Word		lbssndx = 0;
18854d82594Sseizo 	Addr		lbssaddr = 0;
18954d82594Sseizo #endif
1907c478bd9Sstevel@tonic-gate 	Addr		bssaddr, etext = 0, edata = 0, end = 0, start = 0;
1917c478bd9Sstevel@tonic-gate 	Addr		tlsbssaddr = 0;
1927c478bd9Sstevel@tonic-gate 	Addr 		sunwbssaddr = 0, sunwdata1addr;
1937c478bd9Sstevel@tonic-gate 	int		start_set = 0;
1949039eeafSab 	Sym		_sym = {0}, *sym, *symtab = 0;
1959039eeafSab 	Sym		*dynsym = 0, *ldynsym = 0;
1967c478bd9Sstevel@tonic-gate 	Word		symtab_ndx = 0;	/* index into .symtab */
1979039eeafSab 	Word		ldynsym_ndx = 0;	/* index into .SUNW_ldynsym */
1989039eeafSab 	Word		dynsym_ndx = 0;		/* index into .dynsym */
1997c478bd9Sstevel@tonic-gate 	Word		scopesym_ndx = 0; /* index into scoped symbols */
2009039eeafSab 	Word		ldynscopesym_ndx = 0; /* index to ldynsym scoped syms */
201d579eb63Sab 	Word		*dynsymsort = NULL; /* SUNW_dynsymsort index vector */
202d579eb63Sab 	Word		*dyntlssort = NULL; /* SUNW_dyntlssort index vector */
203d579eb63Sab 	Word		dynsymsort_ndx;		/* index dynsymsort array */
204d579eb63Sab 	Word		dyntlssort_ndx;		/* index dyntlssort array */
2059039eeafSab 	Word		*symndx;	/* Symbol index (for relocation use) */
2067c478bd9Sstevel@tonic-gate 	Word		*symshndx = 0;	/* .symtab_shndx table */
2077c478bd9Sstevel@tonic-gate 	Word		*dynshndx = 0;	/* .dynsym_shndx table */
2089039eeafSab 	Word		*ldynshndx = 0;	/* .SUNW_ldynsym_shndx table */
209d579eb63Sab 	Word		ldynsym_cnt = 0; /* # of items in .SUNW_ldynsym */
2107c478bd9Sstevel@tonic-gate 	Str_tbl		*shstrtab;
2117c478bd9Sstevel@tonic-gate 	Str_tbl		*strtab;
2127c478bd9Sstevel@tonic-gate 	Str_tbl		*dynstr;
2137c478bd9Sstevel@tonic-gate 	Word		*hashtab;	/* hash table pointer */
2147c478bd9Sstevel@tonic-gate 	Word		*hashbkt;	/* hash table bucket pointer */
2157c478bd9Sstevel@tonic-gate 	Word		*hashchain;	/* hash table chain pointer */
2167c478bd9Sstevel@tonic-gate 	Word		hashval;	/* value of hash function */
2177c478bd9Sstevel@tonic-gate 	Wk_desc		*wkp;
2187c478bd9Sstevel@tonic-gate 	List		weak = {NULL, NULL};
2191d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
2207c478bd9Sstevel@tonic-gate 	Word		dtflags_1 = ofl->ofl_dtflags_1;
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 */
228cce0e03bSab 	size_t		stoff;		/* string offset */
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/*
2317c478bd9Sstevel@tonic-gate 	 * Initialize pointers to the symbol table entries and the symbol
2327c478bd9Sstevel@tonic-gate 	 * table strings.  Skip the first symbol entry and the first string
2337c478bd9Sstevel@tonic-gate 	 * table byte.  Note that if we are not generating any output symbol
2347c478bd9Sstevel@tonic-gate 	 * tables we must still generate and update an internal copies so
2357c478bd9Sstevel@tonic-gate 	 * that the relocation phase has the correct information.
2367c478bd9Sstevel@tonic-gate 	 */
2377c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) ||
2387c478bd9Sstevel@tonic-gate 	    ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) {
2397c478bd9Sstevel@tonic-gate 		symtab = (Sym *)ofl->ofl_ossymtab->os_outdata->d_buf;
2407c478bd9Sstevel@tonic-gate 		symtab[symtab_ndx++] = _sym;
2417c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ossymshndx)
242d840867fSab 			symshndx =
243d840867fSab 			    (Word *)ofl->ofl_ossymshndx->os_outdata->d_buf;
2447c478bd9Sstevel@tonic-gate 	}
2459039eeafSab 	if (OFL_ALLOW_DYNSYM(ofl)) {
2467c478bd9Sstevel@tonic-gate 		dynsym = (Sym *)ofl->ofl_osdynsym->os_outdata->d_buf;
2477c478bd9Sstevel@tonic-gate 		dynsym[dynsym_ndx++] = _sym;
2489039eeafSab 		/*
2499039eeafSab 		 * If we are also constructing a .SUNW_ldynsym section
2509039eeafSab 		 * to contain local function symbols, then set it up too.
2519039eeafSab 		 */
2529039eeafSab 		if (ofl->ofl_osldynsym) {
2539039eeafSab 			ldynsym = (Sym *)ofl->ofl_osldynsym->os_outdata->d_buf;
2549039eeafSab 			ldynsym[ldynsym_ndx++] = _sym;
255d579eb63Sab 			ldynsym_cnt = 1 + ofl->ofl_dynlocscnt +
256d579eb63Sab 			    ofl->ofl_dynscopecnt;
257d579eb63Sab 
258d579eb63Sab 			/*
259d579eb63Sab 			 * If there is a SUNW_ldynsym, then there may also
260d579eb63Sab 			 * be a .SUNW_dynsymsort and/or .SUNW_dyntlssort
261d579eb63Sab 			 * sections, used to collect indices of function
262d579eb63Sab 			 * and data symbols sorted by address order.
263d579eb63Sab 			 */
264d579eb63Sab 			if (ofl->ofl_osdynsymsort) {	/* .SUNW_dynsymsort */
265d579eb63Sab 				dynsymsort = (Word *)
266d579eb63Sab 				    ofl->ofl_osdynsymsort->os_outdata->d_buf;
267d579eb63Sab 				dynsymsort_ndx = 0;
268d579eb63Sab 			}
269d579eb63Sab 			if (ofl->ofl_osdyntlssort) {	/* .SUNW_dyntlssort */
270d579eb63Sab 				dyntlssort = (Word *)
271d579eb63Sab 				    ofl->ofl_osdyntlssort->os_outdata->d_buf;
272d579eb63Sab 				dyntlssort_ndx = 0;
273d579eb63Sab 			}
2749039eeafSab 		}
2759039eeafSab 
2767c478bd9Sstevel@tonic-gate 		/*
2777c478bd9Sstevel@tonic-gate 		 * Initialize the hash table.
2787c478bd9Sstevel@tonic-gate 		 */
2797c478bd9Sstevel@tonic-gate 		hashtab = (Word *)(ofl->ofl_oshash->os_outdata->d_buf);
2807c478bd9Sstevel@tonic-gate 		hashbkt = &hashtab[2];
2817c478bd9Sstevel@tonic-gate 		hashchain = &hashtab[2 + ofl->ofl_hashbkts];
2827c478bd9Sstevel@tonic-gate 		hashtab[0] = ofl->ofl_hashbkts;
2837c478bd9Sstevel@tonic-gate 		hashtab[1] = ofl->ofl_dynshdrcnt + ofl->ofl_globcnt +
2847c478bd9Sstevel@tonic-gate 		    ofl->ofl_lregsymcnt + 1;
2857c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynshndx)
286d840867fSab 			dynshndx =
287d840867fSab 			    (Word *)ofl->ofl_osdynshndx->os_outdata->d_buf;
2889039eeafSab 		if (ofl->ofl_osldynshndx)
289d840867fSab 			ldynshndx =
290d840867fSab 			    (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 	 */
3077c478bd9Sstevel@tonic-gate 	if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) == FLG_OF_VERDEF) {
3087c478bd9Sstevel@tonic-gate 		versym = (Versym *)ofl->ofl_osversym->os_outdata->d_buf;
3097c478bd9Sstevel@tonic-gate 		versym[0] = 0;
3107c478bd9Sstevel@tonic-gate 	} else
3117c478bd9Sstevel@tonic-gate 		versym = 0;
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	/*
3147c478bd9Sstevel@tonic-gate 	 * If syminfo section exists be prepared to fill it in.
3157c478bd9Sstevel@tonic-gate 	 */
3167c478bd9Sstevel@tonic-gate 	if (ofl->ofl_ossyminfo) {
3177c478bd9Sstevel@tonic-gate 		syminfo = ofl->ofl_ossyminfo->os_outdata->d_buf;
3187c478bd9Sstevel@tonic-gate 		syminfo[0].si_flags = SYMINFO_CURRENT;
3197c478bd9Sstevel@tonic-gate 	} else
3207c478bd9Sstevel@tonic-gate 		syminfo = 0;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/*
3237c478bd9Sstevel@tonic-gate 	 * Setup our string tables.
3247c478bd9Sstevel@tonic-gate 	 */
3257c478bd9Sstevel@tonic-gate 	shstrtab = ofl->ofl_shdrsttab;
3267c478bd9Sstevel@tonic-gate 	strtab = ofl->ofl_strtab;
3277c478bd9Sstevel@tonic-gate 	dynstr = ofl->ofl_dynstrtab;
3287c478bd9Sstevel@tonic-gate 
3295aefb655Srie 	DBG_CALL(Dbg_syms_sec_title(ofl->ofl_lml));
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	/*
3329039eeafSab 	 * Put output file name to the first .symtab and .SUNW_ldynsym symbol.
3337c478bd9Sstevel@tonic-gate 	 */
3347c478bd9Sstevel@tonic-gate 	if (symtab) {
3357c478bd9Sstevel@tonic-gate 		(void) st_setstring(strtab, ofl->ofl_name, &stoff);
3367c478bd9Sstevel@tonic-gate 		sym = &symtab[symtab_ndx++];
3377c478bd9Sstevel@tonic-gate 		/* LINTED */
3387c478bd9Sstevel@tonic-gate 		sym->st_name = stoff;
3397c478bd9Sstevel@tonic-gate 		sym->st_value = 0;
3407c478bd9Sstevel@tonic-gate 		sym->st_size = 0;
3417c478bd9Sstevel@tonic-gate 		sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE);
3427c478bd9Sstevel@tonic-gate 		sym->st_other = 0;
3437c478bd9Sstevel@tonic-gate 		sym->st_shndx = SHN_ABS;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 		if (versym && !dynsym)
3467c478bd9Sstevel@tonic-gate 			versym[1] = 0;
3477c478bd9Sstevel@tonic-gate 	}
348d579eb63Sab 	if (ldynsym) {
3499039eeafSab 		(void) st_setstring(dynstr, ofl->ofl_name, &stoff);
3509039eeafSab 		sym = &ldynsym[ldynsym_ndx];
3519039eeafSab 		/* LINTED */
3529039eeafSab 		sym->st_name = stoff;
3539039eeafSab 		sym->st_value = 0;
3549039eeafSab 		sym->st_size = 0;
3559039eeafSab 		sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE);
3569039eeafSab 		sym->st_other = 0;
3579039eeafSab 		sym->st_shndx = SHN_ABS;
3589039eeafSab 
3599039eeafSab 		/* Scoped symbols get filled in global loop below */
3609039eeafSab 		ldynscopesym_ndx = ldynsym_ndx + 1;
3619039eeafSab 		ldynsym_ndx += ofl->ofl_dynscopecnt;
3629039eeafSab 	}
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	/*
3657c478bd9Sstevel@tonic-gate 	 * If we are to display GOT summary information, then allocate
3667c478bd9Sstevel@tonic-gate 	 * the buffer to 'cache' the GOT symbols into now.
3677c478bd9Sstevel@tonic-gate 	 */
3685aefb655Srie 	if (DBG_ENABLED) {
369d326b23bSrie 		if ((ofl->ofl_gottable = gottable =
370d326b23bSrie 		    libld_calloc(ofl->ofl_gotcnt, sizeof (Gottable))) == 0)
3717c478bd9Sstevel@tonic-gate 		return ((Addr)S_ERROR);
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	/*
3757c478bd9Sstevel@tonic-gate 	 * Traverse the program headers.  Determine the last executable segment
3767c478bd9Sstevel@tonic-gate 	 * and the last data segment so that we can update etext and edata. If
3777c478bd9Sstevel@tonic-gate 	 * we have empty segments (reservations) record them for setting _end.
3787c478bd9Sstevel@tonic-gate 	 */
3797c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) {
3800bc07c75Srie 		Phdr	*phd = &(sgp->sg_phdr);
381cce0e03bSab 		Os_desc	*osp;
382cce0e03bSab 		Aliste	idx;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		if (phd->p_type == PT_LOAD) {
3850bc07c75Srie 			if (sgp->sg_osdescs != NULL) {
386d840867fSab 				Word	_flags = phd->p_flags & (PF_W | PF_R);
3870bc07c75Srie 
388d840867fSab 				if (_flags == PF_R)
389d840867fSab 					tsgp = sgp;
390d840867fSab 				else if (_flags == (PF_W | PF_R))
391d840867fSab 					dsgp = sgp;
3927c478bd9Sstevel@tonic-gate 			} else if (sgp->sg_flags & FLG_SG_EMPTY)
393d840867fSab 				esgp = sgp;
3947c478bd9Sstevel@tonic-gate 		}
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 		/*
3977c478bd9Sstevel@tonic-gate 		 * Generate a section symbol for each output section.
3987c478bd9Sstevel@tonic-gate 		 */
399cce0e03bSab 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) {
4007c478bd9Sstevel@tonic-gate 			Word	sectndx;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 			sym = &_sym;
4037c478bd9Sstevel@tonic-gate 			sym->st_value = osp->os_shdr->sh_addr;
4047c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION);
4057c478bd9Sstevel@tonic-gate 			/* LINTED */
4067c478bd9Sstevel@tonic-gate 			sectndx = elf_ndxscn(osp->os_scn);
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 			if (symtab) {
4097c478bd9Sstevel@tonic-gate 				if (sectndx >= SHN_LORESERVE) {
4107c478bd9Sstevel@tonic-gate 					symshndx[symtab_ndx] = sectndx;
4117c478bd9Sstevel@tonic-gate 					sym->st_shndx = SHN_XINDEX;
4127c478bd9Sstevel@tonic-gate 				} else {
4137c478bd9Sstevel@tonic-gate 					/* LINTED */
4147c478bd9Sstevel@tonic-gate 					sym->st_shndx = (Half)sectndx;
4157c478bd9Sstevel@tonic-gate 				}
4167c478bd9Sstevel@tonic-gate 				symtab[symtab_ndx++] = *sym;
4177c478bd9Sstevel@tonic-gate 			}
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 			if (dynsym && (osp->os_flags & FLG_OS_OUTREL))
4207c478bd9Sstevel@tonic-gate 				dynsym[dynsym_ndx++] = *sym;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 			if ((dynsym == 0) || (osp->os_flags & FLG_OS_OUTREL)) {
4237c478bd9Sstevel@tonic-gate 				if (versym)
4247c478bd9Sstevel@tonic-gate 					versym[*symndx - 1] = 0;
4257c478bd9Sstevel@tonic-gate 				osp->os_scnsymndx = *symndx - 1;
4265aefb655Srie 				DBG_CALL(Dbg_syms_sec_entry(ofl->ofl_lml,
4275aefb655Srie 				    osp->os_scnsymndx, sgp, osp));
4287c478bd9Sstevel@tonic-gate 			}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 			/*
4317c478bd9Sstevel@tonic-gate 			 * Generate the .shstrtab for this section.
4327c478bd9Sstevel@tonic-gate 			 */
4337c478bd9Sstevel@tonic-gate 			(void) st_setstring(shstrtab, osp->os_name, &stoff);
4347c478bd9Sstevel@tonic-gate 			osp->os_shdr->sh_name = (Word)stoff;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 			/*
4377c478bd9Sstevel@tonic-gate 			 * Find the section index for our special symbols.
4387c478bd9Sstevel@tonic-gate 			 */
4397c478bd9Sstevel@tonic-gate 			if (sgp == tsgp) {
4407c478bd9Sstevel@tonic-gate 				/* LINTED */
4417c478bd9Sstevel@tonic-gate 				etext_ndx = elf_ndxscn(osp->os_scn);
4427c478bd9Sstevel@tonic-gate 			} else if (dsgp == sgp) {
4437c478bd9Sstevel@tonic-gate 				if (osp->os_shdr->sh_type != SHT_NOBITS) {
4447c478bd9Sstevel@tonic-gate 					/* LINTED */
4457c478bd9Sstevel@tonic-gate 					edata_ndx = elf_ndxscn(osp->os_scn);
4467c478bd9Sstevel@tonic-gate 				}
4477c478bd9Sstevel@tonic-gate 			}
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 			if (start_set == 0) {
4507c478bd9Sstevel@tonic-gate 				start = sgp->sg_phdr.p_vaddr;
4517c478bd9Sstevel@tonic-gate 				/* LINTED */
4527c478bd9Sstevel@tonic-gate 				start_ndx = elf_ndxscn(osp->os_scn);
4537c478bd9Sstevel@tonic-gate 				start_set++;
4547c478bd9Sstevel@tonic-gate 			}
455c1c6f601Srie 
456c1c6f601Srie 			/*
457c1c6f601Srie 			 * While we're here, determine whether a .init or .fini
458c1c6f601Srie 			 * section exist.
459c1c6f601Srie 			 */
460c1c6f601Srie 			if ((iosp == 0) && (strcmp(osp->os_name,
461c1c6f601Srie 			    MSG_ORIG(MSG_SCN_INIT)) == 0))
462c1c6f601Srie 				iosp = osp;
463c1c6f601Srie 			if ((fosp == 0) && (strcmp(osp->os_name,
464c1c6f601Srie 			    MSG_ORIG(MSG_SCN_FINI)) == 0))
465c1c6f601Srie 				fosp = osp;
4667c478bd9Sstevel@tonic-gate 		}
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	/*
4707c478bd9Sstevel@tonic-gate 	 * Add local register symbols to the .dynsym.  These are required as
4717c478bd9Sstevel@tonic-gate 	 * DT_REGISTER .dynamic entries must have a symbol to reference.
4727c478bd9Sstevel@tonic-gate 	 */
4737c478bd9Sstevel@tonic-gate 	if (ofl->ofl_regsyms && dynsym) {
4747c478bd9Sstevel@tonic-gate 		int	ndx;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 		for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
4777c478bd9Sstevel@tonic-gate 			Sym_desc *	rsdp;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 			if ((rsdp = ofl->ofl_regsyms[ndx]) == 0)
4807c478bd9Sstevel@tonic-gate 				continue;
4817c478bd9Sstevel@tonic-gate 
48260758829Srie 			if (((rsdp->sd_flags1 & FLG_SY1_HIDDEN) == 0) &&
4837c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(rsdp->sd_sym->st_info) != STB_LOCAL))
4847c478bd9Sstevel@tonic-gate 				continue;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 			dynsym[dynsym_ndx] = *(rsdp->sd_sym);
4877c478bd9Sstevel@tonic-gate 			rsdp->sd_symndx = *symndx;
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 			if (dynsym[dynsym_ndx].st_name) {
4907c478bd9Sstevel@tonic-gate 				(void) st_setstring(dynstr, rsdp->sd_name,
4917c478bd9Sstevel@tonic-gate 				    &stoff);
4927c478bd9Sstevel@tonic-gate 				dynsym[dynsym_ndx].st_name = stoff;
4937c478bd9Sstevel@tonic-gate 			}
4947c478bd9Sstevel@tonic-gate 			dynsym_ndx++;
4957c478bd9Sstevel@tonic-gate 		}
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	/*
4997c478bd9Sstevel@tonic-gate 	 * Having traversed all the output segments, warn the user if the
5007c478bd9Sstevel@tonic-gate 	 * traditional text or data segments don't exist.  Otherwise from these
5017c478bd9Sstevel@tonic-gate 	 * segments establish the values for `etext', `edata', `end', `END',
5027c478bd9Sstevel@tonic-gate 	 * and `START'.
5037c478bd9Sstevel@tonic-gate 	 */
5047c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_RELOBJ)) {
5057c478bd9Sstevel@tonic-gate 		Sg_desc *	sgp;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 		if (tsgp)
5087c478bd9Sstevel@tonic-gate 			etext = tsgp->sg_phdr.p_vaddr + tsgp->sg_phdr.p_filesz;
5097c478bd9Sstevel@tonic-gate 		else {
5107c478bd9Sstevel@tonic-gate 			etext = (Addr)0;
5117c478bd9Sstevel@tonic-gate 			etext_ndx = SHN_ABS;
5127c478bd9Sstevel@tonic-gate 			etext_abs = 1;
5131d9df23bSab 			if (flags & FLG_OF_VERBOSE)
5145aefb655Srie 				eprintf(ofl->ofl_lml, ERR_WARNING,
5157c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_UPD_NOREADSEG));
5167c478bd9Sstevel@tonic-gate 		}
5177c478bd9Sstevel@tonic-gate 		if (dsgp) {
5187c478bd9Sstevel@tonic-gate 			edata = dsgp->sg_phdr.p_vaddr + dsgp->sg_phdr.p_filesz;
5197c478bd9Sstevel@tonic-gate 		} else {
5207c478bd9Sstevel@tonic-gate 			edata = (Addr)0;
5217c478bd9Sstevel@tonic-gate 			edata_ndx = SHN_ABS;
5227c478bd9Sstevel@tonic-gate 			edata_abs = 1;
5231d9df23bSab 			if (flags & FLG_OF_VERBOSE)
5245aefb655Srie 				eprintf(ofl->ofl_lml, ERR_WARNING,
5257c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_UPD_NORDWRSEG));
5267c478bd9Sstevel@tonic-gate 		}
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 		if (dsgp == 0) {
5297c478bd9Sstevel@tonic-gate 			if (tsgp)
5307c478bd9Sstevel@tonic-gate 				sgp = tsgp;
5317c478bd9Sstevel@tonic-gate 			else
5327c478bd9Sstevel@tonic-gate 				sgp = 0;
5337c478bd9Sstevel@tonic-gate 		} else if (tsgp == 0)
5347c478bd9Sstevel@tonic-gate 			sgp = dsgp;
5357c478bd9Sstevel@tonic-gate 		else if (dsgp->sg_phdr.p_vaddr > tsgp->sg_phdr.p_vaddr)
5367c478bd9Sstevel@tonic-gate 			sgp = dsgp;
5377c478bd9Sstevel@tonic-gate 		else if (dsgp->sg_phdr.p_vaddr < tsgp->sg_phdr.p_vaddr)
5387c478bd9Sstevel@tonic-gate 			sgp = tsgp;
5397c478bd9Sstevel@tonic-gate 		else {
5407c478bd9Sstevel@tonic-gate 			/*
5417c478bd9Sstevel@tonic-gate 			 * One of the segments must be of zero size.
5427c478bd9Sstevel@tonic-gate 			 */
5437c478bd9Sstevel@tonic-gate 			if (tsgp->sg_phdr.p_memsz)
5447c478bd9Sstevel@tonic-gate 				sgp = tsgp;
5457c478bd9Sstevel@tonic-gate 			else
5467c478bd9Sstevel@tonic-gate 				sgp = dsgp;
5477c478bd9Sstevel@tonic-gate 		}
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 		if (esgp && (esgp->sg_phdr.p_vaddr > sgp->sg_phdr.p_vaddr))
5507c478bd9Sstevel@tonic-gate 			sgp = esgp;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 		if (sgp) {
5537c478bd9Sstevel@tonic-gate 			end = sgp->sg_phdr.p_vaddr + sgp->sg_phdr.p_memsz;
5547c478bd9Sstevel@tonic-gate 
555fdf855a7Sseizo 			/*
556fdf855a7Sseizo 			 * If the last loadable segment is a read-only segment,
557fdf855a7Sseizo 			 * then the application which uses the symbol _end to
558fdf855a7Sseizo 			 * find the beginning of writable heap area may cause
559fdf855a7Sseizo 			 * segmentation violation. We adjust the value of the
560fdf855a7Sseizo 			 * _end to skip to the next page boundary.
561fdf855a7Sseizo 			 *
562fdf855a7Sseizo 			 * 6401812 System interface which returs beginning
563fdf855a7Sseizo 			 *	   heap would be nice.
564fdf855a7Sseizo 			 * When the above RFE is implemented, the changes below
565fdf855a7Sseizo 			 * could be changed in a better way.
566fdf855a7Sseizo 			 */
567fdf855a7Sseizo 			if ((sgp->sg_phdr.p_flags & PF_W) == 0)
56860758829Srie 				end = (Addr)S_ROUND(end, sysconf(_SC_PAGESIZE));
569fdf855a7Sseizo 
5707c478bd9Sstevel@tonic-gate 			/*
5717c478bd9Sstevel@tonic-gate 			 * If we're dealing with a memory reservation there are
5727c478bd9Sstevel@tonic-gate 			 * no sections to establish an index for _end, so assign
5737c478bd9Sstevel@tonic-gate 			 * it as an absolute.
5747c478bd9Sstevel@tonic-gate 			 */
5750bc07c75Srie 			if (sgp->sg_osdescs != NULL) {
5760bc07c75Srie 				/*
5770bc07c75Srie 				 * Determine the last section for this segment.
5780bc07c75Srie 				 */
579cce0e03bSab 				Os_desc	*osp = sgp->sg_osdescs->apl_data
580cce0e03bSab 				    [sgp->sg_osdescs->apl_nitems - 1];
581cce0e03bSab 
5820bc07c75Srie 				/* LINTED */
583cce0e03bSab 				end_ndx = elf_ndxscn(osp->os_scn);
5847c478bd9Sstevel@tonic-gate 			} else {
5857c478bd9Sstevel@tonic-gate 				end_ndx = SHN_ABS;
5867c478bd9Sstevel@tonic-gate 				end_abs = 1;
5877c478bd9Sstevel@tonic-gate 			}
5887c478bd9Sstevel@tonic-gate 		} else {
5897c478bd9Sstevel@tonic-gate 			end = (Addr) 0;
5907c478bd9Sstevel@tonic-gate 			end_ndx = SHN_ABS;
5917c478bd9Sstevel@tonic-gate 			end_abs = 1;
5925aefb655Srie 			eprintf(ofl->ofl_lml, ERR_WARNING,
5935aefb655Srie 			    MSG_INTL(MSG_UPD_NOSEG));
5947c478bd9Sstevel@tonic-gate 		}
5957c478bd9Sstevel@tonic-gate 	}
5967c478bd9Sstevel@tonic-gate 
5975aefb655Srie 	DBG_CALL(Dbg_syms_up_title(ofl->ofl_lml));
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	/*
6007c478bd9Sstevel@tonic-gate 	 * Initialize the scoped symbol table entry point.  This is for all
6017c478bd9Sstevel@tonic-gate 	 * the global symbols that have been scoped to locals and will be
6027c478bd9Sstevel@tonic-gate 	 * filled in during global symbol processing so that we don't have
6037c478bd9Sstevel@tonic-gate 	 * to traverse the globals symbol hash array more than once.
6047c478bd9Sstevel@tonic-gate 	 */
6057c478bd9Sstevel@tonic-gate 	if (symtab) {
6067c478bd9Sstevel@tonic-gate 		scopesym_ndx = symtab_ndx;
6077c478bd9Sstevel@tonic-gate 		symtab_ndx += ofl->ofl_scopecnt;
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/*
6117c478bd9Sstevel@tonic-gate 	 * Assign .sunwdata1 information
6127c478bd9Sstevel@tonic-gate 	 */
6137c478bd9Sstevel@tonic-gate 	if (ofl->ofl_issunwdata1) {
6147c478bd9Sstevel@tonic-gate 		osp = ofl->ofl_issunwdata1->is_osdesc;
6157c478bd9Sstevel@tonic-gate 		sunwdata1addr = (Addr)(osp->os_shdr->sh_addr +
616d840867fSab 		    ofl->ofl_issunwdata1->is_indata->d_off);
6177c478bd9Sstevel@tonic-gate 		/* LINTED */
6187c478bd9Sstevel@tonic-gate 		sunwdata1ndx = elf_ndxscn(osp->os_scn);
6197c478bd9Sstevel@tonic-gate 		ofl->ofl_sunwdata1ndx = osp->os_scnsymndx;
6207c478bd9Sstevel@tonic-gate 	}
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	/*
6237c478bd9Sstevel@tonic-gate 	 * If we are generating a .symtab collect all the local symbols,
6247c478bd9Sstevel@tonic-gate 	 * assigning a new virtual address or displacement (value).
6257c478bd9Sstevel@tonic-gate 	 */
6267c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_objs, lnp1, ifl)) {
6277c478bd9Sstevel@tonic-gate 		Xword		lndx, local;
6287c478bd9Sstevel@tonic-gate 		Is_desc *	isc;
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 		/*
6317c478bd9Sstevel@tonic-gate 		 * Check that we have local symbols to process.  If the user
6327c478bd9Sstevel@tonic-gate 		 * has indicated scoping then scan the global symbols also
6337c478bd9Sstevel@tonic-gate 		 * looking for entries from this file to reduce to locals.
6347c478bd9Sstevel@tonic-gate 		 */
6357c478bd9Sstevel@tonic-gate 		if ((local = ifl->ifl_locscnt) == 0)
6367c478bd9Sstevel@tonic-gate 			continue;
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 		for (lndx = 1; lndx < local; lndx++) {
6397c478bd9Sstevel@tonic-gate 			Listnode	*lnp2;
6407c478bd9Sstevel@tonic-gate 			Gotndx		*gnp;
641d579eb63Sab 			uchar_t		type;
6427c478bd9Sstevel@tonic-gate 			Word		*_symshndx;
6439039eeafSab 			int		enter_in_symtab, enter_in_ldynsym;
6449039eeafSab 			int		update_done;
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 			sdp = ifl->ifl_oldndx[lndx];
6477c478bd9Sstevel@tonic-gate 			sym = sdp->sd_sym;
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 			/*
6507c478bd9Sstevel@tonic-gate 			 * Assign a got offset if necessary.
6517c478bd9Sstevel@tonic-gate 			 */
652ba2be530Sab 			if ((ld_targ.t_mr.mr_assign_got != NULL) &&
653ba2be530Sab 			    (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR)
6547c478bd9Sstevel@tonic-gate 				return ((Addr)S_ERROR);
655ba2be530Sab 
6565aefb655Srie 			if (DBG_ENABLED) {
657d840867fSab 				for (LIST_TRAVERSE(&sdp->sd_GOTndxs,
658d840867fSab 				    lnp2, gnp)) {
659d840867fSab 					gottable->gt_sym = sdp;
660d840867fSab 					gottable->gt_gndx.gn_gotndx =
661d840867fSab 					    gnp->gn_gotndx;
662d840867fSab 					gottable->gt_gndx.gn_addend =
663d840867fSab 					    gnp->gn_addend;
664d840867fSab 					gottable++;
665d840867fSab 				}
6667c478bd9Sstevel@tonic-gate 			}
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 			if ((type = ELF_ST_TYPE(sym->st_info)) == STT_SECTION)
6697c478bd9Sstevel@tonic-gate 				continue;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 			/*
6727c478bd9Sstevel@tonic-gate 			 * Ignore any symbols that have been marked as invalid
6737c478bd9Sstevel@tonic-gate 			 * during input processing.  Providing these aren't used
6747c478bd9Sstevel@tonic-gate 			 * for relocation they'll just be dropped from the
6757c478bd9Sstevel@tonic-gate 			 * output image.
6767c478bd9Sstevel@tonic-gate 			 */
6777c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_INVALID)
6787c478bd9Sstevel@tonic-gate 				continue;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 			/*
6817c478bd9Sstevel@tonic-gate 			 * If the section that this symbol was associated
6827c478bd9Sstevel@tonic-gate 			 * with has been discarded - then we discard
6837c478bd9Sstevel@tonic-gate 			 * the local symbol along with it.
6847c478bd9Sstevel@tonic-gate 			 */
6857c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_ISDISC)
6867c478bd9Sstevel@tonic-gate 				continue;
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 			/*
6897c478bd9Sstevel@tonic-gate 			 * Generate an output symbol to represent this input
6907c478bd9Sstevel@tonic-gate 			 * symbol.  Even if the symbol table is to be stripped
6917c478bd9Sstevel@tonic-gate 			 * we still need to update any local symbols that are
6927c478bd9Sstevel@tonic-gate 			 * used during relocation.
6937c478bd9Sstevel@tonic-gate 			 */
6949039eeafSab 			enter_in_symtab = symtab &&
695*44bac77bSrie 			    (!(ofl->ofl_flags & FLG_OF_REDLSYM) ||
6969039eeafSab 			    (sdp->sd_psyminfo));
6979039eeafSab 			enter_in_ldynsym = ldynsym && sdp->sd_name &&
698d579eb63Sab 			    ldynsym_symtype[type] &&
699*44bac77bSrie 			    !(ofl->ofl_flags & FLG_OF_REDLSYM);
7007c478bd9Sstevel@tonic-gate 			_symshndx = 0;
7019039eeafSab 			if (enter_in_symtab) {
7027c478bd9Sstevel@tonic-gate 				if (!dynsym)
7037c478bd9Sstevel@tonic-gate 					sdp->sd_symndx = *symndx;
7047c478bd9Sstevel@tonic-gate 				symtab[symtab_ndx] = *sym;
7057c478bd9Sstevel@tonic-gate 				/*
7067c478bd9Sstevel@tonic-gate 				 * Provided this isn't an unnamed register
7077c478bd9Sstevel@tonic-gate 				 * symbol, update its name.
7087c478bd9Sstevel@tonic-gate 				 */
7097c478bd9Sstevel@tonic-gate 				if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) ||
7107c478bd9Sstevel@tonic-gate 				    symtab[symtab_ndx].st_name) {
7117c478bd9Sstevel@tonic-gate 					(void) st_setstring(strtab,
7127c478bd9Sstevel@tonic-gate 					    sdp->sd_name, &stoff);
7137c478bd9Sstevel@tonic-gate 					symtab[symtab_ndx].st_name = stoff;
7147c478bd9Sstevel@tonic-gate 				}
7157c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_CLEAN;
7167c478bd9Sstevel@tonic-gate 				if (symshndx)
7177c478bd9Sstevel@tonic-gate 					_symshndx = &symshndx[symtab_ndx];
7187c478bd9Sstevel@tonic-gate 				sdp->sd_sym = sym = &symtab[symtab_ndx++];
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 				if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
7219039eeafSab 				    (sym->st_shndx == SHN_ABS) &&
7229039eeafSab 				    !enter_in_ldynsym)
7237c478bd9Sstevel@tonic-gate 					continue;
7249039eeafSab 			} else if (enter_in_ldynsym) {
7259039eeafSab 				/*
7269039eeafSab 				 * Not using symtab, but we do have ldynsym
7279039eeafSab 				 * available.
7289039eeafSab 				 */
7299039eeafSab 				ldynsym[ldynsym_ndx] = *sym;
7309039eeafSab 				(void) st_setstring(dynstr, sdp->sd_name,
731d840867fSab 				    &stoff);
7329039eeafSab 				ldynsym[ldynsym_ndx].st_name = stoff;
7339039eeafSab 
7349039eeafSab 				sdp->sd_flags &= ~FLG_SY_CLEAN;
7359039eeafSab 				if (ldynshndx)
7369039eeafSab 					_symshndx = &ldynshndx[ldynsym_ndx];
737d579eb63Sab 				sdp->sd_sym = sym = &ldynsym[ldynsym_ndx];
738d579eb63Sab 				/* Add it to sort section if it qualifies */
739d579eb63Sab 				ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx);
740d579eb63Sab 				ldynsym_ndx++;
7419039eeafSab 			} else {	/* Not using symtab or ldynsym */
7427c478bd9Sstevel@tonic-gate 				/*
7437c478bd9Sstevel@tonic-gate 				 * If this symbol requires modifying to provide
7447c478bd9Sstevel@tonic-gate 				 * for a relocation or move table update, make
7457c478bd9Sstevel@tonic-gate 				 * a copy of it.
7467c478bd9Sstevel@tonic-gate 				 */
7477c478bd9Sstevel@tonic-gate 				if (!(sdp->sd_flags & FLG_SY_UPREQD) &&
7487c478bd9Sstevel@tonic-gate 				    !(sdp->sd_psyminfo))
7497c478bd9Sstevel@tonic-gate 					continue;
7507c478bd9Sstevel@tonic-gate 				if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
7517c478bd9Sstevel@tonic-gate 				    (sym->st_shndx == SHN_ABS))
7527c478bd9Sstevel@tonic-gate 					continue;
7537c478bd9Sstevel@tonic-gate 
7545aefb655Srie 				if (ld_sym_copy(sdp) == S_ERROR)
7557c478bd9Sstevel@tonic-gate 					return ((Addr)S_ERROR);
7567c478bd9Sstevel@tonic-gate 				sym = sdp->sd_sym;
7577c478bd9Sstevel@tonic-gate 			}
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 			/*
7607c478bd9Sstevel@tonic-gate 			 * Update the symbols contents if necessary.
7617c478bd9Sstevel@tonic-gate 			 */
7629039eeafSab 			update_done = 0;
7637c478bd9Sstevel@tonic-gate 			if (type == STT_FILE) {
7647c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = sym->st_shndx = SHN_ABS;
7657c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_SPECSEC;
7669039eeafSab 				update_done = 1;
7677c478bd9Sstevel@tonic-gate 			}
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 			/*
7707c478bd9Sstevel@tonic-gate 			 * If we are expanding the locally bound partially
7717c478bd9Sstevel@tonic-gate 			 * initialized symbols, then update the address here.
7727c478bd9Sstevel@tonic-gate 			 */
7737c478bd9Sstevel@tonic-gate 			if (ofl->ofl_issunwdata1 &&
7749039eeafSab 			    (sdp->sd_flags & FLG_SY_PAREXPN) && !update_done) {
7757c478bd9Sstevel@tonic-gate 				static	Addr	laddr = 0;
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 				sym->st_shndx = sunwdata1ndx;
7787c478bd9Sstevel@tonic-gate 				sdp->sd_isc = ofl->ofl_issunwdata1;
7791d9df23bSab 				if (flags & FLG_OF_RELOBJ) {
7807c478bd9Sstevel@tonic-gate 					sym->st_value = sunwdata1addr;
7819039eeafSab 				} else {
7827c478bd9Sstevel@tonic-gate 					sym->st_value = laddr;
7837c478bd9Sstevel@tonic-gate 					laddr += sym->st_size;
7847c478bd9Sstevel@tonic-gate 				}
7857c478bd9Sstevel@tonic-gate 				sunwdata1addr += sym->st_size;
7867c478bd9Sstevel@tonic-gate 			}
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 			/*
7897c478bd9Sstevel@tonic-gate 			 * If this isn't an UNDEF symbol (ie. an input section
7907c478bd9Sstevel@tonic-gate 			 * is associated), update the symbols value and index.
7917c478bd9Sstevel@tonic-gate 			 */
7929039eeafSab 			if (((isc = sdp->sd_isc) != 0) && !update_done) {
7937c478bd9Sstevel@tonic-gate 				Word	sectndx;
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 				osp = isc->is_osdesc;
7967c478bd9Sstevel@tonic-gate 				/* LINTED */
7977c478bd9Sstevel@tonic-gate 				sym->st_value +=
7987c478bd9Sstevel@tonic-gate 				    (Off)_elf_getxoff(isc->is_indata);
7997c478bd9Sstevel@tonic-gate 				if (!(flags & FLG_OF_RELOBJ)) {
8007c478bd9Sstevel@tonic-gate 					sym->st_value += osp->os_shdr->sh_addr;
8017c478bd9Sstevel@tonic-gate 					/*
8027c478bd9Sstevel@tonic-gate 					 * TLS symbols are relative to
8037c478bd9Sstevel@tonic-gate 					 * the TLS segment.
8047c478bd9Sstevel@tonic-gate 					 */
805d579eb63Sab 					if ((type == STT_TLS) &&
806d579eb63Sab 					    (ofl->ofl_tlsphdr)) {
8077c478bd9Sstevel@tonic-gate 						sym->st_value -=
8087c478bd9Sstevel@tonic-gate 						    ofl->ofl_tlsphdr->p_vaddr;
8099039eeafSab 					}
8107c478bd9Sstevel@tonic-gate 				}
8117c478bd9Sstevel@tonic-gate 				/* LINTED */
8127c478bd9Sstevel@tonic-gate 				if ((sdp->sd_shndx = sectndx =
8137c478bd9Sstevel@tonic-gate 				    elf_ndxscn(osp->os_scn)) >= SHN_LORESERVE) {
8147c478bd9Sstevel@tonic-gate 					if (_symshndx) {
8157c478bd9Sstevel@tonic-gate 						*_symshndx = sectndx;
8167c478bd9Sstevel@tonic-gate 					}
8177c478bd9Sstevel@tonic-gate 					sym->st_shndx = SHN_XINDEX;
8187c478bd9Sstevel@tonic-gate 				} else {
8197c478bd9Sstevel@tonic-gate 					/* LINTED */
8207c478bd9Sstevel@tonic-gate 					sym->st_shndx = sectndx;
8217c478bd9Sstevel@tonic-gate 				}
8227c478bd9Sstevel@tonic-gate 			}
8239039eeafSab 
8249039eeafSab 			/*
8259039eeafSab 			 * If entering the symbol in both the symtab and the
8269039eeafSab 			 * ldynsym, then the one in symtab needs to be
8279039eeafSab 			 * copied to ldynsym. If it is only in the ldynsym,
8289039eeafSab 			 * then the code above already set it up and we have
8299039eeafSab 			 * nothing more to do here.
8309039eeafSab 			 */
8319039eeafSab 			if (enter_in_symtab && enter_in_ldynsym) {
8329039eeafSab 				ldynsym[ldynsym_ndx] = *sym;
8339039eeafSab 				(void) st_setstring(dynstr, sdp->sd_name,
834d840867fSab 				    &stoff);
8359039eeafSab 				ldynsym[ldynsym_ndx].st_name = stoff;
8369039eeafSab 
8379039eeafSab 				if (_symshndx && ldynshndx)
8389039eeafSab 					ldynshndx[ldynsym_ndx] = *_symshndx;
8399039eeafSab 
840d579eb63Sab 				/* Add it to sort section if it qualifies */
841d579eb63Sab 				ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx);
842d579eb63Sab 
8439039eeafSab 				ldynsym_ndx++;
8449039eeafSab 			}
8457c478bd9Sstevel@tonic-gate 		}
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	/*
8497c478bd9Sstevel@tonic-gate 	 * Two special symbols are `_init' and `_fini'.  If these are supplied
8507c478bd9Sstevel@tonic-gate 	 * by crti.o then they are used to represent the total concatenation of
851c1c6f601Srie 	 * the `.init' and `.fini' sections.
852c1c6f601Srie 	 *
853c1c6f601Srie 	 * First, determine whether any .init or .fini sections exist.  If these
854c1c6f601Srie 	 * sections exist when a dynamic object is being built, but no `_init'
855c1c6f601Srie 	 * or `_fini' symbols are found, then the user is probably building this
856c1c6f601Srie 	 * object directly from ld(1) rather than using a compiler driver that
857c1c6f601Srie 	 * provides the symbols via crt's.
858c1c6f601Srie 	 *
859c1c6f601Srie 	 * If the .init or .fini section exist, and their associated symbols,
860c1c6f601Srie 	 * determine the size of the sections and updated the symbols value
861c1c6f601Srie 	 * accordingly.
8627c478bd9Sstevel@tonic-gate 	 */
8635aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U), SYM_NOHASH, 0,
8647c478bd9Sstevel@tonic-gate 	    ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc &&
865c1c6f601Srie 	    (sdp->sd_isc->is_osdesc == iosp)) {
8665aefb655Srie 		if (ld_sym_copy(sdp) == S_ERROR)
8677c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
86860758829Srie 		sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size;
86960758829Srie 
870c1c6f601Srie 	} else if (iosp && !(flags & FLG_OF_RELOBJ)) {
871c1c6f601Srie 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT),
872c1c6f601Srie 		    MSG_ORIG(MSG_SYM_INIT_U), MSG_ORIG(MSG_SCN_INIT));
8737c478bd9Sstevel@tonic-gate 	}
874c1c6f601Srie 
8755aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U), SYM_NOHASH, 0,
8767c478bd9Sstevel@tonic-gate 	    ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc &&
877c1c6f601Srie 	    (sdp->sd_isc->is_osdesc == fosp)) {
8785aefb655Srie 		if (ld_sym_copy(sdp) == S_ERROR)
8797c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
88060758829Srie 		sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size;
88160758829Srie 
882c1c6f601Srie 	} else if (fosp && !(flags & FLG_OF_RELOBJ)) {
883c1c6f601Srie 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT),
884c1c6f601Srie 		    MSG_ORIG(MSG_SYM_FINI_U), MSG_ORIG(MSG_SCN_FINI));
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	/*
8887c478bd9Sstevel@tonic-gate 	 * Assign .bss information for use with updating COMMON symbols.
8897c478bd9Sstevel@tonic-gate 	 */
8907c478bd9Sstevel@tonic-gate 	if (ofl->ofl_isbss) {
8917c478bd9Sstevel@tonic-gate 		osp = ofl->ofl_isbss->is_osdesc;
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 		bssaddr = osp->os_shdr->sh_addr +
894d840867fSab 		    (Off)_elf_getxoff(ofl->ofl_isbss->is_indata);
8957c478bd9Sstevel@tonic-gate 		/* LINTED */
8967c478bd9Sstevel@tonic-gate 		bssndx = elf_ndxscn(osp->os_scn);
8977c478bd9Sstevel@tonic-gate 	}
8987c478bd9Sstevel@tonic-gate 
899ba2be530Sab #if	defined(_ELF64)
90054d82594Sseizo 	/*
901ba2be530Sab 	 * For amd64 target, assign .lbss information for use
902ba2be530Sab 	 * with updating LCOMMON symbols.
90354d82594Sseizo 	 */
904ba2be530Sab 	if ((ld_targ.t_m.m_mach == EM_AMD64) && ofl->ofl_islbss) {
90554d82594Sseizo 		osp = ofl->ofl_islbss->is_osdesc;
90654d82594Sseizo 
90754d82594Sseizo 		lbssaddr = osp->os_shdr->sh_addr +
908d840867fSab 		    (Off)_elf_getxoff(ofl->ofl_islbss->is_indata);
90954d82594Sseizo 		/* LINTED */
91054d82594Sseizo 		lbssndx = elf_ndxscn(osp->os_scn);
91154d82594Sseizo 	}
91254d82594Sseizo #endif
91354d82594Sseizo 
9147c478bd9Sstevel@tonic-gate 	/*
9157c478bd9Sstevel@tonic-gate 	 * Assign .tlsbss information for use with updating COMMON symbols.
9167c478bd9Sstevel@tonic-gate 	 */
9177c478bd9Sstevel@tonic-gate 	if (ofl->ofl_istlsbss) {
9187c478bd9Sstevel@tonic-gate 		osp = ofl->ofl_istlsbss->is_osdesc;
9197c478bd9Sstevel@tonic-gate 		tlsbssaddr = osp->os_shdr->sh_addr +
920d840867fSab 		    (Off)_elf_getxoff(ofl->ofl_istlsbss->is_indata);
9217c478bd9Sstevel@tonic-gate 		/* LINTED */
9227c478bd9Sstevel@tonic-gate 		tlsbssndx = elf_ndxscn(osp->os_scn);
9237c478bd9Sstevel@tonic-gate 	}
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	/*
926d1827f25Srie 	 * Assign .SUNW_bss information for use with updating COMMON symbols.
9277c478bd9Sstevel@tonic-gate 	 */
9287c478bd9Sstevel@tonic-gate 	if (ofl->ofl_issunwbss) {
9297c478bd9Sstevel@tonic-gate 		osp = ofl->ofl_issunwbss->is_osdesc;
9307c478bd9Sstevel@tonic-gate 		sunwbssaddr = (Addr)(osp->os_shdr->sh_addr +
931d840867fSab 		    ofl->ofl_issunwbss->is_indata->d_off);
9327c478bd9Sstevel@tonic-gate 		/* LINTED */
9337c478bd9Sstevel@tonic-gate 		sunwbssndx = elf_ndxscn(osp->os_scn);
9347c478bd9Sstevel@tonic-gate 	}
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	if ((sorted_syms = libld_calloc(ofl->ofl_globcnt +
9387c478bd9Sstevel@tonic-gate 	    ofl->ofl_elimcnt + ofl->ofl_scopecnt, sizeof (*sorted_syms))) == 0)
9397c478bd9Sstevel@tonic-gate 		return ((Addr)S_ERROR);
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	scndx = 0;
9427c478bd9Sstevel@tonic-gate 	ssndx = ofl->ofl_scopecnt + ofl->ofl_elimcnt;
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	/*
9457c478bd9Sstevel@tonic-gate 	 * Traverse the internal symbol table updating information and
9467c478bd9Sstevel@tonic-gate 	 * allocating common.
9477c478bd9Sstevel@tonic-gate 	 */
9487c478bd9Sstevel@tonic-gate 	for (sav = avl_first(&ofl->ofl_symavl); sav;
9497c478bd9Sstevel@tonic-gate 	    sav = AVL_NEXT(&ofl->ofl_symavl, sav)) {
9507c478bd9Sstevel@tonic-gate 		Sym *	symptr;
9517c478bd9Sstevel@tonic-gate 		int	local;
95254d82594Sseizo 		int	restore;
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 		sdp = sav->sav_symdesc;
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 		/*
95760758829Srie 		 * Ignore any symbols that have been marked as invalid during
95860758829Srie 		 * input processing.  Providing these aren't used for
95960758829Srie 		 * relocation, they will be dropped from the output image.
9607c478bd9Sstevel@tonic-gate 		 */
9617c478bd9Sstevel@tonic-gate 		if (sdp->sd_flags & FLG_SY_INVALID) {
9625aefb655Srie 			DBG_CALL(Dbg_syms_old(ofl, sdp));
9635aefb655Srie 			DBG_CALL(Dbg_syms_ignore(ofl, sdp));
9647c478bd9Sstevel@tonic-gate 			continue;
9657c478bd9Sstevel@tonic-gate 		}
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 		/*
96860758829Srie 		 * Only needed symbols are copied to the output symbol table.
9697c478bd9Sstevel@tonic-gate 		 */
9707c478bd9Sstevel@tonic-gate 		if (sdp->sd_ref == REF_DYN_SEEN)
9717c478bd9Sstevel@tonic-gate 			continue;
9727c478bd9Sstevel@tonic-gate 
97360758829Srie 		if ((sdp->sd_flags1 & FLG_SY1_HIDDEN) &&
9747c478bd9Sstevel@tonic-gate 		    (flags & FLG_OF_PROCRED))
9757c478bd9Sstevel@tonic-gate 			local = 1;
9767c478bd9Sstevel@tonic-gate 		else
9777c478bd9Sstevel@tonic-gate 			local = 0;
9787c478bd9Sstevel@tonic-gate 
9797c478bd9Sstevel@tonic-gate 		if (local || (ofl->ofl_hashbkts == 0)) {
9807c478bd9Sstevel@tonic-gate 			sorted_syms[scndx++].sl_sdp = sdp;
9817c478bd9Sstevel@tonic-gate 		} else {
9827c478bd9Sstevel@tonic-gate 			sorted_syms[ssndx].sl_hval = sdp->sd_aux->sa_hash %
9837c478bd9Sstevel@tonic-gate 			    ofl->ofl_hashbkts;
9847c478bd9Sstevel@tonic-gate 			sorted_syms[ssndx].sl_sdp = sdp;
9857c478bd9Sstevel@tonic-gate 			ssndx++;
9867c478bd9Sstevel@tonic-gate 		}
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 		/*
989c1c6f601Srie 		 * Note - expand the COMMON symbols here because an address
990c1c6f601Srie 		 * must be assigned to them in the same order that space was
991c1c6f601Srie 		 * calculated in sym_validate().  If this ordering isn't
992c1c6f601Srie 		 * followed differing alignment requirements can throw us all
993c1c6f601Srie 		 * out of whack.
9947c478bd9Sstevel@tonic-gate 		 *
995c1c6f601Srie 		 * The expanded .bss global symbol is handled here as well.
9967c478bd9Sstevel@tonic-gate 		 *
997c1c6f601Srie 		 * The actual adding entries into the symbol table still occurs
998c1c6f601Srie 		 * below in hashbucket order.
9997c478bd9Sstevel@tonic-gate 		 */
10007c478bd9Sstevel@tonic-gate 		symptr = sdp->sd_sym;
100154d82594Sseizo 		restore = 0;
10027c478bd9Sstevel@tonic-gate 		if ((sdp->sd_flags & FLG_SY_PAREXPN) ||
10037c478bd9Sstevel@tonic-gate 		    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
10047c478bd9Sstevel@tonic-gate 		    (sdp->sd_shndx = symptr->st_shndx) == SHN_COMMON)) {
10057c478bd9Sstevel@tonic-gate 
10067c478bd9Sstevel@tonic-gate 			/*
1007c1c6f601Srie 			 * An expanded symbol goes to .sunwdata1.
10087c478bd9Sstevel@tonic-gate 			 *
1009c1c6f601Srie 			 * A partial initialized global symbol within a shared
1010c1c6f601Srie 			 * object goes to .sunwbss.
10117c478bd9Sstevel@tonic-gate 			 *
1012c1c6f601Srie 			 * Assign COMMON allocations to .bss.
10137c478bd9Sstevel@tonic-gate 			 *
10147c478bd9Sstevel@tonic-gate 			 * Otherwise leave it as is.
10157c478bd9Sstevel@tonic-gate 			 */
10167c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_PAREXPN) {
10177c478bd9Sstevel@tonic-gate 				restore = 1;
10187c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = sunwdata1ndx;
10197c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
10207c478bd9Sstevel@tonic-gate 				symptr->st_value = (Xword) S_ROUND(
10217c478bd9Sstevel@tonic-gate 				    sunwdata1addr, symptr->st_value);
10227c478bd9Sstevel@tonic-gate 				sunwdata1addr = symptr->st_value +
1023d840867fSab 				    symptr->st_size;
10247c478bd9Sstevel@tonic-gate 				sdp->sd_isc = ofl->ofl_issunwdata1;
10257c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_COMMEXP;
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 			} else if ((sdp->sd_psyminfo != (Psym_info *)NULL) &&
10281d9df23bSab 			    (flags & FLG_OF_SHAROBJ) &&
10297c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(symptr->st_info) != STB_LOCAL)) {
10307c478bd9Sstevel@tonic-gate 				restore = 1;
10317c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = sunwbssndx;
10327c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
103360758829Srie 				symptr->st_value = (Xword)S_ROUND(sunwbssaddr,
103460758829Srie 				    symptr->st_value);
10357c478bd9Sstevel@tonic-gate 				sunwbssaddr = symptr->st_value +
1036d840867fSab 				    symptr->st_size;
10377c478bd9Sstevel@tonic-gate 				sdp->sd_isc = ofl->ofl_issunwbss;
10387c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_COMMEXP;
1039c1c6f601Srie 
10407c478bd9Sstevel@tonic-gate 			} else if (ELF_ST_TYPE(symptr->st_info) != STT_TLS &&
10417c478bd9Sstevel@tonic-gate 			    (local || !(flags & FLG_OF_RELOBJ))) {
10427c478bd9Sstevel@tonic-gate 				restore = 1;
10437c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = bssndx;
10447c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
104560758829Srie 				symptr->st_value = (Xword)S_ROUND(bssaddr,
1046d840867fSab 				    symptr->st_value);
10477c478bd9Sstevel@tonic-gate 				bssaddr = symptr->st_value + symptr->st_size;
10487c478bd9Sstevel@tonic-gate 				sdp->sd_isc = ofl->ofl_isbss;
10497c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_COMMEXP;
1050c1c6f601Srie 
10517c478bd9Sstevel@tonic-gate 			} else if (ELF_ST_TYPE(symptr->st_info) == STT_TLS &&
10527c478bd9Sstevel@tonic-gate 			    (local || !(flags & FLG_OF_RELOBJ))) {
10537c478bd9Sstevel@tonic-gate 				restore = 1;
10547c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = tlsbssndx;
10557c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
10567c478bd9Sstevel@tonic-gate 				symptr->st_value = (Xword)S_ROUND(tlsbssaddr,
1057d840867fSab 				    symptr->st_value);
10587c478bd9Sstevel@tonic-gate 				tlsbssaddr = symptr->st_value + symptr->st_size;
10597c478bd9Sstevel@tonic-gate 				sdp->sd_isc = ofl->ofl_istlsbss;
10607c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_COMMEXP;
10617c478bd9Sstevel@tonic-gate 				/*
1062dd94ecefSrie 				 * TLS symbols are relative to the TLS segment.
10637c478bd9Sstevel@tonic-gate 				 */
10647c478bd9Sstevel@tonic-gate 				symptr->st_value -= ofl->ofl_tlsphdr->p_vaddr;
10657c478bd9Sstevel@tonic-gate 			}
1066ba2be530Sab #if	defined(_ELF64)
1067ba2be530Sab 		} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
1068ba2be530Sab 		    (sdp->sd_flags & FLG_SY_SPECSEC) &&
106954d82594Sseizo 		    ((sdp->sd_shndx = symptr->st_shndx) ==
107054d82594Sseizo 		    SHN_X86_64_LCOMMON) &&
107154d82594Sseizo 		    ((local || !(flags & FLG_OF_RELOBJ)))) {
107254d82594Sseizo 			restore = 1;
107354d82594Sseizo 			sdp->sd_shndx = lbssndx;
107454d82594Sseizo 			sdp->sd_flags &= ~FLG_SY_SPECSEC;
107560758829Srie 			symptr->st_value = (Xword)S_ROUND(lbssaddr,
1076d840867fSab 			    symptr->st_value);
107754d82594Sseizo 			lbssaddr = symptr->st_value + symptr->st_size;
107854d82594Sseizo 			sdp->sd_isc = ofl->ofl_islbss;
107954d82594Sseizo 			sdp->sd_flags |= FLG_SY_COMMEXP;
108054d82594Sseizo #endif
108154d82594Sseizo 		}
10827c478bd9Sstevel@tonic-gate 
108354d82594Sseizo 		if (restore != 0) {
1084d579eb63Sab 			uchar_t		type, bind;
1085c1c6f601Srie 
108654d82594Sseizo 			/*
1087c1c6f601Srie 			 * Make sure this COMMON symbol is returned to the same
1088c1c6f601Srie 			 * binding as was defined in the original relocatable
108954d82594Sseizo 			 * object reference.
109054d82594Sseizo 			 */
109154d82594Sseizo 			type = ELF_ST_TYPE(symptr->st_info);
109254d82594Sseizo 			if (sdp->sd_flags & FLG_SY_GLOBREF)
109354d82594Sseizo 				bind = STB_GLOBAL;
109454d82594Sseizo 			else
109554d82594Sseizo 				bind = STB_WEAK;
10967c478bd9Sstevel@tonic-gate 
109754d82594Sseizo 			symptr->st_info = ELF_ST_INFO(bind, type);
10987c478bd9Sstevel@tonic-gate 		}
10997c478bd9Sstevel@tonic-gate 	}
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	if (ofl->ofl_hashbkts) {
11027c478bd9Sstevel@tonic-gate 		qsort(sorted_syms + ofl->ofl_scopecnt + ofl->ofl_elimcnt,
11037c478bd9Sstevel@tonic-gate 		    ofl->ofl_globcnt, sizeof (Sym_s_list),
11047c478bd9Sstevel@tonic-gate 		    (int (*)(const void *, const void *))sym_hash_compare);
11057c478bd9Sstevel@tonic-gate 	}
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	for (ssndx = 0; ssndx < (ofl->ofl_elimcnt + ofl->ofl_scopecnt +
11087c478bd9Sstevel@tonic-gate 	    ofl->ofl_globcnt); ssndx++) {
11097c478bd9Sstevel@tonic-gate 		const char	*name;
11107c478bd9Sstevel@tonic-gate 		Sym		*sym;
11117c478bd9Sstevel@tonic-gate 		Sym_aux		*sap;
11127c478bd9Sstevel@tonic-gate 		Half		spec;
11139039eeafSab 		int		local = 0, dynlocal = 0, enter_in_symtab;
11147c478bd9Sstevel@tonic-gate 		Listnode	*lnp2;
11157c478bd9Sstevel@tonic-gate 		Gotndx		*gnp;
11167c478bd9Sstevel@tonic-gate 		Word		sectndx;
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 		sdp = sorted_syms[ssndx].sl_sdp;
11197c478bd9Sstevel@tonic-gate 		sectndx = 0;
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate 		if (symtab)
11227c478bd9Sstevel@tonic-gate 			enter_in_symtab = 1;
11237c478bd9Sstevel@tonic-gate 		else
11247c478bd9Sstevel@tonic-gate 			enter_in_symtab = 0;
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 		/*
11277c478bd9Sstevel@tonic-gate 		 * Assign a got offset if necessary.
11287c478bd9Sstevel@tonic-gate 		 */
1129ba2be530Sab 		if ((ld_targ.t_mr.mr_assign_got != NULL) &&
1130ba2be530Sab 		    (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR)
11317c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
1132c1c6f601Srie 
11335aefb655Srie 		if (DBG_ENABLED) {
11347c478bd9Sstevel@tonic-gate 			for (LIST_TRAVERSE(&sdp->sd_GOTndxs, lnp2, gnp)) {
1135d326b23bSrie 				gottable->gt_sym = sdp;
1136d326b23bSrie 				gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx;
1137d326b23bSrie 				gottable->gt_gndx.gn_addend = gnp->gn_addend;
1138d326b23bSrie 				gottable++;
11397c478bd9Sstevel@tonic-gate 			}
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 			if (sdp->sd_aux && sdp->sd_aux->sa_PLTGOTndx) {
1142d326b23bSrie 				gottable->gt_sym = sdp;
1143d326b23bSrie 				gottable->gt_gndx.gn_gotndx =
11447c478bd9Sstevel@tonic-gate 				    sdp->sd_aux->sa_PLTGOTndx;
1145d326b23bSrie 				gottable++;
11467c478bd9Sstevel@tonic-gate 			}
11477c478bd9Sstevel@tonic-gate 		}
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 		/*
11517c478bd9Sstevel@tonic-gate 		 * If this symbol has been marked as being reduced to local
11527c478bd9Sstevel@tonic-gate 		 * scope then it will have to be placed in the scoped portion
11537c478bd9Sstevel@tonic-gate 		 * of the .symtab.  Retain the appropriate index for use in
11547c478bd9Sstevel@tonic-gate 		 * version symbol indexing and relocation.
11557c478bd9Sstevel@tonic-gate 		 */
1156d4517e84Srie 		if ((sdp->sd_flags1 & FLG_SY1_HIDDEN) &&
11577c478bd9Sstevel@tonic-gate 		    (flags & FLG_OF_PROCRED)) {
11587c478bd9Sstevel@tonic-gate 			local = 1;
11597c478bd9Sstevel@tonic-gate 			if (!(sdp->sd_flags1 & FLG_SY1_ELIM) && !dynsym)
11607c478bd9Sstevel@tonic-gate 				sdp->sd_symndx = scopesym_ndx;
11617c478bd9Sstevel@tonic-gate 			else
11627c478bd9Sstevel@tonic-gate 				sdp->sd_symndx = 0;
11637c478bd9Sstevel@tonic-gate 
11649039eeafSab 			if (sdp->sd_flags1 & FLG_SY1_ELIM) {
11657c478bd9Sstevel@tonic-gate 				enter_in_symtab = 0;
11669039eeafSab 			} else if (ldynsym && sdp->sd_sym->st_name &&
1167d579eb63Sab 			    ldynsym_symtype[
1168d579eb63Sab 			    ELF_ST_TYPE(sdp->sd_sym->st_info)]) {
11699039eeafSab 				dynlocal = 1;
11709039eeafSab 			}
11719039eeafSab 		} else {
11727c478bd9Sstevel@tonic-gate 			sdp->sd_symndx = *symndx;
11739039eeafSab 		}
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 		/*
11767c478bd9Sstevel@tonic-gate 		 * Copy basic symbol and string information.
11777c478bd9Sstevel@tonic-gate 		 */
11787c478bd9Sstevel@tonic-gate 		name = sdp->sd_name;
11797c478bd9Sstevel@tonic-gate 		sap = sdp->sd_aux;
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 		/*
11827c478bd9Sstevel@tonic-gate 		 * If we require to record version symbol indexes, update the
11837c478bd9Sstevel@tonic-gate 		 * associated version symbol information for all defined
11847c478bd9Sstevel@tonic-gate 		 * symbols.  If a version definition is required any zero value
11857c478bd9Sstevel@tonic-gate 		 * symbol indexes would have been flagged as undefined symbol
11867c478bd9Sstevel@tonic-gate 		 * errors, however if we're just scoping these need to fall into
11877c478bd9Sstevel@tonic-gate 		 * the base of global symbols.
11887c478bd9Sstevel@tonic-gate 		 */
11897c478bd9Sstevel@tonic-gate 		if (sdp->sd_symndx && versym) {
11907c478bd9Sstevel@tonic-gate 			Half	vndx = 0;
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_MVTOCOMM)
11937c478bd9Sstevel@tonic-gate 				vndx = VER_NDX_GLOBAL;
11947c478bd9Sstevel@tonic-gate 			else if (sdp->sd_ref == REF_REL_NEED) {
11957c478bd9Sstevel@tonic-gate 				Half	symflags1 = sdp->sd_flags1;
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 				vndx = sap->sa_overndx;
11987c478bd9Sstevel@tonic-gate 				if ((vndx == 0) &&
11997c478bd9Sstevel@tonic-gate 				    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
120060758829Srie 					if (symflags1 & FLG_SY1_HIDDEN)
12017c478bd9Sstevel@tonic-gate 						vndx = VER_NDX_LOCAL;
12027c478bd9Sstevel@tonic-gate 					else
12037c478bd9Sstevel@tonic-gate 						vndx = VER_NDX_GLOBAL;
12047c478bd9Sstevel@tonic-gate 				}
12057c478bd9Sstevel@tonic-gate 			}
12067c478bd9Sstevel@tonic-gate 			versym[sdp->sd_symndx] = vndx;
12077c478bd9Sstevel@tonic-gate 		}
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 		/*
12107c478bd9Sstevel@tonic-gate 		 * If we are creating the .syminfo section then set per symbol
12117c478bd9Sstevel@tonic-gate 		 * flags here.
12127c478bd9Sstevel@tonic-gate 		 */
12137c478bd9Sstevel@tonic-gate 		if (sdp->sd_symndx && syminfo &&
12147c478bd9Sstevel@tonic-gate 		    !(sdp->sd_flags & FLG_SY_NOTAVAIL)) {
12157c478bd9Sstevel@tonic-gate 			int	ndx = sdp->sd_symndx;
12167c478bd9Sstevel@tonic-gate 			List	*sip = &(ofl->ofl_syminfsyms);
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_MVTOCOMM)
12197c478bd9Sstevel@tonic-gate 				/*
12207c478bd9Sstevel@tonic-gate 				 * Identify a copy relocation symbol.
12217c478bd9Sstevel@tonic-gate 				 */
12227c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_COPY;
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 			if (sdp->sd_ref == REF_DYN_NEED) {
12257c478bd9Sstevel@tonic-gate 				/*
12267c478bd9Sstevel@tonic-gate 				 * A reference is bound to a needed dependency.
12277c478bd9Sstevel@tonic-gate 				 * Save this symbol descriptor, as its boundto
12287c478bd9Sstevel@tonic-gate 				 * element will need updating after the .dynamic
12297c478bd9Sstevel@tonic-gate 				 * section has been created.  Flag whether this
12307c478bd9Sstevel@tonic-gate 				 * reference is lazy loadable, and if a direct
12317c478bd9Sstevel@tonic-gate 				 * binding is to be established.
12327c478bd9Sstevel@tonic-gate 				 */
12337c478bd9Sstevel@tonic-gate 				if (list_appendc(sip, sdp) == 0)
12347c478bd9Sstevel@tonic-gate 					return (0);
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT;
12377c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags & FLG_SY_LAZYLD)
12387c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12397c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_LAZYLOAD;
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 				/*
12427c478bd9Sstevel@tonic-gate 				 * Enable direct symbol bindings if:
12437c478bd9Sstevel@tonic-gate 				 *
12447c478bd9Sstevel@tonic-gate 				 *  .	Symbol was identified with the DIRECT
12457c478bd9Sstevel@tonic-gate 				 *	keyword in a mapfile.
12467c478bd9Sstevel@tonic-gate 				 *
12477c478bd9Sstevel@tonic-gate 				 *  .	Symbol reference has been bound to a
12487c478bd9Sstevel@tonic-gate 				 * 	dependency which was specified as
12497c478bd9Sstevel@tonic-gate 				 *	requiring direct bindings with -zdirect.
12507c478bd9Sstevel@tonic-gate 				 *
12517c478bd9Sstevel@tonic-gate 				 *  .	All symbol references are required to
12527c478bd9Sstevel@tonic-gate 				 *	use direct bindings via -Bdirect.
12537c478bd9Sstevel@tonic-gate 				 */
12547c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_DIR)
12557c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12567c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_DIRECTBIND;
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 			} else if ((sdp->sd_flags & FLG_SY_EXTERN) &&
12597c478bd9Sstevel@tonic-gate 			    (sdp->sd_sym->st_shndx == SHN_UNDEF)) {
12607c478bd9Sstevel@tonic-gate 				/*
12617c478bd9Sstevel@tonic-gate 				 * If this symbol has been explicitly defined
12627c478bd9Sstevel@tonic-gate 				 * as external, and remains unresolved, mark
12637c478bd9Sstevel@tonic-gate 				 * it as external.
12647c478bd9Sstevel@tonic-gate 				 */
12657c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_boundto = SYMINFO_BT_EXTERN;
12667c478bd9Sstevel@tonic-gate 
12679a411307Srie 			} else if ((sdp->sd_flags & FLG_SY_PARENT) &&
12689a411307Srie 			    (sdp->sd_sym->st_shndx == SHN_UNDEF)) {
12697c478bd9Sstevel@tonic-gate 				/*
12709a411307Srie 				 * If this symbol has been explicitly defined
12719a411307Srie 				 * to be a reference to a parent object,
12729a411307Srie 				 * indicate whether a direct binding should be
12737c478bd9Sstevel@tonic-gate 				 * established.
12747c478bd9Sstevel@tonic-gate 				 */
12757c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT;
12767c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_boundto = SYMINFO_BT_PARENT;
12777c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_DIR)
12787c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12797c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_DIRECTBIND;
12807c478bd9Sstevel@tonic-gate 
12817c478bd9Sstevel@tonic-gate 			} else if (sdp->sd_flags & FLG_SY_STDFLTR) {
12827c478bd9Sstevel@tonic-gate 				/*
12837c478bd9Sstevel@tonic-gate 				 * A filter definition.  Although this symbol
12847c478bd9Sstevel@tonic-gate 				 * can only be a stub, it might be necessary to
12857c478bd9Sstevel@tonic-gate 				 * prevent external direct bindings.
12867c478bd9Sstevel@tonic-gate 				 */
12877c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_FILTER;
12887c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_NDIR)
12897c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12907c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_NOEXTDIRECT;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 			} else if (sdp->sd_flags & FLG_SY_AUXFLTR) {
12937c478bd9Sstevel@tonic-gate 				/*
12947c478bd9Sstevel@tonic-gate 				 * An auxiliary filter definition.  By nature,
12957c478bd9Sstevel@tonic-gate 				 * this definition is direct, in that should the
12967c478bd9Sstevel@tonic-gate 				 * filtee lookup fail, we'll fall back to this
12977c478bd9Sstevel@tonic-gate 				 * object.  It may still be necesssary to
12987c478bd9Sstevel@tonic-gate 				 * prevent external direct bindings.
12997c478bd9Sstevel@tonic-gate 				 */
13007c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_AUXILIARY;
13017c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_NDIR)
13027c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
13037c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_NOEXTDIRECT;
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate 			} else if ((sdp->sd_ref == REF_REL_NEED) &&
13067c478bd9Sstevel@tonic-gate 			    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
13079a411307Srie 
13087c478bd9Sstevel@tonic-gate 				/*
13097c478bd9Sstevel@tonic-gate 				 * This definition exists within the object
13107c478bd9Sstevel@tonic-gate 				 * being created.  Flag whether it is necessary
13117c478bd9Sstevel@tonic-gate 				 * to prevent external direct bindings.
13127c478bd9Sstevel@tonic-gate 				 */
13137c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_NDIR) {
13147c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_boundto =
13157c478bd9Sstevel@tonic-gate 					    SYMINFO_BT_NONE;
13167c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
13177c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_NOEXTDIRECT;
13187c478bd9Sstevel@tonic-gate 				}
13197c478bd9Sstevel@tonic-gate 
13209a411307Srie 				/*
13219a411307Srie 				 * Indicate that this symbol is acting as an
13229a411307Srie 				 * individual interposer.
13239a411307Srie 				 */
13249a411307Srie 				if (sdp->sd_flags & FLG_SY_INTPOSE) {
13259a411307Srie 					syminfo[ndx].si_flags |=
13269a411307Srie 					    SYMINFO_FLG_INTERPOSE;
13279a411307Srie 				}
13289a411307Srie 
13297c478bd9Sstevel@tonic-gate 				/*
13307c478bd9Sstevel@tonic-gate 				 * If external bindings are allowed, or this is
13317c478bd9Sstevel@tonic-gate 				 * a translator symbol, indicate the binding,
13327c478bd9Sstevel@tonic-gate 				 * and a direct binding if necessary.
13337c478bd9Sstevel@tonic-gate 				 */
13347c478bd9Sstevel@tonic-gate 				if (((sdp->sd_flags1 & FLG_SY1_NDIR) == 0) ||
13357c478bd9Sstevel@tonic-gate 				    ((dtflags_1 & DF_1_TRANS) && sdp->sd_aux &&
13367c478bd9Sstevel@tonic-gate 				    sdp->sd_aux->sa_bindto)) {
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
13397c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_DIRECT;
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 					if (sdp->sd_flags1 & FLG_SY1_DIR)
13427c478bd9Sstevel@tonic-gate 						syminfo[ndx].si_flags |=
13437c478bd9Sstevel@tonic-gate 						    SYMINFO_FLG_DIRECTBIND;
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 					/*
13467c478bd9Sstevel@tonic-gate 					 * If this is a translator, the symbols
13477c478bd9Sstevel@tonic-gate 					 * boundto element will indicate the
13487c478bd9Sstevel@tonic-gate 					 * dependency to which it should resolve
13497c478bd9Sstevel@tonic-gate 					 * rather than itself.  Save this info
13507c478bd9Sstevel@tonic-gate 					 * for updating after the .dynamic
13517c478bd9Sstevel@tonic-gate 					 * section has been created.
13527c478bd9Sstevel@tonic-gate 					 */
13537c478bd9Sstevel@tonic-gate 					if ((dtflags_1 & DF_1_TRANS) &&
13547c478bd9Sstevel@tonic-gate 					    sdp->sd_aux &&
13557c478bd9Sstevel@tonic-gate 					    sdp->sd_aux->sa_bindto) {
13567c478bd9Sstevel@tonic-gate 						if (list_appendc(sip, sdp) == 0)
13577c478bd9Sstevel@tonic-gate 							return (0);
13587c478bd9Sstevel@tonic-gate 					} else {
13597c478bd9Sstevel@tonic-gate 						syminfo[ndx].si_boundto =
13607c478bd9Sstevel@tonic-gate 						    SYMINFO_BT_SELF;
13617c478bd9Sstevel@tonic-gate 					}
13627c478bd9Sstevel@tonic-gate 				}
13637c478bd9Sstevel@tonic-gate 			}
13647c478bd9Sstevel@tonic-gate 		}
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 		/*
13677c478bd9Sstevel@tonic-gate 		 * Note that the `sym' value is reset to be one of the new
13687c478bd9Sstevel@tonic-gate 		 * symbol table entries.  This symbol will be updated further
13697c478bd9Sstevel@tonic-gate 		 * depending on the type of the symbol.  Process the .symtab
13707c478bd9Sstevel@tonic-gate 		 * first, followed by the .dynsym, thus the `sym' value will
13717c478bd9Sstevel@tonic-gate 		 * remain as the .dynsym value when the .dynsym is present.
1372c1c6f601Srie 		 * This ensures that any versioning symbols st_name value will
13739039eeafSab 		 * be appropriate for the string table used by version
13747c478bd9Sstevel@tonic-gate 		 * entries.
13757c478bd9Sstevel@tonic-gate 		 */
13767c478bd9Sstevel@tonic-gate 		if (enter_in_symtab) {
13777c478bd9Sstevel@tonic-gate 			Word	_symndx;
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate 			if (local)
13807c478bd9Sstevel@tonic-gate 				_symndx = scopesym_ndx;
13817c478bd9Sstevel@tonic-gate 			else
13827c478bd9Sstevel@tonic-gate 				_symndx = symtab_ndx;
13839039eeafSab 
13847c478bd9Sstevel@tonic-gate 			symtab[_symndx] = *sdp->sd_sym;
13857c478bd9Sstevel@tonic-gate 			sdp->sd_sym = sym = &symtab[_symndx];
13867c478bd9Sstevel@tonic-gate 			(void) st_setstring(strtab, name, &stoff);
13877c478bd9Sstevel@tonic-gate 			sym->st_name = stoff;
13887c478bd9Sstevel@tonic-gate 		}
13899039eeafSab 		if (dynlocal) {
13909039eeafSab 			ldynsym[ldynscopesym_ndx] = *sdp->sd_sym;
13919039eeafSab 			sdp->sd_sym = sym = &ldynsym[ldynscopesym_ndx];
13929039eeafSab 			(void) st_setstring(dynstr, name, &stoff);
13939039eeafSab 			ldynsym[ldynscopesym_ndx].st_name = stoff;
1394d579eb63Sab 			/* Add it to sort section if it qualifies */
1395d579eb63Sab 			ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info),
1396d579eb63Sab 			    ldynscopesym_ndx);
13979039eeafSab 		}
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate 		if (dynsym && !local) {
14007c478bd9Sstevel@tonic-gate 			dynsym[dynsym_ndx] = *sdp->sd_sym;
140160758829Srie 
14027c478bd9Sstevel@tonic-gate 			/*
14037c478bd9Sstevel@tonic-gate 			 * Provided this isn't an unnamed register symbol,
140460758829Srie 			 * update the symbols name and hash value.
14057c478bd9Sstevel@tonic-gate 			 */
14067c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) ||
14077c478bd9Sstevel@tonic-gate 			    dynsym[dynsym_ndx].st_name) {
1408d840867fSab 				(void) st_setstring(dynstr, name, &stoff);
1409d840867fSab 				dynsym[dynsym_ndx].st_name = stoff;
141060758829Srie 
1411d840867fSab 				if (stoff) {
1412d840867fSab 					Word _hashndx;
141360758829Srie 
141460758829Srie 					hashval =
141560758829Srie 					    sap->sa_hash % ofl->ofl_hashbkts;
141660758829Srie 
1417d840867fSab 					/* LINTED */
1418d840867fSab 					if (_hashndx = hashbkt[hashval]) {
141960758829Srie 						while (hashchain[_hashndx]) {
1420d840867fSab 							_hashndx =
1421d840867fSab 							    hashchain[_hashndx];
142260758829Srie 						}
1423d840867fSab 						hashchain[_hashndx] =
1424d840867fSab 						    sdp->sd_symndx;
1425d840867fSab 					} else {
1426d840867fSab 						hashbkt[hashval] =
1427d840867fSab 						    sdp->sd_symndx;
1428d840867fSab 					}
14297c478bd9Sstevel@tonic-gate 				}
14307c478bd9Sstevel@tonic-gate 			}
14317c478bd9Sstevel@tonic-gate 			sdp->sd_sym = sym = &dynsym[dynsym_ndx];
143260758829Srie 
1433d579eb63Sab 			/*
1434d579eb63Sab 			 * Add it to sort section if it qualifies.
1435d579eb63Sab 			 * The indexes in that section are relative to the
1436d579eb63Sab 			 * the adjacent SUNW_ldynsym/dymsym pair, so we
1437d579eb63Sab 			 * add the number of items in SUNW_ldynsym to the
1438d579eb63Sab 			 * dynsym index.
1439d579eb63Sab 			 */
1440d579eb63Sab 			ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info),
1441d579eb63Sab 			    ldynsym_cnt + dynsym_ndx);
14427c478bd9Sstevel@tonic-gate 		}
14439039eeafSab 		if (!enter_in_symtab && (!dynsym || (local && !dynlocal))) {
14447c478bd9Sstevel@tonic-gate 			if (!(sdp->sd_flags & FLG_SY_UPREQD))
14457c478bd9Sstevel@tonic-gate 				continue;
14467c478bd9Sstevel@tonic-gate 			sym = sdp->sd_sym;
14477c478bd9Sstevel@tonic-gate 		} else
14487c478bd9Sstevel@tonic-gate 			sdp->sd_flags &= ~FLG_SY_CLEAN;
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 		/*
14527c478bd9Sstevel@tonic-gate 		 * If we have a weak data symbol for which we need the real
14537c478bd9Sstevel@tonic-gate 		 * symbol also, save this processing until later.
14547c478bd9Sstevel@tonic-gate 		 *
14557c478bd9Sstevel@tonic-gate 		 * The exception to this is if the weak/strong have PLT's
14567c478bd9Sstevel@tonic-gate 		 * assigned to them.  In that case we don't do the post-weak
14577c478bd9Sstevel@tonic-gate 		 * processing because the PLT's must be maintained so that we
14587c478bd9Sstevel@tonic-gate 		 * can do 'interpositioning' on both of the symbols.
14597c478bd9Sstevel@tonic-gate 		 */
14607c478bd9Sstevel@tonic-gate 		if ((sap->sa_linkndx) &&
14617c478bd9Sstevel@tonic-gate 		    (ELF_ST_BIND(sym->st_info) == STB_WEAK) &&
14627c478bd9Sstevel@tonic-gate 		    (!sap->sa_PLTndx)) {
14637c478bd9Sstevel@tonic-gate 			Sym_desc *	_sdp =
14647c478bd9Sstevel@tonic-gate 			    sdp->sd_file->ifl_oldndx[sap->sa_linkndx];
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 			if (_sdp->sd_ref != REF_DYN_SEEN) {
14677c478bd9Sstevel@tonic-gate 				if ((wkp =
14687c478bd9Sstevel@tonic-gate 				    libld_calloc(sizeof (Wk_desc), 1)) == 0)
14697c478bd9Sstevel@tonic-gate 					return ((Addr)S_ERROR);
14707c478bd9Sstevel@tonic-gate 
14719039eeafSab 				if (enter_in_symtab) {
14727c478bd9Sstevel@tonic-gate 					if (local)
14737c478bd9Sstevel@tonic-gate 						wkp->wk_symtab =
14747c478bd9Sstevel@tonic-gate 						    &symtab[scopesym_ndx];
14757c478bd9Sstevel@tonic-gate 					else
14767c478bd9Sstevel@tonic-gate 						wkp->wk_symtab =
14777c478bd9Sstevel@tonic-gate 						    &symtab[symtab_ndx];
14789039eeafSab 				}
14799039eeafSab 				if (dynsym) {
14809039eeafSab 					if (!local) {
14819039eeafSab 						wkp->wk_dynsym =
14829039eeafSab 						    &dynsym[dynsym_ndx];
14839039eeafSab 					} else if (dynlocal) {
14849039eeafSab 						wkp->wk_dynsym =
14859039eeafSab 						    &ldynsym[ldynscopesym_ndx];
14869039eeafSab 					}
14879039eeafSab 				}
14887c478bd9Sstevel@tonic-gate 				wkp->wk_weak = sdp;
14897c478bd9Sstevel@tonic-gate 				wkp->wk_alias = _sdp;
14907c478bd9Sstevel@tonic-gate 
14917c478bd9Sstevel@tonic-gate 				if (!(list_appendc(&weak, wkp)))
14927c478bd9Sstevel@tonic-gate 					return ((Addr)S_ERROR);
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 				if (enter_in_symtab)
14957c478bd9Sstevel@tonic-gate 					if (local)
14967c478bd9Sstevel@tonic-gate 						scopesym_ndx++;
14977c478bd9Sstevel@tonic-gate 					else
14987c478bd9Sstevel@tonic-gate 						symtab_ndx++;
14999039eeafSab 				if (dynsym) {
15009039eeafSab 					if (!local) {
15019039eeafSab 						dynsym_ndx++;
15029039eeafSab 					} else if (dynlocal) {
15039039eeafSab 						ldynscopesym_ndx++;
15049039eeafSab 					}
15059039eeafSab 				}
15067c478bd9Sstevel@tonic-gate 				continue;
15077c478bd9Sstevel@tonic-gate 			}
15087c478bd9Sstevel@tonic-gate 		}
15097c478bd9Sstevel@tonic-gate 
15105aefb655Srie 		DBG_CALL(Dbg_syms_old(ofl, sdp));
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 		spec = NULL;
15137c478bd9Sstevel@tonic-gate 		/*
15147c478bd9Sstevel@tonic-gate 		 * assign new symbol value.
15157c478bd9Sstevel@tonic-gate 		 */
15167c478bd9Sstevel@tonic-gate 		sectndx = sdp->sd_shndx;
15177c478bd9Sstevel@tonic-gate 		if (sectndx == SHN_UNDEF) {
15187c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) &&
15197c478bd9Sstevel@tonic-gate 			    (sym->st_value != 0)) {
15205aefb655Srie 				eprintf(ofl->ofl_lml, ERR_WARNING,
15215aefb655Srie 				    MSG_INTL(MSG_SYM_NOTNULL),
15227c478bd9Sstevel@tonic-gate 				    demangle(name), sdp->sd_file->ifl_name);
15237c478bd9Sstevel@tonic-gate 			}
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 			/*
15267c478bd9Sstevel@tonic-gate 			 * Undefined weak global, if we are generating a static
15277c478bd9Sstevel@tonic-gate 			 * executable, output as an absolute zero.  Otherwise
15287c478bd9Sstevel@tonic-gate 			 * leave it as is, ld.so.1 will skip symbols of this
15297c478bd9Sstevel@tonic-gate 			 * type (this technique allows applications and
15307c478bd9Sstevel@tonic-gate 			 * libraries to test for the existence of a symbol as an
15317c478bd9Sstevel@tonic-gate 			 * indication of the presence or absence of certain
15327c478bd9Sstevel@tonic-gate 			 * functionality).
15337c478bd9Sstevel@tonic-gate 			 */
15347c478bd9Sstevel@tonic-gate 			if (((flags & (FLG_OF_STATIC | FLG_OF_EXEC)) ==
15357c478bd9Sstevel@tonic-gate 			    (FLG_OF_STATIC | FLG_OF_EXEC)) &&
15367c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(sym->st_info) == STB_WEAK)) {
15377c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_SPECSEC;
15387c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = sectndx = SHN_ABS;
15397c478bd9Sstevel@tonic-gate 			}
15407c478bd9Sstevel@tonic-gate 		} else if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
15417c478bd9Sstevel@tonic-gate 		    (sectndx == SHN_COMMON)) {
15427c478bd9Sstevel@tonic-gate 			/* COMMONs have already been processed */
15437c478bd9Sstevel@tonic-gate 			/* EMPTY */
15447c478bd9Sstevel@tonic-gate 			;
15457c478bd9Sstevel@tonic-gate 		} else {
15467c478bd9Sstevel@tonic-gate 			if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
15477c478bd9Sstevel@tonic-gate 			    (sectndx == SHN_ABS))
15487c478bd9Sstevel@tonic-gate 				spec = sdp->sd_aux->sa_symspec;
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 			/* LINTED */
15517c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_COMMEXP) {
15527c478bd9Sstevel@tonic-gate 				/*
15537c478bd9Sstevel@tonic-gate 				 * This is (or was) a COMMON symbol which was
15547c478bd9Sstevel@tonic-gate 				 * processed above - no processing
15557c478bd9Sstevel@tonic-gate 				 * required here.
15567c478bd9Sstevel@tonic-gate 				 */
15577c478bd9Sstevel@tonic-gate 				;
15587c478bd9Sstevel@tonic-gate 			} else if (sdp->sd_ref == REF_DYN_NEED) {
1559d579eb63Sab 				uchar_t	type, bind;
15607c478bd9Sstevel@tonic-gate 
15617c478bd9Sstevel@tonic-gate 				sectndx = SHN_UNDEF;
15627c478bd9Sstevel@tonic-gate 				sym->st_value = 0;
15637c478bd9Sstevel@tonic-gate 				sym->st_size = 0;
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 				/*
15667c478bd9Sstevel@tonic-gate 				 * Make sure this undefined symbol is returned
15677c478bd9Sstevel@tonic-gate 				 * to the same binding as was defined in the
15687c478bd9Sstevel@tonic-gate 				 * original relocatable object reference.
15697c478bd9Sstevel@tonic-gate 				 */
15707c478bd9Sstevel@tonic-gate 				type = ELF_ST_TYPE(sym-> st_info);
15717c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags & FLG_SY_GLOBREF)
15727c478bd9Sstevel@tonic-gate 					bind = STB_GLOBAL;
15737c478bd9Sstevel@tonic-gate 				else
15747c478bd9Sstevel@tonic-gate 					bind = STB_WEAK;
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 				sym->st_info = ELF_ST_INFO(bind, type);
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate 			} else if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) &&
15797c478bd9Sstevel@tonic-gate 			    (sdp->sd_ref == REF_REL_NEED)) {
15807c478bd9Sstevel@tonic-gate 				osp = sdp->sd_isc->is_osdesc;
15817c478bd9Sstevel@tonic-gate 				/* LINTED */
15827c478bd9Sstevel@tonic-gate 				sectndx = elf_ndxscn(osp->os_scn);
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 				/*
15857c478bd9Sstevel@tonic-gate 				 * In an executable, the new symbol value is the
15867c478bd9Sstevel@tonic-gate 				 * old value (offset into defining section) plus
15877c478bd9Sstevel@tonic-gate 				 * virtual address of defining section.  In a
15887c478bd9Sstevel@tonic-gate 				 * relocatable, the new value is the old value
15897c478bd9Sstevel@tonic-gate 				 * plus the displacement of the section within
15907c478bd9Sstevel@tonic-gate 				 * the file.
15917c478bd9Sstevel@tonic-gate 				 */
15927c478bd9Sstevel@tonic-gate 				/* LINTED */
15937c478bd9Sstevel@tonic-gate 				sym->st_value +=
15947c478bd9Sstevel@tonic-gate 				    (Off)_elf_getxoff(sdp->sd_isc->is_indata);
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate 				if (!(flags & FLG_OF_RELOBJ)) {
15977c478bd9Sstevel@tonic-gate 					sym->st_value += osp->os_shdr->sh_addr;
15987c478bd9Sstevel@tonic-gate 					/*
15997c478bd9Sstevel@tonic-gate 					 * TLS symbols are relative to
16007c478bd9Sstevel@tonic-gate 					 * the TLS segment.
16017c478bd9Sstevel@tonic-gate 					 */
16027c478bd9Sstevel@tonic-gate 					if ((ELF_ST_TYPE(sym->st_info) ==
16037c478bd9Sstevel@tonic-gate 					    STT_TLS) && (ofl->ofl_tlsphdr))
16047c478bd9Sstevel@tonic-gate 						sym->st_value -=
16057c478bd9Sstevel@tonic-gate 						    ofl->ofl_tlsphdr->p_vaddr;
16067c478bd9Sstevel@tonic-gate 				}
16077c478bd9Sstevel@tonic-gate 			}
16087c478bd9Sstevel@tonic-gate 		}
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 		if (spec) {
16117c478bd9Sstevel@tonic-gate 			switch (spec) {
16127c478bd9Sstevel@tonic-gate 			case SDAUX_ID_ETEXT:
16137c478bd9Sstevel@tonic-gate 				sym->st_value = etext;
16147c478bd9Sstevel@tonic-gate 				sectndx = etext_ndx;
16157c478bd9Sstevel@tonic-gate 				if (etext_abs)
16167c478bd9Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_SPECSEC;
16177c478bd9Sstevel@tonic-gate 				else
16187c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16197c478bd9Sstevel@tonic-gate 				break;
16207c478bd9Sstevel@tonic-gate 			case SDAUX_ID_EDATA:
16217c478bd9Sstevel@tonic-gate 				sym->st_value = edata;
16227c478bd9Sstevel@tonic-gate 				sectndx = edata_ndx;
16237c478bd9Sstevel@tonic-gate 				if (edata_abs)
16247c478bd9Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_SPECSEC;
16257c478bd9Sstevel@tonic-gate 				else
16267c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16277c478bd9Sstevel@tonic-gate 				break;
16287c478bd9Sstevel@tonic-gate 			case SDAUX_ID_END:
16297c478bd9Sstevel@tonic-gate 				sym->st_value = end;
16307c478bd9Sstevel@tonic-gate 				sectndx = end_ndx;
16317c478bd9Sstevel@tonic-gate 				if (end_abs)
16327c478bd9Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_SPECSEC;
16337c478bd9Sstevel@tonic-gate 				else
16347c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16357c478bd9Sstevel@tonic-gate 				break;
16367c478bd9Sstevel@tonic-gate 			case SDAUX_ID_START:
16377c478bd9Sstevel@tonic-gate 				sym->st_value = start;
16387c478bd9Sstevel@tonic-gate 				sectndx = start_ndx;
16397c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
16407c478bd9Sstevel@tonic-gate 				break;
16417c478bd9Sstevel@tonic-gate 			case SDAUX_ID_DYN:
16427c478bd9Sstevel@tonic-gate 				if (flags & FLG_OF_DYNAMIC) {
16437c478bd9Sstevel@tonic-gate 					sym->st_value = ofl->
16447c478bd9Sstevel@tonic-gate 					    ofl_osdynamic->os_shdr->sh_addr;
16457c478bd9Sstevel@tonic-gate 					/* LINTED */
16467c478bd9Sstevel@tonic-gate 					sectndx = elf_ndxscn(
16477c478bd9Sstevel@tonic-gate 					    ofl->ofl_osdynamic->os_scn);
16487c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16497c478bd9Sstevel@tonic-gate 				}
16507c478bd9Sstevel@tonic-gate 				break;
16517c478bd9Sstevel@tonic-gate 			case SDAUX_ID_PLT:
16527c478bd9Sstevel@tonic-gate 				if (ofl->ofl_osplt) {
16537c478bd9Sstevel@tonic-gate 					sym->st_value = ofl->
16547c478bd9Sstevel@tonic-gate 					    ofl_osplt->os_shdr->sh_addr;
16557c478bd9Sstevel@tonic-gate 					/* LINTED */
16567c478bd9Sstevel@tonic-gate 					sectndx = elf_ndxscn(
16577c478bd9Sstevel@tonic-gate 					    ofl->ofl_osplt->os_scn);
16587c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16597c478bd9Sstevel@tonic-gate 				}
16607c478bd9Sstevel@tonic-gate 				break;
16617c478bd9Sstevel@tonic-gate 			case SDAUX_ID_GOT:
16627c478bd9Sstevel@tonic-gate 				/*
16637c478bd9Sstevel@tonic-gate 				 * Symbol bias for negative growing tables is
16647c478bd9Sstevel@tonic-gate 				 * stored in symbol's value during
16657c478bd9Sstevel@tonic-gate 				 * allocate_got().
16667c478bd9Sstevel@tonic-gate 				 */
16677c478bd9Sstevel@tonic-gate 				sym->st_value += ofl->
16687c478bd9Sstevel@tonic-gate 				    ofl_osgot->os_shdr->sh_addr;
16697c478bd9Sstevel@tonic-gate 				/* LINTED */
16707c478bd9Sstevel@tonic-gate 				sectndx = elf_ndxscn(ofl->
16717c478bd9Sstevel@tonic-gate 				    ofl_osgot->os_scn);
16727c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
16737c478bd9Sstevel@tonic-gate 				break;
16747c478bd9Sstevel@tonic-gate 			default:
16757c478bd9Sstevel@tonic-gate 				/* NOTHING */
16767c478bd9Sstevel@tonic-gate 				;
16777c478bd9Sstevel@tonic-gate 			}
16787c478bd9Sstevel@tonic-gate 		}
16797c478bd9Sstevel@tonic-gate 
16807c478bd9Sstevel@tonic-gate 		/*
16817c478bd9Sstevel@tonic-gate 		 * If a plt index has been assigned to an undefined function,
16827c478bd9Sstevel@tonic-gate 		 * update the symbols value to the appropriate .plt address.
16837c478bd9Sstevel@tonic-gate 		 */
16847c478bd9Sstevel@tonic-gate 		if ((flags & FLG_OF_DYNAMIC) && (flags & FLG_OF_EXEC) &&
16857c478bd9Sstevel@tonic-gate 		    (sdp->sd_file) &&
16867c478bd9Sstevel@tonic-gate 		    (sdp->sd_file->ifl_ehdr->e_type == ET_DYN) &&
16877c478bd9Sstevel@tonic-gate 		    (ELF_ST_TYPE(sym->st_info) == STT_FUNC) &&
16887c478bd9Sstevel@tonic-gate 		    !(flags & FLG_OF_BFLAG)) {
16897c478bd9Sstevel@tonic-gate 			if (sap->sa_PLTndx)
1690ba2be530Sab 				sym->st_value =
1691ba2be530Sab 				    (*ld_targ.t_mr.mr_calc_plt_addr)(sdp, ofl);
16927c478bd9Sstevel@tonic-gate 		}
16937c478bd9Sstevel@tonic-gate 
16947c478bd9Sstevel@tonic-gate 		/*
16957c478bd9Sstevel@tonic-gate 		 * Finish updating the symbols.
16967c478bd9Sstevel@tonic-gate 		 */
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate 		/*
16997c478bd9Sstevel@tonic-gate 		 * Sym Update: if scoped local - set local binding
17007c478bd9Sstevel@tonic-gate 		 */
17017c478bd9Sstevel@tonic-gate 		if (local)
17027c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(STB_LOCAL,
17037c478bd9Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info));
17047c478bd9Sstevel@tonic-gate 
17057c478bd9Sstevel@tonic-gate 		/*
17067c478bd9Sstevel@tonic-gate 		 * Sym Updated: If both the .symtab and .dynsym
17077c478bd9Sstevel@tonic-gate 		 * are present then we've actually updated the information in
17087c478bd9Sstevel@tonic-gate 		 * the .dynsym, therefore copy this same information to the
17097c478bd9Sstevel@tonic-gate 		 * .symtab entry.
17107c478bd9Sstevel@tonic-gate 		 */
17117c478bd9Sstevel@tonic-gate 		sdp->sd_shndx = sectndx;
17129039eeafSab 		if (enter_in_symtab && dynsym && (!local || dynlocal)) {
17139039eeafSab 			Word _symndx = dynlocal ? scopesym_ndx : symtab_ndx;
17149039eeafSab 
17159039eeafSab 			symtab[_symndx].st_value = sym->st_value;
17169039eeafSab 			symtab[_symndx].st_size = sym->st_size;
17179039eeafSab 			symtab[_symndx].st_info = sym->st_info;
17189039eeafSab 			symtab[_symndx].st_other = sym->st_other;
17197c478bd9Sstevel@tonic-gate 		}
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 
17227c478bd9Sstevel@tonic-gate 		if (enter_in_symtab) {
17237c478bd9Sstevel@tonic-gate 			Word	_symndx;
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate 			if (local)
17267c478bd9Sstevel@tonic-gate 				_symndx = scopesym_ndx++;
17277c478bd9Sstevel@tonic-gate 			else
17287c478bd9Sstevel@tonic-gate 				_symndx = symtab_ndx++;
17297c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) &&
17307c478bd9Sstevel@tonic-gate 			    (sectndx >= SHN_LORESERVE)) {
17317c478bd9Sstevel@tonic-gate 				assert(symshndx != 0);
17327c478bd9Sstevel@tonic-gate 				symshndx[_symndx] = sectndx;
17337c478bd9Sstevel@tonic-gate 				symtab[_symndx].st_shndx = SHN_XINDEX;
17347c478bd9Sstevel@tonic-gate 			} else {
17357c478bd9Sstevel@tonic-gate 				/* LINTED */
17367c478bd9Sstevel@tonic-gate 				symtab[_symndx].st_shndx = (Half)sectndx;
17377c478bd9Sstevel@tonic-gate 			}
17387c478bd9Sstevel@tonic-gate 		}
17397c478bd9Sstevel@tonic-gate 
17409039eeafSab 		if (dynsym && (!local || dynlocal)) {
17419039eeafSab 			/*
17429039eeafSab 			 * dynsym and ldynsym are distinct tables, so
17439039eeafSab 			 * we use indirection to access the right one
17449039eeafSab 			 * and the related extended section index array.
17459039eeafSab 			 */
17469039eeafSab 			Word	_symndx;
17479039eeafSab 			Sym	*_dynsym;
17489039eeafSab 			Word	*_dynshndx;
17499039eeafSab 
17509039eeafSab 			if (!local) {
17519039eeafSab 				_symndx = dynsym_ndx++;
17529039eeafSab 				_dynsym = dynsym;
17539039eeafSab 				_dynshndx = dynshndx;
17549039eeafSab 			} else {
17559039eeafSab 				_symndx = ldynscopesym_ndx++;
17569039eeafSab 				_dynsym = ldynsym;
17579039eeafSab 				_dynshndx = ldynshndx;
17589039eeafSab 			}
17597c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) &&
17607c478bd9Sstevel@tonic-gate 			    (sectndx >= SHN_LORESERVE)) {
17619039eeafSab 				assert(_dynshndx != 0);
17629039eeafSab 				_dynshndx[_symndx] = sectndx;
17639039eeafSab 				_dynsym[_symndx].st_shndx = SHN_XINDEX;
17647c478bd9Sstevel@tonic-gate 			} else {
17657c478bd9Sstevel@tonic-gate 				/* LINTED */
17669039eeafSab 				_dynsym[_symndx].st_shndx = (Half)sectndx;
17677c478bd9Sstevel@tonic-gate 			}
17687c478bd9Sstevel@tonic-gate 		}
17697c478bd9Sstevel@tonic-gate 
17705aefb655Srie 		DBG_CALL(Dbg_syms_new(ofl, sym, sdp));
17717c478bd9Sstevel@tonic-gate 	}
17727c478bd9Sstevel@tonic-gate 
17737c478bd9Sstevel@tonic-gate 	/*
17747c478bd9Sstevel@tonic-gate 	 * Now that all the symbols have been processed update any weak symbols
17757c478bd9Sstevel@tonic-gate 	 * information (ie. copy all information except `st_name').  As both
17767c478bd9Sstevel@tonic-gate 	 * symbols will be represented in the output, return the weak symbol to
17777c478bd9Sstevel@tonic-gate 	 * its correct type.
17787c478bd9Sstevel@tonic-gate 	 */
17797c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&weak, lnp1, wkp)) {
17807c478bd9Sstevel@tonic-gate 		Sym_desc *	sdp, * _sdp;
17817c478bd9Sstevel@tonic-gate 		Sym *		sym, * _sym, * __sym;
1782d579eb63Sab 		uchar_t		bind;
17837c478bd9Sstevel@tonic-gate 
17847c478bd9Sstevel@tonic-gate 		sdp = wkp->wk_weak;
17857c478bd9Sstevel@tonic-gate 		_sdp = wkp->wk_alias;
17867c478bd9Sstevel@tonic-gate 		_sym = _sdp->sd_sym;
17877c478bd9Sstevel@tonic-gate 
17887c478bd9Sstevel@tonic-gate 		sdp->sd_flags |= FLG_SY_WEAKDEF;
17897c478bd9Sstevel@tonic-gate 
17907c478bd9Sstevel@tonic-gate 		/*
17917c478bd9Sstevel@tonic-gate 		 * If the symbol definition has been scoped then assign it to
17927c478bd9Sstevel@tonic-gate 		 * be local, otherwise if it's from a shared object then we need
17937c478bd9Sstevel@tonic-gate 		 * to maintain the binding of the original reference.
17947c478bd9Sstevel@tonic-gate 		 */
179560758829Srie 		if (sdp->sd_flags1 & FLG_SY1_HIDDEN) {
17967c478bd9Sstevel@tonic-gate 			if (flags & FLG_OF_PROCRED)
17977c478bd9Sstevel@tonic-gate 				bind = STB_LOCAL;
17987c478bd9Sstevel@tonic-gate 			else
17997c478bd9Sstevel@tonic-gate 				bind = STB_WEAK;
18007c478bd9Sstevel@tonic-gate 		} else if ((sdp->sd_ref == REF_DYN_NEED) &&
18017c478bd9Sstevel@tonic-gate 		    (sdp->sd_flags & FLG_SY_GLOBREF))
18027c478bd9Sstevel@tonic-gate 			bind = STB_GLOBAL;
18037c478bd9Sstevel@tonic-gate 		else
18047c478bd9Sstevel@tonic-gate 			bind = STB_WEAK;
18057c478bd9Sstevel@tonic-gate 
18065aefb655Srie 		DBG_CALL(Dbg_syms_old(ofl, sdp));
18077c478bd9Sstevel@tonic-gate 		if ((sym = wkp->wk_symtab) != 0) {
18087c478bd9Sstevel@tonic-gate 			sym = wkp->wk_symtab;
18097c478bd9Sstevel@tonic-gate 			sym->st_value = _sym->st_value;
18107c478bd9Sstevel@tonic-gate 			sym->st_size = _sym->st_size;
18117c478bd9Sstevel@tonic-gate 			sym->st_other = _sym->st_other;
18127c478bd9Sstevel@tonic-gate 			sym->st_shndx = _sym->st_shndx;
18137c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(bind,
18147c478bd9Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info));
18157c478bd9Sstevel@tonic-gate 			__sym = sym;
18167c478bd9Sstevel@tonic-gate 		}
18177c478bd9Sstevel@tonic-gate 		if ((sym = wkp->wk_dynsym) != 0) {
18187c478bd9Sstevel@tonic-gate 			sym = wkp->wk_dynsym;
18197c478bd9Sstevel@tonic-gate 			sym->st_value = _sym->st_value;
18207c478bd9Sstevel@tonic-gate 			sym->st_size = _sym->st_size;
18217c478bd9Sstevel@tonic-gate 			sym->st_other = _sym->st_other;
18227c478bd9Sstevel@tonic-gate 			sym->st_shndx = _sym->st_shndx;
18237c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(bind,
18247c478bd9Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info));
18257c478bd9Sstevel@tonic-gate 			__sym = sym;
18267c478bd9Sstevel@tonic-gate 		}
18275aefb655Srie 		DBG_CALL(Dbg_syms_new(ofl, __sym, sdp));
18287c478bd9Sstevel@tonic-gate 	}
18297c478bd9Sstevel@tonic-gate 
18307c478bd9Sstevel@tonic-gate 	/*
18315aefb655Srie 	 * Now display GOT debugging information if required.
18327c478bd9Sstevel@tonic-gate 	 */
1833ba2be530Sab 	DBG_CALL(Dbg_got_display(ofl, 0, 0,
1834ba2be530Sab 	    ld_targ.t_m.m_got_xnumber, ld_targ.t_m.m_got_entsize));
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 	/*
18379039eeafSab 	 * Update the section headers information. sh_info is
18389039eeafSab 	 * supposed to contain the offset at which the first
18399039eeafSab 	 * global symbol resides in the symbol table, while
18409039eeafSab 	 * sh_link contains the section index of the associated
18419039eeafSab 	 * string table.
18427c478bd9Sstevel@tonic-gate 	 */
18437c478bd9Sstevel@tonic-gate 	if (symtab) {
184460758829Srie 		Shdr	*shdr = ofl->ofl_ossymtab->os_shdr;
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate 		shdr->sh_info = ofl->ofl_shdrcnt + ofl->ofl_locscnt +
1847d840867fSab 		    ofl->ofl_scopecnt + 2;
18487c478bd9Sstevel@tonic-gate 		/* LINTED */
18497c478bd9Sstevel@tonic-gate 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osstrtab->os_scn);
18507c478bd9Sstevel@tonic-gate 		if (symshndx) {
18517c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_ossymshndx->os_shdr;
18527c478bd9Sstevel@tonic-gate 			shdr->sh_link =
1853d840867fSab 			    (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn);
18547c478bd9Sstevel@tonic-gate 		}
18557c478bd9Sstevel@tonic-gate 	}
18567c478bd9Sstevel@tonic-gate 	if (dynsym) {
185760758829Srie 		Shdr	*shdr = ofl->ofl_osdynsym->os_shdr;
18587c478bd9Sstevel@tonic-gate 
18599039eeafSab 		shdr->sh_info = 1 + ofl->ofl_dynshdrcnt + ofl->ofl_lregsymcnt;
18607c478bd9Sstevel@tonic-gate 		/* LINTED */
18617c478bd9Sstevel@tonic-gate 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 		ofl->ofl_oshash->os_shdr->sh_link =
18647c478bd9Sstevel@tonic-gate 		    /* LINTED */
18657c478bd9Sstevel@tonic-gate 		    (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn);
18667c478bd9Sstevel@tonic-gate 		if (dynshndx) {
18677c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osdynshndx->os_shdr;
18687c478bd9Sstevel@tonic-gate 			shdr->sh_link =
1869d840867fSab 			    (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn);
18707c478bd9Sstevel@tonic-gate 		}
18717c478bd9Sstevel@tonic-gate 	}
18729039eeafSab 	if (ldynsym) {
187360758829Srie 		Shdr	*shdr = ofl->ofl_osldynsym->os_shdr;
18749039eeafSab 
18759039eeafSab 		/* ldynsym has no globals, so give index one past the end */
18769039eeafSab 		shdr->sh_info = ldynsym_ndx;
18779039eeafSab 
18789039eeafSab 		/*
18799039eeafSab 		 * The ldynsym and dynsym must be adjacent. The
18809039eeafSab 		 * idea is that rtld should be able to start with
18819039eeafSab 		 * the ldynsym and march straight through the end
18829039eeafSab 		 * of dynsym, seeing them as a single symbol table,
18839039eeafSab 		 * despite the fact that they are in distinct sections.
18849039eeafSab 		 * Ensure that this happened correctly.
18859039eeafSab 		 *
18869039eeafSab 		 * Note that I use ldynsym_ndx here instead of the
18879039eeafSab 		 * computation I used to set the section size
1888d579eb63Sab 		 * (found in ldynsym_cnt). The two will agree, unless
1889d579eb63Sab 		 * we somehow miscounted symbols or failed to insert them
1890d579eb63Sab 		 * all. Using ldynsym_ndx here catches that error in
1891d579eb63Sab 		 * addition to checking for adjacency.
18929039eeafSab 		 */
18939039eeafSab 		assert(dynsym == (ldynsym + ldynsym_ndx));
18949039eeafSab 
18959039eeafSab 
18969039eeafSab 		/* LINTED */
18979039eeafSab 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
18989039eeafSab 
18999039eeafSab 		if (ldynshndx) {
19009039eeafSab 			shdr = ofl->ofl_osldynshndx->os_shdr;
19019039eeafSab 			shdr->sh_link =
1902d840867fSab 			    (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn);
19039039eeafSab 		}
1904d579eb63Sab 
1905d579eb63Sab 		/*
1906d579eb63Sab 		 * The presence of .SUNW_ldynsym means that there may be
1907d579eb63Sab 		 * associated sort sections, one for regular symbols
1908d579eb63Sab 		 * and the other for TLS. Each sort section needs the
1909d579eb63Sab 		 * following done:
1910d579eb63Sab 		 *	- Section header link references .SUNW_ldynsym
1911d579eb63Sab 		 *	- Should have received the expected # of items
1912d579eb63Sab 		 *	- Sorted by increasing address
1913d579eb63Sab 		 */
1914d579eb63Sab 		if (ofl->ofl_osdynsymsort) {	/* .SUNW_dynsymsort */
1915d579eb63Sab 			ofl->ofl_osdynsymsort->os_shdr->sh_link =
1916d579eb63Sab 			    (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn);
1917d579eb63Sab 			assert(ofl->ofl_dynsymsortcnt == dynsymsort_ndx);
191860758829Srie 
1919d579eb63Sab 			if (dynsymsort_ndx > 1) {
1920d579eb63Sab 				dynsort_compare_syms = ldynsym;
1921d579eb63Sab 				qsort(dynsymsort, dynsymsort_ndx,
1922d579eb63Sab 				    sizeof (*dynsymsort), dynsort_compare);
1923a194faf8Srie 				dynsort_dupwarn(ofl, ldynsym,
1924a194faf8Srie 				    st_getstrbuf(dynstr),
1925d579eb63Sab 				    dynsymsort, dynsymsort_ndx,
1926d579eb63Sab 				    MSG_ORIG(MSG_SCN_DYNSYMSORT));
1927d579eb63Sab 			}
1928d579eb63Sab 		}
1929d579eb63Sab 		if (ofl->ofl_osdyntlssort) {	/* .SUNW_dyntlssort */
1930d579eb63Sab 			ofl->ofl_osdyntlssort->os_shdr->sh_link =
1931d579eb63Sab 			    (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn);
1932d579eb63Sab 			assert(ofl->ofl_dyntlssortcnt == dyntlssort_ndx);
193360758829Srie 
1934d579eb63Sab 			if (dyntlssort_ndx > 1) {
1935d579eb63Sab 				dynsort_compare_syms = ldynsym;
1936d579eb63Sab 				qsort(dyntlssort, dyntlssort_ndx,
1937d579eb63Sab 				    sizeof (*dyntlssort), dynsort_compare);
1938a194faf8Srie 				dynsort_dupwarn(ofl, ldynsym,
1939a194faf8Srie 				    st_getstrbuf(dynstr),
1940d579eb63Sab 				    dyntlssort, dyntlssort_ndx,
1941d579eb63Sab 				    MSG_ORIG(MSG_SCN_DYNTLSSORT));
1942d579eb63Sab 			}
1943d579eb63Sab 		}
19449039eeafSab 	}
19457c478bd9Sstevel@tonic-gate 
19467c478bd9Sstevel@tonic-gate 	/*
19477c478bd9Sstevel@tonic-gate 	 * Used by ld.so.1 only.
19487c478bd9Sstevel@tonic-gate 	 */
19497c478bd9Sstevel@tonic-gate 	return (etext);
1950d579eb63Sab 
1951d579eb63Sab #undef ADD_TO_DYNSORT
19527c478bd9Sstevel@tonic-gate }
19537c478bd9Sstevel@tonic-gate 
19547c478bd9Sstevel@tonic-gate /*
19557c478bd9Sstevel@tonic-gate  * Build the dynamic section.
19561d9df23bSab  *
19571d9df23bSab  * This routine must be maintained in parallel with make_dynamic()
19581d9df23bSab  * in sections.c
19597c478bd9Sstevel@tonic-gate  */
19605aefb655Srie static int
19617c478bd9Sstevel@tonic-gate update_odynamic(Ofl_desc *ofl)
19627c478bd9Sstevel@tonic-gate {
19637c478bd9Sstevel@tonic-gate 	Listnode	*lnp;
19647c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
19657c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
19667c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
19677c478bd9Sstevel@tonic-gate 	Dyn		*_dyn = (Dyn *)ofl->ofl_osdynamic->os_outdata->d_buf;
19687c478bd9Sstevel@tonic-gate 	Dyn		*dyn;
19697c478bd9Sstevel@tonic-gate 	Str_tbl		*dynstr;
1970cce0e03bSab 	size_t		stoff;
19711d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
19721d9df23bSab 	int		not_relobj = !(flags & FLG_OF_RELOBJ);
19733244bcaaSab 	Word		cnt;
19747c478bd9Sstevel@tonic-gate 
19751d9df23bSab 
19761d9df23bSab 	/*
19771d9df23bSab 	 * A relocatable object with a dynamic section is possible, though
19781d9df23bSab 	 * rare. One use for this feature is to produce drivers
19791d9df23bSab 	 * for the kernel, loaded by krtld.
19801d9df23bSab 	 *
19811d9df23bSab 	 * Only a limited subset of DT_ entries apply to relocatable
19821d9df23bSab 	 * objects:
19831d9df23bSab 	 *
19841d9df23bSab 	 *	DT_NEEDED
19851d9df23bSab 	 *	DT_RUNPATH/DT_RPATH
19861d9df23bSab 	 *	DT_FLAGS
19871d9df23bSab 	 *	DT_FLAGS1
19881d9df23bSab 	 *	DT_SUNW_STRPAD
19891d9df23bSab 	 *	DT_LDMACH
19901d9df23bSab 	 */
19911d9df23bSab 
19927c478bd9Sstevel@tonic-gate 	dynstr = ofl->ofl_dynstrtab;
19937c478bd9Sstevel@tonic-gate 	ofl->ofl_osdynamic->os_shdr->sh_link =
19947c478bd9Sstevel@tonic-gate 	    /* LINTED */
19957c478bd9Sstevel@tonic-gate 	    (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
19967c478bd9Sstevel@tonic-gate 
19977c478bd9Sstevel@tonic-gate 	dyn = _dyn;
19987c478bd9Sstevel@tonic-gate 
19997c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_sos, lnp, ifl)) {
20007c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_flags &
20017c478bd9Sstevel@tonic-gate 		    (FLG_IF_IGNORE | FLG_IF_DEPREQD)) == FLG_IF_IGNORE)
20027c478bd9Sstevel@tonic-gate 			continue;
20037c478bd9Sstevel@tonic-gate 
20047c478bd9Sstevel@tonic-gate 		/*
20057c478bd9Sstevel@tonic-gate 		 * Create and set up the DT_POSFLAG_1 entry here if required.
20067c478bd9Sstevel@tonic-gate 		 */
20077c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_flags & (FLG_IF_LAZYLD|FLG_IF_GRPPRM)) &&
20081d9df23bSab 		    (ifl->ifl_flags & (FLG_IF_NEEDED)) && not_relobj) {
20097c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_POSFLAG_1;
20107c478bd9Sstevel@tonic-gate 			if (ifl->ifl_flags & FLG_IF_LAZYLD)
20117c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = DF_P1_LAZYLOAD;
20127c478bd9Sstevel@tonic-gate 			if (ifl->ifl_flags & FLG_IF_GRPPRM)
20137c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val |= DF_P1_GROUPPERM;
20147c478bd9Sstevel@tonic-gate 			dyn++;
20157c478bd9Sstevel@tonic-gate 		}
20167c478bd9Sstevel@tonic-gate 
20177c478bd9Sstevel@tonic-gate 		if (ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR))
20187c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_NEEDED;
20197c478bd9Sstevel@tonic-gate 		else
20207c478bd9Sstevel@tonic-gate 			continue;
20217c478bd9Sstevel@tonic-gate 
20227c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ifl->ifl_soname, &stoff);
20237c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20247c478bd9Sstevel@tonic-gate 		/* LINTED */
20257c478bd9Sstevel@tonic-gate 		ifl->ifl_neededndx = (Half)(((uintptr_t)dyn - (uintptr_t)_dyn) /
20267c478bd9Sstevel@tonic-gate 		    sizeof (Dyn));
20277c478bd9Sstevel@tonic-gate 		dyn++;
20287c478bd9Sstevel@tonic-gate 	}
20297c478bd9Sstevel@tonic-gate 
20301d9df23bSab 	if (not_relobj) {
20311d9df23bSab 		if (ofl->ofl_dtsfltrs != NULL) {
20321d9df23bSab 			Dfltr_desc	*dftp;
20331d9df23bSab 			Aliste		idx;
20347c478bd9Sstevel@tonic-gate 
20351d9df23bSab 			for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, idx, dftp)) {
20361d9df23bSab 				if (dftp->dft_flag == FLG_SY_AUXFLTR)
20371d9df23bSab 					dyn->d_tag = DT_SUNW_AUXILIARY;
20381d9df23bSab 				else
20391d9df23bSab 					dyn->d_tag = DT_SUNW_FILTER;
20407c478bd9Sstevel@tonic-gate 
20411d9df23bSab 				(void) st_setstring(dynstr, dftp->dft_str,
20421d9df23bSab 				    &stoff);
20431d9df23bSab 				dyn->d_un.d_val = stoff;
20441d9df23bSab 				dftp->dft_ndx = (Half)(((uintptr_t)dyn -
20451d9df23bSab 				    (uintptr_t)_dyn) / sizeof (Dyn));
20461d9df23bSab 				dyn++;
20471d9df23bSab 			}
20481d9df23bSab 		}
20491d9df23bSab 		if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U),
20501d9df23bSab 		    SYM_NOHASH, 0, ofl)) != NULL) &&
20511d9df23bSab 		    (sdp->sd_ref == REF_REL_NEED) &&
20521d9df23bSab 		    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
20531d9df23bSab 			dyn->d_tag = DT_INIT;
20541d9df23bSab 			dyn->d_un.d_ptr = sdp->sd_sym->st_value;
20551d9df23bSab 			dyn++;
20561d9df23bSab 		}
20571d9df23bSab 		if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U),
20581d9df23bSab 		    SYM_NOHASH, 0, ofl)) != NULL) &&
20591d9df23bSab 		    (sdp->sd_ref == REF_REL_NEED) &&
20601d9df23bSab 		    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
20611d9df23bSab 			dyn->d_tag = DT_FINI;
20621d9df23bSab 			dyn->d_un.d_ptr = sdp->sd_sym->st_value;
20631d9df23bSab 			dyn++;
20641d9df23bSab 		}
20651d9df23bSab 		if (ofl->ofl_soname) {
20661d9df23bSab 			dyn->d_tag = DT_SONAME;
20671d9df23bSab 			(void) st_setstring(dynstr, ofl->ofl_soname, &stoff);
20687c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = stoff;
20697c478bd9Sstevel@tonic-gate 			dyn++;
20707c478bd9Sstevel@tonic-gate 		}
20711d9df23bSab 		if (ofl->ofl_filtees) {
20721d9df23bSab 			if (flags & FLG_OF_AUX) {
20731d9df23bSab 				dyn->d_tag = DT_AUXILIARY;
20741d9df23bSab 			} else {
20751d9df23bSab 				dyn->d_tag = DT_FILTER;
20761d9df23bSab 			}
20771d9df23bSab 			(void) st_setstring(dynstr, ofl->ofl_filtees, &stoff);
20781d9df23bSab 			dyn->d_un.d_val = stoff;
20791d9df23bSab 			dyn++;
20807c478bd9Sstevel@tonic-gate 		}
20817c478bd9Sstevel@tonic-gate 	}
20821d9df23bSab 
20837c478bd9Sstevel@tonic-gate 	if (ofl->ofl_rpath) {
20847c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ofl->ofl_rpath, &stoff);
20857c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_RUNPATH;
20867c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20877c478bd9Sstevel@tonic-gate 		dyn++;
20887c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_RPATH;
20897c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20907c478bd9Sstevel@tonic-gate 		dyn++;
20917c478bd9Sstevel@tonic-gate 	}
20927c478bd9Sstevel@tonic-gate 
20931d9df23bSab 	if (not_relobj) {
20941d9df23bSab 		if (ofl->ofl_config) {
20951d9df23bSab 			dyn->d_tag = DT_CONFIG;
20961d9df23bSab 			(void) st_setstring(dynstr, ofl->ofl_config, &stoff);
20971d9df23bSab 			dyn->d_un.d_val = stoff;
20981d9df23bSab 			dyn++;
20991d9df23bSab 		}
21001d9df23bSab 		if (ofl->ofl_depaudit) {
21011d9df23bSab 			dyn->d_tag = DT_DEPAUDIT;
21021d9df23bSab 			(void) st_setstring(dynstr, ofl->ofl_depaudit, &stoff);
21031d9df23bSab 			dyn->d_un.d_val = stoff;
21041d9df23bSab 			dyn++;
21051d9df23bSab 		}
21061d9df23bSab 		if (ofl->ofl_audit) {
21071d9df23bSab 			dyn->d_tag = DT_AUDIT;
21081d9df23bSab 			(void) st_setstring(dynstr, ofl->ofl_audit, &stoff);
21091d9df23bSab 			dyn->d_un.d_val = stoff;
21101d9df23bSab 			dyn++;
21111d9df23bSab 		}
21127c478bd9Sstevel@tonic-gate 
21137c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_HASH;
21147c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = ofl->ofl_oshash->os_shdr->sh_addr;
21157c478bd9Sstevel@tonic-gate 		dyn++;
21167c478bd9Sstevel@tonic-gate 
21177c478bd9Sstevel@tonic-gate 		shdr = ofl->ofl_osdynstr->os_shdr;
21187c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_STRTAB;
21197c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_addr;
21207c478bd9Sstevel@tonic-gate 		dyn++;
21217c478bd9Sstevel@tonic-gate 
21227c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_STRSZ;
21237c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_size;
21247c478bd9Sstevel@tonic-gate 		dyn++;
21257c478bd9Sstevel@tonic-gate 
21267c478bd9Sstevel@tonic-gate 		shdr = ofl->ofl_osdynsym->os_shdr;
21277c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_SYMTAB;
21287c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_addr;
21297c478bd9Sstevel@tonic-gate 		dyn++;
21307c478bd9Sstevel@tonic-gate 
21317c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_SYMENT;
21327c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_entsize;
21337c478bd9Sstevel@tonic-gate 		dyn++;
21347c478bd9Sstevel@tonic-gate 
21359039eeafSab 		if (ofl->ofl_osldynsym) {
21369039eeafSab 			/*
21379039eeafSab 			 * We have arranged for the .SUNW_ldynsym data to be
21389039eeafSab 			 * immediately in front of the .dynsym data.
21399039eeafSab 			 * This means that you could start at the top
21409039eeafSab 			 * of .SUNW_ldynsym and see the data for both tables
21419039eeafSab 			 * without a break. This is the view we want to
21429039eeafSab 			 * provide for DT_SUNW_SYMTAB, which is why we
21439039eeafSab 			 * add the lengths together.
21449039eeafSab 			 */
21459039eeafSab 			Shdr *lshdr = ofl->ofl_osldynsym->os_shdr;
21469039eeafSab 			dyn->d_tag = DT_SUNW_SYMTAB;
21479039eeafSab 			dyn->d_un.d_ptr = lshdr->sh_addr;
21489039eeafSab 			dyn++;
21499039eeafSab 
21509039eeafSab 			dyn->d_tag = DT_SUNW_SYMSZ;
21519039eeafSab 			dyn->d_un.d_val = lshdr->sh_size + shdr->sh_size;
21529039eeafSab 			dyn++;
21539039eeafSab 		}
21549039eeafSab 
2155d579eb63Sab 		if (ofl->ofl_osdynsymsort || ofl->ofl_osdyntlssort) {
2156d579eb63Sab 			dyn->d_tag = DT_SUNW_SORTENT;
2157d579eb63Sab 			dyn->d_un.d_val = sizeof (Word);
2158d579eb63Sab 			dyn++;
2159d579eb63Sab 		}
2160d579eb63Sab 
2161d579eb63Sab 		if (ofl->ofl_osdynsymsort) {
2162d579eb63Sab 			dyn->d_tag = DT_SUNW_SYMSORT;
2163d579eb63Sab 			dyn->d_un.d_ptr =
2164d579eb63Sab 			    ofl->ofl_osdynsymsort->os_shdr->sh_addr;
2165d579eb63Sab 			dyn++;
2166d579eb63Sab 
2167d579eb63Sab 			dyn->d_tag = DT_SUNW_SYMSORTSZ;
2168d579eb63Sab 			dyn->d_un.d_val =
2169d579eb63Sab 			    ofl->ofl_osdynsymsort->os_shdr->sh_size;
2170d579eb63Sab 			dyn++;
2171d579eb63Sab 		}
2172d579eb63Sab 
2173d579eb63Sab 		if (ofl->ofl_osdyntlssort) {
2174d579eb63Sab 			dyn->d_tag = DT_SUNW_TLSSORT;
2175d579eb63Sab 			dyn->d_un.d_ptr =
2176d579eb63Sab 			    ofl->ofl_osdyntlssort->os_shdr->sh_addr;
2177d579eb63Sab 			dyn++;
2178d579eb63Sab 
2179d579eb63Sab 			dyn->d_tag = DT_SUNW_TLSSORTSZ;
2180d579eb63Sab 			dyn->d_un.d_val =
2181d579eb63Sab 			    ofl->ofl_osdyntlssort->os_shdr->sh_size;
2182d579eb63Sab 			dyn++;
2183d579eb63Sab 		}
2184d579eb63Sab 
21857c478bd9Sstevel@tonic-gate 		/*
21867c478bd9Sstevel@tonic-gate 		 * Reserve the DT_CHECKSUM entry.  Its value will be filled in
21877c478bd9Sstevel@tonic-gate 		 * after the complete image is built.
21887c478bd9Sstevel@tonic-gate 		 */
21897c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_CHECKSUM;
21907c478bd9Sstevel@tonic-gate 		ofl->ofl_checksum = &dyn->d_un.d_val;
21917c478bd9Sstevel@tonic-gate 		dyn++;
21927c478bd9Sstevel@tonic-gate 
2193d840867fSab 		/*
2194d840867fSab 		 * Versioning sections: DT_VERDEF and DT_VERNEED.
2195d840867fSab 		 *
2196d840867fSab 		 * The Solaris ld does not produce DT_VERSYM, but the GNU ld
2197d840867fSab 		 * does, in order to support their style of versioning, which
2198d840867fSab 		 * differs from ours:
2199d840867fSab 		 *
2200d840867fSab 		 *	- The top bit of the 16-bit Versym index is
2201d840867fSab 		 *		not part of the version, but is interpreted
2202d840867fSab 		 *		as a "hidden bit".
2203d840867fSab 		 *
2204d840867fSab 		 *	- External (SHN_UNDEF) symbols can have non-zero
2205d840867fSab 		 *		Versym values, which specify versions in
2206d840867fSab 		 *		referenced objects, via the Verneed section.
2207d840867fSab 		 *
2208d840867fSab 		 *	- The vna_other field of the Vernaux structures
2209d840867fSab 		 *		found in the Verneed section are not zero as
2210d840867fSab 		 *		with Solaris, but instead contain the version
2211d840867fSab 		 *		index to be used by Versym indices to reference
2212d840867fSab 		 *		the given external version.
2213d840867fSab 		 *
2214d840867fSab 		 * The Solaris ld, rtld, and elfdump programs all interpret the
2215d840867fSab 		 * presence of DT_VERSYM as meaning that GNU versioning rules
2216d840867fSab 		 * apply to the given file. If DT_VERSYM is not present,
2217d840867fSab 		 * then Solaris versioning rules apply. If we should ever need
2218d840867fSab 		 * to change our ld so that it does issue DT_VERSYM, then
2219d840867fSab 		 * this rule for detecting GNU versioning will no longer work.
2220d840867fSab 		 * In that case, we will have to invent a way to explicitly
2221d840867fSab 		 * specify the style of versioning in use, perhaps via a
2222d840867fSab 		 * new dynamic entry named something like DT_SUNW_VERSIONSTYLE,
2223d840867fSab 		 * where the d_un.d_val value specifies which style is to be
2224d840867fSab 		 * used.
2225d840867fSab 		 */
22267c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) ==
22277c478bd9Sstevel@tonic-gate 		    FLG_OF_VERDEF) {
22287c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osverdef->os_shdr;
22297c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERDEF;
22307c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22317c478bd9Sstevel@tonic-gate 			dyn++;
22327c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERDEFNUM;
22337c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_info;
22347c478bd9Sstevel@tonic-gate 			dyn++;
22357c478bd9Sstevel@tonic-gate 		}
22367c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) ==
22377c478bd9Sstevel@tonic-gate 		    FLG_OF_VERNEED) {
22387c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osverneed->os_shdr;
22397c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERNEED;
22407c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22417c478bd9Sstevel@tonic-gate 			dyn++;
22427c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERNEEDNUM;
22437c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_info;
22447c478bd9Sstevel@tonic-gate 			dyn++;
22457c478bd9Sstevel@tonic-gate 		}
2246d840867fSab 
22471d9df23bSab 		if ((flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt) {
2248ba2be530Sab 			dyn->d_tag = ld_targ.t_m.m_rel_dt_count;
22497c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = ofl->ofl_relocrelcnt;
22507c478bd9Sstevel@tonic-gate 			dyn++;
22517c478bd9Sstevel@tonic-gate 		}
22527c478bd9Sstevel@tonic-gate 		if (flags & FLG_OF_TEXTREL) {
22537c478bd9Sstevel@tonic-gate 			/*
22547c478bd9Sstevel@tonic-gate 			 * Only the presence of this entry is used in this
22557c478bd9Sstevel@tonic-gate 			 * implementation, not the value stored.
22567c478bd9Sstevel@tonic-gate 			 */
22577c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_TEXTREL;
22587c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = 0;
22597c478bd9Sstevel@tonic-gate 			dyn++;
22607c478bd9Sstevel@tonic-gate 		}
22617c478bd9Sstevel@tonic-gate 
22627c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osfiniarray) {
22637c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osfiniarray->os_shdr;
22647c478bd9Sstevel@tonic-gate 
22657c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_FINI_ARRAY;
22667c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22677c478bd9Sstevel@tonic-gate 			dyn++;
22687c478bd9Sstevel@tonic-gate 
22697c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_FINI_ARRAYSZ;
22707c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
22717c478bd9Sstevel@tonic-gate 			dyn++;
22727c478bd9Sstevel@tonic-gate 		}
22737c478bd9Sstevel@tonic-gate 
22747c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osinitarray) {
22757c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osinitarray->os_shdr;
22767c478bd9Sstevel@tonic-gate 
22777c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_INIT_ARRAY;
22787c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22797c478bd9Sstevel@tonic-gate 			dyn++;
22807c478bd9Sstevel@tonic-gate 
22817c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_INIT_ARRAYSZ;
22827c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
22837c478bd9Sstevel@tonic-gate 			dyn++;
22847c478bd9Sstevel@tonic-gate 		}
22857c478bd9Sstevel@tonic-gate 
22867c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ospreinitarray) {
22877c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_ospreinitarray->os_shdr;
22887c478bd9Sstevel@tonic-gate 
22897c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PREINIT_ARRAY;
22907c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22917c478bd9Sstevel@tonic-gate 			dyn++;
22927c478bd9Sstevel@tonic-gate 
22937c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PREINIT_ARRAYSZ;
22947c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
22957c478bd9Sstevel@tonic-gate 			dyn++;
22967c478bd9Sstevel@tonic-gate 		}
22977c478bd9Sstevel@tonic-gate 
22987c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltcnt) {
22997c478bd9Sstevel@tonic-gate 			shdr =  ofl->ofl_osplt->os_relosdesc->os_shdr;
23007c478bd9Sstevel@tonic-gate 
23017c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTRELSZ;
23027c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_size;
23037c478bd9Sstevel@tonic-gate 			dyn++;
23047c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTREL;
2305ba2be530Sab 			dyn->d_un.d_ptr = ld_targ.t_m.m_rel_dt_type;
23067c478bd9Sstevel@tonic-gate 			dyn++;
23077c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_JMPREL;
23087c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
23097c478bd9Sstevel@tonic-gate 			dyn++;
23107c478bd9Sstevel@tonic-gate 		}
23117c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltpad) {
23127c478bd9Sstevel@tonic-gate 			shdr =  ofl->ofl_osplt->os_shdr;
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTPAD;
231560758829Srie 			if (ofl->ofl_pltcnt) {
23167c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = shdr->sh_addr +
2317ba2be530Sab 				    ld_targ.t_m.m_plt_reservsz +
2318ba2be530Sab 				    ofl->ofl_pltcnt * ld_targ.t_m.m_plt_entsize;
231960758829Srie 			} else
23207c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = shdr->sh_addr;
23217c478bd9Sstevel@tonic-gate 			dyn++;
23227c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTPADSZ;
2323ba2be530Sab 			dyn->d_un.d_val = ofl->ofl_pltpad *
2324ba2be530Sab 			    ld_targ.t_m.m_plt_entsize;
23257c478bd9Sstevel@tonic-gate 			dyn++;
23267c478bd9Sstevel@tonic-gate 		}
23277c478bd9Sstevel@tonic-gate 		if (ofl->ofl_relocsz) {
2328ba2be530Sab 			dyn->d_tag = ld_targ.t_m.m_rel_dt_type;
23297c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = ofl->ofl_osrelhead->os_shdr->sh_addr;
23307c478bd9Sstevel@tonic-gate 			dyn++;
2331ba2be530Sab 			dyn->d_tag = ld_targ.t_m.m_rel_dt_size;
23327c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = ofl->ofl_relocsz;
23337c478bd9Sstevel@tonic-gate 			dyn++;
2334ba2be530Sab 			dyn->d_tag = ld_targ.t_m.m_rel_dt_ent;
23357c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osrelhead->os_shdr->sh_type == SHT_REL)
23367c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = sizeof (Rel);
23377c478bd9Sstevel@tonic-gate 			else
23387c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = sizeof (Rela);
23397c478bd9Sstevel@tonic-gate 			dyn++;
23407c478bd9Sstevel@tonic-gate 		}
23417c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ossyminfo) {
23427c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_ossyminfo->os_shdr;
23437c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SYMINFO;
23447c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
23457c478bd9Sstevel@tonic-gate 			dyn++;
23467c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SYMINSZ;
23477c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
23487c478bd9Sstevel@tonic-gate 			dyn++;
23497c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SYMINENT;
23507c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = sizeof (Syminfo);
23517c478bd9Sstevel@tonic-gate 			dyn++;
23527c478bd9Sstevel@tonic-gate 		}
23537c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osmove) {
23547c478bd9Sstevel@tonic-gate 			Os_desc *	osp;
23557c478bd9Sstevel@tonic-gate 
23567c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_MOVEENT;
23577c478bd9Sstevel@tonic-gate 			osp = ofl->ofl_osmove;
23587c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = osp->os_shdr->sh_entsize;
23597c478bd9Sstevel@tonic-gate 			dyn++;
23607c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_MOVESZ;
23617c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = osp->os_shdr->sh_size;
23627c478bd9Sstevel@tonic-gate 			dyn++;
23637c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_MOVETAB;
23647c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = osp->os_shdr->sh_addr;
23657c478bd9Sstevel@tonic-gate 			dyn++;
23667c478bd9Sstevel@tonic-gate 		}
23677c478bd9Sstevel@tonic-gate 		if (ofl->ofl_regsymcnt) {
23687c478bd9Sstevel@tonic-gate 			int	ndx;
23697c478bd9Sstevel@tonic-gate 
23707c478bd9Sstevel@tonic-gate 			for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
23717c478bd9Sstevel@tonic-gate 				if ((sdp = ofl->ofl_regsyms[ndx]) == 0)
23727c478bd9Sstevel@tonic-gate 					continue;
23737c478bd9Sstevel@tonic-gate 
2374ba2be530Sab 				dyn->d_tag = ld_targ.t_m.m_dt_register;
23757c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = sdp->sd_symndx;
23767c478bd9Sstevel@tonic-gate 				dyn++;
23777c478bd9Sstevel@tonic-gate 			}
23787c478bd9Sstevel@tonic-gate 		}
23797c478bd9Sstevel@tonic-gate 
23807c478bd9Sstevel@tonic-gate 		for (LIST_TRAVERSE(&ofl->ofl_rtldinfo, lnp, sdp)) {
23817c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SUNW_RTLDINF;
23827c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = sdp->sd_sym->st_value;
23837c478bd9Sstevel@tonic-gate 			dyn++;
23847c478bd9Sstevel@tonic-gate 		}
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynamic->os_sgdesc &&
23877c478bd9Sstevel@tonic-gate 		    (ofl->ofl_osdynamic->os_sgdesc->sg_phdr.p_flags & PF_W)) {
23887c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osinterp) {
23897c478bd9Sstevel@tonic-gate 				dyn->d_tag = DT_DEBUG;
23907c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = 0;
23917c478bd9Sstevel@tonic-gate 				dyn++;
23927c478bd9Sstevel@tonic-gate 			}
23937c478bd9Sstevel@tonic-gate 
23947c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_FEATURE_1;
23957c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osmove)
23967c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = 0;
23977c478bd9Sstevel@tonic-gate 			else
23987c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = DTF_1_PARINIT;
23997c478bd9Sstevel@tonic-gate 			dyn++;
24007c478bd9Sstevel@tonic-gate 		}
24017c478bd9Sstevel@tonic-gate 
24027c478bd9Sstevel@tonic-gate 		if (ofl->ofl_oscap) {
24037c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SUNW_CAP;
24047c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = ofl->ofl_oscap->os_shdr->sh_addr;
24057c478bd9Sstevel@tonic-gate 			dyn++;
24067c478bd9Sstevel@tonic-gate 		}
24077c478bd9Sstevel@tonic-gate 
24081d9df23bSab 		if (flags & FLG_OF_SYMBOLIC) {
24091d9df23bSab 			dyn->d_tag = DT_SYMBOLIC;
24101d9df23bSab 			dyn->d_un.d_val = 0;
24111d9df23bSab 			dyn++;
24121d9df23bSab 		}
24137c478bd9Sstevel@tonic-gate 	}
24141d9df23bSab 
24157c478bd9Sstevel@tonic-gate 	dyn->d_tag = DT_FLAGS;
24167c478bd9Sstevel@tonic-gate 	dyn->d_un.d_val = ofl->ofl_dtflags;
24177c478bd9Sstevel@tonic-gate 	dyn++;
24187c478bd9Sstevel@tonic-gate 
24197c478bd9Sstevel@tonic-gate 	/*
24207c478bd9Sstevel@tonic-gate 	 * If -Bdirect was specified, but some NODIRECT symbols were specified
24217c478bd9Sstevel@tonic-gate 	 * via a mapfile, or -znodirect was used on the command line, then
24227c478bd9Sstevel@tonic-gate 	 * clear the DF_1_DIRECT flag.  The resultant object will use per-symbol
24237c478bd9Sstevel@tonic-gate 	 * direct bindings rather than be enabled for global direct bindings.
24247c478bd9Sstevel@tonic-gate 	 */
242560758829Srie 	if (ofl->ofl_flags1 & FLG_OF1_NDIRECT) {
24267c478bd9Sstevel@tonic-gate 		ofl->ofl_dtflags_1 &= ~DF_1_DIRECT;
242760758829Srie 		ofl->ofl_dtflags_1 |= DF_1_NODIRECT;
242860758829Srie 	}
24297c478bd9Sstevel@tonic-gate 
24307c478bd9Sstevel@tonic-gate 	dyn->d_tag = DT_FLAGS_1;
24317c478bd9Sstevel@tonic-gate 	dyn->d_un.d_val = ofl->ofl_dtflags_1;
24327c478bd9Sstevel@tonic-gate 	dyn++;
24337c478bd9Sstevel@tonic-gate 
24343244bcaaSab 	dyn->d_tag = DT_SUNW_STRPAD;
24353244bcaaSab 	dyn->d_un.d_val = DYNSTR_EXTRA_PAD;
24363244bcaaSab 	dyn++;
24373244bcaaSab 
2438ba2be530Sab 	dyn->d_tag = DT_SUNW_LDMACH;
2439ba2be530Sab 	dyn->d_un.d_val = ld_sunw_ldmach();
2440ba2be530Sab 	dyn++;
2441ba2be530Sab 
2442ba2be530Sab 	(*ld_targ.t_mr.mr_mach_update_odynamic)(ofl, &dyn);
24437c478bd9Sstevel@tonic-gate 
24443244bcaaSab 	for (cnt = 1 + DYNAMIC_EXTRA_ELTS; cnt--; dyn++) {
24453244bcaaSab 		dyn->d_tag = DT_NULL;
24463244bcaaSab 		dyn->d_un.d_val = 0;
24473244bcaaSab 	}
24487c478bd9Sstevel@tonic-gate 
24495b59e4caSab 	/*
24505b59e4caSab 	 * Ensure that we wrote the right number of entries. If not,
24515b59e4caSab 	 * we either miscounted in make_dynamic(), or we did something wrong
24525b59e4caSab 	 * in this function.
24535b59e4caSab 	 */
24545b59e4caSab 	assert((ofl->ofl_osdynamic->os_shdr->sh_size /
24555b59e4caSab 	    ofl->ofl_osdynamic->os_shdr->sh_entsize) ==
24563244bcaaSab 	    ((uintptr_t)dyn - (uintptr_t)_dyn) / sizeof (*dyn));
24575b59e4caSab 
24587c478bd9Sstevel@tonic-gate 	return (1);
24597c478bd9Sstevel@tonic-gate }
24607c478bd9Sstevel@tonic-gate 
24617c478bd9Sstevel@tonic-gate /*
24627c478bd9Sstevel@tonic-gate  * Build the version definition section
24637c478bd9Sstevel@tonic-gate  */
24645aefb655Srie static int
24657c478bd9Sstevel@tonic-gate update_overdef(Ofl_desc *ofl)
24667c478bd9Sstevel@tonic-gate {
24677c478bd9Sstevel@tonic-gate 	Listnode	*lnp1, *lnp2;
24687c478bd9Sstevel@tonic-gate 	Ver_desc	*vdp, *_vdp;
24697c478bd9Sstevel@tonic-gate 	Verdef		*vdf, *_vdf;
24707c478bd9Sstevel@tonic-gate 	int		num = 0;
24717c478bd9Sstevel@tonic-gate 	Os_desc		*strosp, *symosp;
24727c478bd9Sstevel@tonic-gate 
24737c478bd9Sstevel@tonic-gate 	/*
24747c478bd9Sstevel@tonic-gate 	 * Traverse the version descriptors and update the version structures
24757c478bd9Sstevel@tonic-gate 	 * to point to the dynstr name in preparation for building the version
24767c478bd9Sstevel@tonic-gate 	 * section structure.
24777c478bd9Sstevel@tonic-gate 	 */
24787c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_verdesc, lnp1, vdp)) {
24797c478bd9Sstevel@tonic-gate 		Sym_desc *	sdp;
24807c478bd9Sstevel@tonic-gate 
24817c478bd9Sstevel@tonic-gate 		if (vdp->vd_flags & VER_FLG_BASE) {
24827c478bd9Sstevel@tonic-gate 			const char	*name = vdp->vd_name;
2483cce0e03bSab 			size_t		stoff;
24847c478bd9Sstevel@tonic-gate 
24857c478bd9Sstevel@tonic-gate 			/*
24867c478bd9Sstevel@tonic-gate 			 * Create a new string table entry to represent the base
24877c478bd9Sstevel@tonic-gate 			 * version name (there is no corresponding symbol for
24887c478bd9Sstevel@tonic-gate 			 * this).
24897c478bd9Sstevel@tonic-gate 			 */
24907c478bd9Sstevel@tonic-gate 			if (!(ofl->ofl_flags & FLG_OF_DYNAMIC)) {
24917c478bd9Sstevel@tonic-gate 				(void) st_setstring(ofl->ofl_strtab,
2492d840867fSab 				    name, &stoff);
24937c478bd9Sstevel@tonic-gate 				/* LINTED */
2494cce0e03bSab 				vdp->vd_name = (const char *)stoff;
24957c478bd9Sstevel@tonic-gate 			} else {
24967c478bd9Sstevel@tonic-gate 				(void) st_setstring(ofl->ofl_dynstrtab,
2497d840867fSab 				    name, &stoff);
24987c478bd9Sstevel@tonic-gate 				/* LINTED */
2499cce0e03bSab 				vdp->vd_name = (const char *)stoff;
25007c478bd9Sstevel@tonic-gate 			}
25017c478bd9Sstevel@tonic-gate 		} else {
25025aefb655Srie 			sdp = ld_sym_find(vdp->vd_name, vdp->vd_hash, 0, ofl);
25037c478bd9Sstevel@tonic-gate 			/* LINTED */
25047c478bd9Sstevel@tonic-gate 			vdp->vd_name = (const char *)
2505d840867fSab 			    (uintptr_t)sdp->sd_sym->st_name;
25067c478bd9Sstevel@tonic-gate 		}
25077c478bd9Sstevel@tonic-gate 	}
25087c478bd9Sstevel@tonic-gate 
25097c478bd9Sstevel@tonic-gate 	_vdf = vdf = (Verdef *)ofl->ofl_osverdef->os_outdata->d_buf;
25107c478bd9Sstevel@tonic-gate 
25117c478bd9Sstevel@tonic-gate 	/*
25127c478bd9Sstevel@tonic-gate 	 * Traverse the version descriptors and update the version section to
25137c478bd9Sstevel@tonic-gate 	 * reflect each version and its associated dependencies.
25147c478bd9Sstevel@tonic-gate 	 */
25157c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_verdesc, lnp1, vdp)) {
25167c478bd9Sstevel@tonic-gate 		Half		cnt = 1;
25177c478bd9Sstevel@tonic-gate 		Verdaux *	vdap, * _vdap;
25187c478bd9Sstevel@tonic-gate 
25197c478bd9Sstevel@tonic-gate 		_vdap = vdap = (Verdaux *)(vdf + 1);
25207c478bd9Sstevel@tonic-gate 
25217c478bd9Sstevel@tonic-gate 		vdf->vd_version = VER_DEF_CURRENT;
25227c478bd9Sstevel@tonic-gate 		vdf->vd_flags	= vdp->vd_flags & MSK_VER_USER;
25237c478bd9Sstevel@tonic-gate 		vdf->vd_ndx	= vdp->vd_ndx;
25247c478bd9Sstevel@tonic-gate 		vdf->vd_hash	= vdp->vd_hash;
25257c478bd9Sstevel@tonic-gate 
25267c478bd9Sstevel@tonic-gate 		/* LINTED */
25277c478bd9Sstevel@tonic-gate 		vdap->vda_name = (uintptr_t)vdp->vd_name;
25287c478bd9Sstevel@tonic-gate 		vdap++;
25297c478bd9Sstevel@tonic-gate 		/* LINTED */
25307c478bd9Sstevel@tonic-gate 		_vdap->vda_next = (Word)((uintptr_t)vdap - (uintptr_t)_vdap);
25317c478bd9Sstevel@tonic-gate 
25327c478bd9Sstevel@tonic-gate 		/*
25337c478bd9Sstevel@tonic-gate 		 * Traverse this versions dependency list generating the
25347c478bd9Sstevel@tonic-gate 		 * appropriate version dependency entries.
25357c478bd9Sstevel@tonic-gate 		 */
25367c478bd9Sstevel@tonic-gate 		for (LIST_TRAVERSE(&vdp->vd_deps, lnp2, _vdp)) {
25377c478bd9Sstevel@tonic-gate 			/* LINTED */
25387c478bd9Sstevel@tonic-gate 			vdap->vda_name = (uintptr_t)_vdp->vd_name;
25397c478bd9Sstevel@tonic-gate 			_vdap = vdap;
25407c478bd9Sstevel@tonic-gate 			vdap++, cnt++;
25417c478bd9Sstevel@tonic-gate 			/* LINTED */
25427c478bd9Sstevel@tonic-gate 			_vdap->vda_next = (Word)((uintptr_t)vdap -
25437c478bd9Sstevel@tonic-gate 			    (uintptr_t)_vdap);
25447c478bd9Sstevel@tonic-gate 		}
25457c478bd9Sstevel@tonic-gate 		_vdap->vda_next = 0;
25467c478bd9Sstevel@tonic-gate 
25477c478bd9Sstevel@tonic-gate 		/*
25487c478bd9Sstevel@tonic-gate 		 * Record the versions auxiliary array offset and the associated
25497c478bd9Sstevel@tonic-gate 		 * dependency count.
25507c478bd9Sstevel@tonic-gate 		 */
25517c478bd9Sstevel@tonic-gate 		/* LINTED */
25527c478bd9Sstevel@tonic-gate 		vdf->vd_aux = (Word)((uintptr_t)(vdf + 1) - (uintptr_t)vdf);
25537c478bd9Sstevel@tonic-gate 		vdf->vd_cnt = cnt;
25547c478bd9Sstevel@tonic-gate 
25557c478bd9Sstevel@tonic-gate 		/*
25567c478bd9Sstevel@tonic-gate 		 * Record the next versions offset and update the version
25577c478bd9Sstevel@tonic-gate 		 * pointer.  Remember the previous version offset as the very
25587c478bd9Sstevel@tonic-gate 		 * last structures next pointer should be null.
25597c478bd9Sstevel@tonic-gate 		 */
25607c478bd9Sstevel@tonic-gate 		_vdf = vdf;
25617c478bd9Sstevel@tonic-gate 		vdf = (Verdef *)vdap, num++;
25627c478bd9Sstevel@tonic-gate 		/* LINTED */
25637c478bd9Sstevel@tonic-gate 		_vdf->vd_next = (Word)((uintptr_t)vdf - (uintptr_t)_vdf);
25647c478bd9Sstevel@tonic-gate 	}
25657c478bd9Sstevel@tonic-gate 	_vdf->vd_next = 0;
25667c478bd9Sstevel@tonic-gate 
25677c478bd9Sstevel@tonic-gate 	/*
25687c478bd9Sstevel@tonic-gate 	 * Record the string table association with the version definition
25697c478bd9Sstevel@tonic-gate 	 * section, and the symbol table associated with the version symbol
25707c478bd9Sstevel@tonic-gate 	 * table (the actual contents of the version symbol table are filled
25717c478bd9Sstevel@tonic-gate 	 * in during symbol update).
25727c478bd9Sstevel@tonic-gate 	 */
25737c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_flags & FLG_OF_RELOBJ) ||
25747c478bd9Sstevel@tonic-gate 	    (ofl->ofl_flags & FLG_OF_STATIC)) {
25757c478bd9Sstevel@tonic-gate 		strosp = ofl->ofl_osstrtab;
25767c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_ossymtab;
25777c478bd9Sstevel@tonic-gate 	} else {
25787c478bd9Sstevel@tonic-gate 		strosp = ofl->ofl_osdynstr;
25797c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_osdynsym;
25807c478bd9Sstevel@tonic-gate 	}
25817c478bd9Sstevel@tonic-gate 	/* LINTED */
25827c478bd9Sstevel@tonic-gate 	ofl->ofl_osverdef->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn);
25837c478bd9Sstevel@tonic-gate 	/* LINTED */
25847c478bd9Sstevel@tonic-gate 	ofl->ofl_osversym->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn);
25857c478bd9Sstevel@tonic-gate 
25867c478bd9Sstevel@tonic-gate 	/*
25877c478bd9Sstevel@tonic-gate 	 * The version definition sections `info' field is used to indicate the
25887c478bd9Sstevel@tonic-gate 	 * number of entries in this section.
25897c478bd9Sstevel@tonic-gate 	 */
25907c478bd9Sstevel@tonic-gate 	ofl->ofl_osverdef->os_shdr->sh_info = num;
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 	return (1);
25937c478bd9Sstevel@tonic-gate }
25947c478bd9Sstevel@tonic-gate 
25957c478bd9Sstevel@tonic-gate /*
25967c478bd9Sstevel@tonic-gate  * Build the version needed section
25977c478bd9Sstevel@tonic-gate  */
25985aefb655Srie static int
25997c478bd9Sstevel@tonic-gate update_overneed(Ofl_desc *ofl)
26007c478bd9Sstevel@tonic-gate {
26017c478bd9Sstevel@tonic-gate 	Listnode	*lnp;
26027c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
26037c478bd9Sstevel@tonic-gate 	Verneed		*vnd, *_vnd;
26047c478bd9Sstevel@tonic-gate 	Str_tbl		*dynstr;
26057c478bd9Sstevel@tonic-gate 	Word		num = 0, cnt = 0;
26067c478bd9Sstevel@tonic-gate 
26077c478bd9Sstevel@tonic-gate 	dynstr = ofl->ofl_dynstrtab;
26087c478bd9Sstevel@tonic-gate 	_vnd = vnd = (Verneed *)ofl->ofl_osverneed->os_outdata->d_buf;
26097c478bd9Sstevel@tonic-gate 
26107c478bd9Sstevel@tonic-gate 	/*
26117c478bd9Sstevel@tonic-gate 	 * Traverse the shared object list looking for dependencies that have
26127c478bd9Sstevel@tonic-gate 	 * versions defined within them.
26137c478bd9Sstevel@tonic-gate 	 */
26147c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_sos, lnp, ifl)) {
26157c478bd9Sstevel@tonic-gate 		Half		_cnt;
26167c478bd9Sstevel@tonic-gate 		Vernaux		*_vnap, *vnap;
26177c478bd9Sstevel@tonic-gate 		Sdf_desc	*sdf = ifl->ifl_sdfdesc;
2618cce0e03bSab 		size_t		stoff;
26197c478bd9Sstevel@tonic-gate 
26207c478bd9Sstevel@tonic-gate 		if (!(ifl->ifl_flags & FLG_IF_VERNEED))
26217c478bd9Sstevel@tonic-gate 			continue;
26227c478bd9Sstevel@tonic-gate 
26237c478bd9Sstevel@tonic-gate 		vnd->vn_version = VER_NEED_CURRENT;
26247c478bd9Sstevel@tonic-gate 
26257c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ifl->ifl_soname, &stoff);
26267c478bd9Sstevel@tonic-gate 		vnd->vn_file = stoff;
26277c478bd9Sstevel@tonic-gate 
26287c478bd9Sstevel@tonic-gate 		_vnap = vnap = (Vernaux *)(vnd + 1);
26297c478bd9Sstevel@tonic-gate 
26307c478bd9Sstevel@tonic-gate 		if (sdf && (sdf->sdf_flags & FLG_SDF_SPECVER)) {
263160758829Srie 			Sdv_desc	*sdv;
263260758829Srie 			Listnode	*lnp2;
26337c478bd9Sstevel@tonic-gate 
26347c478bd9Sstevel@tonic-gate 			/*
26357c478bd9Sstevel@tonic-gate 			 * If version needed definitions were specified in
26367c478bd9Sstevel@tonic-gate 			 * a mapfile ($VERSION=*) then record those
26377c478bd9Sstevel@tonic-gate 			 * definitions.
26387c478bd9Sstevel@tonic-gate 			 */
26397c478bd9Sstevel@tonic-gate 			for (LIST_TRAVERSE(&sdf->sdf_verneed, lnp2, sdv)) {
2640d840867fSab 				(void) st_setstring(dynstr, sdv->sdv_name,
2641d840867fSab 				    &stoff);
26427c478bd9Sstevel@tonic-gate 				vnap->vna_name = stoff;
26437c478bd9Sstevel@tonic-gate 				/* LINTED */
26447c478bd9Sstevel@tonic-gate 				vnap->vna_hash = (Word)elf_hash(sdv->sdv_name);
26457c478bd9Sstevel@tonic-gate 				vnap->vna_flags = 0;
26467c478bd9Sstevel@tonic-gate 				vnap->vna_other = 0;
26477c478bd9Sstevel@tonic-gate 				_vnap = vnap;
26487c478bd9Sstevel@tonic-gate 				vnap++;
26497c478bd9Sstevel@tonic-gate 				cnt++;
26507c478bd9Sstevel@tonic-gate 				/* LINTED */
26517c478bd9Sstevel@tonic-gate 				_vnap->vna_next = (Word)((uintptr_t)vnap -
26527c478bd9Sstevel@tonic-gate 				    (uintptr_t)_vnap);
26537c478bd9Sstevel@tonic-gate 			}
26547c478bd9Sstevel@tonic-gate 		} else {
26557c478bd9Sstevel@tonic-gate 
26567c478bd9Sstevel@tonic-gate 			/*
26577c478bd9Sstevel@tonic-gate 			 * Traverse the version index list recording
26587c478bd9Sstevel@tonic-gate 			 * each version as a needed dependency.
26597c478bd9Sstevel@tonic-gate 			 */
26607c478bd9Sstevel@tonic-gate 			for (cnt = _cnt = 0; _cnt <= ifl->ifl_vercnt;
26617c478bd9Sstevel@tonic-gate 			    _cnt++) {
266260758829Srie 				Ver_index	*vip = &ifl->ifl_verndx[_cnt];
26637c478bd9Sstevel@tonic-gate 
26647c478bd9Sstevel@tonic-gate 				if (vip->vi_flags & FLG_VER_REFER) {
26657c478bd9Sstevel@tonic-gate 					(void) st_setstring(dynstr,
2666d840867fSab 					    vip->vi_name, &stoff);
26677c478bd9Sstevel@tonic-gate 					vnap->vna_name = stoff;
266860758829Srie 
26697c478bd9Sstevel@tonic-gate 					if (vip->vi_desc) {
2670d840867fSab 						vnap->vna_hash =
2671d840867fSab 						    vip->vi_desc->vd_hash;
2672d840867fSab 						vnap->vna_flags =
2673d840867fSab 						    vip->vi_desc->vd_flags;
26747c478bd9Sstevel@tonic-gate 					} else {
2675d840867fSab 						vnap->vna_hash = 0;
2676d840867fSab 						vnap->vna_flags = 0;
26777c478bd9Sstevel@tonic-gate 					}
26787c478bd9Sstevel@tonic-gate 					vnap->vna_other = 0;
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 					_vnap = vnap;
26817c478bd9Sstevel@tonic-gate 					vnap++, cnt++;
26827c478bd9Sstevel@tonic-gate 					_vnap->vna_next =
2683d840867fSab 					    /* LINTED */
2684d840867fSab 					    (Word)((uintptr_t)vnap -
2685d840867fSab 					    (uintptr_t)_vnap);
26867c478bd9Sstevel@tonic-gate 				}
26877c478bd9Sstevel@tonic-gate 			}
26887c478bd9Sstevel@tonic-gate 		}
26897c478bd9Sstevel@tonic-gate 		_vnap->vna_next = 0;
26907c478bd9Sstevel@tonic-gate 
26917c478bd9Sstevel@tonic-gate 		/*
26927c478bd9Sstevel@tonic-gate 		 * Record the versions auxiliary array offset and
26937c478bd9Sstevel@tonic-gate 		 * the associated dependency count.
26947c478bd9Sstevel@tonic-gate 		 */
26957c478bd9Sstevel@tonic-gate 		/* LINTED */
26967c478bd9Sstevel@tonic-gate 		vnd->vn_aux = (Word)((uintptr_t)(vnd + 1) - (uintptr_t)vnd);
26977c478bd9Sstevel@tonic-gate 		/* LINTED */
26987c478bd9Sstevel@tonic-gate 		vnd->vn_cnt = (Half)cnt;
26997c478bd9Sstevel@tonic-gate 
27007c478bd9Sstevel@tonic-gate 		/*
27017c478bd9Sstevel@tonic-gate 		 * Record the next versions offset and update the version
27027c478bd9Sstevel@tonic-gate 		 * pointer.  Remember the previous version offset as the very
27037c478bd9Sstevel@tonic-gate 		 * last structures next pointer should be null.
27047c478bd9Sstevel@tonic-gate 		 */
27057c478bd9Sstevel@tonic-gate 		_vnd = vnd;
27067c478bd9Sstevel@tonic-gate 		vnd = (Verneed *)vnap, num++;
27077c478bd9Sstevel@tonic-gate 		/* LINTED */
27087c478bd9Sstevel@tonic-gate 		_vnd->vn_next = (Word)((uintptr_t)vnd - (uintptr_t)_vnd);
27097c478bd9Sstevel@tonic-gate 	}
27107c478bd9Sstevel@tonic-gate 	_vnd->vn_next = 0;
27117c478bd9Sstevel@tonic-gate 
27127c478bd9Sstevel@tonic-gate 	/*
27137c478bd9Sstevel@tonic-gate 	 * Record association on string table section and use the
27147c478bd9Sstevel@tonic-gate 	 * `info' field to indicate the number of entries in this
27157c478bd9Sstevel@tonic-gate 	 * section.
27167c478bd9Sstevel@tonic-gate 	 */
27177c478bd9Sstevel@tonic-gate 	ofl->ofl_osverneed->os_shdr->sh_link =
27187c478bd9Sstevel@tonic-gate 	    /* LINTED */
27197c478bd9Sstevel@tonic-gate 	    (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
27207c478bd9Sstevel@tonic-gate 	ofl->ofl_osverneed->os_shdr->sh_info = num;
27217c478bd9Sstevel@tonic-gate 
27227c478bd9Sstevel@tonic-gate 	return (1);
27237c478bd9Sstevel@tonic-gate }
27247c478bd9Sstevel@tonic-gate 
27257c478bd9Sstevel@tonic-gate 
27267c478bd9Sstevel@tonic-gate /*
27277c478bd9Sstevel@tonic-gate  * Update syminfo section.
27287c478bd9Sstevel@tonic-gate  */
27295aefb655Srie static uintptr_t
27307c478bd9Sstevel@tonic-gate update_osyminfo(Ofl_desc * ofl)
27317c478bd9Sstevel@tonic-gate {
27327c478bd9Sstevel@tonic-gate 	Os_desc *	symosp, * infosp = ofl->ofl_ossyminfo;
27337c478bd9Sstevel@tonic-gate 	Syminfo *	sip = infosp->os_outdata->d_buf;
27347c478bd9Sstevel@tonic-gate 	Shdr *		shdr = infosp->os_shdr;
27357c478bd9Sstevel@tonic-gate 	char		*strtab;
27367c478bd9Sstevel@tonic-gate 	Listnode *	lnp;
27377c478bd9Sstevel@tonic-gate 	Sym_desc *	sdp;
2738cce0e03bSab 	Aliste		idx;
27397c478bd9Sstevel@tonic-gate 	Sfltr_desc *	sftp;
27407c478bd9Sstevel@tonic-gate 
27417c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_RELOBJ) {
27427c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_ossymtab;
27437c478bd9Sstevel@tonic-gate 		strtab = ofl->ofl_osstrtab->os_outdata->d_buf;
27447c478bd9Sstevel@tonic-gate 	} else {
27457c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_osdynsym;
27467c478bd9Sstevel@tonic-gate 		strtab = ofl->ofl_osdynstr->os_outdata->d_buf;
27477c478bd9Sstevel@tonic-gate 	}
27487c478bd9Sstevel@tonic-gate 
27497c478bd9Sstevel@tonic-gate 	/* LINTED */
27507c478bd9Sstevel@tonic-gate 	infosp->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn);
27517c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osdynamic)
27527c478bd9Sstevel@tonic-gate 		infosp->os_shdr->sh_info =
27537c478bd9Sstevel@tonic-gate 		    /* LINTED */
27547c478bd9Sstevel@tonic-gate 		    (Word)elf_ndxscn(ofl->ofl_osdynamic->os_scn);
27557c478bd9Sstevel@tonic-gate 
27567c478bd9Sstevel@tonic-gate 	/*
27577c478bd9Sstevel@tonic-gate 	 * Update any references with the index into the dynamic table.
27587c478bd9Sstevel@tonic-gate 	 */
27597c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_syminfsyms, lnp, sdp)) {
27607c478bd9Sstevel@tonic-gate 		Ifl_desc *	ifl;
27617c478bd9Sstevel@tonic-gate 		if (sdp->sd_aux && sdp->sd_aux->sa_bindto)
27627c478bd9Sstevel@tonic-gate 			ifl = sdp->sd_aux->sa_bindto;
27637c478bd9Sstevel@tonic-gate 		else
27647c478bd9Sstevel@tonic-gate 			ifl = sdp->sd_file;
27657c478bd9Sstevel@tonic-gate 		sip[sdp->sd_symndx].si_boundto = ifl->ifl_neededndx;
27667c478bd9Sstevel@tonic-gate 	}
27677c478bd9Sstevel@tonic-gate 
27687c478bd9Sstevel@tonic-gate 	/*
27697c478bd9Sstevel@tonic-gate 	 * Update any filtee references with the index into the dynamic table.
27707c478bd9Sstevel@tonic-gate 	 */
2771cce0e03bSab 	for (ALIST_TRAVERSE(ofl->ofl_symfltrs, idx, sftp)) {
2772cce0e03bSab 		Dfltr_desc	*dftp;
27737c478bd9Sstevel@tonic-gate 
2774cce0e03bSab 		dftp = alist_item(ofl->ofl_dtsfltrs, sftp->sft_idx);
27757c478bd9Sstevel@tonic-gate 		sip[sftp->sft_sdp->sd_symndx].si_boundto = dftp->dft_ndx;
27767c478bd9Sstevel@tonic-gate 	}
27777c478bd9Sstevel@tonic-gate 
27787c478bd9Sstevel@tonic-gate 	/*
27797c478bd9Sstevel@tonic-gate 	 * Display debugging information about section.
27807c478bd9Sstevel@tonic-gate 	 */
27815aefb655Srie 	DBG_CALL(Dbg_syminfo_title(ofl->ofl_lml));
27825aefb655Srie 	if (DBG_ENABLED) {
27835aefb655Srie 		Word	_cnt, cnt = shdr->sh_size / shdr->sh_entsize;
27847c478bd9Sstevel@tonic-gate 		Sym *	symtab = symosp->os_outdata->d_buf;
27857c478bd9Sstevel@tonic-gate 		Dyn *	dyn;
27867c478bd9Sstevel@tonic-gate 
27877c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynamic)
27887c478bd9Sstevel@tonic-gate 			dyn = ofl->ofl_osdynamic->os_outdata->d_buf;
27897c478bd9Sstevel@tonic-gate 		else
27907c478bd9Sstevel@tonic-gate 			dyn = 0;
27917c478bd9Sstevel@tonic-gate 
27927c478bd9Sstevel@tonic-gate 		for (_cnt = 1; _cnt < cnt; _cnt++) {
27937c478bd9Sstevel@tonic-gate 			if (sip[_cnt].si_flags || sip[_cnt].si_boundto)
27947c478bd9Sstevel@tonic-gate 				/* LINTED */
27955aefb655Srie 				DBG_CALL(Dbg_syminfo_entry(ofl->ofl_lml, _cnt,
27967c478bd9Sstevel@tonic-gate 				    &sip[_cnt], &symtab[_cnt], strtab, dyn));
27977c478bd9Sstevel@tonic-gate 		}
27987c478bd9Sstevel@tonic-gate 	}
27997c478bd9Sstevel@tonic-gate 	return (1);
28007c478bd9Sstevel@tonic-gate }
28017c478bd9Sstevel@tonic-gate 
28027c478bd9Sstevel@tonic-gate /*
28037c478bd9Sstevel@tonic-gate  * Build the output elf header.
28047c478bd9Sstevel@tonic-gate  */
28055aefb655Srie static uintptr_t
28067c478bd9Sstevel@tonic-gate update_oehdr(Ofl_desc * ofl)
28077c478bd9Sstevel@tonic-gate {
28085aefb655Srie 	Ehdr	*ehdr = ofl->ofl_nehdr;
28097c478bd9Sstevel@tonic-gate 
28107c478bd9Sstevel@tonic-gate 	/*
28117c478bd9Sstevel@tonic-gate 	 * If an entry point symbol has already been established (refer
28127c478bd9Sstevel@tonic-gate 	 * sym_validate()) simply update the elf header entry point with the
28137c478bd9Sstevel@tonic-gate 	 * symbols value.  If no entry point is defined it will have been filled
28147c478bd9Sstevel@tonic-gate 	 * with the start address of the first section within the text segment
28157c478bd9Sstevel@tonic-gate 	 * (refer update_outfile()).
28167c478bd9Sstevel@tonic-gate 	 */
28177c478bd9Sstevel@tonic-gate 	if (ofl->ofl_entry)
28187c478bd9Sstevel@tonic-gate 		ehdr->e_entry =
2819d840867fSab 		    ((Sym_desc *)(ofl->ofl_entry))->sd_sym->st_value;
28207c478bd9Sstevel@tonic-gate 
28217c478bd9Sstevel@tonic-gate 	/*
28227c478bd9Sstevel@tonic-gate 	 * Note. it may be necessary to update the `e_flags' field in the
28237c478bd9Sstevel@tonic-gate 	 * machine dependent section.
28247c478bd9Sstevel@tonic-gate 	 */
2825ba2be530Sab 	ehdr->e_ident[EI_DATA] = ld_targ.t_m.m_data;
28265aefb655Srie 	ehdr->e_machine = ofl->ofl_dehdr->e_machine;
28275aefb655Srie 	ehdr->e_flags = ofl->ofl_dehdr->e_flags;
28285aefb655Srie 	ehdr->e_version = ofl->ofl_dehdr->e_version;
28295aefb655Srie 
2830ba2be530Sab 	if (ehdr->e_machine != ld_targ.t_m.m_mach) {
2831ba2be530Sab 		if (ehdr->e_machine != ld_targ.t_m.m_machplus)
28327c478bd9Sstevel@tonic-gate 			return (S_ERROR);
2833ba2be530Sab 		if ((ehdr->e_flags & ld_targ.t_m.m_flagsplus) == 0)
28347c478bd9Sstevel@tonic-gate 			return (S_ERROR);
28357c478bd9Sstevel@tonic-gate 	}
28367c478bd9Sstevel@tonic-gate 
28377c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_SHAROBJ)
28387c478bd9Sstevel@tonic-gate 		ehdr->e_type = ET_DYN;
28397c478bd9Sstevel@tonic-gate 	else if (ofl->ofl_flags & FLG_OF_RELOBJ)
28407c478bd9Sstevel@tonic-gate 		ehdr->e_type = ET_REL;
28417c478bd9Sstevel@tonic-gate 	else
28427c478bd9Sstevel@tonic-gate 		ehdr->e_type = ET_EXEC;
28437c478bd9Sstevel@tonic-gate 
28447c478bd9Sstevel@tonic-gate 	return (1);
28457c478bd9Sstevel@tonic-gate }
28467c478bd9Sstevel@tonic-gate 
28477c478bd9Sstevel@tonic-gate /*
28487c478bd9Sstevel@tonic-gate  * Perform move table expansion.
28497c478bd9Sstevel@tonic-gate  */
28507c478bd9Sstevel@tonic-gate static uintptr_t
28517c478bd9Sstevel@tonic-gate expand_move(Ofl_desc *ofl, Sym_desc *sdp, Move *u1)
28527c478bd9Sstevel@tonic-gate {
28537c478bd9Sstevel@tonic-gate 	Move		*mv;
28547c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
28557c478bd9Sstevel@tonic-gate 	unsigned char	*taddr, *taddr0;
28567c478bd9Sstevel@tonic-gate 	Sxword		offset;
28577c478bd9Sstevel@tonic-gate 	int		i;
28587c478bd9Sstevel@tonic-gate 	Addr		base1;
28597c478bd9Sstevel@tonic-gate 	unsigned int	stride;
28607c478bd9Sstevel@tonic-gate 
28617c478bd9Sstevel@tonic-gate 	osp = ofl->ofl_issunwdata1->is_osdesc;
28627c478bd9Sstevel@tonic-gate 	base1 = (Addr)(osp->os_shdr->sh_addr +
2863d840867fSab 	    ofl->ofl_issunwdata1->is_indata->d_off);
28647c478bd9Sstevel@tonic-gate 	taddr0 = taddr = osp->os_outdata->d_buf;
28657c478bd9Sstevel@tonic-gate 	mv = u1;
28667c478bd9Sstevel@tonic-gate 
28677c478bd9Sstevel@tonic-gate 	offset = sdp->sd_sym->st_value - base1;
28687c478bd9Sstevel@tonic-gate 	taddr += offset;
28697c478bd9Sstevel@tonic-gate 	taddr = taddr + mv->m_poffset;
28707c478bd9Sstevel@tonic-gate 	for (i = 0; i < mv->m_repeat; i++) {
28717c478bd9Sstevel@tonic-gate 		/* LINTED */
28725aefb655Srie 		DBG_CALL(Dbg_move_expand(ofl->ofl_lml, mv,
28735aefb655Srie 		    (Addr)(taddr - taddr0)));
28747c478bd9Sstevel@tonic-gate 		stride = (unsigned int)mv->m_stride + 1;
28757c478bd9Sstevel@tonic-gate 		/* LINTED */
28767c478bd9Sstevel@tonic-gate 		switch (ELF_M_SIZE(mv->m_info)) {
28777c478bd9Sstevel@tonic-gate 		case 1:
28787c478bd9Sstevel@tonic-gate 			/* LINTED */
28797c478bd9Sstevel@tonic-gate 			*taddr = (unsigned char)mv->m_value;
28807c478bd9Sstevel@tonic-gate 			taddr += stride;
28817c478bd9Sstevel@tonic-gate 			break;
28827c478bd9Sstevel@tonic-gate 		case 2:
28837c478bd9Sstevel@tonic-gate 			/* LINTED */
28847c478bd9Sstevel@tonic-gate 			*((Half *)taddr) = (Half)mv->m_value;
28857c478bd9Sstevel@tonic-gate 			taddr += 2*stride;
28867c478bd9Sstevel@tonic-gate 			break;
28877c478bd9Sstevel@tonic-gate 		case 4:
28887c478bd9Sstevel@tonic-gate 			/* LINTED */
28897c478bd9Sstevel@tonic-gate 			*((Word *)taddr) = (Word)mv->m_value;
28907c478bd9Sstevel@tonic-gate 			taddr += 4*stride;
28917c478bd9Sstevel@tonic-gate 			break;
28927c478bd9Sstevel@tonic-gate 		case 8:
28937c478bd9Sstevel@tonic-gate 			/* LINTED */
2894d840867fSab 			*((unsigned long long *)taddr) = mv->m_value;
28957c478bd9Sstevel@tonic-gate 			taddr += 8*stride;
28967c478bd9Sstevel@tonic-gate 			break;
28977c478bd9Sstevel@tonic-gate 		default:
28987c478bd9Sstevel@tonic-gate 			/*
28997c478bd9Sstevel@tonic-gate 			 * Should never come here since this is already
29007c478bd9Sstevel@tonic-gate 			 * checked at sunwmove_preprocess().
29017c478bd9Sstevel@tonic-gate 			 */
29027c478bd9Sstevel@tonic-gate 			return (S_ERROR);
29037c478bd9Sstevel@tonic-gate 		}
29047c478bd9Sstevel@tonic-gate 	}
29057c478bd9Sstevel@tonic-gate 	return (1);
29067c478bd9Sstevel@tonic-gate }
29077c478bd9Sstevel@tonic-gate 
29087c478bd9Sstevel@tonic-gate /*
29097c478bd9Sstevel@tonic-gate  * Update Move sections.
29107c478bd9Sstevel@tonic-gate  */
29115aefb655Srie static uintptr_t
29127c478bd9Sstevel@tonic-gate update_move(Ofl_desc *ofl)
29137c478bd9Sstevel@tonic-gate {
29147c478bd9Sstevel@tonic-gate 	Word		ndx = 0;
29157c478bd9Sstevel@tonic-gate 	Is_desc *	isp;
29161d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
29177c478bd9Sstevel@tonic-gate 	Move *		mv1, * mv2;
29187c478bd9Sstevel@tonic-gate 	Listnode *	lnp1;
29197c478bd9Sstevel@tonic-gate 	Psym_info *	psym;
29207c478bd9Sstevel@tonic-gate 
29217c478bd9Sstevel@tonic-gate 	/*
29227c478bd9Sstevel@tonic-gate 	 * Determine the index of the symbol table that will be referenced by
29237c478bd9Sstevel@tonic-gate 	 * the relocation entries.
29247c478bd9Sstevel@tonic-gate 	 */
29259039eeafSab 	if (OFL_ALLOW_DYNSYM(ofl))
29267c478bd9Sstevel@tonic-gate 		/* LINTED */
29277c478bd9Sstevel@tonic-gate 		ndx = (Word) elf_ndxscn(ofl->ofl_osdynsym->os_scn);
29287c478bd9Sstevel@tonic-gate 	else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ))
29297c478bd9Sstevel@tonic-gate 		/* LINTED */
29307c478bd9Sstevel@tonic-gate 		ndx = (Word) elf_ndxscn(ofl->ofl_ossymtab->os_scn);
29317c478bd9Sstevel@tonic-gate 
29327c478bd9Sstevel@tonic-gate 	/*
29337c478bd9Sstevel@tonic-gate 	 * update sh_link and mv pointer for updating move table.
29347c478bd9Sstevel@tonic-gate 	 */
29357c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osmove) {
29367c478bd9Sstevel@tonic-gate 		ofl->ofl_osmove->os_shdr->sh_link = ndx;
29377c478bd9Sstevel@tonic-gate 		mv1 = (Move *) ofl->ofl_osmove->os_outdata->d_buf;
29387c478bd9Sstevel@tonic-gate 	}
29397c478bd9Sstevel@tonic-gate 
29407c478bd9Sstevel@tonic-gate 	/*
29417c478bd9Sstevel@tonic-gate 	 * Update symbol entry index
29427c478bd9Sstevel@tonic-gate 	 */
29437c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_parsym, lnp1, psym)) {
29447c478bd9Sstevel@tonic-gate 		Listnode *	lnp2;
29457c478bd9Sstevel@tonic-gate 		Mv_itm *	mvp;
29467c478bd9Sstevel@tonic-gate 		Sym_desc 	*sdp;
29477c478bd9Sstevel@tonic-gate 
29487c478bd9Sstevel@tonic-gate 		/*
29497c478bd9Sstevel@tonic-gate 		 * Expand move table
29507c478bd9Sstevel@tonic-gate 		 */
29517c478bd9Sstevel@tonic-gate 		if (psym->psym_symd->sd_flags & FLG_SY_PAREXPN) {
29527c478bd9Sstevel@tonic-gate 			const char	*s;
29537c478bd9Sstevel@tonic-gate 
29541d9df23bSab 			if (flags & FLG_OF_STATIC)
29557c478bd9Sstevel@tonic-gate 				s = MSG_INTL(MSG_PSYM_EXPREASON1);
29567c478bd9Sstevel@tonic-gate 			else if (ofl->ofl_flags1 & FLG_OF1_NOPARTI)
29577c478bd9Sstevel@tonic-gate 				s = MSG_INTL(MSG_PSYM_EXPREASON2);
29587c478bd9Sstevel@tonic-gate 			else
29597c478bd9Sstevel@tonic-gate 				s = MSG_INTL(MSG_PSYM_EXPREASON3);
29605aefb655Srie 			DBG_CALL(Dbg_move_parexpn(ofl->ofl_lml,
29615aefb655Srie 			    psym->psym_symd->sd_name, s));
29627c478bd9Sstevel@tonic-gate 			for (LIST_TRAVERSE(&(psym->psym_mvs), lnp2, mvp)) {
29637c478bd9Sstevel@tonic-gate 				if ((mvp->mv_flag & FLG_MV_OUTSECT) == 0)
29647c478bd9Sstevel@tonic-gate 					continue;
29657c478bd9Sstevel@tonic-gate 				mv2 = mvp->mv_ientry;
29667c478bd9Sstevel@tonic-gate 				sdp = psym->psym_symd;
29675aefb655Srie 				DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0,
29685aefb655Srie 				    mv2, sdp));
29697c478bd9Sstevel@tonic-gate 				(void) expand_move(ofl, sdp, mv2);
29707c478bd9Sstevel@tonic-gate 			}
29717c478bd9Sstevel@tonic-gate 			continue;
29727c478bd9Sstevel@tonic-gate 		}
29737c478bd9Sstevel@tonic-gate 
29747c478bd9Sstevel@tonic-gate 		/*
29757c478bd9Sstevel@tonic-gate 		 * Process move table
29767c478bd9Sstevel@tonic-gate 		 */
29775aefb655Srie 		DBG_CALL(Dbg_move_outmove(ofl->ofl_lml,
29785aefb655Srie 		    psym->psym_symd->sd_name));
29797c478bd9Sstevel@tonic-gate 		for (LIST_TRAVERSE(&(psym->psym_mvs), lnp2, mvp)) {
29807c478bd9Sstevel@tonic-gate 			int	idx = 1;
298160758829Srie 			Sym	*sym;
298260758829Srie 
29837c478bd9Sstevel@tonic-gate 			if ((mvp->mv_flag & FLG_MV_OUTSECT) == 0)
29847c478bd9Sstevel@tonic-gate 				continue;
298560758829Srie 
29867c478bd9Sstevel@tonic-gate 			isp = mvp->mv_isp;
29877c478bd9Sstevel@tonic-gate 			mv2 = mvp->mv_ientry;
2988d840867fSab 			sdp = isp->is_file->ifl_oldndx[ELF_M_SYM(mv2->m_info)];
298960758829Srie 			sym = sdp->sd_sym;
29907c478bd9Sstevel@tonic-gate 
29915aefb655Srie 			DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0, mv2, sdp));
299260758829Srie 
29937c478bd9Sstevel@tonic-gate 			*mv1 = *mv2;
29941d9df23bSab 			if ((flags & FLG_OF_RELOBJ) == 0) {
299560758829Srie 				if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
299660758829Srie 					Half	symbssndx = ofl->ofl_isbss->
2997d840867fSab 					    is_osdesc->os_scnsymndx;
299860758829Srie 
2999d840867fSab 					mv1->m_info =
3000d840867fSab 					    /* LINTED */
3001d840867fSab 					    ELF_M_INFO(symbssndx, mv2->m_info);
300260758829Srie 
300360758829Srie 					if (ELF_ST_TYPE(sym->st_info) !=
3004d840867fSab 					    STT_SECTION) {
300560758829Srie 						mv1->m_poffset = sym->st_value -
300660758829Srie 						    ofl->ofl_isbss->is_osdesc->
300760758829Srie 						    os_shdr->sh_addr +
300860758829Srie 						    mv2->m_poffset;
3009d840867fSab 					}
30107c478bd9Sstevel@tonic-gate 				} else {
3011d840867fSab 					mv1->m_info =
3012d840867fSab 					    /* LINTED */
3013d840867fSab 					    ELF_M_INFO(sdp->sd_symndx,
3014d840867fSab 					    mv2->m_info);
30157c478bd9Sstevel@tonic-gate 				}
30167c478bd9Sstevel@tonic-gate 			} else {
30177c478bd9Sstevel@tonic-gate 				Boolean 	isredloc = FALSE;
30187c478bd9Sstevel@tonic-gate 
301960758829Srie 				if ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) &&
3020*44bac77bSrie 				    (ofl->ofl_flags & FLG_OF_REDLSYM))
30217c478bd9Sstevel@tonic-gate 					isredloc = TRUE;
30227c478bd9Sstevel@tonic-gate 
30237c478bd9Sstevel@tonic-gate 				if (isredloc && !(sdp->sd_psyminfo)) {
302460758829Srie 					Word	symndx = sdp->sd_isc->
302560758829Srie 					    is_osdesc->os_scnsymndx;
302660758829Srie 
30277c478bd9Sstevel@tonic-gate 					mv1->m_info =
3028d840867fSab 					    /* LINTED */
3029d840867fSab 					    ELF_M_INFO(symndx, mv2->m_info);
303060758829Srie 					mv1->m_poffset += sym->st_value;
30317c478bd9Sstevel@tonic-gate 				} else {
30327c478bd9Sstevel@tonic-gate 					if (isredloc)
3033d840867fSab 						DBG_CALL(Dbg_syms_reduce(ofl,
3034d840867fSab 						    DBG_SYM_REDUCE_RETAIN, sdp,
3035d840867fSab 						    idx,
3036d840867fSab 						    ofl->ofl_osmove->os_name));
30377c478bd9Sstevel@tonic-gate 
30387c478bd9Sstevel@tonic-gate 					mv1->m_info =
3039d840867fSab 					    /* LINTED */
3040d840867fSab 					    ELF_M_INFO(sdp->sd_symndx,
3041d840867fSab 					    mv2->m_info);
30427c478bd9Sstevel@tonic-gate 				}
30437c478bd9Sstevel@tonic-gate 			}
30445aefb655Srie 			DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 1, mv1, sdp));
30457c478bd9Sstevel@tonic-gate 			mv1++;
30467c478bd9Sstevel@tonic-gate 			idx++;
30477c478bd9Sstevel@tonic-gate 		}
30487c478bd9Sstevel@tonic-gate 	}
30497c478bd9Sstevel@tonic-gate 	return (1);
30507c478bd9Sstevel@tonic-gate }
30517c478bd9Sstevel@tonic-gate 
30527c478bd9Sstevel@tonic-gate 
30537c478bd9Sstevel@tonic-gate /*
30547c478bd9Sstevel@tonic-gate  * Scan through the SHT_GROUP output sections.  Update their
30557c478bd9Sstevel@tonic-gate  * sh_link/sh_info fields as well as the section contents.
30567c478bd9Sstevel@tonic-gate  */
30575aefb655Srie static uintptr_t
30587c478bd9Sstevel@tonic-gate update_ogroup(Ofl_desc * ofl)
30597c478bd9Sstevel@tonic-gate {
30607c478bd9Sstevel@tonic-gate 	Listnode	*lnp;
30617c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
30627c478bd9Sstevel@tonic-gate 	uintptr_t	error = 0;
30637c478bd9Sstevel@tonic-gate 
30647c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_osgroups, lnp, osp)) {
30657c478bd9Sstevel@tonic-gate 		Is_desc		*isp;
30667c478bd9Sstevel@tonic-gate 		Ifl_desc	*ifl;
30677c478bd9Sstevel@tonic-gate 		Shdr		*shdr = osp->os_shdr;
30687c478bd9Sstevel@tonic-gate 		Sym_desc	*sdp;
30697c478bd9Sstevel@tonic-gate 		Xword		i, grpcnt;
30707c478bd9Sstevel@tonic-gate 		Word		*gdata;
30717c478bd9Sstevel@tonic-gate 
30727c478bd9Sstevel@tonic-gate 		/*
30737c478bd9Sstevel@tonic-gate 		 * Since input GROUP sections always create unique
30747c478bd9Sstevel@tonic-gate 		 * output GROUP sections - we know there is only one
30757c478bd9Sstevel@tonic-gate 		 * item on the list.
30767c478bd9Sstevel@tonic-gate 		 */
30777c478bd9Sstevel@tonic-gate 		isp = (Is_desc *)osp->os_isdescs.head->data;
30787c478bd9Sstevel@tonic-gate 
30797c478bd9Sstevel@tonic-gate 		ifl = isp->is_file;
30807c478bd9Sstevel@tonic-gate 		sdp = ifl->ifl_oldndx[isp->is_shdr->sh_info];
30817c478bd9Sstevel@tonic-gate 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn);
30827c478bd9Sstevel@tonic-gate 		shdr->sh_info = sdp->sd_symndx;
30837c478bd9Sstevel@tonic-gate 
30847c478bd9Sstevel@tonic-gate 		/*
30857c478bd9Sstevel@tonic-gate 		 * Scan through the group data section and update
30867c478bd9Sstevel@tonic-gate 		 * all of the links to new values.
30877c478bd9Sstevel@tonic-gate 		 */
30887c478bd9Sstevel@tonic-gate 		grpcnt = shdr->sh_size / shdr->sh_entsize;
30897c478bd9Sstevel@tonic-gate 		gdata = (Word *)osp->os_outdata->d_buf;
30907c478bd9Sstevel@tonic-gate 		for (i = 1; i < grpcnt; i++) {
30917c478bd9Sstevel@tonic-gate 			Is_desc	*	_isp;
30927c478bd9Sstevel@tonic-gate 			Os_desc	*	_osp;
30937c478bd9Sstevel@tonic-gate 
30947c478bd9Sstevel@tonic-gate 			/*
30957c478bd9Sstevel@tonic-gate 			 * Perform a sanity check that the section index
30967c478bd9Sstevel@tonic-gate 			 * stored in the SHT_GROUP section is valid
30977c478bd9Sstevel@tonic-gate 			 * for the file it came from.
30987c478bd9Sstevel@tonic-gate 			 */
30997c478bd9Sstevel@tonic-gate 			if (gdata[i] >= ifl->ifl_shnum) {
31005aefb655Srie 				eprintf(ofl->ofl_lml, ERR_FATAL,
31015aefb655Srie 				    MSG_INTL(MSG_GRP_INVALNDX), isp->is_name,
31025aefb655Srie 				    ifl->ifl_name, i, gdata[i]);
31037c478bd9Sstevel@tonic-gate 				error = S_ERROR;
31047c478bd9Sstevel@tonic-gate 				gdata[i] = 0;
31057c478bd9Sstevel@tonic-gate 				continue;
31067c478bd9Sstevel@tonic-gate 			}
31077c478bd9Sstevel@tonic-gate 
31087c478bd9Sstevel@tonic-gate 			_isp = ifl->ifl_isdesc[gdata[i]];
31097c478bd9Sstevel@tonic-gate 
31107c478bd9Sstevel@tonic-gate 			/*
31117c478bd9Sstevel@tonic-gate 			 * If the referenced section didn't make it to the
31127c478bd9Sstevel@tonic-gate 			 * output file - just zero out the entry.
31137c478bd9Sstevel@tonic-gate 			 */
31147c478bd9Sstevel@tonic-gate 			if ((_osp = _isp->is_osdesc) == 0)
31157c478bd9Sstevel@tonic-gate 				gdata[i] = 0;
31167c478bd9Sstevel@tonic-gate 			else
31177c478bd9Sstevel@tonic-gate 				gdata[i] = (Word)elf_ndxscn(_osp->os_scn);
31187c478bd9Sstevel@tonic-gate 		}
31197c478bd9Sstevel@tonic-gate 	}
31207c478bd9Sstevel@tonic-gate 	return (error);
31217c478bd9Sstevel@tonic-gate }
31227c478bd9Sstevel@tonic-gate 
31235aefb655Srie static void
31243244bcaaSab update_ostrtab(Os_desc *osp, Str_tbl *stp, uint_t extra)
31257c478bd9Sstevel@tonic-gate {
31267c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
31273244bcaaSab 
31287c478bd9Sstevel@tonic-gate 	if (osp == 0)
31297c478bd9Sstevel@tonic-gate 		return;
31307c478bd9Sstevel@tonic-gate 
31317c478bd9Sstevel@tonic-gate 	data = osp->os_outdata;
31323244bcaaSab 	assert(data->d_size == (st_getstrtab_sz(stp) + extra));
3133cce0e03bSab 	(void) st_setstrbuf(stp, data->d_buf, data->d_size - extra);
31343244bcaaSab 	/* If leaving an extra hole at the end, zero it */
31353244bcaaSab 	if (extra > 0)
31363244bcaaSab 		(void) memset((char *)data->d_buf + data->d_size - extra,
31373244bcaaSab 		    0x0, extra);
31387c478bd9Sstevel@tonic-gate }
31397c478bd9Sstevel@tonic-gate 
31407c478bd9Sstevel@tonic-gate /*
31417c478bd9Sstevel@tonic-gate  * Translate the shdr->sh_{link, info} from its input section value to that
31427c478bd9Sstevel@tonic-gate  * of the corresponding shdr->sh_{link, info} output section value.
31437c478bd9Sstevel@tonic-gate  */
31445aefb655Srie static Word
31455aefb655Srie translate_link(Ofl_desc *ofl, Os_desc *osp, Word link, const char *msg)
31467c478bd9Sstevel@tonic-gate {
31477c478bd9Sstevel@tonic-gate 	Is_desc *	isp;
31487c478bd9Sstevel@tonic-gate 	Ifl_desc *	ifl;
31497c478bd9Sstevel@tonic-gate 
31507c478bd9Sstevel@tonic-gate 	/*
31517c478bd9Sstevel@tonic-gate 	 * Don't translate the special section numbers.
31527c478bd9Sstevel@tonic-gate 	 */
31537c478bd9Sstevel@tonic-gate 	if (link >= SHN_LORESERVE)
31547c478bd9Sstevel@tonic-gate 		return (link);
31557c478bd9Sstevel@tonic-gate 
31567c478bd9Sstevel@tonic-gate 	/*
31577c478bd9Sstevel@tonic-gate 	 * Does this output section translate back to an input file.  If not
31587c478bd9Sstevel@tonic-gate 	 * then there is no translation to do.  In this case we will assume that
31597c478bd9Sstevel@tonic-gate 	 * if sh_link has a value, it's the right value.
31607c478bd9Sstevel@tonic-gate 	 */
31617c478bd9Sstevel@tonic-gate 	isp = (Is_desc *)osp->os_isdescs.head->data;
31627c478bd9Sstevel@tonic-gate 	if ((ifl = isp->is_file) == NULL)
31637c478bd9Sstevel@tonic-gate 		return (link);
31647c478bd9Sstevel@tonic-gate 
31657c478bd9Sstevel@tonic-gate 	/*
31667c478bd9Sstevel@tonic-gate 	 * Sanity check to make sure that the sh_{link, info} value
31677c478bd9Sstevel@tonic-gate 	 * is within range for the input file.
31687c478bd9Sstevel@tonic-gate 	 */
31697c478bd9Sstevel@tonic-gate 	if (link >= ifl->ifl_shnum) {
31705aefb655Srie 		eprintf(ofl->ofl_lml, ERR_WARNING, msg, ifl->ifl_name,
31717c478bd9Sstevel@tonic-gate 		    isp->is_name, EC_XWORD(link));
31727c478bd9Sstevel@tonic-gate 		return (link);
31737c478bd9Sstevel@tonic-gate 	}
31747c478bd9Sstevel@tonic-gate 
31757c478bd9Sstevel@tonic-gate 	/*
31767c478bd9Sstevel@tonic-gate 	 * Follow the link to the input section.
31777c478bd9Sstevel@tonic-gate 	 */
31787c478bd9Sstevel@tonic-gate 	if ((isp = ifl->ifl_isdesc[link]) == 0)
31797c478bd9Sstevel@tonic-gate 		return (0);
31807c478bd9Sstevel@tonic-gate 	if ((osp = isp->is_osdesc) == 0)
31817c478bd9Sstevel@tonic-gate 		return (0);
31827c478bd9Sstevel@tonic-gate 
31837c478bd9Sstevel@tonic-gate 	/* LINTED */
31847c478bd9Sstevel@tonic-gate 	return ((Word)elf_ndxscn(osp->os_scn));
31857c478bd9Sstevel@tonic-gate }
31867c478bd9Sstevel@tonic-gate 
31877c478bd9Sstevel@tonic-gate /*
31887c478bd9Sstevel@tonic-gate  * Having created all of the necessary sections, segments, and associated
31897c478bd9Sstevel@tonic-gate  * headers, fill in the program headers and update any other data in the
31907c478bd9Sstevel@tonic-gate  * output image.  Some general rules:
31917c478bd9Sstevel@tonic-gate  *
319270d3e49eSrie  *  o	If an interpreter is required always generate a PT_PHDR entry as
31937c478bd9Sstevel@tonic-gate  *	well.  It is this entry that triggers the kernel into passing the
319470d3e49eSrie  *	interpreter an aux vector instead of just a file descriptor.
31957c478bd9Sstevel@tonic-gate  *
31967c478bd9Sstevel@tonic-gate  *  o	When generating an image that will be interpreted (ie. a dynamic
31977c478bd9Sstevel@tonic-gate  *	executable, a shared object, or a static executable that has been
319870d3e49eSrie  *	provided with an interpreter - weird, but possible), make the initial
31997c478bd9Sstevel@tonic-gate  *	loadable segment include both the ehdr and phdr[].  Both of these
320070d3e49eSrie  *	tables are used by the interpreter therefore it seems more intuitive
32017c478bd9Sstevel@tonic-gate  *	to explicitly defined them as part of the mapped image rather than
320270d3e49eSrie  *	relying on page rounding by the interpreter to allow their access.
32037c478bd9Sstevel@tonic-gate  *
320470d3e49eSrie  *  o	When generating a static image that does not require an interpreter
32057c478bd9Sstevel@tonic-gate  *	have the first loadable segment indicate the address of the first
32067c478bd9Sstevel@tonic-gate  *	.section as the start address (things like /kernel/unix and ufsboot
32077c478bd9Sstevel@tonic-gate  *	expect this behavior).
32087c478bd9Sstevel@tonic-gate  */
32097c478bd9Sstevel@tonic-gate uintptr_t
32105aefb655Srie ld_update_outfile(Ofl_desc *ofl)
32117c478bd9Sstevel@tonic-gate {
32127c478bd9Sstevel@tonic-gate 	Addr		size, etext, vaddr = ofl->ofl_segorigin;
32137c478bd9Sstevel@tonic-gate 	Listnode	*lnp1, *lnp2;
3214d1827f25Srie 	Sg_desc		*sgp, *dtracesgp = 0, *capsgp = 0;
3215cce0e03bSab 	Os_desc		*osp;
3216d1827f25Srie 	int		phdrndx = 0, segndx = -1, secndx;
3217d1827f25Srie 	int		dtracepndx, dtracesndx, cappndx, capsndx;
32185aefb655Srie 	Ehdr		*ehdr = ofl->ofl_nehdr;
32197c478bd9Sstevel@tonic-gate 	Shdr		*hshdr;
3220d1827f25Srie 	Phdr		*_phdr = 0;
3221d1827f25Srie 	Word		phdrsz = (ehdr->e_phnum * ehdr->e_phentsize), shscnndx;
32221d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
32231d9df23bSab 	Word		ehdrsz = ehdr->e_ehsize;
32247c478bd9Sstevel@tonic-gate 	Boolean		nobits;
32257c478bd9Sstevel@tonic-gate 	Off		offset;
3226cce0e03bSab 	Aliste		idx;
32277c478bd9Sstevel@tonic-gate 
32287c478bd9Sstevel@tonic-gate 	/*
32297c478bd9Sstevel@tonic-gate 	 * Loop through the segment descriptors and pick out what we need.
32307c478bd9Sstevel@tonic-gate 	 */
32315aefb655Srie 	DBG_CALL(Dbg_seg_title(ofl->ofl_lml));
32327c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) {
3233d1827f25Srie 		Phdr	*phdr = &(sgp->sg_phdr);
32347c478bd9Sstevel@tonic-gate 		Xword 	p_align;
32357c478bd9Sstevel@tonic-gate 
32367c478bd9Sstevel@tonic-gate 		segndx++;
32377c478bd9Sstevel@tonic-gate 
32387c478bd9Sstevel@tonic-gate 		/*
32397c478bd9Sstevel@tonic-gate 		 * If an interpreter is required generate a PT_INTERP and
32407c478bd9Sstevel@tonic-gate 		 * PT_PHDR program header entry.  The PT_PHDR entry describes
32417c478bd9Sstevel@tonic-gate 		 * the program header table itself.  This information will be
32427c478bd9Sstevel@tonic-gate 		 * passed via the aux vector to the interpreter (ld.so.1).
32437c478bd9Sstevel@tonic-gate 		 * The program header array is actually part of the first
32447c478bd9Sstevel@tonic-gate 		 * loadable segment (and the PT_PHDR entry is the first entry),
32457c478bd9Sstevel@tonic-gate 		 * therefore its virtual address isn't known until the first
32467c478bd9Sstevel@tonic-gate 		 * loadable segment is processed.
32477c478bd9Sstevel@tonic-gate 		 */
32487c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_PHDR) {
32497c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osinterp) {
32507c478bd9Sstevel@tonic-gate 				phdr->p_offset = ehdr->e_phoff;
32517c478bd9Sstevel@tonic-gate 				phdr->p_filesz = phdr->p_memsz = phdrsz;
3252d1827f25Srie 
32535aefb655Srie 				DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
32547c478bd9Sstevel@tonic-gate 				ofl->ofl_phdr[phdrndx++] = *phdr;
32557c478bd9Sstevel@tonic-gate 			}
32567c478bd9Sstevel@tonic-gate 			continue;
32577c478bd9Sstevel@tonic-gate 		}
32587c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_INTERP) {
32597c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osinterp) {
3260d1827f25Srie 				Shdr	*shdr = ofl->ofl_osinterp->os_shdr;
32617c478bd9Sstevel@tonic-gate 
32627c478bd9Sstevel@tonic-gate 				phdr->p_vaddr = phdr->p_memsz = 0;
32637c478bd9Sstevel@tonic-gate 				phdr->p_offset = shdr->sh_offset;
32647c478bd9Sstevel@tonic-gate 				phdr->p_filesz = shdr->sh_size;
3265d1827f25Srie 
32665aefb655Srie 				DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
32677c478bd9Sstevel@tonic-gate 				ofl->ofl_phdr[phdrndx++] = *phdr;
32687c478bd9Sstevel@tonic-gate 			}
32697c478bd9Sstevel@tonic-gate 			continue;
32707c478bd9Sstevel@tonic-gate 		}
32717c478bd9Sstevel@tonic-gate 
32727c478bd9Sstevel@tonic-gate 		/*
3273d1827f25Srie 		 * If we are creating a PT_SUNWDTRACE segment, remember where
3274d1827f25Srie 		 * the program header is.  The header values are assigned after
3275d1827f25Srie 		 * update_osym() has completed and the symbol table addresses
3276d1827f25Srie 		 * have been udpated.
32777c478bd9Sstevel@tonic-gate 		 */
32787c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_SUNWDTRACE) {
32797c478bd9Sstevel@tonic-gate 			if ((ofl->ofl_dtracesym) &&
32807c478bd9Sstevel@tonic-gate 			    ((flags & FLG_OF_RELOBJ) == 0)) {
3281d1827f25Srie 				dtracesgp = sgp;
3282d1827f25Srie 				dtracesndx = segndx;
3283d1827f25Srie 				dtracepndx = phdrndx++;
32847c478bd9Sstevel@tonic-gate 			}
32857c478bd9Sstevel@tonic-gate 			continue;
32867c478bd9Sstevel@tonic-gate 		}
32877c478bd9Sstevel@tonic-gate 
32887c478bd9Sstevel@tonic-gate 		/*
32897c478bd9Sstevel@tonic-gate 		 * If a hardware/software capabilities section is required,
32907c478bd9Sstevel@tonic-gate 		 * generate the PT_SUNWCAP header.  Note, as this comes before
32917c478bd9Sstevel@tonic-gate 		 * the first loadable segment, we don't yet know its real
32927c478bd9Sstevel@tonic-gate 		 * virtual address.  This is updated later.
32937c478bd9Sstevel@tonic-gate 		 */
32947c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_SUNWCAP) {
32957c478bd9Sstevel@tonic-gate 			if (ofl->ofl_oscap) {
3296d1827f25Srie 				capsgp = sgp;
3297d1827f25Srie 				capsndx = segndx;
3298d1827f25Srie 				cappndx = phdrndx++;
32997c478bd9Sstevel@tonic-gate 			}
33007c478bd9Sstevel@tonic-gate 			continue;
33017c478bd9Sstevel@tonic-gate 		}
33027c478bd9Sstevel@tonic-gate 
33037c478bd9Sstevel@tonic-gate 		/*
33047c478bd9Sstevel@tonic-gate 		 * As the dynamic program header occurs after the loadable
33057c478bd9Sstevel@tonic-gate 		 * headers in the segment descriptor table, all the address
33067c478bd9Sstevel@tonic-gate 		 * information for the .dynamic output section will have been
33077c478bd9Sstevel@tonic-gate 		 * figured out by now.
33087c478bd9Sstevel@tonic-gate 		 */
33097c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_DYNAMIC) {
33109039eeafSab 			if (OFL_ALLOW_DYNSYM(ofl)) {
3311d1827f25Srie 				Shdr	*shdr = ofl->ofl_osdynamic->os_shdr;
33127c478bd9Sstevel@tonic-gate 
33137c478bd9Sstevel@tonic-gate 				phdr->p_vaddr = shdr->sh_addr;
33147c478bd9Sstevel@tonic-gate 				phdr->p_offset = shdr->sh_offset;
33157c478bd9Sstevel@tonic-gate 				phdr->p_filesz = shdr->sh_size;
3316ba2be530Sab 				phdr->p_flags = ld_targ.t_m.m_dataseg_perm;
3317d1827f25Srie 
33185aefb655Srie 				DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
33197c478bd9Sstevel@tonic-gate 				ofl->ofl_phdr[phdrndx++] = *phdr;
33207c478bd9Sstevel@tonic-gate 			}
33217c478bd9Sstevel@tonic-gate 			continue;
33227c478bd9Sstevel@tonic-gate 		}
3323d1827f25Srie 
3324d1827f25Srie 		/*
3325d1827f25Srie 		 * As the AMD unwind program header occurs after the loadable
3326d1827f25Srie 		 * headers in the segment descriptor table, all the address
3327d1827f25Srie 		 * information for the .eh_frame output section will have been
3328d1827f25Srie 		 * figured out by now.
3329d1827f25Srie 		 */
3330ba2be530Sab #if	defined(_ELF64)
3331ba2be530Sab 		if ((ld_targ.t_m.m_mach == EM_AMD64) &&
3332ba2be530Sab 		    (phdr->p_type == PT_SUNW_UNWIND)) {
33337c478bd9Sstevel@tonic-gate 			Shdr	    *shdr;
3334d1827f25Srie 
33357c478bd9Sstevel@tonic-gate 			if (ofl->ofl_unwindhdr == 0)
33367c478bd9Sstevel@tonic-gate 				continue;
3337d1827f25Srie 
33387c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_unwindhdr->os_shdr;
33397c478bd9Sstevel@tonic-gate 
33407c478bd9Sstevel@tonic-gate 			phdr->p_flags = PF_R;
33417c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = shdr->sh_addr;
33427c478bd9Sstevel@tonic-gate 			phdr->p_memsz = shdr->sh_size;
33437c478bd9Sstevel@tonic-gate 			phdr->p_filesz = shdr->sh_size;
33447c478bd9Sstevel@tonic-gate 			phdr->p_offset = shdr->sh_offset;
33457c478bd9Sstevel@tonic-gate 			phdr->p_align = shdr->sh_addralign;
33467c478bd9Sstevel@tonic-gate 			phdr->p_paddr = 0;
33477c478bd9Sstevel@tonic-gate 			ofl->ofl_phdr[phdrndx++] = *phdr;
33487c478bd9Sstevel@tonic-gate 			continue;
33497c478bd9Sstevel@tonic-gate 		}
33507c478bd9Sstevel@tonic-gate #endif
3351d1827f25Srie 		/*
3352d1827f25Srie 		 * As the TLS program header occurs after the loadable
3353d1827f25Srie 		 * headers in the segment descriptor table, all the address
3354d1827f25Srie 		 * information for the .tls output section will have been
3355d1827f25Srie 		 * figured out by now.
3356d1827f25Srie 		 */
33577c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_TLS) {
3358dd94ecefSrie 			Os_desc	*tlsosp;
3359f79d60b6Srie 			Shdr	*firstshdr = 0, *lastfileshdr = 0, *lastshdr;
33607c478bd9Sstevel@tonic-gate 
3361dd94ecefSrie 			if (ofl->ofl_ostlsseg.head == NULL)
33627c478bd9Sstevel@tonic-gate 				continue;
3363dd94ecefSrie 
3364f79d60b6Srie 			/*
3365f79d60b6Srie 			 * Scan through the sections that have contributed TLS.
3366f79d60b6Srie 			 * Remember the first and last so as to determine the
3367f79d60b6Srie 			 * TLS memory size requirement.  Remember the last
3368f79d60b6Srie 			 * non-nobits section to determine the TLS data
3369f79d60b6Srie 			 * contribution, which determines the TLS file size.
3370f79d60b6Srie 			 */
3371dd94ecefSrie 			for (LIST_TRAVERSE(&ofl->ofl_ostlsseg, lnp2, tlsosp)) {
3372dd94ecefSrie 				Shdr	*tlsshdr = tlsosp->os_shdr;
3373dd94ecefSrie 
3374f79d60b6Srie 				if (firstshdr == 0)
3375f79d60b6Srie 					firstshdr = tlsshdr;
3376f79d60b6Srie 				if (tlsshdr->sh_type != SHT_NOBITS)
3377f79d60b6Srie 					lastfileshdr = tlsshdr;
3378f79d60b6Srie 				lastshdr = tlsshdr;
33797c478bd9Sstevel@tonic-gate 			}
3380dd94ecefSrie 
3381dd94ecefSrie 			phdr->p_flags = PF_R | PF_W;
33827c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = firstshdr->sh_addr;
33837c478bd9Sstevel@tonic-gate 			phdr->p_offset = firstshdr->sh_offset;
3384dd94ecefSrie 			phdr->p_align = firstshdr->sh_addralign;
3385f79d60b6Srie 
3386f79d60b6Srie 			if (lastfileshdr)
3387f79d60b6Srie 				phdr->p_filesz = lastfileshdr->sh_offset +
3388f79d60b6Srie 				    lastfileshdr->sh_size - phdr->p_offset;
3389f79d60b6Srie 			else
3390f79d60b6Srie 				phdr->p_filesz = 0;
3391f79d60b6Srie 
3392f79d60b6Srie 			phdr->p_memsz = lastshdr->sh_offset +
3393f79d60b6Srie 			    lastshdr->sh_size - phdr->p_offset;
3394dd94ecefSrie 
33955aefb655Srie 			DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
3396d1827f25Srie 			ofl->ofl_phdr[phdrndx] = *phdr;
3397d1827f25Srie 			ofl->ofl_tlsphdr = &ofl->ofl_phdr[phdrndx++];
33987c478bd9Sstevel@tonic-gate 			continue;
33997c478bd9Sstevel@tonic-gate 		}
34007c478bd9Sstevel@tonic-gate 
34017c478bd9Sstevel@tonic-gate 		/*
34027c478bd9Sstevel@tonic-gate 		 * If this is an empty segment declaration, it will occur after
3403d1827f25Srie 		 * all other loadable segments.  As empty segments can be
3404d1827f25Srie 		 * defind with fixed addresses, make sure that no loadable
3405d1827f25Srie 		 * segments overlap.  This might occur as the object evolves
3406d1827f25Srie 		 * and the loadable segments grow, thus encroaching upon an
3407d1827f25Srie 		 * existing segment reservation.
3408d1827f25Srie 		 *
3409d1827f25Srie 		 * Segments are only created for dynamic objects, thus this
3410d1827f25Srie 		 * checking can be skipped when building a relocatable object.
34117c478bd9Sstevel@tonic-gate 		 */
34121d9df23bSab 		if (!(flags & FLG_OF_RELOBJ) &&
34137c478bd9Sstevel@tonic-gate 		    (sgp->sg_flags & FLG_SG_EMPTY)) {
3414d1827f25Srie 			int	i;
34157c478bd9Sstevel@tonic-gate 			Addr	v_e;
34167c478bd9Sstevel@tonic-gate 
34177c478bd9Sstevel@tonic-gate 			vaddr = phdr->p_vaddr;
34187c478bd9Sstevel@tonic-gate 			phdr->p_memsz = sgp->sg_length;
34195aefb655Srie 			DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
34207c478bd9Sstevel@tonic-gate 			ofl->ofl_phdr[phdrndx++] = *phdr;
34217c478bd9Sstevel@tonic-gate 
34227c478bd9Sstevel@tonic-gate 			if (phdr->p_type != PT_LOAD)
34237c478bd9Sstevel@tonic-gate 				continue;
34247c478bd9Sstevel@tonic-gate 
34257c478bd9Sstevel@tonic-gate 			v_e = vaddr + phdr->p_memsz;
3426d1827f25Srie 
34277c478bd9Sstevel@tonic-gate 			/*
34287c478bd9Sstevel@tonic-gate 			 * Check overlaps
34297c478bd9Sstevel@tonic-gate 			 */
34307c478bd9Sstevel@tonic-gate 			for (i = 0; i < phdrndx - 1; i++) {
34317c478bd9Sstevel@tonic-gate 				Addr 	p_s = (ofl->ofl_phdr[i]).p_vaddr;
34327c478bd9Sstevel@tonic-gate 				Addr 	p_e;
34337c478bd9Sstevel@tonic-gate 
34347c478bd9Sstevel@tonic-gate 				if ((ofl->ofl_phdr[i]).p_type != PT_LOAD)
34357c478bd9Sstevel@tonic-gate 					continue;
34367c478bd9Sstevel@tonic-gate 
34377c478bd9Sstevel@tonic-gate 				p_e = p_s + (ofl->ofl_phdr[i]).p_memsz;
34387c478bd9Sstevel@tonic-gate 				if (((p_s <= vaddr) && (p_e > vaddr)) ||
34397c478bd9Sstevel@tonic-gate 				    ((vaddr <= p_s) && (v_e > p_s)))
34405aefb655Srie 					eprintf(ofl->ofl_lml, ERR_WARNING,
34417c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_UPD_SEGOVERLAP),
34425aefb655Srie 					    ofl->ofl_name, EC_ADDR(p_e),
34435aefb655Srie 					    sgp->sg_name, EC_ADDR(vaddr));
34447c478bd9Sstevel@tonic-gate 			}
34457c478bd9Sstevel@tonic-gate 			continue;
34467c478bd9Sstevel@tonic-gate 		}
34477c478bd9Sstevel@tonic-gate 
34487c478bd9Sstevel@tonic-gate 		/*
34497c478bd9Sstevel@tonic-gate 		 * Having processed any of the special program headers any
34507c478bd9Sstevel@tonic-gate 		 * remaining headers will be built to express individual
34517c478bd9Sstevel@tonic-gate 		 * segments.  Segments are only built if they have output
34527c478bd9Sstevel@tonic-gate 		 * section descriptors associated with them (ie. some form of
34537c478bd9Sstevel@tonic-gate 		 * input section has been matched to this segment).
34547c478bd9Sstevel@tonic-gate 		 */
34550bc07c75Srie 		if (sgp->sg_osdescs == NULL)
34567c478bd9Sstevel@tonic-gate 			continue;
34577c478bd9Sstevel@tonic-gate 
34587c478bd9Sstevel@tonic-gate 		/*
34597c478bd9Sstevel@tonic-gate 		 * Determine the segments offset and size from the section
34607c478bd9Sstevel@tonic-gate 		 * information provided from elf_update().
34617c478bd9Sstevel@tonic-gate 		 * Allow for multiple NOBITS sections.
34627c478bd9Sstevel@tonic-gate 		 */
3463cce0e03bSab 		osp = sgp->sg_osdescs->apl_data[0];
346454d82594Sseizo 		hshdr = osp->os_shdr;
34657c478bd9Sstevel@tonic-gate 
34667c478bd9Sstevel@tonic-gate 		phdr->p_filesz = 0;
34677c478bd9Sstevel@tonic-gate 		phdr->p_memsz = 0;
34687c478bd9Sstevel@tonic-gate 		phdr->p_offset = offset = hshdr->sh_offset;
34690bc07c75Srie 
347054d82594Sseizo 		nobits = ((hshdr->sh_type == SHT_NOBITS) &&
34710bc07c75Srie 		    ((sgp->sg_flags & FLG_SG_PHREQ) == 0));
34720bc07c75Srie 
3473cce0e03bSab 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) {
3474cce0e03bSab 			Shdr	*shdr = osp->os_shdr;
34757c478bd9Sstevel@tonic-gate 
34767c478bd9Sstevel@tonic-gate 			p_align = 0;
34777c478bd9Sstevel@tonic-gate 			if (shdr->sh_addralign > p_align)
34787c478bd9Sstevel@tonic-gate 				p_align = shdr->sh_addralign;
34790bc07c75Srie 
34807c478bd9Sstevel@tonic-gate 			offset = (Off)S_ROUND(offset, shdr->sh_addralign);
34817c478bd9Sstevel@tonic-gate 			offset += shdr->sh_size;
34820bc07c75Srie 
34837c478bd9Sstevel@tonic-gate 			if (shdr->sh_type != SHT_NOBITS) {
34847c478bd9Sstevel@tonic-gate 				if (nobits) {
34855aefb655Srie 					eprintf(ofl->ofl_lml, ERR_FATAL,
34867c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_UPD_NOBITS));
34877c478bd9Sstevel@tonic-gate 					return (S_ERROR);
34887c478bd9Sstevel@tonic-gate 				}
34897c478bd9Sstevel@tonic-gate 				phdr->p_filesz = offset - phdr->p_offset;
349054d82594Sseizo 			} else if ((sgp->sg_flags & FLG_SG_PHREQ) == 0)
34917c478bd9Sstevel@tonic-gate 				nobits = TRUE;
34927c478bd9Sstevel@tonic-gate 		}
34937c478bd9Sstevel@tonic-gate 		phdr->p_memsz = offset - hshdr->sh_offset;
34947c478bd9Sstevel@tonic-gate 
34957c478bd9Sstevel@tonic-gate 		/*
34967c478bd9Sstevel@tonic-gate 		 * If this is PT_SUNWBSS, set alignment
34977c478bd9Sstevel@tonic-gate 		 */
34987c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_SUNWBSS)
34997c478bd9Sstevel@tonic-gate 			phdr->p_align = p_align;
35007c478bd9Sstevel@tonic-gate 
35017c478bd9Sstevel@tonic-gate 		/*
35027c478bd9Sstevel@tonic-gate 		 * If this is the first loadable segment of a dynamic object,
350370d3e49eSrie 		 * or an interpreter has been specified (a static object built
350470d3e49eSrie 		 * with an interpreter will still be given a PT_HDR entry), then
35057c478bd9Sstevel@tonic-gate 		 * compensate for the elf header and program header array.  Both
35067c478bd9Sstevel@tonic-gate 		 * of these are actually part of the loadable segment as they
350770d3e49eSrie 		 * may be inspected by the interpreter.  Adjust the segments
35087c478bd9Sstevel@tonic-gate 		 * size and offset accordingly.
35097c478bd9Sstevel@tonic-gate 		 */
35107c478bd9Sstevel@tonic-gate 		if ((_phdr == 0) && (phdr->p_type == PT_LOAD) &&
35117c478bd9Sstevel@tonic-gate 		    ((ofl->ofl_osinterp) || (flags & FLG_OF_DYNAMIC)) &&
35124899432aSab 		    (!(ofl->ofl_dtflags_1 & DF_1_NOHDR))) {
35137c478bd9Sstevel@tonic-gate 			size = (Addr)S_ROUND((phdrsz + ehdrsz),
35147c478bd9Sstevel@tonic-gate 			    hshdr->sh_addralign);
35157c478bd9Sstevel@tonic-gate 			phdr->p_offset -= size;
35167c478bd9Sstevel@tonic-gate 			phdr->p_filesz += size;
35177c478bd9Sstevel@tonic-gate 			phdr->p_memsz += size;
35187c478bd9Sstevel@tonic-gate 		}
35197c478bd9Sstevel@tonic-gate 
35207c478bd9Sstevel@tonic-gate 		/*
35217c478bd9Sstevel@tonic-gate 		 * If a segment size symbol is required (specified via a
35227c478bd9Sstevel@tonic-gate 		 * mapfile) update its value.
35237c478bd9Sstevel@tonic-gate 		 */
35247c478bd9Sstevel@tonic-gate 		if (sgp->sg_sizesym != NULL)
35257c478bd9Sstevel@tonic-gate 			sgp->sg_sizesym->sd_sym->st_value = phdr->p_memsz;
35267c478bd9Sstevel@tonic-gate 
35277c478bd9Sstevel@tonic-gate 		/*
35287c478bd9Sstevel@tonic-gate 		 * If no file content has been assigned to this segment (it
35297c478bd9Sstevel@tonic-gate 		 * only contains no-bits sections), then reset the offset for
35307c478bd9Sstevel@tonic-gate 		 * consistency.
35317c478bd9Sstevel@tonic-gate 		 */
35327c478bd9Sstevel@tonic-gate 		if (phdr->p_filesz == 0)
35337c478bd9Sstevel@tonic-gate 			phdr->p_offset = 0;
35347c478bd9Sstevel@tonic-gate 
35357c478bd9Sstevel@tonic-gate 		/*
35367c478bd9Sstevel@tonic-gate 		 * If a virtual address has been specified for this segment
35377c478bd9Sstevel@tonic-gate 		 * (presumably from a map file) use it and make sure the
35387c478bd9Sstevel@tonic-gate 		 * previous segment does not run into this segment.
35397c478bd9Sstevel@tonic-gate 		 */
35407c478bd9Sstevel@tonic-gate 		if ((phdr->p_type == PT_LOAD) ||
35417c478bd9Sstevel@tonic-gate 		    (phdr->p_type == PT_SUNWBSS)) {
35427c478bd9Sstevel@tonic-gate 			if ((sgp->sg_flags & FLG_SG_VADDR)) {
35437c478bd9Sstevel@tonic-gate 				if (_phdr && (vaddr > phdr->p_vaddr) &&
35447c478bd9Sstevel@tonic-gate 				    (phdr->p_type == PT_LOAD))
35455aefb655Srie 					eprintf(ofl->ofl_lml, ERR_WARNING,
35467c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_UPD_SEGOVERLAP),
35477c478bd9Sstevel@tonic-gate 					    ofl->ofl_name, EC_ADDR(vaddr),
35487c478bd9Sstevel@tonic-gate 					    sgp->sg_name,
35497c478bd9Sstevel@tonic-gate 					    EC_ADDR(phdr->p_vaddr));
35507c478bd9Sstevel@tonic-gate 				vaddr = phdr->p_vaddr;
35517c478bd9Sstevel@tonic-gate 				phdr->p_align = 0;
35527c478bd9Sstevel@tonic-gate 			} else {
35537c478bd9Sstevel@tonic-gate 				vaddr = phdr->p_vaddr =
35547c478bd9Sstevel@tonic-gate 				    (Addr)S_ROUND(vaddr, phdr->p_align);
35557c478bd9Sstevel@tonic-gate 			}
35567c478bd9Sstevel@tonic-gate 		}
35577c478bd9Sstevel@tonic-gate 
35587c478bd9Sstevel@tonic-gate 		/*
35597c478bd9Sstevel@tonic-gate 		 * Adjust the address offset and p_align if needed.
35607c478bd9Sstevel@tonic-gate 		 */
35613906e0c2Srie 		if (((sgp->sg_flags & FLG_SG_VADDR) == 0) &&
35623906e0c2Srie 		    ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0)) {
35637c478bd9Sstevel@tonic-gate 			if (phdr->p_align != 0)
35647c478bd9Sstevel@tonic-gate 				vaddr += phdr->p_offset % phdr->p_align;
35657c478bd9Sstevel@tonic-gate 			else
35667c478bd9Sstevel@tonic-gate 				vaddr += phdr->p_offset;
35677c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = vaddr;
35687c478bd9Sstevel@tonic-gate 		}
35697c478bd9Sstevel@tonic-gate 
35707c478bd9Sstevel@tonic-gate 		/*
35717c478bd9Sstevel@tonic-gate 		 * If an interpreter is required set the virtual address of the
35727c478bd9Sstevel@tonic-gate 		 * PT_PHDR program header now that we know the virtual address
35737c478bd9Sstevel@tonic-gate 		 * of the loadable segment that contains it.  Update the
35747c478bd9Sstevel@tonic-gate 		 * PT_SUNWCAP header similarly.
35757c478bd9Sstevel@tonic-gate 		 */
35767c478bd9Sstevel@tonic-gate 		if ((_phdr == 0) && (phdr->p_type == PT_LOAD)) {
35777c478bd9Sstevel@tonic-gate 			_phdr = phdr;
35787c478bd9Sstevel@tonic-gate 
3579d1827f25Srie 			if ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0) {
35807c478bd9Sstevel@tonic-gate 				if (ofl->ofl_osinterp)
35817c478bd9Sstevel@tonic-gate 					ofl->ofl_phdr[0].p_vaddr =
35827c478bd9Sstevel@tonic-gate 					    vaddr + ehdrsz;
35837c478bd9Sstevel@tonic-gate 
35847c478bd9Sstevel@tonic-gate 				/*
35857c478bd9Sstevel@tonic-gate 				 * Finally, if we're creating a dynamic object
358670d3e49eSrie 				 * (or a static object in which an interpreter
35877c478bd9Sstevel@tonic-gate 				 * is specified) update the vaddr to reflect
35887c478bd9Sstevel@tonic-gate 				 * the address of the first section within this
35897c478bd9Sstevel@tonic-gate 				 * segment.
35907c478bd9Sstevel@tonic-gate 				 */
35917c478bd9Sstevel@tonic-gate 				if ((ofl->ofl_osinterp) ||
35927c478bd9Sstevel@tonic-gate 				    (flags & FLG_OF_DYNAMIC))
35937c478bd9Sstevel@tonic-gate 					vaddr += size;
35947c478bd9Sstevel@tonic-gate 			} else {
35957c478bd9Sstevel@tonic-gate 				/*
3596d1827f25Srie 				 * If the DF_1_NOHDR flag was set, and an
3597d1827f25Srie 				 * interpreter is being generated, the PT_PHDR
35987c478bd9Sstevel@tonic-gate 				 * will not be part of any loadable segment.
35997c478bd9Sstevel@tonic-gate 				 */
3600d1827f25Srie 				if (ofl->ofl_osinterp) {
3601d1827f25Srie 					ofl->ofl_phdr[0].p_vaddr = 0;
3602d1827f25Srie 					ofl->ofl_phdr[0].p_memsz = 0;
3603d1827f25Srie 					ofl->ofl_phdr[0].p_flags = 0;
3604d1827f25Srie 				}
36057c478bd9Sstevel@tonic-gate 			}
36067c478bd9Sstevel@tonic-gate 		}
36077c478bd9Sstevel@tonic-gate 
36087c478bd9Sstevel@tonic-gate 		/*
3609c1c6f601Srie 		 * Ensure the ELF entry point defaults to zero.  Typically, this
3610c1c6f601Srie 		 * value is overridden in update_oehdr() to one of the standard
3611c1c6f601Srie 		 * entry points.  Historically, this default was set to the
3612c1c6f601Srie 		 * address of first executable section, but this has since been
3613c1c6f601Srie 		 * found to be more confusing than it is helpful.
36147c478bd9Sstevel@tonic-gate 		 */
3615c1c6f601Srie 		ehdr->e_entry = 0;
36167c478bd9Sstevel@tonic-gate 
36175aefb655Srie 		DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
36187c478bd9Sstevel@tonic-gate 
36197c478bd9Sstevel@tonic-gate 		/*
36207c478bd9Sstevel@tonic-gate 		 * Traverse the output section descriptors for this segment so
36217c478bd9Sstevel@tonic-gate 		 * that we can update the section headers addresses.  We've
36227c478bd9Sstevel@tonic-gate 		 * calculated the virtual address of the initial section within
36237c478bd9Sstevel@tonic-gate 		 * this segment, so each successive section can be calculated
36247c478bd9Sstevel@tonic-gate 		 * based on their offsets from each other.
36257c478bd9Sstevel@tonic-gate 		 */
36267c478bd9Sstevel@tonic-gate 		secndx = 0;
36277c478bd9Sstevel@tonic-gate 		hshdr = 0;
3628cce0e03bSab 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) {
3629cce0e03bSab 			Shdr	*shdr = osp->os_shdr;
36307c478bd9Sstevel@tonic-gate 
36317c478bd9Sstevel@tonic-gate 			if (shdr->sh_link)
363260758829Srie 				shdr->sh_link = translate_link(ofl, osp,
363360758829Srie 				    shdr->sh_link, MSG_INTL(MSG_FIL_INVSHLINK));
36347c478bd9Sstevel@tonic-gate 
36357c478bd9Sstevel@tonic-gate 			if (shdr->sh_info && (shdr->sh_flags & SHF_INFO_LINK))
363660758829Srie 				shdr->sh_info = translate_link(ofl, osp,
363760758829Srie 				    shdr->sh_info, MSG_INTL(MSG_FIL_INVSHINFO));
36387c478bd9Sstevel@tonic-gate 
36397c478bd9Sstevel@tonic-gate 			if (!(flags & FLG_OF_RELOBJ) &&
36407c478bd9Sstevel@tonic-gate 			    (phdr->p_type == PT_LOAD) ||
36417c478bd9Sstevel@tonic-gate 			    (phdr->p_type == PT_SUNWBSS)) {
36427c478bd9Sstevel@tonic-gate 				if (hshdr)
36437c478bd9Sstevel@tonic-gate 					vaddr += (shdr->sh_offset -
36447c478bd9Sstevel@tonic-gate 					    hshdr->sh_offset);
36457c478bd9Sstevel@tonic-gate 
36467c478bd9Sstevel@tonic-gate 				shdr->sh_addr = vaddr;
36477c478bd9Sstevel@tonic-gate 				hshdr = shdr;
36487c478bd9Sstevel@tonic-gate 			}
36497c478bd9Sstevel@tonic-gate 
36507c478bd9Sstevel@tonic-gate 			DBG_CALL(Dbg_seg_os(ofl, osp, secndx));
36517c478bd9Sstevel@tonic-gate 			secndx++;
36527c478bd9Sstevel@tonic-gate 		}
36537c478bd9Sstevel@tonic-gate 
36547c478bd9Sstevel@tonic-gate 		/*
36557c478bd9Sstevel@tonic-gate 		 * Establish the virtual address of the end of the last section
36567c478bd9Sstevel@tonic-gate 		 * in this segment so that the next segments offset can be
36577c478bd9Sstevel@tonic-gate 		 * calculated from this.
36587c478bd9Sstevel@tonic-gate 		 */
36597c478bd9Sstevel@tonic-gate 		if (hshdr)
36607c478bd9Sstevel@tonic-gate 			vaddr += hshdr->sh_size;
36617c478bd9Sstevel@tonic-gate 
36627c478bd9Sstevel@tonic-gate 		/*
36637c478bd9Sstevel@tonic-gate 		 * Output sections for this segment complete.  Adjust the
36647c478bd9Sstevel@tonic-gate 		 * virtual offset for the last sections size, and make sure we
36657c478bd9Sstevel@tonic-gate 		 * haven't exceeded any maximum segment length specification.
36667c478bd9Sstevel@tonic-gate 		 */
36677c478bd9Sstevel@tonic-gate 		if ((sgp->sg_length != 0) && (sgp->sg_length < phdr->p_memsz)) {
36685aefb655Srie 			eprintf(ofl->ofl_lml, ERR_FATAL,
36695aefb655Srie 			    MSG_INTL(MSG_UPD_LARGSIZE), ofl->ofl_name,
36705aefb655Srie 			    sgp->sg_name, EC_XWORD(phdr->p_memsz),
36717c478bd9Sstevel@tonic-gate 			    EC_XWORD(sgp->sg_length));
36727c478bd9Sstevel@tonic-gate 			return (S_ERROR);
36737c478bd9Sstevel@tonic-gate 		}
36747c478bd9Sstevel@tonic-gate 
36757c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_NOTE) {
36767c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = 0;
36777c478bd9Sstevel@tonic-gate 			phdr->p_paddr = 0;
36787c478bd9Sstevel@tonic-gate 			phdr->p_align = 0;
36797c478bd9Sstevel@tonic-gate 			phdr->p_memsz = 0;
36807c478bd9Sstevel@tonic-gate 		}
3681d1827f25Srie 
36827c478bd9Sstevel@tonic-gate 		if ((phdr->p_type != PT_NULL) && !(flags & FLG_OF_RELOBJ))
36837c478bd9Sstevel@tonic-gate 			ofl->ofl_phdr[phdrndx++] = *phdr;
36847c478bd9Sstevel@tonic-gate 	}
36857c478bd9Sstevel@tonic-gate 
36867c478bd9Sstevel@tonic-gate 	/*
36877c478bd9Sstevel@tonic-gate 	 * Update any new output sections.  When building the initial output
36887c478bd9Sstevel@tonic-gate 	 * image, a number of sections were created but left uninitialized (eg.
36897c478bd9Sstevel@tonic-gate 	 * .dynsym, .dynstr, .symtab, .symtab, etc.).  Here we update these
36907c478bd9Sstevel@tonic-gate 	 * sections with the appropriate data.  Other sections may still be
36917c478bd9Sstevel@tonic-gate 	 * modified via reloc_process().
36927c478bd9Sstevel@tonic-gate 	 *
369370d3e49eSrie 	 * Copy the interpreter name into the .interp section.
36947c478bd9Sstevel@tonic-gate 	 */
36957c478bd9Sstevel@tonic-gate 	if (ofl->ofl_interp)
36967c478bd9Sstevel@tonic-gate 		(void) strcpy((char *)ofl->ofl_osinterp->os_outdata->d_buf,
36977c478bd9Sstevel@tonic-gate 		    ofl->ofl_interp);
36987c478bd9Sstevel@tonic-gate 
36997c478bd9Sstevel@tonic-gate 	/*
37007c478bd9Sstevel@tonic-gate 	 * Update the .shstrtab, .strtab and .dynstr sections.
37017c478bd9Sstevel@tonic-gate 	 */
37023244bcaaSab 	update_ostrtab(ofl->ofl_osshstrtab, ofl->ofl_shdrsttab, 0);
37033244bcaaSab 	update_ostrtab(ofl->ofl_osstrtab, ofl->ofl_strtab, 0);
37043244bcaaSab 	update_ostrtab(ofl->ofl_osdynstr, ofl->ofl_dynstrtab, DYNSTR_EXTRA_PAD);
37057c478bd9Sstevel@tonic-gate 
37067c478bd9Sstevel@tonic-gate 	/*
37077c478bd9Sstevel@tonic-gate 	 * Build any output symbol tables, the symbols information is copied
37087c478bd9Sstevel@tonic-gate 	 * and updated into the new output image.
37097c478bd9Sstevel@tonic-gate 	 */
37107c478bd9Sstevel@tonic-gate 	if ((etext = update_osym(ofl)) == (Addr)S_ERROR)
37117c478bd9Sstevel@tonic-gate 		return (S_ERROR);
37127c478bd9Sstevel@tonic-gate 
37137c478bd9Sstevel@tonic-gate 	/*
37147c478bd9Sstevel@tonic-gate 	 * If we have a PT_SUNWDTRACE phdr, update it now with the address of
37157c478bd9Sstevel@tonic-gate 	 * the symbol.  It's only now been updated via update_sym().
37167c478bd9Sstevel@tonic-gate 	 */
3717d1827f25Srie 	if (dtracesgp && ofl->ofl_dtracesym) {
3718d1827f25Srie 		Phdr		*aphdr, *phdr = &(dtracesgp->sg_phdr);
37197c478bd9Sstevel@tonic-gate 		Sym_desc	*sdp = ofl->ofl_dtracesym;
37207c478bd9Sstevel@tonic-gate 
3721d1827f25Srie 		phdr->p_vaddr = sdp->sd_sym->st_value;
3722d1827f25Srie 		phdr->p_memsz = sdp->sd_sym->st_size;
37237c478bd9Sstevel@tonic-gate 
37247c478bd9Sstevel@tonic-gate 		/*
37257c478bd9Sstevel@tonic-gate 		 * Take permisions of the segment the symbol is associated with.
37267c478bd9Sstevel@tonic-gate 		 */
3727d1827f25Srie 		aphdr = &sdp->sd_isc->is_osdesc->os_sgdesc->sg_phdr;
3728d1827f25Srie 		assert(aphdr);
3729d1827f25Srie 		phdr->p_flags = aphdr->p_flags;
3730d1827f25Srie 
3731d1827f25Srie 		DBG_CALL(Dbg_seg_entry(ofl, dtracesndx, dtracesgp));
3732d1827f25Srie 		ofl->ofl_phdr[dtracepndx] = *phdr;
3733d1827f25Srie 	}
3734d1827f25Srie 
3735d1827f25Srie 	/*
3736d1827f25Srie 	 * If we have a PT_SUNWCAP phdr, update it now from the associated
3737d1827f25Srie 	 * section information.
3738d1827f25Srie 	 */
3739d1827f25Srie 	if (capsgp && ofl->ofl_oscap) {
3740d1827f25Srie 		Phdr	*phdr = &(capsgp->sg_phdr);
3741d1827f25Srie 		Shdr	*shdr = ofl->ofl_oscap->os_shdr;
3742d1827f25Srie 
3743d1827f25Srie 		phdr->p_vaddr = shdr->sh_addr;
3744d1827f25Srie 		phdr->p_offset = shdr->sh_offset;
3745d1827f25Srie 		phdr->p_filesz = shdr->sh_size;
3746d1827f25Srie 		phdr->p_flags = PF_R;
3747d1827f25Srie 
3748d1827f25Srie 		DBG_CALL(Dbg_seg_entry(ofl, capsndx, capsgp));
3749d1827f25Srie 		ofl->ofl_phdr[cappndx] = *phdr;
37507c478bd9Sstevel@tonic-gate 	}
37517c478bd9Sstevel@tonic-gate 
37527c478bd9Sstevel@tonic-gate 	/*
37537c478bd9Sstevel@tonic-gate 	 * Update the GROUP sections.
37547c478bd9Sstevel@tonic-gate 	 */
37557c478bd9Sstevel@tonic-gate 	if (update_ogroup(ofl) == S_ERROR)
37567c478bd9Sstevel@tonic-gate 		return (S_ERROR);
37577c478bd9Sstevel@tonic-gate 
37587c478bd9Sstevel@tonic-gate 	/*
37597c478bd9Sstevel@tonic-gate 	 * Update Move Table.
37607c478bd9Sstevel@tonic-gate 	 */
37617c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osmove || ofl->ofl_issunwdata1) {
37627c478bd9Sstevel@tonic-gate 		if (update_move(ofl) == S_ERROR)
37637c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37647c478bd9Sstevel@tonic-gate 	}
37657c478bd9Sstevel@tonic-gate 
37667c478bd9Sstevel@tonic-gate 	/*
37677c478bd9Sstevel@tonic-gate 	 * Build any output headers, version information, dynamic structure and
37687c478bd9Sstevel@tonic-gate 	 * syminfo structure.
37697c478bd9Sstevel@tonic-gate 	 */
37707c478bd9Sstevel@tonic-gate 	if (update_oehdr(ofl) == S_ERROR)
37717c478bd9Sstevel@tonic-gate 		return (S_ERROR);
37727c478bd9Sstevel@tonic-gate 	if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) == FLG_OF_VERDEF)
37737c478bd9Sstevel@tonic-gate 		if (update_overdef(ofl) == S_ERROR)
37747c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37757c478bd9Sstevel@tonic-gate 	if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) == FLG_OF_VERNEED)
37767c478bd9Sstevel@tonic-gate 		if (update_overneed(ofl) == S_ERROR)
37777c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37787c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_DYNAMIC) {
37797c478bd9Sstevel@tonic-gate 		if (update_odynamic(ofl) == S_ERROR)
37807c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37817c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ossyminfo)
37827c478bd9Sstevel@tonic-gate 			if (update_osyminfo(ofl) == S_ERROR)
37837c478bd9Sstevel@tonic-gate 				return (S_ERROR);
37847c478bd9Sstevel@tonic-gate 	}
37857c478bd9Sstevel@tonic-gate 
37867c478bd9Sstevel@tonic-gate 	/*
37877c478bd9Sstevel@tonic-gate 	 * Emit Strtab diagnostics.
37887c478bd9Sstevel@tonic-gate 	 */
37895aefb655Srie 	DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osshstrtab,
37905aefb655Srie 	    ofl->ofl_shdrsttab));
37915aefb655Srie 	DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osstrtab,
37925aefb655Srie 	    ofl->ofl_strtab));
37935aefb655Srie 	DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osdynstr,
37945aefb655Srie 	    ofl->ofl_dynstrtab));
37957c478bd9Sstevel@tonic-gate 
37967c478bd9Sstevel@tonic-gate 	/*
37977c478bd9Sstevel@tonic-gate 	 * Initialize the section headers string table index within the elf
37987c478bd9Sstevel@tonic-gate 	 * header.
37997c478bd9Sstevel@tonic-gate 	 */
38007c478bd9Sstevel@tonic-gate 	/* LINTED */
38017c478bd9Sstevel@tonic-gate 	if ((shscnndx = elf_ndxscn(ofl->ofl_osshstrtab->os_scn)) <
38027c478bd9Sstevel@tonic-gate 	    SHN_LORESERVE) {
38035aefb655Srie 		ofl->ofl_nehdr->e_shstrndx =
38047c478bd9Sstevel@tonic-gate 		    /* LINTED */
38057c478bd9Sstevel@tonic-gate 		    (Half)shscnndx;
38067c478bd9Sstevel@tonic-gate 	} else {
38077c478bd9Sstevel@tonic-gate 		/*
38087c478bd9Sstevel@tonic-gate 		 * If the STRTAB section index doesn't fit into
38097c478bd9Sstevel@tonic-gate 		 * e_shstrndx, then we store it in 'shdr[0].st_link'.
38107c478bd9Sstevel@tonic-gate 		 */
38117c478bd9Sstevel@tonic-gate 		Elf_Scn	*scn;
38127c478bd9Sstevel@tonic-gate 		Shdr	*shdr0;
38135aefb655Srie 
38147c478bd9Sstevel@tonic-gate 		if ((scn = elf_getscn(ofl->ofl_elf, 0)) == NULL) {
38155aefb655Srie 			eprintf(ofl->ofl_lml, ERR_ELF,
38165aefb655Srie 			    MSG_INTL(MSG_ELF_GETSCN), ofl->ofl_name);
38177c478bd9Sstevel@tonic-gate 			return (S_ERROR);
38187c478bd9Sstevel@tonic-gate 		}
38197c478bd9Sstevel@tonic-gate 		if ((shdr0 = elf_getshdr(scn)) == NULL) {
38205aefb655Srie 			eprintf(ofl->ofl_lml, ERR_ELF,
38215aefb655Srie 			    MSG_INTL(MSG_ELF_GETSHDR), ofl->ofl_name);
38227c478bd9Sstevel@tonic-gate 			return (S_ERROR);
38237c478bd9Sstevel@tonic-gate 		}
38245aefb655Srie 		ofl->ofl_nehdr->e_shstrndx = SHN_XINDEX;
38257c478bd9Sstevel@tonic-gate 		shdr0->sh_link = shscnndx;
38267c478bd9Sstevel@tonic-gate 	}
38277c478bd9Sstevel@tonic-gate 
38287c478bd9Sstevel@tonic-gate 	return ((uintptr_t)etext);
38297c478bd9Sstevel@tonic-gate }
3830