xref: /illumos-gate/usr/src/cmd/sgs/libld/common/update.c (revision cce0e03b)
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  */
367c478bd9Sstevel@tonic-gate #include	<stdio.h>
377c478bd9Sstevel@tonic-gate #include	<string.h>
38fdf855a7Sseizo #include	<unistd.h>
395aefb655Srie #include	<debug.h>
407c478bd9Sstevel@tonic-gate #include	"msg.h"
417c478bd9Sstevel@tonic-gate #include	"_libld.h"
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
449039eeafSab  * Comparison routine used by qsort() for sorting of the global symbol list
457c478bd9Sstevel@tonic-gate  * based off of the hashbuckets the symbol will eventually be deposited in.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate static int
487c478bd9Sstevel@tonic-gate sym_hash_compare(Sym_s_list * s1, Sym_s_list * s2)
497c478bd9Sstevel@tonic-gate {
507c478bd9Sstevel@tonic-gate 	return (s1->sl_hval - s2->sl_hval);
517c478bd9Sstevel@tonic-gate }
527c478bd9Sstevel@tonic-gate 
53d579eb63Sab /*
54d579eb63Sab  * Comparison routine used by qsort() for sorting of dyn[sym|tls]sort section
55d579eb63Sab  * indices based on the address of the symbols they reference. The
56d579eb63Sab  * use of the global dynsort_compare_syms variable is needed because
57d579eb63Sab  * we need to examine the symbols the indices reference. It is safe, because
58d579eb63Sab  * the linker is single threaded.
59d579eb63Sab  */
60d579eb63Sab Sym *dynsort_compare_syms;
61d579eb63Sab 
62d579eb63Sab static int
63d579eb63Sab dynsort_compare(const void *idx1, const void *idx2)
64d579eb63Sab {
65d579eb63Sab 	Sym *s1 = dynsort_compare_syms + *((const Word *) idx1);
66d579eb63Sab 	Sym *s2 = dynsort_compare_syms + *((const Word *) idx2);
67d579eb63Sab 
68d579eb63Sab 	/*
69d579eb63Sab 	 * Note: the logical computation for this is
70d579eb63Sab 	 *	(st_value1 - st_value2)
71d579eb63Sab 	 * However, that is only correct if the address type is smaller
72d579eb63Sab 	 * than a pointer. Writing it this way makes it immune to the
73d579eb63Sab 	 * class (32 or 64-bit) of the linker.
74d579eb63Sab 	 */
75d579eb63Sab 	return ((s1->st_value < s2->st_value) ? -1 :
76d579eb63Sab 	    (s1->st_value > s2->st_value));
77d579eb63Sab }
78d579eb63Sab 
79d579eb63Sab 
80d579eb63Sab /*
81d579eb63Sab  * Scan the sorted symbols, and issue warnings if there are any duplicate
82d579eb63Sab  * values in the list. We only do this if -zverbose is set, or we are
83d579eb63Sab  * running with LD_DEBUG defined
84d579eb63Sab  *
85d579eb63Sab  * entry:
86d579eb63Sab  *	ofl - Output file descriptor
87d579eb63Sab  *	ldynsym - Pointer to start of .SUNW_ldynsym section that the
88d579eb63Sab  *		sort section indexes reference.
89d579eb63Sab  *	symsort - Pointer to start of .SUNW_dynsymsort or .SUNW_dyntlssort
90d579eb63Sab  *		section.
91d579eb63Sab  *	n - # of indices in symsort array
92d579eb63Sab  *	secname - Name of the symsort section.
93d579eb63Sab  *
94d579eb63Sab  * exit:
95d579eb63Sab  *	If the symsort section contains indexes to more than one
96d579eb63Sab  *	symbol with the same address value, a warning is issued.
97d579eb63Sab  */
98d579eb63Sab static void
99d579eb63Sab dynsort_dupwarn(Ofl_desc *ofl, Sym *ldynsym, const char *str,
100d579eb63Sab     Word *symsort, Word n, const char *secname)
101d579eb63Sab {
102d579eb63Sab 	int zverbose = (ofl->ofl_flags & FLG_OF_VERBOSE) != 0;
103d579eb63Sab 	Word ndx, cmp_ndx;
104d579eb63Sab 	Addr addr, cmp_addr;
105d579eb63Sab 
106d579eb63Sab 	/* Nothing to do if -zverbose or LD_DEBUG are not active */
107d579eb63Sab 	if (!(zverbose || DBG_ENABLED))
108d579eb63Sab 		return;
109d579eb63Sab 
110d579eb63Sab 	cmp_ndx = 0;
111d579eb63Sab 	cmp_addr = ldynsym[symsort[cmp_ndx]].st_value;
112d579eb63Sab 	for (ndx = 1; ndx < n; ndx++) {
113d579eb63Sab 		addr = ldynsym[symsort[ndx]].st_value;
114d579eb63Sab 		if (cmp_addr == addr) {
115d579eb63Sab 			if (zverbose)
116d579eb63Sab 				eprintf(ofl->ofl_lml, ERR_WARNING,
117d579eb63Sab 				    MSG_INTL(MSG_SYM_DUPSORTADDR), secname,
118d579eb63Sab 				    str + ldynsym[symsort[cmp_ndx]].st_name,
119d579eb63Sab 				    str + ldynsym[symsort[ndx]].st_name,
120d579eb63Sab 				    EC_ADDR(addr));
121d579eb63Sab 			DBG_CALL(Dbg_syms_dup_sort_addr(ofl->ofl_lml, secname,
122d579eb63Sab 			    str + ldynsym[symsort[cmp_ndx]].st_name,
123d579eb63Sab 			    str + ldynsym[symsort[ndx]].st_name,
124d579eb63Sab 			    EC_ADDR(addr)));
125d579eb63Sab 		} else {	/* Not a dup. Move reference up */
126d579eb63Sab 			cmp_ndx = ndx;
127d579eb63Sab 			cmp_addr = addr;
128d579eb63Sab 		}
129d579eb63Sab 	}
130d579eb63Sab }
131d579eb63Sab 
132d579eb63Sab 
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate  * Build and update any output symbol tables.  Here we work on all the symbol
1357c478bd9Sstevel@tonic-gate  * tables at once to reduce the duplication of symbol and string manipulation.
1367c478bd9Sstevel@tonic-gate  * Symbols and their associated strings are copied from the read-only input
1377c478bd9Sstevel@tonic-gate  * file images to the output image and their values and index's updated in the
1387c478bd9Sstevel@tonic-gate  * output image.
1397c478bd9Sstevel@tonic-gate  */
1405aefb655Srie static Addr
1417c478bd9Sstevel@tonic-gate update_osym(Ofl_desc *ofl)
1427c478bd9Sstevel@tonic-gate {
143d579eb63Sab 	/*
144d579eb63Sab 	 * There are several places in this function where we wish
145d579eb63Sab 	 * to insert a symbol index to the combined .SUNW_ldynsym/.dynsym
146d579eb63Sab 	 * symbol table into one of the two sort sections (.SUNW_dynsymsort
147d579eb63Sab 	 * or .SUNW_dyntlssort), if that symbol has the right attributes.
148d579eb63Sab 	 * This macro is used to generate the necessary code from a single
149d579eb63Sab 	 * specification.
150d579eb63Sab 	 *
151d579eb63Sab 	 * entry:
152d579eb63Sab 	 *	_sdp, _sym, _type - As per DYNSORT_COUNT. See _libld.h
153d579eb63Sab 	 *	_sym_ndx - Index that _sym will have in the combined
154d579eb63Sab 	 *		.SUNW_ldynsym/.dynsym symbol table.
155d579eb63Sab 	 */
156d579eb63Sab #define	ADD_TO_DYNSORT(_sdp, _sym, _type, _sym_ndx) \
157d579eb63Sab 	{ \
158d579eb63Sab 		Word *_dynsort_arr, *_dynsort_ndx; \
159d579eb63Sab 		\
160d579eb63Sab 		if (dynsymsort_symtype[_type]) { \
161d579eb63Sab 			_dynsort_arr = dynsymsort; \
162d579eb63Sab 			_dynsort_ndx = &dynsymsort_ndx; \
163d579eb63Sab 		} else if (_type == STT_TLS) { \
164d579eb63Sab 			_dynsort_arr = dyntlssort; \
165d579eb63Sab 			_dynsort_ndx = &dyntlssort_ndx; \
166d579eb63Sab 		} else { \
167d579eb63Sab 			_dynsort_arr = NULL; \
168d579eb63Sab 		} \
169d579eb63Sab 		if ((_dynsort_arr != NULL) && DYNSORT_TEST_ATTR(_sdp, _sym)) \
170d579eb63Sab 			_dynsort_arr[(*_dynsort_ndx)++] = _sym_ndx; \
171d579eb63Sab 	}
172d579eb63Sab 
173d579eb63Sab 
1740bc07c75Srie 	Listnode	*lnp1;
1757c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
1767c478bd9Sstevel@tonic-gate 	Sym_avlnode	*sav;
1777c478bd9Sstevel@tonic-gate 	Sg_desc		*sgp, *tsgp = 0, *dsgp = 0, *esgp = 0;
178c1c6f601Srie 	Os_desc		*osp, *iosp = 0, *fosp = 0;
1797c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
1807c478bd9Sstevel@tonic-gate 	Word		bssndx, etext_ndx, edata_ndx = 0, end_ndx, start_ndx;
1817c478bd9Sstevel@tonic-gate 	Word		end_abs = 0, etext_abs = 0, edata_abs;
1827c478bd9Sstevel@tonic-gate 	Word		tlsbssndx = 0, sunwbssndx = 0, sunwdata1ndx;
18302ca3e02Srie #if	defined(__x86) && defined(_ELF64)
18454d82594Sseizo 	Word		lbssndx = 0;
18554d82594Sseizo 	Addr		lbssaddr = 0;
18654d82594Sseizo #endif
1877c478bd9Sstevel@tonic-gate 	Addr		bssaddr, etext = 0, edata = 0, end = 0, start = 0;
1887c478bd9Sstevel@tonic-gate 	Addr		tlsbssaddr = 0;
1897c478bd9Sstevel@tonic-gate 	Addr 		sunwbssaddr = 0, sunwdata1addr;
1907c478bd9Sstevel@tonic-gate 	int		start_set = 0;
1919039eeafSab 	Sym		_sym = {0}, *sym, *symtab = 0;
1929039eeafSab 	Sym		*dynsym = 0, *ldynsym = 0;
1937c478bd9Sstevel@tonic-gate 	Word		symtab_ndx = 0;	/* index into .symtab */
1949039eeafSab 	Word		ldynsym_ndx = 0;	/* index into .SUNW_ldynsym */
1959039eeafSab 	Word		dynsym_ndx = 0;		/* index into .dynsym */
1967c478bd9Sstevel@tonic-gate 	Word		scopesym_ndx = 0; /* index into scoped symbols */
1979039eeafSab 	Word		ldynscopesym_ndx = 0; /* index to ldynsym scoped syms */
198d579eb63Sab 	Word		*dynsymsort = NULL; /* SUNW_dynsymsort index vector */
199d579eb63Sab 	Word		*dyntlssort = NULL; /* SUNW_dyntlssort index vector */
200d579eb63Sab 	Word		dynsymsort_ndx;		/* index dynsymsort array */
201d579eb63Sab 	Word		dyntlssort_ndx;		/* index dyntlssort array */
2029039eeafSab 	Word		*symndx;	/* Symbol index (for relocation use) */
2037c478bd9Sstevel@tonic-gate 	Word		*symshndx = 0;	/* .symtab_shndx table */
2047c478bd9Sstevel@tonic-gate 	Word		*dynshndx = 0;	/* .dynsym_shndx table */
2059039eeafSab 	Word		*ldynshndx = 0;	/* .SUNW_ldynsym_shndx table */
206d579eb63Sab 	Word		ldynsym_cnt = 0; /* # of items in .SUNW_ldynsym */
2077c478bd9Sstevel@tonic-gate 	Str_tbl		*shstrtab;
2087c478bd9Sstevel@tonic-gate 	Str_tbl		*strtab;
2097c478bd9Sstevel@tonic-gate 	Str_tbl		*dynstr;
2107c478bd9Sstevel@tonic-gate 	Word		*hashtab;	/* hash table pointer */
2117c478bd9Sstevel@tonic-gate 	Word		*hashbkt;	/* hash table bucket pointer */
2127c478bd9Sstevel@tonic-gate 	Word		*hashchain;	/* hash table chain pointer */
2137c478bd9Sstevel@tonic-gate 	Word		hashval;	/* value of hash function */
2147c478bd9Sstevel@tonic-gate 	Wk_desc		*wkp;
2157c478bd9Sstevel@tonic-gate 	List		weak = {NULL, NULL};
2167c478bd9Sstevel@tonic-gate 	Word		flags = ofl->ofl_flags;
2177c478bd9Sstevel@tonic-gate 	Word		dtflags_1 = ofl->ofl_dtflags_1;
2187c478bd9Sstevel@tonic-gate 	Versym		*versym;
2197c478bd9Sstevel@tonic-gate 	Gottable	*gottable;	/* used for display got debugging */
2207c478bd9Sstevel@tonic-gate 					/*	information */
2217c478bd9Sstevel@tonic-gate 	Syminfo		*syminfo;
2227c478bd9Sstevel@tonic-gate 	Sym_s_list	*sorted_syms;	/* table to hold sorted symbols */
2237c478bd9Sstevel@tonic-gate 	Word		ssndx;		/* global index into sorted_syms */
2247c478bd9Sstevel@tonic-gate 	Word		scndx;		/* scoped index into sorted_syms */
225*cce0e03bSab 	size_t		stoff;		/* string offset */
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/*
2287c478bd9Sstevel@tonic-gate 	 * Initialize pointers to the symbol table entries and the symbol
2297c478bd9Sstevel@tonic-gate 	 * table strings.  Skip the first symbol entry and the first string
2307c478bd9Sstevel@tonic-gate 	 * table byte.  Note that if we are not generating any output symbol
2317c478bd9Sstevel@tonic-gate 	 * tables we must still generate and update an internal copies so
2327c478bd9Sstevel@tonic-gate 	 * that the relocation phase has the correct information.
2337c478bd9Sstevel@tonic-gate 	 */
2347c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) ||
2357c478bd9Sstevel@tonic-gate 	    ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) {
2367c478bd9Sstevel@tonic-gate 		symtab = (Sym *)ofl->ofl_ossymtab->os_outdata->d_buf;
2377c478bd9Sstevel@tonic-gate 		symtab[symtab_ndx++] = _sym;
2387c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ossymshndx)
239d840867fSab 			symshndx =
240d840867fSab 			    (Word *)ofl->ofl_ossymshndx->os_outdata->d_buf;
2417c478bd9Sstevel@tonic-gate 	}
2429039eeafSab 	if (OFL_ALLOW_DYNSYM(ofl)) {
2437c478bd9Sstevel@tonic-gate 		dynsym = (Sym *)ofl->ofl_osdynsym->os_outdata->d_buf;
2447c478bd9Sstevel@tonic-gate 		dynsym[dynsym_ndx++] = _sym;
2459039eeafSab 		/*
2469039eeafSab 		 * If we are also constructing a .SUNW_ldynsym section
2479039eeafSab 		 * to contain local function symbols, then set it up too.
2489039eeafSab 		 */
2499039eeafSab 		if (ofl->ofl_osldynsym) {
2509039eeafSab 			ldynsym = (Sym *)ofl->ofl_osldynsym->os_outdata->d_buf;
2519039eeafSab 			ldynsym[ldynsym_ndx++] = _sym;
252d579eb63Sab 			ldynsym_cnt = 1 + ofl->ofl_dynlocscnt +
253d579eb63Sab 			    ofl->ofl_dynscopecnt;
254d579eb63Sab 
255d579eb63Sab 			/*
256d579eb63Sab 			 * If there is a SUNW_ldynsym, then there may also
257d579eb63Sab 			 * be a .SUNW_dynsymsort and/or .SUNW_dyntlssort
258d579eb63Sab 			 * sections, used to collect indices of function
259d579eb63Sab 			 * and data symbols sorted by address order.
260d579eb63Sab 			 */
261d579eb63Sab 			if (ofl->ofl_osdynsymsort) {	/* .SUNW_dynsymsort */
262d579eb63Sab 				dynsymsort = (Word *)
263d579eb63Sab 				    ofl->ofl_osdynsymsort->os_outdata->d_buf;
264d579eb63Sab 				dynsymsort_ndx = 0;
265d579eb63Sab 			}
266d579eb63Sab 			if (ofl->ofl_osdyntlssort) {	/* .SUNW_dyntlssort */
267d579eb63Sab 				dyntlssort = (Word *)
268d579eb63Sab 				    ofl->ofl_osdyntlssort->os_outdata->d_buf;
269d579eb63Sab 				dyntlssort_ndx = 0;
270d579eb63Sab 			}
2719039eeafSab 		}
2729039eeafSab 
2737c478bd9Sstevel@tonic-gate 		/*
2747c478bd9Sstevel@tonic-gate 		 * Initialize the hash table.
2757c478bd9Sstevel@tonic-gate 		 */
2767c478bd9Sstevel@tonic-gate 		hashtab = (Word *)(ofl->ofl_oshash->os_outdata->d_buf);
2777c478bd9Sstevel@tonic-gate 		hashbkt = &hashtab[2];
2787c478bd9Sstevel@tonic-gate 		hashchain = &hashtab[2 + ofl->ofl_hashbkts];
2797c478bd9Sstevel@tonic-gate 		hashtab[0] = ofl->ofl_hashbkts;
2807c478bd9Sstevel@tonic-gate 		hashtab[1] = ofl->ofl_dynshdrcnt + ofl->ofl_globcnt +
2817c478bd9Sstevel@tonic-gate 		    ofl->ofl_lregsymcnt + 1;
2827c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynshndx)
283d840867fSab 			dynshndx =
284d840867fSab 			    (Word *)ofl->ofl_osdynshndx->os_outdata->d_buf;
2859039eeafSab 		if (ofl->ofl_osldynshndx)
286d840867fSab 			ldynshndx =
287d840867fSab 			    (Word *)ofl->ofl_osldynshndx->os_outdata->d_buf;
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	/*
2917c478bd9Sstevel@tonic-gate 	 * symndx is the symbol index to be used for relocation processing.  It
2927c478bd9Sstevel@tonic-gate 	 * points to the relevant symtab's (.dynsym or .symtab) symbol ndx.
2937c478bd9Sstevel@tonic-gate 	 */
2947c478bd9Sstevel@tonic-gate 	if (dynsym)
2957c478bd9Sstevel@tonic-gate 		symndx = &dynsym_ndx;
2967c478bd9Sstevel@tonic-gate 	else
2977c478bd9Sstevel@tonic-gate 		symndx = &symtab_ndx;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	/*
3007c478bd9Sstevel@tonic-gate 	 * If we have version definitions initialize the version symbol index
3017c478bd9Sstevel@tonic-gate 	 * table.  There is one entry for each symbol which contains the symbols
3027c478bd9Sstevel@tonic-gate 	 * version index.
3037c478bd9Sstevel@tonic-gate 	 */
3047c478bd9Sstevel@tonic-gate 	if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) == FLG_OF_VERDEF) {
3057c478bd9Sstevel@tonic-gate 		versym = (Versym *)ofl->ofl_osversym->os_outdata->d_buf;
3067c478bd9Sstevel@tonic-gate 		versym[0] = 0;
3077c478bd9Sstevel@tonic-gate 	} else
3087c478bd9Sstevel@tonic-gate 		versym = 0;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	/*
3117c478bd9Sstevel@tonic-gate 	 * If syminfo section exists be prepared to fill it in.
3127c478bd9Sstevel@tonic-gate 	 */
3137c478bd9Sstevel@tonic-gate 	if (ofl->ofl_ossyminfo) {
3147c478bd9Sstevel@tonic-gate 		syminfo = ofl->ofl_ossyminfo->os_outdata->d_buf;
3157c478bd9Sstevel@tonic-gate 		syminfo[0].si_flags = SYMINFO_CURRENT;
3167c478bd9Sstevel@tonic-gate 	} else
3177c478bd9Sstevel@tonic-gate 		syminfo = 0;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	/*
3207c478bd9Sstevel@tonic-gate 	 * Setup our string tables.
3217c478bd9Sstevel@tonic-gate 	 */
3227c478bd9Sstevel@tonic-gate 	shstrtab = ofl->ofl_shdrsttab;
3237c478bd9Sstevel@tonic-gate 	strtab = ofl->ofl_strtab;
3247c478bd9Sstevel@tonic-gate 	dynstr = ofl->ofl_dynstrtab;
3257c478bd9Sstevel@tonic-gate 
3265aefb655Srie 	DBG_CALL(Dbg_syms_sec_title(ofl->ofl_lml));
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	/*
3299039eeafSab 	 * Put output file name to the first .symtab and .SUNW_ldynsym symbol.
3307c478bd9Sstevel@tonic-gate 	 */
3317c478bd9Sstevel@tonic-gate 	if (symtab) {
3327c478bd9Sstevel@tonic-gate 		(void) st_setstring(strtab, ofl->ofl_name, &stoff);
3337c478bd9Sstevel@tonic-gate 		sym = &symtab[symtab_ndx++];
3347c478bd9Sstevel@tonic-gate 		/* LINTED */
3357c478bd9Sstevel@tonic-gate 		sym->st_name = stoff;
3367c478bd9Sstevel@tonic-gate 		sym->st_value = 0;
3377c478bd9Sstevel@tonic-gate 		sym->st_size = 0;
3387c478bd9Sstevel@tonic-gate 		sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE);
3397c478bd9Sstevel@tonic-gate 		sym->st_other = 0;
3407c478bd9Sstevel@tonic-gate 		sym->st_shndx = SHN_ABS;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		if (versym && !dynsym)
3437c478bd9Sstevel@tonic-gate 			versym[1] = 0;
3447c478bd9Sstevel@tonic-gate 	}
345d579eb63Sab 	if (ldynsym) {
3469039eeafSab 		(void) st_setstring(dynstr, ofl->ofl_name, &stoff);
3479039eeafSab 		sym = &ldynsym[ldynsym_ndx];
3489039eeafSab 		/* LINTED */
3499039eeafSab 		sym->st_name = stoff;
3509039eeafSab 		sym->st_value = 0;
3519039eeafSab 		sym->st_size = 0;
3529039eeafSab 		sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE);
3539039eeafSab 		sym->st_other = 0;
3549039eeafSab 		sym->st_shndx = SHN_ABS;
3559039eeafSab 
3569039eeafSab 		/* Scoped symbols get filled in global loop below */
3579039eeafSab 		ldynscopesym_ndx = ldynsym_ndx + 1;
3589039eeafSab 		ldynsym_ndx += ofl->ofl_dynscopecnt;
3599039eeafSab 	}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/*
3627c478bd9Sstevel@tonic-gate 	 * If we are to display GOT summary information, then allocate
3637c478bd9Sstevel@tonic-gate 	 * the buffer to 'cache' the GOT symbols into now.
3647c478bd9Sstevel@tonic-gate 	 */
3655aefb655Srie 	if (DBG_ENABLED) {
366d326b23bSrie 		if ((ofl->ofl_gottable = gottable =
367d326b23bSrie 		    libld_calloc(ofl->ofl_gotcnt, sizeof (Gottable))) == 0)
3687c478bd9Sstevel@tonic-gate 		return ((Addr)S_ERROR);
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	/*
3727c478bd9Sstevel@tonic-gate 	 * Traverse the program headers.  Determine the last executable segment
3737c478bd9Sstevel@tonic-gate 	 * and the last data segment so that we can update etext and edata. If
3747c478bd9Sstevel@tonic-gate 	 * we have empty segments (reservations) record them for setting _end.
3757c478bd9Sstevel@tonic-gate 	 */
3767c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) {
3770bc07c75Srie 		Phdr	*phd = &(sgp->sg_phdr);
378*cce0e03bSab 		Os_desc	*osp;
379*cce0e03bSab 		Aliste	idx;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 		if (phd->p_type == PT_LOAD) {
3820bc07c75Srie 			if (sgp->sg_osdescs != NULL) {
383d840867fSab 				Word	_flags = phd->p_flags & (PF_W | PF_R);
3840bc07c75Srie 
385d840867fSab 				if (_flags == PF_R)
386d840867fSab 					tsgp = sgp;
387d840867fSab 				else if (_flags == (PF_W | PF_R))
388d840867fSab 					dsgp = sgp;
3897c478bd9Sstevel@tonic-gate 			} else if (sgp->sg_flags & FLG_SG_EMPTY)
390d840867fSab 				esgp = sgp;
3917c478bd9Sstevel@tonic-gate 		}
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 		/*
3947c478bd9Sstevel@tonic-gate 		 * Generate a section symbol for each output section.
3957c478bd9Sstevel@tonic-gate 		 */
396*cce0e03bSab 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) {
3977c478bd9Sstevel@tonic-gate 			Word	sectndx;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 			sym = &_sym;
4007c478bd9Sstevel@tonic-gate 			sym->st_value = osp->os_shdr->sh_addr;
4017c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION);
4027c478bd9Sstevel@tonic-gate 			/* LINTED */
4037c478bd9Sstevel@tonic-gate 			sectndx = elf_ndxscn(osp->os_scn);
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 			if (symtab) {
4067c478bd9Sstevel@tonic-gate 				if (sectndx >= SHN_LORESERVE) {
4077c478bd9Sstevel@tonic-gate 					symshndx[symtab_ndx] = sectndx;
4087c478bd9Sstevel@tonic-gate 					sym->st_shndx = SHN_XINDEX;
4097c478bd9Sstevel@tonic-gate 				} else {
4107c478bd9Sstevel@tonic-gate 					/* LINTED */
4117c478bd9Sstevel@tonic-gate 					sym->st_shndx = (Half)sectndx;
4127c478bd9Sstevel@tonic-gate 				}
4137c478bd9Sstevel@tonic-gate 				symtab[symtab_ndx++] = *sym;
4147c478bd9Sstevel@tonic-gate 			}
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 			if (dynsym && (osp->os_flags & FLG_OS_OUTREL))
4177c478bd9Sstevel@tonic-gate 				dynsym[dynsym_ndx++] = *sym;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 			if ((dynsym == 0) || (osp->os_flags & FLG_OS_OUTREL)) {
4207c478bd9Sstevel@tonic-gate 				if (versym)
4217c478bd9Sstevel@tonic-gate 					versym[*symndx - 1] = 0;
4227c478bd9Sstevel@tonic-gate 				osp->os_scnsymndx = *symndx - 1;
4235aefb655Srie 				DBG_CALL(Dbg_syms_sec_entry(ofl->ofl_lml,
4245aefb655Srie 				    osp->os_scnsymndx, sgp, osp));
4257c478bd9Sstevel@tonic-gate 			}
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 			/*
4287c478bd9Sstevel@tonic-gate 			 * Generate the .shstrtab for this section.
4297c478bd9Sstevel@tonic-gate 			 */
4307c478bd9Sstevel@tonic-gate 			(void) st_setstring(shstrtab, osp->os_name, &stoff);
4317c478bd9Sstevel@tonic-gate 			osp->os_shdr->sh_name = (Word)stoff;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 			/*
4347c478bd9Sstevel@tonic-gate 			 * Find the section index for our special symbols.
4357c478bd9Sstevel@tonic-gate 			 */
4367c478bd9Sstevel@tonic-gate 			if (sgp == tsgp) {
4377c478bd9Sstevel@tonic-gate 				/* LINTED */
4387c478bd9Sstevel@tonic-gate 				etext_ndx = elf_ndxscn(osp->os_scn);
4397c478bd9Sstevel@tonic-gate 			} else if (dsgp == sgp) {
4407c478bd9Sstevel@tonic-gate 				if (osp->os_shdr->sh_type != SHT_NOBITS) {
4417c478bd9Sstevel@tonic-gate 					/* LINTED */
4427c478bd9Sstevel@tonic-gate 					edata_ndx = elf_ndxscn(osp->os_scn);
4437c478bd9Sstevel@tonic-gate 				}
4447c478bd9Sstevel@tonic-gate 			}
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 			if (start_set == 0) {
4477c478bd9Sstevel@tonic-gate 				start = sgp->sg_phdr.p_vaddr;
4487c478bd9Sstevel@tonic-gate 				/* LINTED */
4497c478bd9Sstevel@tonic-gate 				start_ndx = elf_ndxscn(osp->os_scn);
4507c478bd9Sstevel@tonic-gate 				start_set++;
4517c478bd9Sstevel@tonic-gate 			}
452c1c6f601Srie 
453c1c6f601Srie 			/*
454c1c6f601Srie 			 * While we're here, determine whether a .init or .fini
455c1c6f601Srie 			 * section exist.
456c1c6f601Srie 			 */
457c1c6f601Srie 			if ((iosp == 0) && (strcmp(osp->os_name,
458c1c6f601Srie 			    MSG_ORIG(MSG_SCN_INIT)) == 0))
459c1c6f601Srie 				iosp = osp;
460c1c6f601Srie 			if ((fosp == 0) && (strcmp(osp->os_name,
461c1c6f601Srie 			    MSG_ORIG(MSG_SCN_FINI)) == 0))
462c1c6f601Srie 				fosp = osp;
4637c478bd9Sstevel@tonic-gate 		}
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	/*
4677c478bd9Sstevel@tonic-gate 	 * Add local register symbols to the .dynsym.  These are required as
4687c478bd9Sstevel@tonic-gate 	 * DT_REGISTER .dynamic entries must have a symbol to reference.
4697c478bd9Sstevel@tonic-gate 	 */
4707c478bd9Sstevel@tonic-gate 	if (ofl->ofl_regsyms && dynsym) {
4717c478bd9Sstevel@tonic-gate 		int	ndx;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 		for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
4747c478bd9Sstevel@tonic-gate 			Sym_desc *	rsdp;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 			if ((rsdp = ofl->ofl_regsyms[ndx]) == 0)
4777c478bd9Sstevel@tonic-gate 				continue;
4787c478bd9Sstevel@tonic-gate 
47960758829Srie 			if (((rsdp->sd_flags1 & FLG_SY1_HIDDEN) == 0) &&
4807c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(rsdp->sd_sym->st_info) != STB_LOCAL))
4817c478bd9Sstevel@tonic-gate 				continue;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 			dynsym[dynsym_ndx] = *(rsdp->sd_sym);
4847c478bd9Sstevel@tonic-gate 			rsdp->sd_symndx = *symndx;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 			if (dynsym[dynsym_ndx].st_name) {
4877c478bd9Sstevel@tonic-gate 				(void) st_setstring(dynstr, rsdp->sd_name,
4887c478bd9Sstevel@tonic-gate 				    &stoff);
4897c478bd9Sstevel@tonic-gate 				dynsym[dynsym_ndx].st_name = stoff;
4907c478bd9Sstevel@tonic-gate 			}
4917c478bd9Sstevel@tonic-gate 			dynsym_ndx++;
4927c478bd9Sstevel@tonic-gate 		}
4937c478bd9Sstevel@tonic-gate 	}
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	/*
4967c478bd9Sstevel@tonic-gate 	 * Having traversed all the output segments, warn the user if the
4977c478bd9Sstevel@tonic-gate 	 * traditional text or data segments don't exist.  Otherwise from these
4987c478bd9Sstevel@tonic-gate 	 * segments establish the values for `etext', `edata', `end', `END',
4997c478bd9Sstevel@tonic-gate 	 * and `START'.
5007c478bd9Sstevel@tonic-gate 	 */
5017c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_RELOBJ)) {
5027c478bd9Sstevel@tonic-gate 		Sg_desc *	sgp;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 		if (tsgp)
5057c478bd9Sstevel@tonic-gate 			etext = tsgp->sg_phdr.p_vaddr + tsgp->sg_phdr.p_filesz;
5067c478bd9Sstevel@tonic-gate 		else {
5077c478bd9Sstevel@tonic-gate 			etext = (Addr)0;
5087c478bd9Sstevel@tonic-gate 			etext_ndx = SHN_ABS;
5097c478bd9Sstevel@tonic-gate 			etext_abs = 1;
5107c478bd9Sstevel@tonic-gate 			if (ofl->ofl_flags & FLG_OF_VERBOSE)
5115aefb655Srie 				eprintf(ofl->ofl_lml, ERR_WARNING,
5127c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_UPD_NOREADSEG));
5137c478bd9Sstevel@tonic-gate 		}
5147c478bd9Sstevel@tonic-gate 		if (dsgp) {
5157c478bd9Sstevel@tonic-gate 			edata = dsgp->sg_phdr.p_vaddr + dsgp->sg_phdr.p_filesz;
5167c478bd9Sstevel@tonic-gate 		} else {
5177c478bd9Sstevel@tonic-gate 			edata = (Addr)0;
5187c478bd9Sstevel@tonic-gate 			edata_ndx = SHN_ABS;
5197c478bd9Sstevel@tonic-gate 			edata_abs = 1;
5207c478bd9Sstevel@tonic-gate 			if (ofl->ofl_flags & FLG_OF_VERBOSE)
5215aefb655Srie 				eprintf(ofl->ofl_lml, ERR_WARNING,
5227c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_UPD_NORDWRSEG));
5237c478bd9Sstevel@tonic-gate 		}
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 		if (dsgp == 0) {
5267c478bd9Sstevel@tonic-gate 			if (tsgp)
5277c478bd9Sstevel@tonic-gate 				sgp = tsgp;
5287c478bd9Sstevel@tonic-gate 			else
5297c478bd9Sstevel@tonic-gate 				sgp = 0;
5307c478bd9Sstevel@tonic-gate 		} else if (tsgp == 0)
5317c478bd9Sstevel@tonic-gate 			sgp = dsgp;
5327c478bd9Sstevel@tonic-gate 		else if (dsgp->sg_phdr.p_vaddr > tsgp->sg_phdr.p_vaddr)
5337c478bd9Sstevel@tonic-gate 			sgp = dsgp;
5347c478bd9Sstevel@tonic-gate 		else if (dsgp->sg_phdr.p_vaddr < tsgp->sg_phdr.p_vaddr)
5357c478bd9Sstevel@tonic-gate 			sgp = tsgp;
5367c478bd9Sstevel@tonic-gate 		else {
5377c478bd9Sstevel@tonic-gate 			/*
5387c478bd9Sstevel@tonic-gate 			 * One of the segments must be of zero size.
5397c478bd9Sstevel@tonic-gate 			 */
5407c478bd9Sstevel@tonic-gate 			if (tsgp->sg_phdr.p_memsz)
5417c478bd9Sstevel@tonic-gate 				sgp = tsgp;
5427c478bd9Sstevel@tonic-gate 			else
5437c478bd9Sstevel@tonic-gate 				sgp = dsgp;
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		if (esgp && (esgp->sg_phdr.p_vaddr > sgp->sg_phdr.p_vaddr))
5477c478bd9Sstevel@tonic-gate 			sgp = esgp;
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 		if (sgp) {
5507c478bd9Sstevel@tonic-gate 			end = sgp->sg_phdr.p_vaddr + sgp->sg_phdr.p_memsz;
5517c478bd9Sstevel@tonic-gate 
552fdf855a7Sseizo 			/*
553fdf855a7Sseizo 			 * If the last loadable segment is a read-only segment,
554fdf855a7Sseizo 			 * then the application which uses the symbol _end to
555fdf855a7Sseizo 			 * find the beginning of writable heap area may cause
556fdf855a7Sseizo 			 * segmentation violation. We adjust the value of the
557fdf855a7Sseizo 			 * _end to skip to the next page boundary.
558fdf855a7Sseizo 			 *
559fdf855a7Sseizo 			 * 6401812 System interface which returs beginning
560fdf855a7Sseizo 			 *	   heap would be nice.
561fdf855a7Sseizo 			 * When the above RFE is implemented, the changes below
562fdf855a7Sseizo 			 * could be changed in a better way.
563fdf855a7Sseizo 			 */
564fdf855a7Sseizo 			if ((sgp->sg_phdr.p_flags & PF_W) == 0)
56560758829Srie 				end = (Addr)S_ROUND(end, sysconf(_SC_PAGESIZE));
566fdf855a7Sseizo 
5677c478bd9Sstevel@tonic-gate 			/*
5687c478bd9Sstevel@tonic-gate 			 * If we're dealing with a memory reservation there are
5697c478bd9Sstevel@tonic-gate 			 * no sections to establish an index for _end, so assign
5707c478bd9Sstevel@tonic-gate 			 * it as an absolute.
5717c478bd9Sstevel@tonic-gate 			 */
5720bc07c75Srie 			if (sgp->sg_osdescs != NULL) {
5730bc07c75Srie 				/*
5740bc07c75Srie 				 * Determine the last section for this segment.
5750bc07c75Srie 				 */
576*cce0e03bSab 				Os_desc	*osp = sgp->sg_osdescs->apl_data
577*cce0e03bSab 				    [sgp->sg_osdescs->apl_nitems - 1];
578*cce0e03bSab 
5790bc07c75Srie 				/* LINTED */
580*cce0e03bSab 				end_ndx = elf_ndxscn(osp->os_scn);
5817c478bd9Sstevel@tonic-gate 			} else {
5827c478bd9Sstevel@tonic-gate 				end_ndx = SHN_ABS;
5837c478bd9Sstevel@tonic-gate 				end_abs = 1;
5847c478bd9Sstevel@tonic-gate 			}
5857c478bd9Sstevel@tonic-gate 		} else {
5867c478bd9Sstevel@tonic-gate 			end = (Addr) 0;
5877c478bd9Sstevel@tonic-gate 			end_ndx = SHN_ABS;
5887c478bd9Sstevel@tonic-gate 			end_abs = 1;
5895aefb655Srie 			eprintf(ofl->ofl_lml, ERR_WARNING,
5905aefb655Srie 			    MSG_INTL(MSG_UPD_NOSEG));
5917c478bd9Sstevel@tonic-gate 		}
5927c478bd9Sstevel@tonic-gate 	}
5937c478bd9Sstevel@tonic-gate 
5945aefb655Srie 	DBG_CALL(Dbg_syms_up_title(ofl->ofl_lml));
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/*
5977c478bd9Sstevel@tonic-gate 	 * Initialize the scoped symbol table entry point.  This is for all
5987c478bd9Sstevel@tonic-gate 	 * the global symbols that have been scoped to locals and will be
5997c478bd9Sstevel@tonic-gate 	 * filled in during global symbol processing so that we don't have
6007c478bd9Sstevel@tonic-gate 	 * to traverse the globals symbol hash array more than once.
6017c478bd9Sstevel@tonic-gate 	 */
6027c478bd9Sstevel@tonic-gate 	if (symtab) {
6037c478bd9Sstevel@tonic-gate 		scopesym_ndx = symtab_ndx;
6047c478bd9Sstevel@tonic-gate 		symtab_ndx += ofl->ofl_scopecnt;
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	/*
6087c478bd9Sstevel@tonic-gate 	 * Assign .sunwdata1 information
6097c478bd9Sstevel@tonic-gate 	 */
6107c478bd9Sstevel@tonic-gate 	if (ofl->ofl_issunwdata1) {
6117c478bd9Sstevel@tonic-gate 		osp = ofl->ofl_issunwdata1->is_osdesc;
6127c478bd9Sstevel@tonic-gate 		sunwdata1addr = (Addr)(osp->os_shdr->sh_addr +
613d840867fSab 		    ofl->ofl_issunwdata1->is_indata->d_off);
6147c478bd9Sstevel@tonic-gate 		/* LINTED */
6157c478bd9Sstevel@tonic-gate 		sunwdata1ndx = elf_ndxscn(osp->os_scn);
6167c478bd9Sstevel@tonic-gate 		ofl->ofl_sunwdata1ndx = osp->os_scnsymndx;
6177c478bd9Sstevel@tonic-gate 	}
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	/*
6207c478bd9Sstevel@tonic-gate 	 * If we are generating a .symtab collect all the local symbols,
6217c478bd9Sstevel@tonic-gate 	 * assigning a new virtual address or displacement (value).
6227c478bd9Sstevel@tonic-gate 	 */
6237c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_objs, lnp1, ifl)) {
6247c478bd9Sstevel@tonic-gate 		Xword		lndx, local;
6257c478bd9Sstevel@tonic-gate 		Is_desc *	isc;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 		/*
6287c478bd9Sstevel@tonic-gate 		 * Check that we have local symbols to process.  If the user
6297c478bd9Sstevel@tonic-gate 		 * has indicated scoping then scan the global symbols also
6307c478bd9Sstevel@tonic-gate 		 * looking for entries from this file to reduce to locals.
6317c478bd9Sstevel@tonic-gate 		 */
6327c478bd9Sstevel@tonic-gate 		if ((local = ifl->ifl_locscnt) == 0)
6337c478bd9Sstevel@tonic-gate 			continue;
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 		for (lndx = 1; lndx < local; lndx++) {
6367c478bd9Sstevel@tonic-gate 			Listnode	*lnp2;
6377c478bd9Sstevel@tonic-gate 			Gotndx		*gnp;
638d579eb63Sab 			uchar_t		type;
6397c478bd9Sstevel@tonic-gate 			Word		*_symshndx;
6409039eeafSab 			int		enter_in_symtab, enter_in_ldynsym;
6419039eeafSab 			int		update_done;
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 			sdp = ifl->ifl_oldndx[lndx];
6447c478bd9Sstevel@tonic-gate 			sym = sdp->sd_sym;
6457c478bd9Sstevel@tonic-gate 
64602ca3e02Srie #if	defined(__sparc)
6477c478bd9Sstevel@tonic-gate 			/*
6487c478bd9Sstevel@tonic-gate 			 * Assign a got offset if necessary.
6497c478bd9Sstevel@tonic-gate 			 */
6505aefb655Srie 			if (ld_assign_got(ofl, sdp) == S_ERROR)
6517c478bd9Sstevel@tonic-gate 				return ((Addr)S_ERROR);
65202ca3e02Srie #elif	defined(__x86)
6537c478bd9Sstevel@tonic-gate /* nothing to do */
6547c478bd9Sstevel@tonic-gate #else
6557c478bd9Sstevel@tonic-gate #error Unknown architecture!
6567c478bd9Sstevel@tonic-gate #endif
6575aefb655Srie 			if (DBG_ENABLED) {
658d840867fSab 				for (LIST_TRAVERSE(&sdp->sd_GOTndxs,
659d840867fSab 				    lnp2, gnp)) {
660d840867fSab 					gottable->gt_sym = sdp;
661d840867fSab 					gottable->gt_gndx.gn_gotndx =
662d840867fSab 					    gnp->gn_gotndx;
663d840867fSab 					gottable->gt_gndx.gn_addend =
664d840867fSab 					    gnp->gn_addend;
665d840867fSab 					gottable++;
666d840867fSab 				}
6677c478bd9Sstevel@tonic-gate 			}
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 			if ((type = ELF_ST_TYPE(sym->st_info)) == STT_SECTION)
6707c478bd9Sstevel@tonic-gate 				continue;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 			/*
6737c478bd9Sstevel@tonic-gate 			 * Ignore any symbols that have been marked as invalid
6747c478bd9Sstevel@tonic-gate 			 * during input processing.  Providing these aren't used
6757c478bd9Sstevel@tonic-gate 			 * for relocation they'll just be dropped from the
6767c478bd9Sstevel@tonic-gate 			 * output image.
6777c478bd9Sstevel@tonic-gate 			 */
6787c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_INVALID)
6797c478bd9Sstevel@tonic-gate 				continue;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 			/*
6827c478bd9Sstevel@tonic-gate 			 * If the section that this symbol was associated
6837c478bd9Sstevel@tonic-gate 			 * with has been discarded - then we discard
6847c478bd9Sstevel@tonic-gate 			 * the local symbol along with it.
6857c478bd9Sstevel@tonic-gate 			 */
6867c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_ISDISC)
6877c478bd9Sstevel@tonic-gate 				continue;
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 			/*
6907c478bd9Sstevel@tonic-gate 			 * Generate an output symbol to represent this input
6917c478bd9Sstevel@tonic-gate 			 * symbol.  Even if the symbol table is to be stripped
6927c478bd9Sstevel@tonic-gate 			 * we still need to update any local symbols that are
6937c478bd9Sstevel@tonic-gate 			 * used during relocation.
6947c478bd9Sstevel@tonic-gate 			 */
6959039eeafSab 			enter_in_symtab = symtab &&
6969039eeafSab 			    (!(ofl->ofl_flags1 & FLG_OF1_REDLSYM) ||
6979039eeafSab 			    (sdp->sd_psyminfo));
6989039eeafSab 			enter_in_ldynsym = ldynsym && sdp->sd_name &&
699d579eb63Sab 			    ldynsym_symtype[type] &&
700d579eb63Sab 			    !(ofl->ofl_flags1 & FLG_OF1_REDLSYM);
7017c478bd9Sstevel@tonic-gate 			_symshndx = 0;
7029039eeafSab 			if (enter_in_symtab) {
7037c478bd9Sstevel@tonic-gate 				if (!dynsym)
7047c478bd9Sstevel@tonic-gate 					sdp->sd_symndx = *symndx;
7057c478bd9Sstevel@tonic-gate 				symtab[symtab_ndx] = *sym;
7067c478bd9Sstevel@tonic-gate 				/*
7077c478bd9Sstevel@tonic-gate 				 * Provided this isn't an unnamed register
7087c478bd9Sstevel@tonic-gate 				 * symbol, update its name.
7097c478bd9Sstevel@tonic-gate 				 */
7107c478bd9Sstevel@tonic-gate 				if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) ||
7117c478bd9Sstevel@tonic-gate 				    symtab[symtab_ndx].st_name) {
7127c478bd9Sstevel@tonic-gate 					(void) st_setstring(strtab,
7137c478bd9Sstevel@tonic-gate 					    sdp->sd_name, &stoff);
7147c478bd9Sstevel@tonic-gate 					symtab[symtab_ndx].st_name = stoff;
7157c478bd9Sstevel@tonic-gate 				}
7167c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_CLEAN;
7177c478bd9Sstevel@tonic-gate 				if (symshndx)
7187c478bd9Sstevel@tonic-gate 					_symshndx = &symshndx[symtab_ndx];
7197c478bd9Sstevel@tonic-gate 				sdp->sd_sym = sym = &symtab[symtab_ndx++];
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 				if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
7229039eeafSab 				    (sym->st_shndx == SHN_ABS) &&
7239039eeafSab 				    !enter_in_ldynsym)
7247c478bd9Sstevel@tonic-gate 					continue;
7259039eeafSab 			} else if (enter_in_ldynsym) {
7269039eeafSab 				/*
7279039eeafSab 				 * Not using symtab, but we do have ldynsym
7289039eeafSab 				 * available.
7299039eeafSab 				 */
7309039eeafSab 				ldynsym[ldynsym_ndx] = *sym;
7319039eeafSab 				(void) st_setstring(dynstr, sdp->sd_name,
732d840867fSab 				    &stoff);
7339039eeafSab 				ldynsym[ldynsym_ndx].st_name = stoff;
7349039eeafSab 
7359039eeafSab 				sdp->sd_flags &= ~FLG_SY_CLEAN;
7369039eeafSab 				if (ldynshndx)
7379039eeafSab 					_symshndx = &ldynshndx[ldynsym_ndx];
738d579eb63Sab 				sdp->sd_sym = sym = &ldynsym[ldynsym_ndx];
739d579eb63Sab 				/* Add it to sort section if it qualifies */
740d579eb63Sab 				ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx);
741d579eb63Sab 				ldynsym_ndx++;
7429039eeafSab 			} else {	/* Not using symtab or ldynsym */
7437c478bd9Sstevel@tonic-gate 				/*
7447c478bd9Sstevel@tonic-gate 				 * If this symbol requires modifying to provide
7457c478bd9Sstevel@tonic-gate 				 * for a relocation or move table update, make
7467c478bd9Sstevel@tonic-gate 				 * a copy of it.
7477c478bd9Sstevel@tonic-gate 				 */
7487c478bd9Sstevel@tonic-gate 				if (!(sdp->sd_flags & FLG_SY_UPREQD) &&
7497c478bd9Sstevel@tonic-gate 				    !(sdp->sd_psyminfo))
7507c478bd9Sstevel@tonic-gate 					continue;
7517c478bd9Sstevel@tonic-gate 				if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
7527c478bd9Sstevel@tonic-gate 				    (sym->st_shndx == SHN_ABS))
7537c478bd9Sstevel@tonic-gate 					continue;
7547c478bd9Sstevel@tonic-gate 
7555aefb655Srie 				if (ld_sym_copy(sdp) == S_ERROR)
7567c478bd9Sstevel@tonic-gate 					return ((Addr)S_ERROR);
7577c478bd9Sstevel@tonic-gate 				sym = sdp->sd_sym;
7587c478bd9Sstevel@tonic-gate 			}
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 			/*
7617c478bd9Sstevel@tonic-gate 			 * Update the symbols contents if necessary.
7627c478bd9Sstevel@tonic-gate 			 */
7639039eeafSab 			update_done = 0;
7647c478bd9Sstevel@tonic-gate 			if (type == STT_FILE) {
7657c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = sym->st_shndx = SHN_ABS;
7667c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_SPECSEC;
7679039eeafSab 				update_done = 1;
7687c478bd9Sstevel@tonic-gate 			}
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 			/*
7717c478bd9Sstevel@tonic-gate 			 * If we are expanding the locally bound partially
7727c478bd9Sstevel@tonic-gate 			 * initialized symbols, then update the address here.
7737c478bd9Sstevel@tonic-gate 			 */
7747c478bd9Sstevel@tonic-gate 			if (ofl->ofl_issunwdata1 &&
7759039eeafSab 			    (sdp->sd_flags & FLG_SY_PAREXPN) && !update_done) {
7767c478bd9Sstevel@tonic-gate 				static	Addr	laddr = 0;
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 				sym->st_shndx = sunwdata1ndx;
7797c478bd9Sstevel@tonic-gate 				sdp->sd_isc = ofl->ofl_issunwdata1;
7809039eeafSab 				if (ofl->ofl_flags & FLG_OF_RELOBJ) {
7817c478bd9Sstevel@tonic-gate 					sym->st_value = sunwdata1addr;
7829039eeafSab 				} else {
7837c478bd9Sstevel@tonic-gate 					sym->st_value = laddr;
7847c478bd9Sstevel@tonic-gate 					laddr += sym->st_size;
7857c478bd9Sstevel@tonic-gate 				}
7867c478bd9Sstevel@tonic-gate 				sunwdata1addr += sym->st_size;
7877c478bd9Sstevel@tonic-gate 			}
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 			/*
7907c478bd9Sstevel@tonic-gate 			 * If this isn't an UNDEF symbol (ie. an input section
7917c478bd9Sstevel@tonic-gate 			 * is associated), update the symbols value and index.
7927c478bd9Sstevel@tonic-gate 			 */
7939039eeafSab 			if (((isc = sdp->sd_isc) != 0) && !update_done) {
7947c478bd9Sstevel@tonic-gate 				Word	sectndx;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 				osp = isc->is_osdesc;
7977c478bd9Sstevel@tonic-gate 				/* LINTED */
7987c478bd9Sstevel@tonic-gate 				sym->st_value +=
7997c478bd9Sstevel@tonic-gate 				    (Off)_elf_getxoff(isc->is_indata);
8007c478bd9Sstevel@tonic-gate 				if (!(flags & FLG_OF_RELOBJ)) {
8017c478bd9Sstevel@tonic-gate 					sym->st_value += osp->os_shdr->sh_addr;
8027c478bd9Sstevel@tonic-gate 					/*
8037c478bd9Sstevel@tonic-gate 					 * TLS symbols are relative to
8047c478bd9Sstevel@tonic-gate 					 * the TLS segment.
8057c478bd9Sstevel@tonic-gate 					 */
806d579eb63Sab 					if ((type == STT_TLS) &&
807d579eb63Sab 					    (ofl->ofl_tlsphdr)) {
8087c478bd9Sstevel@tonic-gate 						sym->st_value -=
8097c478bd9Sstevel@tonic-gate 						    ofl->ofl_tlsphdr->p_vaddr;
8109039eeafSab 					}
8117c478bd9Sstevel@tonic-gate 				}
8127c478bd9Sstevel@tonic-gate 				/* LINTED */
8137c478bd9Sstevel@tonic-gate 				if ((sdp->sd_shndx = sectndx =
8147c478bd9Sstevel@tonic-gate 				    elf_ndxscn(osp->os_scn)) >= SHN_LORESERVE) {
8157c478bd9Sstevel@tonic-gate 					if (_symshndx) {
8167c478bd9Sstevel@tonic-gate 						*_symshndx = sectndx;
8177c478bd9Sstevel@tonic-gate 					}
8187c478bd9Sstevel@tonic-gate 					sym->st_shndx = SHN_XINDEX;
8197c478bd9Sstevel@tonic-gate 				} else {
8207c478bd9Sstevel@tonic-gate 					/* LINTED */
8217c478bd9Sstevel@tonic-gate 					sym->st_shndx = sectndx;
8227c478bd9Sstevel@tonic-gate 				}
8237c478bd9Sstevel@tonic-gate 			}
8249039eeafSab 
8259039eeafSab 			/*
8269039eeafSab 			 * If entering the symbol in both the symtab and the
8279039eeafSab 			 * ldynsym, then the one in symtab needs to be
8289039eeafSab 			 * copied to ldynsym. If it is only in the ldynsym,
8299039eeafSab 			 * then the code above already set it up and we have
8309039eeafSab 			 * nothing more to do here.
8319039eeafSab 			 */
8329039eeafSab 			if (enter_in_symtab && enter_in_ldynsym) {
8339039eeafSab 				ldynsym[ldynsym_ndx] = *sym;
8349039eeafSab 				(void) st_setstring(dynstr, sdp->sd_name,
835d840867fSab 				    &stoff);
8369039eeafSab 				ldynsym[ldynsym_ndx].st_name = stoff;
8379039eeafSab 
8389039eeafSab 				if (_symshndx && ldynshndx)
8399039eeafSab 					ldynshndx[ldynsym_ndx] = *_symshndx;
8409039eeafSab 
841d579eb63Sab 				/* Add it to sort section if it qualifies */
842d579eb63Sab 				ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx);
843d579eb63Sab 
8449039eeafSab 				ldynsym_ndx++;
8459039eeafSab 			}
8467c478bd9Sstevel@tonic-gate 		}
8477c478bd9Sstevel@tonic-gate 	}
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	/*
8507c478bd9Sstevel@tonic-gate 	 * Two special symbols are `_init' and `_fini'.  If these are supplied
8517c478bd9Sstevel@tonic-gate 	 * by crti.o then they are used to represent the total concatenation of
852c1c6f601Srie 	 * the `.init' and `.fini' sections.
853c1c6f601Srie 	 *
854c1c6f601Srie 	 * First, determine whether any .init or .fini sections exist.  If these
855c1c6f601Srie 	 * sections exist when a dynamic object is being built, but no `_init'
856c1c6f601Srie 	 * or `_fini' symbols are found, then the user is probably building this
857c1c6f601Srie 	 * object directly from ld(1) rather than using a compiler driver that
858c1c6f601Srie 	 * provides the symbols via crt's.
859c1c6f601Srie 	 *
860c1c6f601Srie 	 * If the .init or .fini section exist, and their associated symbols,
861c1c6f601Srie 	 * determine the size of the sections and updated the symbols value
862c1c6f601Srie 	 * accordingly.
8637c478bd9Sstevel@tonic-gate 	 */
8645aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U), SYM_NOHASH, 0,
8657c478bd9Sstevel@tonic-gate 	    ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc &&
866c1c6f601Srie 	    (sdp->sd_isc->is_osdesc == iosp)) {
8675aefb655Srie 		if (ld_sym_copy(sdp) == S_ERROR)
8687c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
86960758829Srie 		sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size;
87060758829Srie 
871c1c6f601Srie 	} else if (iosp && !(flags & FLG_OF_RELOBJ)) {
872c1c6f601Srie 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT),
873c1c6f601Srie 		    MSG_ORIG(MSG_SYM_INIT_U), MSG_ORIG(MSG_SCN_INIT));
8747c478bd9Sstevel@tonic-gate 	}
875c1c6f601Srie 
8765aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U), SYM_NOHASH, 0,
8777c478bd9Sstevel@tonic-gate 	    ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc &&
878c1c6f601Srie 	    (sdp->sd_isc->is_osdesc == fosp)) {
8795aefb655Srie 		if (ld_sym_copy(sdp) == S_ERROR)
8807c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
88160758829Srie 		sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size;
88260758829Srie 
883c1c6f601Srie 	} else if (fosp && !(flags & FLG_OF_RELOBJ)) {
884c1c6f601Srie 		eprintf(ofl->ofl_lml, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT),
885c1c6f601Srie 		    MSG_ORIG(MSG_SYM_FINI_U), MSG_ORIG(MSG_SCN_FINI));
8867c478bd9Sstevel@tonic-gate 	}
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 	/*
8897c478bd9Sstevel@tonic-gate 	 * Assign .bss information for use with updating COMMON symbols.
8907c478bd9Sstevel@tonic-gate 	 */
8917c478bd9Sstevel@tonic-gate 	if (ofl->ofl_isbss) {
8927c478bd9Sstevel@tonic-gate 		osp = ofl->ofl_isbss->is_osdesc;
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 		bssaddr = osp->os_shdr->sh_addr +
895d840867fSab 		    (Off)_elf_getxoff(ofl->ofl_isbss->is_indata);
8967c478bd9Sstevel@tonic-gate 		/* LINTED */
8977c478bd9Sstevel@tonic-gate 		bssndx = elf_ndxscn(osp->os_scn);
8987c478bd9Sstevel@tonic-gate 	}
8997c478bd9Sstevel@tonic-gate 
90054d82594Sseizo #if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
90154d82594Sseizo 	/*
90254d82594Sseizo 	 * Assign .lbss information for use with updating LCOMMON symbols.
90354d82594Sseizo 	 */
90454d82594Sseizo 	if (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) &&
10287c478bd9Sstevel@tonic-gate 			    (ofl->ofl_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 			}
106654d82594Sseizo #if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
106754d82594Sseizo 		} else if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
106854d82594Sseizo 		    ((sdp->sd_shndx = symptr->st_shndx) ==
106954d82594Sseizo 		    SHN_X86_64_LCOMMON) &&
107054d82594Sseizo 		    ((local || !(flags & FLG_OF_RELOBJ)))) {
107154d82594Sseizo 			restore = 1;
107254d82594Sseizo 			sdp->sd_shndx = lbssndx;
107354d82594Sseizo 			sdp->sd_flags &= ~FLG_SY_SPECSEC;
107460758829Srie 			symptr->st_value = (Xword)S_ROUND(lbssaddr,
1075d840867fSab 			    symptr->st_value);
107654d82594Sseizo 			lbssaddr = symptr->st_value + symptr->st_size;
107754d82594Sseizo 			sdp->sd_isc = ofl->ofl_islbss;
107854d82594Sseizo 			sdp->sd_flags |= FLG_SY_COMMEXP;
107954d82594Sseizo #endif
108054d82594Sseizo 		}
10817c478bd9Sstevel@tonic-gate 
108254d82594Sseizo 		if (restore != 0) {
1083d579eb63Sab 			uchar_t		type, bind;
1084c1c6f601Srie 
108554d82594Sseizo 			/*
1086c1c6f601Srie 			 * Make sure this COMMON symbol is returned to the same
1087c1c6f601Srie 			 * binding as was defined in the original relocatable
108854d82594Sseizo 			 * object reference.
108954d82594Sseizo 			 */
109054d82594Sseizo 			type = ELF_ST_TYPE(symptr->st_info);
109154d82594Sseizo 			if (sdp->sd_flags & FLG_SY_GLOBREF)
109254d82594Sseizo 				bind = STB_GLOBAL;
109354d82594Sseizo 			else
109454d82594Sseizo 				bind = STB_WEAK;
10957c478bd9Sstevel@tonic-gate 
109654d82594Sseizo 			symptr->st_info = ELF_ST_INFO(bind, type);
10977c478bd9Sstevel@tonic-gate 		}
10987c478bd9Sstevel@tonic-gate 	}
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	if (ofl->ofl_hashbkts) {
11017c478bd9Sstevel@tonic-gate 		qsort(sorted_syms + ofl->ofl_scopecnt + ofl->ofl_elimcnt,
11027c478bd9Sstevel@tonic-gate 		    ofl->ofl_globcnt, sizeof (Sym_s_list),
11037c478bd9Sstevel@tonic-gate 		    (int (*)(const void *, const void *))sym_hash_compare);
11047c478bd9Sstevel@tonic-gate 	}
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 	for (ssndx = 0; ssndx < (ofl->ofl_elimcnt + ofl->ofl_scopecnt +
11077c478bd9Sstevel@tonic-gate 	    ofl->ofl_globcnt); ssndx++) {
11087c478bd9Sstevel@tonic-gate 		const char	*name;
11097c478bd9Sstevel@tonic-gate 		Sym		*sym;
11107c478bd9Sstevel@tonic-gate 		Sym_aux		*sap;
11117c478bd9Sstevel@tonic-gate 		Half		spec;
11129039eeafSab 		int		local = 0, dynlocal = 0, enter_in_symtab;
11137c478bd9Sstevel@tonic-gate 		Listnode	*lnp2;
11147c478bd9Sstevel@tonic-gate 		Gotndx		*gnp;
11157c478bd9Sstevel@tonic-gate 		Word		sectndx;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 		sdp = sorted_syms[ssndx].sl_sdp;
11187c478bd9Sstevel@tonic-gate 		sectndx = 0;
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 		if (symtab)
11217c478bd9Sstevel@tonic-gate 			enter_in_symtab = 1;
11227c478bd9Sstevel@tonic-gate 		else
11237c478bd9Sstevel@tonic-gate 			enter_in_symtab = 0;
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 		/*
11267c478bd9Sstevel@tonic-gate 		 * Assign a got offset if necessary.
11277c478bd9Sstevel@tonic-gate 		 */
112802ca3e02Srie #if	defined(__sparc)
11295aefb655Srie 		if (ld_assign_got(ofl, sdp) == S_ERROR)
11307c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
113102ca3e02Srie #elif	defined(__x86)
11327c478bd9Sstevel@tonic-gate /* nothing to do */
11337c478bd9Sstevel@tonic-gate #else
11347c478bd9Sstevel@tonic-gate #error Unknown architecture!
11357c478bd9Sstevel@tonic-gate #endif
1136c1c6f601Srie 
11375aefb655Srie 		if (DBG_ENABLED) {
11387c478bd9Sstevel@tonic-gate 			for (LIST_TRAVERSE(&sdp->sd_GOTndxs, lnp2, gnp)) {
1139d326b23bSrie 				gottable->gt_sym = sdp;
1140d326b23bSrie 				gottable->gt_gndx.gn_gotndx = gnp->gn_gotndx;
1141d326b23bSrie 				gottable->gt_gndx.gn_addend = gnp->gn_addend;
1142d326b23bSrie 				gottable++;
11437c478bd9Sstevel@tonic-gate 			}
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 			if (sdp->sd_aux && sdp->sd_aux->sa_PLTGOTndx) {
1146d326b23bSrie 				gottable->gt_sym = sdp;
1147d326b23bSrie 				gottable->gt_gndx.gn_gotndx =
11487c478bd9Sstevel@tonic-gate 				    sdp->sd_aux->sa_PLTGOTndx;
1149d326b23bSrie 				gottable++;
11507c478bd9Sstevel@tonic-gate 			}
11517c478bd9Sstevel@tonic-gate 		}
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 		/*
11557c478bd9Sstevel@tonic-gate 		 * If this symbol has been marked as being reduced to local
11567c478bd9Sstevel@tonic-gate 		 * scope then it will have to be placed in the scoped portion
11577c478bd9Sstevel@tonic-gate 		 * of the .symtab.  Retain the appropriate index for use in
11587c478bd9Sstevel@tonic-gate 		 * version symbol indexing and relocation.
11597c478bd9Sstevel@tonic-gate 		 */
116060758829Srie 		if ((sdp->sd_flags1 & (FLG_SY1_HIDDEN | FLG_SY1_ELIM)) &&
11617c478bd9Sstevel@tonic-gate 		    (flags & FLG_OF_PROCRED)) {
11627c478bd9Sstevel@tonic-gate 			local = 1;
11637c478bd9Sstevel@tonic-gate 			if (!(sdp->sd_flags1 & FLG_SY1_ELIM) && !dynsym)
11647c478bd9Sstevel@tonic-gate 				sdp->sd_symndx = scopesym_ndx;
11657c478bd9Sstevel@tonic-gate 			else
11667c478bd9Sstevel@tonic-gate 				sdp->sd_symndx = 0;
11677c478bd9Sstevel@tonic-gate 
11689039eeafSab 			if (sdp->sd_flags1 & FLG_SY1_ELIM) {
11697c478bd9Sstevel@tonic-gate 				enter_in_symtab = 0;
11709039eeafSab 			} else if (ldynsym && sdp->sd_sym->st_name &&
1171d579eb63Sab 			    ldynsym_symtype[
1172d579eb63Sab 			    ELF_ST_TYPE(sdp->sd_sym->st_info)]) {
11739039eeafSab 				dynlocal = 1;
11749039eeafSab 			}
11759039eeafSab 		} else {
11767c478bd9Sstevel@tonic-gate 			sdp->sd_symndx = *symndx;
11779039eeafSab 		}
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 		/*
11807c478bd9Sstevel@tonic-gate 		 * Copy basic symbol and string information.
11817c478bd9Sstevel@tonic-gate 		 */
11827c478bd9Sstevel@tonic-gate 		name = sdp->sd_name;
11837c478bd9Sstevel@tonic-gate 		sap = sdp->sd_aux;
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 		/*
11867c478bd9Sstevel@tonic-gate 		 * If we require to record version symbol indexes, update the
11877c478bd9Sstevel@tonic-gate 		 * associated version symbol information for all defined
11887c478bd9Sstevel@tonic-gate 		 * symbols.  If a version definition is required any zero value
11897c478bd9Sstevel@tonic-gate 		 * symbol indexes would have been flagged as undefined symbol
11907c478bd9Sstevel@tonic-gate 		 * errors, however if we're just scoping these need to fall into
11917c478bd9Sstevel@tonic-gate 		 * the base of global symbols.
11927c478bd9Sstevel@tonic-gate 		 */
11937c478bd9Sstevel@tonic-gate 		if (sdp->sd_symndx && versym) {
11947c478bd9Sstevel@tonic-gate 			Half	vndx = 0;
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_MVTOCOMM)
11977c478bd9Sstevel@tonic-gate 				vndx = VER_NDX_GLOBAL;
11987c478bd9Sstevel@tonic-gate 			else if (sdp->sd_ref == REF_REL_NEED) {
11997c478bd9Sstevel@tonic-gate 				Half	symflags1 = sdp->sd_flags1;
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 				vndx = sap->sa_overndx;
12027c478bd9Sstevel@tonic-gate 				if ((vndx == 0) &&
12037c478bd9Sstevel@tonic-gate 				    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
120460758829Srie 					if (symflags1 & FLG_SY1_HIDDEN)
12057c478bd9Sstevel@tonic-gate 						vndx = VER_NDX_LOCAL;
12067c478bd9Sstevel@tonic-gate 					else
12077c478bd9Sstevel@tonic-gate 						vndx = VER_NDX_GLOBAL;
12087c478bd9Sstevel@tonic-gate 				}
12097c478bd9Sstevel@tonic-gate 			}
12107c478bd9Sstevel@tonic-gate 			versym[sdp->sd_symndx] = vndx;
12117c478bd9Sstevel@tonic-gate 		}
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate 		/*
12147c478bd9Sstevel@tonic-gate 		 * If we are creating the .syminfo section then set per symbol
12157c478bd9Sstevel@tonic-gate 		 * flags here.
12167c478bd9Sstevel@tonic-gate 		 */
12177c478bd9Sstevel@tonic-gate 		if (sdp->sd_symndx && syminfo &&
12187c478bd9Sstevel@tonic-gate 		    !(sdp->sd_flags & FLG_SY_NOTAVAIL)) {
12197c478bd9Sstevel@tonic-gate 			int	ndx = sdp->sd_symndx;
12207c478bd9Sstevel@tonic-gate 			List	*sip = &(ofl->ofl_syminfsyms);
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_MVTOCOMM)
12237c478bd9Sstevel@tonic-gate 				/*
12247c478bd9Sstevel@tonic-gate 				 * Identify a copy relocation symbol.
12257c478bd9Sstevel@tonic-gate 				 */
12267c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_COPY;
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate 			if (sdp->sd_ref == REF_DYN_NEED) {
12297c478bd9Sstevel@tonic-gate 				/*
12307c478bd9Sstevel@tonic-gate 				 * A reference is bound to a needed dependency.
12317c478bd9Sstevel@tonic-gate 				 * Save this symbol descriptor, as its boundto
12327c478bd9Sstevel@tonic-gate 				 * element will need updating after the .dynamic
12337c478bd9Sstevel@tonic-gate 				 * section has been created.  Flag whether this
12347c478bd9Sstevel@tonic-gate 				 * reference is lazy loadable, and if a direct
12357c478bd9Sstevel@tonic-gate 				 * binding is to be established.
12367c478bd9Sstevel@tonic-gate 				 */
12377c478bd9Sstevel@tonic-gate 				if (list_appendc(sip, sdp) == 0)
12387c478bd9Sstevel@tonic-gate 					return (0);
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT;
12417c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags & FLG_SY_LAZYLD)
12427c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12437c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_LAZYLOAD;
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 				/*
12467c478bd9Sstevel@tonic-gate 				 * Enable direct symbol bindings if:
12477c478bd9Sstevel@tonic-gate 				 *
12487c478bd9Sstevel@tonic-gate 				 *  .	Symbol was identified with the DIRECT
12497c478bd9Sstevel@tonic-gate 				 *	keyword in a mapfile.
12507c478bd9Sstevel@tonic-gate 				 *
12517c478bd9Sstevel@tonic-gate 				 *  .	Symbol reference has been bound to a
12527c478bd9Sstevel@tonic-gate 				 * 	dependency which was specified as
12537c478bd9Sstevel@tonic-gate 				 *	requiring direct bindings with -zdirect.
12547c478bd9Sstevel@tonic-gate 				 *
12557c478bd9Sstevel@tonic-gate 				 *  .	All symbol references are required to
12567c478bd9Sstevel@tonic-gate 				 *	use direct bindings via -Bdirect.
12577c478bd9Sstevel@tonic-gate 				 */
12587c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_DIR)
12597c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12607c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_DIRECTBIND;
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 			} else if ((sdp->sd_flags & FLG_SY_EXTERN) &&
12637c478bd9Sstevel@tonic-gate 			    (sdp->sd_sym->st_shndx == SHN_UNDEF)) {
12647c478bd9Sstevel@tonic-gate 				/*
12657c478bd9Sstevel@tonic-gate 				 * If this symbol has been explicitly defined
12667c478bd9Sstevel@tonic-gate 				 * as external, and remains unresolved, mark
12677c478bd9Sstevel@tonic-gate 				 * it as external.
12687c478bd9Sstevel@tonic-gate 				 */
12697c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_boundto = SYMINFO_BT_EXTERN;
12707c478bd9Sstevel@tonic-gate 
12719a411307Srie 			} else if ((sdp->sd_flags & FLG_SY_PARENT) &&
12729a411307Srie 			    (sdp->sd_sym->st_shndx == SHN_UNDEF)) {
12737c478bd9Sstevel@tonic-gate 				/*
12749a411307Srie 				 * If this symbol has been explicitly defined
12759a411307Srie 				 * to be a reference to a parent object,
12769a411307Srie 				 * indicate whether a direct binding should be
12777c478bd9Sstevel@tonic-gate 				 * established.
12787c478bd9Sstevel@tonic-gate 				 */
12797c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_DIRECT;
12807c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_boundto = SYMINFO_BT_PARENT;
12817c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_DIR)
12827c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12837c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_DIRECTBIND;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 			} else if (sdp->sd_flags & FLG_SY_STDFLTR) {
12867c478bd9Sstevel@tonic-gate 				/*
12877c478bd9Sstevel@tonic-gate 				 * A filter definition.  Although this symbol
12887c478bd9Sstevel@tonic-gate 				 * can only be a stub, it might be necessary to
12897c478bd9Sstevel@tonic-gate 				 * prevent external direct bindings.
12907c478bd9Sstevel@tonic-gate 				 */
12917c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_FILTER;
12927c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_NDIR)
12937c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
12947c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_NOEXTDIRECT;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 			} else if (sdp->sd_flags & FLG_SY_AUXFLTR) {
12977c478bd9Sstevel@tonic-gate 				/*
12987c478bd9Sstevel@tonic-gate 				 * An auxiliary filter definition.  By nature,
12997c478bd9Sstevel@tonic-gate 				 * this definition is direct, in that should the
13007c478bd9Sstevel@tonic-gate 				 * filtee lookup fail, we'll fall back to this
13017c478bd9Sstevel@tonic-gate 				 * object.  It may still be necesssary to
13027c478bd9Sstevel@tonic-gate 				 * prevent external direct bindings.
13037c478bd9Sstevel@tonic-gate 				 */
13047c478bd9Sstevel@tonic-gate 				syminfo[ndx].si_flags |= SYMINFO_FLG_AUXILIARY;
13057c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_NDIR)
13067c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
13077c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_NOEXTDIRECT;
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 			} else if ((sdp->sd_ref == REF_REL_NEED) &&
13107c478bd9Sstevel@tonic-gate 			    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
13119a411307Srie 
13127c478bd9Sstevel@tonic-gate 				/*
13137c478bd9Sstevel@tonic-gate 				 * This definition exists within the object
13147c478bd9Sstevel@tonic-gate 				 * being created.  Flag whether it is necessary
13157c478bd9Sstevel@tonic-gate 				 * to prevent external direct bindings.
13167c478bd9Sstevel@tonic-gate 				 */
13177c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags1 & FLG_SY1_NDIR) {
13187c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_boundto =
13197c478bd9Sstevel@tonic-gate 					    SYMINFO_BT_NONE;
13207c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
13217c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_NOEXTDIRECT;
13227c478bd9Sstevel@tonic-gate 				}
13237c478bd9Sstevel@tonic-gate 
13249a411307Srie 				/*
13259a411307Srie 				 * Indicate that this symbol is acting as an
13269a411307Srie 				 * individual interposer.
13279a411307Srie 				 */
13289a411307Srie 				if (sdp->sd_flags & FLG_SY_INTPOSE) {
13299a411307Srie 					syminfo[ndx].si_flags |=
13309a411307Srie 					    SYMINFO_FLG_INTERPOSE;
13319a411307Srie 				}
13329a411307Srie 
13337c478bd9Sstevel@tonic-gate 				/*
13347c478bd9Sstevel@tonic-gate 				 * If external bindings are allowed, or this is
13357c478bd9Sstevel@tonic-gate 				 * a translator symbol, indicate the binding,
13367c478bd9Sstevel@tonic-gate 				 * and a direct binding if necessary.
13377c478bd9Sstevel@tonic-gate 				 */
13387c478bd9Sstevel@tonic-gate 				if (((sdp->sd_flags1 & FLG_SY1_NDIR) == 0) ||
13397c478bd9Sstevel@tonic-gate 				    ((dtflags_1 & DF_1_TRANS) && sdp->sd_aux &&
13407c478bd9Sstevel@tonic-gate 				    sdp->sd_aux->sa_bindto)) {
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 					syminfo[ndx].si_flags |=
13437c478bd9Sstevel@tonic-gate 					    SYMINFO_FLG_DIRECT;
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 					if (sdp->sd_flags1 & FLG_SY1_DIR)
13467c478bd9Sstevel@tonic-gate 						syminfo[ndx].si_flags |=
13477c478bd9Sstevel@tonic-gate 						    SYMINFO_FLG_DIRECTBIND;
13487c478bd9Sstevel@tonic-gate 
13497c478bd9Sstevel@tonic-gate 					/*
13507c478bd9Sstevel@tonic-gate 					 * If this is a translator, the symbols
13517c478bd9Sstevel@tonic-gate 					 * boundto element will indicate the
13527c478bd9Sstevel@tonic-gate 					 * dependency to which it should resolve
13537c478bd9Sstevel@tonic-gate 					 * rather than itself.  Save this info
13547c478bd9Sstevel@tonic-gate 					 * for updating after the .dynamic
13557c478bd9Sstevel@tonic-gate 					 * section has been created.
13567c478bd9Sstevel@tonic-gate 					 */
13577c478bd9Sstevel@tonic-gate 					if ((dtflags_1 & DF_1_TRANS) &&
13587c478bd9Sstevel@tonic-gate 					    sdp->sd_aux &&
13597c478bd9Sstevel@tonic-gate 					    sdp->sd_aux->sa_bindto) {
13607c478bd9Sstevel@tonic-gate 						if (list_appendc(sip, sdp) == 0)
13617c478bd9Sstevel@tonic-gate 							return (0);
13627c478bd9Sstevel@tonic-gate 					} else {
13637c478bd9Sstevel@tonic-gate 						syminfo[ndx].si_boundto =
13647c478bd9Sstevel@tonic-gate 						    SYMINFO_BT_SELF;
13657c478bd9Sstevel@tonic-gate 					}
13667c478bd9Sstevel@tonic-gate 				}
13677c478bd9Sstevel@tonic-gate 			}
13687c478bd9Sstevel@tonic-gate 		}
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 		/*
13717c478bd9Sstevel@tonic-gate 		 * Note that the `sym' value is reset to be one of the new
13727c478bd9Sstevel@tonic-gate 		 * symbol table entries.  This symbol will be updated further
13737c478bd9Sstevel@tonic-gate 		 * depending on the type of the symbol.  Process the .symtab
13747c478bd9Sstevel@tonic-gate 		 * first, followed by the .dynsym, thus the `sym' value will
13757c478bd9Sstevel@tonic-gate 		 * remain as the .dynsym value when the .dynsym is present.
1376c1c6f601Srie 		 * This ensures that any versioning symbols st_name value will
13779039eeafSab 		 * be appropriate for the string table used by version
13787c478bd9Sstevel@tonic-gate 		 * entries.
13797c478bd9Sstevel@tonic-gate 		 */
13807c478bd9Sstevel@tonic-gate 		if (enter_in_symtab) {
13817c478bd9Sstevel@tonic-gate 			Word	_symndx;
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 			if (local)
13847c478bd9Sstevel@tonic-gate 				_symndx = scopesym_ndx;
13857c478bd9Sstevel@tonic-gate 			else
13867c478bd9Sstevel@tonic-gate 				_symndx = symtab_ndx;
13879039eeafSab 
13887c478bd9Sstevel@tonic-gate 			symtab[_symndx] = *sdp->sd_sym;
13897c478bd9Sstevel@tonic-gate 			sdp->sd_sym = sym = &symtab[_symndx];
13907c478bd9Sstevel@tonic-gate 			(void) st_setstring(strtab, name, &stoff);
13917c478bd9Sstevel@tonic-gate 			sym->st_name = stoff;
13927c478bd9Sstevel@tonic-gate 		}
13939039eeafSab 		if (dynlocal) {
13949039eeafSab 			ldynsym[ldynscopesym_ndx] = *sdp->sd_sym;
13959039eeafSab 			sdp->sd_sym = sym = &ldynsym[ldynscopesym_ndx];
13969039eeafSab 			(void) st_setstring(dynstr, name, &stoff);
13979039eeafSab 			ldynsym[ldynscopesym_ndx].st_name = stoff;
1398d579eb63Sab 			/* Add it to sort section if it qualifies */
1399d579eb63Sab 			ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info),
1400d579eb63Sab 			    ldynscopesym_ndx);
14019039eeafSab 		}
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 		if (dynsym && !local) {
14047c478bd9Sstevel@tonic-gate 			dynsym[dynsym_ndx] = *sdp->sd_sym;
140560758829Srie 
14067c478bd9Sstevel@tonic-gate 			/*
14077c478bd9Sstevel@tonic-gate 			 * Provided this isn't an unnamed register symbol,
140860758829Srie 			 * update the symbols name and hash value.
14097c478bd9Sstevel@tonic-gate 			 */
14107c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) ||
14117c478bd9Sstevel@tonic-gate 			    dynsym[dynsym_ndx].st_name) {
1412d840867fSab 				(void) st_setstring(dynstr, name, &stoff);
1413d840867fSab 				dynsym[dynsym_ndx].st_name = stoff;
141460758829Srie 
1415d840867fSab 				if (stoff) {
1416d840867fSab 					Word _hashndx;
141760758829Srie 
141860758829Srie 					hashval =
141960758829Srie 					    sap->sa_hash % ofl->ofl_hashbkts;
142060758829Srie 
1421d840867fSab 					/* LINTED */
1422d840867fSab 					if (_hashndx = hashbkt[hashval]) {
142360758829Srie 						while (hashchain[_hashndx]) {
1424d840867fSab 							_hashndx =
1425d840867fSab 							    hashchain[_hashndx];
142660758829Srie 						}
1427d840867fSab 						hashchain[_hashndx] =
1428d840867fSab 						    sdp->sd_symndx;
1429d840867fSab 					} else {
1430d840867fSab 						hashbkt[hashval] =
1431d840867fSab 						    sdp->sd_symndx;
1432d840867fSab 					}
14337c478bd9Sstevel@tonic-gate 				}
14347c478bd9Sstevel@tonic-gate 			}
14357c478bd9Sstevel@tonic-gate 			sdp->sd_sym = sym = &dynsym[dynsym_ndx];
143660758829Srie 
1437d579eb63Sab 			/*
1438d579eb63Sab 			 * Add it to sort section if it qualifies.
1439d579eb63Sab 			 * The indexes in that section are relative to the
1440d579eb63Sab 			 * the adjacent SUNW_ldynsym/dymsym pair, so we
1441d579eb63Sab 			 * add the number of items in SUNW_ldynsym to the
1442d579eb63Sab 			 * dynsym index.
1443d579eb63Sab 			 */
1444d579eb63Sab 			ADD_TO_DYNSORT(sdp, sym, ELF_ST_TYPE(sym->st_info),
1445d579eb63Sab 			    ldynsym_cnt + dynsym_ndx);
14467c478bd9Sstevel@tonic-gate 		}
14479039eeafSab 		if (!enter_in_symtab && (!dynsym || (local && !dynlocal))) {
14487c478bd9Sstevel@tonic-gate 			if (!(sdp->sd_flags & FLG_SY_UPREQD))
14497c478bd9Sstevel@tonic-gate 				continue;
14507c478bd9Sstevel@tonic-gate 			sym = sdp->sd_sym;
14517c478bd9Sstevel@tonic-gate 		} else
14527c478bd9Sstevel@tonic-gate 			sdp->sd_flags &= ~FLG_SY_CLEAN;
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 
14557c478bd9Sstevel@tonic-gate 		/*
14567c478bd9Sstevel@tonic-gate 		 * If we have a weak data symbol for which we need the real
14577c478bd9Sstevel@tonic-gate 		 * symbol also, save this processing until later.
14587c478bd9Sstevel@tonic-gate 		 *
14597c478bd9Sstevel@tonic-gate 		 * The exception to this is if the weak/strong have PLT's
14607c478bd9Sstevel@tonic-gate 		 * assigned to them.  In that case we don't do the post-weak
14617c478bd9Sstevel@tonic-gate 		 * processing because the PLT's must be maintained so that we
14627c478bd9Sstevel@tonic-gate 		 * can do 'interpositioning' on both of the symbols.
14637c478bd9Sstevel@tonic-gate 		 */
14647c478bd9Sstevel@tonic-gate 		if ((sap->sa_linkndx) &&
14657c478bd9Sstevel@tonic-gate 		    (ELF_ST_BIND(sym->st_info) == STB_WEAK) &&
14667c478bd9Sstevel@tonic-gate 		    (!sap->sa_PLTndx)) {
14677c478bd9Sstevel@tonic-gate 			Sym_desc *	_sdp =
14687c478bd9Sstevel@tonic-gate 			    sdp->sd_file->ifl_oldndx[sap->sa_linkndx];
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 			if (_sdp->sd_ref != REF_DYN_SEEN) {
14717c478bd9Sstevel@tonic-gate 				if ((wkp =
14727c478bd9Sstevel@tonic-gate 				    libld_calloc(sizeof (Wk_desc), 1)) == 0)
14737c478bd9Sstevel@tonic-gate 					return ((Addr)S_ERROR);
14747c478bd9Sstevel@tonic-gate 
14759039eeafSab 				if (enter_in_symtab) {
14767c478bd9Sstevel@tonic-gate 					if (local)
14777c478bd9Sstevel@tonic-gate 						wkp->wk_symtab =
14787c478bd9Sstevel@tonic-gate 						    &symtab[scopesym_ndx];
14797c478bd9Sstevel@tonic-gate 					else
14807c478bd9Sstevel@tonic-gate 						wkp->wk_symtab =
14817c478bd9Sstevel@tonic-gate 						    &symtab[symtab_ndx];
14829039eeafSab 				}
14839039eeafSab 				if (dynsym) {
14849039eeafSab 					if (!local) {
14859039eeafSab 						wkp->wk_dynsym =
14869039eeafSab 						    &dynsym[dynsym_ndx];
14879039eeafSab 					} else if (dynlocal) {
14889039eeafSab 						wkp->wk_dynsym =
14899039eeafSab 						    &ldynsym[ldynscopesym_ndx];
14909039eeafSab 					}
14919039eeafSab 				}
14927c478bd9Sstevel@tonic-gate 				wkp->wk_weak = sdp;
14937c478bd9Sstevel@tonic-gate 				wkp->wk_alias = _sdp;
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate 				if (!(list_appendc(&weak, wkp)))
14967c478bd9Sstevel@tonic-gate 					return ((Addr)S_ERROR);
14977c478bd9Sstevel@tonic-gate 
14987c478bd9Sstevel@tonic-gate 				if (enter_in_symtab)
14997c478bd9Sstevel@tonic-gate 					if (local)
15007c478bd9Sstevel@tonic-gate 						scopesym_ndx++;
15017c478bd9Sstevel@tonic-gate 					else
15027c478bd9Sstevel@tonic-gate 						symtab_ndx++;
15039039eeafSab 				if (dynsym) {
15049039eeafSab 					if (!local) {
15059039eeafSab 						dynsym_ndx++;
15069039eeafSab 					} else if (dynlocal) {
15079039eeafSab 						ldynscopesym_ndx++;
15089039eeafSab 					}
15099039eeafSab 				}
15107c478bd9Sstevel@tonic-gate 				continue;
15117c478bd9Sstevel@tonic-gate 			}
15127c478bd9Sstevel@tonic-gate 		}
15137c478bd9Sstevel@tonic-gate 
15145aefb655Srie 		DBG_CALL(Dbg_syms_old(ofl, sdp));
15157c478bd9Sstevel@tonic-gate 
15167c478bd9Sstevel@tonic-gate 		spec = NULL;
15177c478bd9Sstevel@tonic-gate 		/*
15187c478bd9Sstevel@tonic-gate 		 * assign new symbol value.
15197c478bd9Sstevel@tonic-gate 		 */
15207c478bd9Sstevel@tonic-gate 		sectndx = sdp->sd_shndx;
15217c478bd9Sstevel@tonic-gate 		if (sectndx == SHN_UNDEF) {
15227c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) &&
15237c478bd9Sstevel@tonic-gate 			    (sym->st_value != 0)) {
15245aefb655Srie 				eprintf(ofl->ofl_lml, ERR_WARNING,
15255aefb655Srie 				    MSG_INTL(MSG_SYM_NOTNULL),
15267c478bd9Sstevel@tonic-gate 				    demangle(name), sdp->sd_file->ifl_name);
15277c478bd9Sstevel@tonic-gate 			}
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate 			/*
15307c478bd9Sstevel@tonic-gate 			 * Undefined weak global, if we are generating a static
15317c478bd9Sstevel@tonic-gate 			 * executable, output as an absolute zero.  Otherwise
15327c478bd9Sstevel@tonic-gate 			 * leave it as is, ld.so.1 will skip symbols of this
15337c478bd9Sstevel@tonic-gate 			 * type (this technique allows applications and
15347c478bd9Sstevel@tonic-gate 			 * libraries to test for the existence of a symbol as an
15357c478bd9Sstevel@tonic-gate 			 * indication of the presence or absence of certain
15367c478bd9Sstevel@tonic-gate 			 * functionality).
15377c478bd9Sstevel@tonic-gate 			 */
15387c478bd9Sstevel@tonic-gate 			if (((flags & (FLG_OF_STATIC | FLG_OF_EXEC)) ==
15397c478bd9Sstevel@tonic-gate 			    (FLG_OF_STATIC | FLG_OF_EXEC)) &&
15407c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(sym->st_info) == STB_WEAK)) {
15417c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_SPECSEC;
15427c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = sectndx = SHN_ABS;
15437c478bd9Sstevel@tonic-gate 			}
15447c478bd9Sstevel@tonic-gate 		} else if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
15457c478bd9Sstevel@tonic-gate 		    (sectndx == SHN_COMMON)) {
15467c478bd9Sstevel@tonic-gate 			/* COMMONs have already been processed */
15477c478bd9Sstevel@tonic-gate 			/* EMPTY */
15487c478bd9Sstevel@tonic-gate 			;
15497c478bd9Sstevel@tonic-gate 		} else {
15507c478bd9Sstevel@tonic-gate 			if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
15517c478bd9Sstevel@tonic-gate 			    (sectndx == SHN_ABS))
15527c478bd9Sstevel@tonic-gate 				spec = sdp->sd_aux->sa_symspec;
15537c478bd9Sstevel@tonic-gate 
15547c478bd9Sstevel@tonic-gate 			/* LINTED */
15557c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_COMMEXP) {
15567c478bd9Sstevel@tonic-gate 				/*
15577c478bd9Sstevel@tonic-gate 				 * This is (or was) a COMMON symbol which was
15587c478bd9Sstevel@tonic-gate 				 * processed above - no processing
15597c478bd9Sstevel@tonic-gate 				 * required here.
15607c478bd9Sstevel@tonic-gate 				 */
15617c478bd9Sstevel@tonic-gate 				;
15627c478bd9Sstevel@tonic-gate 			} else if (sdp->sd_ref == REF_DYN_NEED) {
1563d579eb63Sab 				uchar_t	type, bind;
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 				sectndx = SHN_UNDEF;
15667c478bd9Sstevel@tonic-gate 				sym->st_value = 0;
15677c478bd9Sstevel@tonic-gate 				sym->st_size = 0;
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate 				/*
15707c478bd9Sstevel@tonic-gate 				 * Make sure this undefined symbol is returned
15717c478bd9Sstevel@tonic-gate 				 * to the same binding as was defined in the
15727c478bd9Sstevel@tonic-gate 				 * original relocatable object reference.
15737c478bd9Sstevel@tonic-gate 				 */
15747c478bd9Sstevel@tonic-gate 				type = ELF_ST_TYPE(sym-> st_info);
15757c478bd9Sstevel@tonic-gate 				if (sdp->sd_flags & FLG_SY_GLOBREF)
15767c478bd9Sstevel@tonic-gate 					bind = STB_GLOBAL;
15777c478bd9Sstevel@tonic-gate 				else
15787c478bd9Sstevel@tonic-gate 					bind = STB_WEAK;
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate 				sym->st_info = ELF_ST_INFO(bind, type);
15817c478bd9Sstevel@tonic-gate 
15827c478bd9Sstevel@tonic-gate 			} else if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) &&
15837c478bd9Sstevel@tonic-gate 			    (sdp->sd_ref == REF_REL_NEED)) {
15847c478bd9Sstevel@tonic-gate 				osp = sdp->sd_isc->is_osdesc;
15857c478bd9Sstevel@tonic-gate 				/* LINTED */
15867c478bd9Sstevel@tonic-gate 				sectndx = elf_ndxscn(osp->os_scn);
15877c478bd9Sstevel@tonic-gate 
15887c478bd9Sstevel@tonic-gate 				/*
15897c478bd9Sstevel@tonic-gate 				 * In an executable, the new symbol value is the
15907c478bd9Sstevel@tonic-gate 				 * old value (offset into defining section) plus
15917c478bd9Sstevel@tonic-gate 				 * virtual address of defining section.  In a
15927c478bd9Sstevel@tonic-gate 				 * relocatable, the new value is the old value
15937c478bd9Sstevel@tonic-gate 				 * plus the displacement of the section within
15947c478bd9Sstevel@tonic-gate 				 * the file.
15957c478bd9Sstevel@tonic-gate 				 */
15967c478bd9Sstevel@tonic-gate 				/* LINTED */
15977c478bd9Sstevel@tonic-gate 				sym->st_value +=
15987c478bd9Sstevel@tonic-gate 				    (Off)_elf_getxoff(sdp->sd_isc->is_indata);
15997c478bd9Sstevel@tonic-gate 
16007c478bd9Sstevel@tonic-gate 				if (!(flags & FLG_OF_RELOBJ)) {
16017c478bd9Sstevel@tonic-gate 					sym->st_value += osp->os_shdr->sh_addr;
16027c478bd9Sstevel@tonic-gate 					/*
16037c478bd9Sstevel@tonic-gate 					 * TLS symbols are relative to
16047c478bd9Sstevel@tonic-gate 					 * the TLS segment.
16057c478bd9Sstevel@tonic-gate 					 */
16067c478bd9Sstevel@tonic-gate 					if ((ELF_ST_TYPE(sym->st_info) ==
16077c478bd9Sstevel@tonic-gate 					    STT_TLS) && (ofl->ofl_tlsphdr))
16087c478bd9Sstevel@tonic-gate 						sym->st_value -=
16097c478bd9Sstevel@tonic-gate 						    ofl->ofl_tlsphdr->p_vaddr;
16107c478bd9Sstevel@tonic-gate 				}
16117c478bd9Sstevel@tonic-gate 			}
16127c478bd9Sstevel@tonic-gate 		}
16137c478bd9Sstevel@tonic-gate 
16147c478bd9Sstevel@tonic-gate 		if (spec) {
16157c478bd9Sstevel@tonic-gate 			switch (spec) {
16167c478bd9Sstevel@tonic-gate 			case SDAUX_ID_ETEXT:
16177c478bd9Sstevel@tonic-gate 				sym->st_value = etext;
16187c478bd9Sstevel@tonic-gate 				sectndx = etext_ndx;
16197c478bd9Sstevel@tonic-gate 				if (etext_abs)
16207c478bd9Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_SPECSEC;
16217c478bd9Sstevel@tonic-gate 				else
16227c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16237c478bd9Sstevel@tonic-gate 				break;
16247c478bd9Sstevel@tonic-gate 			case SDAUX_ID_EDATA:
16257c478bd9Sstevel@tonic-gate 				sym->st_value = edata;
16267c478bd9Sstevel@tonic-gate 				sectndx = edata_ndx;
16277c478bd9Sstevel@tonic-gate 				if (edata_abs)
16287c478bd9Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_SPECSEC;
16297c478bd9Sstevel@tonic-gate 				else
16307c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16317c478bd9Sstevel@tonic-gate 				break;
16327c478bd9Sstevel@tonic-gate 			case SDAUX_ID_END:
16337c478bd9Sstevel@tonic-gate 				sym->st_value = end;
16347c478bd9Sstevel@tonic-gate 				sectndx = end_ndx;
16357c478bd9Sstevel@tonic-gate 				if (end_abs)
16367c478bd9Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_SPECSEC;
16377c478bd9Sstevel@tonic-gate 				else
16387c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16397c478bd9Sstevel@tonic-gate 				break;
16407c478bd9Sstevel@tonic-gate 			case SDAUX_ID_START:
16417c478bd9Sstevel@tonic-gate 				sym->st_value = start;
16427c478bd9Sstevel@tonic-gate 				sectndx = start_ndx;
16437c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
16447c478bd9Sstevel@tonic-gate 				break;
16457c478bd9Sstevel@tonic-gate 			case SDAUX_ID_DYN:
16467c478bd9Sstevel@tonic-gate 				if (flags & FLG_OF_DYNAMIC) {
16477c478bd9Sstevel@tonic-gate 					sym->st_value = ofl->
16487c478bd9Sstevel@tonic-gate 					    ofl_osdynamic->os_shdr->sh_addr;
16497c478bd9Sstevel@tonic-gate 					/* LINTED */
16507c478bd9Sstevel@tonic-gate 					sectndx = elf_ndxscn(
16517c478bd9Sstevel@tonic-gate 					    ofl->ofl_osdynamic->os_scn);
16527c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16537c478bd9Sstevel@tonic-gate 				}
16547c478bd9Sstevel@tonic-gate 				break;
16557c478bd9Sstevel@tonic-gate 			case SDAUX_ID_PLT:
16567c478bd9Sstevel@tonic-gate 				if (ofl->ofl_osplt) {
16577c478bd9Sstevel@tonic-gate 					sym->st_value = ofl->
16587c478bd9Sstevel@tonic-gate 					    ofl_osplt->os_shdr->sh_addr;
16597c478bd9Sstevel@tonic-gate 					/* LINTED */
16607c478bd9Sstevel@tonic-gate 					sectndx = elf_ndxscn(
16617c478bd9Sstevel@tonic-gate 					    ofl->ofl_osplt->os_scn);
16627c478bd9Sstevel@tonic-gate 					sdp->sd_flags &= ~FLG_SY_SPECSEC;
16637c478bd9Sstevel@tonic-gate 				}
16647c478bd9Sstevel@tonic-gate 				break;
16657c478bd9Sstevel@tonic-gate 			case SDAUX_ID_GOT:
16667c478bd9Sstevel@tonic-gate 				/*
16677c478bd9Sstevel@tonic-gate 				 * Symbol bias for negative growing tables is
16687c478bd9Sstevel@tonic-gate 				 * stored in symbol's value during
16697c478bd9Sstevel@tonic-gate 				 * allocate_got().
16707c478bd9Sstevel@tonic-gate 				 */
16717c478bd9Sstevel@tonic-gate 				sym->st_value += ofl->
16727c478bd9Sstevel@tonic-gate 				    ofl_osgot->os_shdr->sh_addr;
16737c478bd9Sstevel@tonic-gate 				/* LINTED */
16747c478bd9Sstevel@tonic-gate 				sectndx = elf_ndxscn(ofl->
16757c478bd9Sstevel@tonic-gate 				    ofl_osgot->os_scn);
16767c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_SPECSEC;
16777c478bd9Sstevel@tonic-gate 				break;
16787c478bd9Sstevel@tonic-gate 			default:
16797c478bd9Sstevel@tonic-gate 				/* NOTHING */
16807c478bd9Sstevel@tonic-gate 				;
16817c478bd9Sstevel@tonic-gate 			}
16827c478bd9Sstevel@tonic-gate 		}
16837c478bd9Sstevel@tonic-gate 
16847c478bd9Sstevel@tonic-gate 		/*
16857c478bd9Sstevel@tonic-gate 		 * If a plt index has been assigned to an undefined function,
16867c478bd9Sstevel@tonic-gate 		 * update the symbols value to the appropriate .plt address.
16877c478bd9Sstevel@tonic-gate 		 */
16887c478bd9Sstevel@tonic-gate 		if ((flags & FLG_OF_DYNAMIC) && (flags & FLG_OF_EXEC) &&
16897c478bd9Sstevel@tonic-gate 		    (sdp->sd_file) &&
16907c478bd9Sstevel@tonic-gate 		    (sdp->sd_file->ifl_ehdr->e_type == ET_DYN) &&
16917c478bd9Sstevel@tonic-gate 		    (ELF_ST_TYPE(sym->st_info) == STT_FUNC) &&
16927c478bd9Sstevel@tonic-gate 		    !(flags & FLG_OF_BFLAG)) {
16937c478bd9Sstevel@tonic-gate 			if (sap->sa_PLTndx)
16945aefb655Srie 				sym->st_value = ld_calc_plt_addr(sdp, ofl);
16957c478bd9Sstevel@tonic-gate 		}
16967c478bd9Sstevel@tonic-gate 
16977c478bd9Sstevel@tonic-gate 		/*
16987c478bd9Sstevel@tonic-gate 		 * Finish updating the symbols.
16997c478bd9Sstevel@tonic-gate 		 */
17007c478bd9Sstevel@tonic-gate 
17017c478bd9Sstevel@tonic-gate 		/*
17027c478bd9Sstevel@tonic-gate 		 * Sym Update: if scoped local - set local binding
17037c478bd9Sstevel@tonic-gate 		 */
17047c478bd9Sstevel@tonic-gate 		if (local)
17057c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(STB_LOCAL,
17067c478bd9Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info));
17077c478bd9Sstevel@tonic-gate 
17087c478bd9Sstevel@tonic-gate 		/*
17097c478bd9Sstevel@tonic-gate 		 * Sym Updated: If both the .symtab and .dynsym
17107c478bd9Sstevel@tonic-gate 		 * are present then we've actually updated the information in
17117c478bd9Sstevel@tonic-gate 		 * the .dynsym, therefore copy this same information to the
17127c478bd9Sstevel@tonic-gate 		 * .symtab entry.
17137c478bd9Sstevel@tonic-gate 		 */
17147c478bd9Sstevel@tonic-gate 		sdp->sd_shndx = sectndx;
17159039eeafSab 		if (enter_in_symtab && dynsym && (!local || dynlocal)) {
17169039eeafSab 			Word _symndx = dynlocal ? scopesym_ndx : symtab_ndx;
17179039eeafSab 
17189039eeafSab 			symtab[_symndx].st_value = sym->st_value;
17199039eeafSab 			symtab[_symndx].st_size = sym->st_size;
17209039eeafSab 			symtab[_symndx].st_info = sym->st_info;
17219039eeafSab 			symtab[_symndx].st_other = sym->st_other;
17227c478bd9Sstevel@tonic-gate 		}
17237c478bd9Sstevel@tonic-gate 
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate 		if (enter_in_symtab) {
17267c478bd9Sstevel@tonic-gate 			Word	_symndx;
17277c478bd9Sstevel@tonic-gate 
17287c478bd9Sstevel@tonic-gate 			if (local)
17297c478bd9Sstevel@tonic-gate 				_symndx = scopesym_ndx++;
17307c478bd9Sstevel@tonic-gate 			else
17317c478bd9Sstevel@tonic-gate 				_symndx = symtab_ndx++;
17327c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) &&
17337c478bd9Sstevel@tonic-gate 			    (sectndx >= SHN_LORESERVE)) {
17347c478bd9Sstevel@tonic-gate 				assert(symshndx != 0);
17357c478bd9Sstevel@tonic-gate 				symshndx[_symndx] = sectndx;
17367c478bd9Sstevel@tonic-gate 				symtab[_symndx].st_shndx = SHN_XINDEX;
17377c478bd9Sstevel@tonic-gate 			} else {
17387c478bd9Sstevel@tonic-gate 				/* LINTED */
17397c478bd9Sstevel@tonic-gate 				symtab[_symndx].st_shndx = (Half)sectndx;
17407c478bd9Sstevel@tonic-gate 			}
17417c478bd9Sstevel@tonic-gate 		}
17427c478bd9Sstevel@tonic-gate 
17439039eeafSab 		if (dynsym && (!local || dynlocal)) {
17449039eeafSab 			/*
17459039eeafSab 			 * dynsym and ldynsym are distinct tables, so
17469039eeafSab 			 * we use indirection to access the right one
17479039eeafSab 			 * and the related extended section index array.
17489039eeafSab 			 */
17499039eeafSab 			Word	_symndx;
17509039eeafSab 			Sym	*_dynsym;
17519039eeafSab 			Word	*_dynshndx;
17529039eeafSab 
17539039eeafSab 			if (!local) {
17549039eeafSab 				_symndx = dynsym_ndx++;
17559039eeafSab 				_dynsym = dynsym;
17569039eeafSab 				_dynshndx = dynshndx;
17579039eeafSab 			} else {
17589039eeafSab 				_symndx = ldynscopesym_ndx++;
17599039eeafSab 				_dynsym = ldynsym;
17609039eeafSab 				_dynshndx = ldynshndx;
17619039eeafSab 			}
17627c478bd9Sstevel@tonic-gate 			if (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) &&
17637c478bd9Sstevel@tonic-gate 			    (sectndx >= SHN_LORESERVE)) {
17649039eeafSab 				assert(_dynshndx != 0);
17659039eeafSab 				_dynshndx[_symndx] = sectndx;
17669039eeafSab 				_dynsym[_symndx].st_shndx = SHN_XINDEX;
17677c478bd9Sstevel@tonic-gate 			} else {
17687c478bd9Sstevel@tonic-gate 				/* LINTED */
17699039eeafSab 				_dynsym[_symndx].st_shndx = (Half)sectndx;
17707c478bd9Sstevel@tonic-gate 			}
17717c478bd9Sstevel@tonic-gate 		}
17727c478bd9Sstevel@tonic-gate 
17735aefb655Srie 		DBG_CALL(Dbg_syms_new(ofl, sym, sdp));
17747c478bd9Sstevel@tonic-gate 	}
17757c478bd9Sstevel@tonic-gate 
17767c478bd9Sstevel@tonic-gate 	/*
17777c478bd9Sstevel@tonic-gate 	 * Now that all the symbols have been processed update any weak symbols
17787c478bd9Sstevel@tonic-gate 	 * information (ie. copy all information except `st_name').  As both
17797c478bd9Sstevel@tonic-gate 	 * symbols will be represented in the output, return the weak symbol to
17807c478bd9Sstevel@tonic-gate 	 * its correct type.
17817c478bd9Sstevel@tonic-gate 	 */
17827c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&weak, lnp1, wkp)) {
17837c478bd9Sstevel@tonic-gate 		Sym_desc *	sdp, * _sdp;
17847c478bd9Sstevel@tonic-gate 		Sym *		sym, * _sym, * __sym;
1785d579eb63Sab 		uchar_t		bind;
17867c478bd9Sstevel@tonic-gate 
17877c478bd9Sstevel@tonic-gate 		sdp = wkp->wk_weak;
17887c478bd9Sstevel@tonic-gate 		_sdp = wkp->wk_alias;
17897c478bd9Sstevel@tonic-gate 		_sym = _sdp->sd_sym;
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate 		sdp->sd_flags |= FLG_SY_WEAKDEF;
17927c478bd9Sstevel@tonic-gate 
17937c478bd9Sstevel@tonic-gate 		/*
17947c478bd9Sstevel@tonic-gate 		 * If the symbol definition has been scoped then assign it to
17957c478bd9Sstevel@tonic-gate 		 * be local, otherwise if it's from a shared object then we need
17967c478bd9Sstevel@tonic-gate 		 * to maintain the binding of the original reference.
17977c478bd9Sstevel@tonic-gate 		 */
179860758829Srie 		if (sdp->sd_flags1 & FLG_SY1_HIDDEN) {
17997c478bd9Sstevel@tonic-gate 			if (flags & FLG_OF_PROCRED)
18007c478bd9Sstevel@tonic-gate 				bind = STB_LOCAL;
18017c478bd9Sstevel@tonic-gate 			else
18027c478bd9Sstevel@tonic-gate 				bind = STB_WEAK;
18037c478bd9Sstevel@tonic-gate 		} else if ((sdp->sd_ref == REF_DYN_NEED) &&
18047c478bd9Sstevel@tonic-gate 		    (sdp->sd_flags & FLG_SY_GLOBREF))
18057c478bd9Sstevel@tonic-gate 			bind = STB_GLOBAL;
18067c478bd9Sstevel@tonic-gate 		else
18077c478bd9Sstevel@tonic-gate 			bind = STB_WEAK;
18087c478bd9Sstevel@tonic-gate 
18095aefb655Srie 		DBG_CALL(Dbg_syms_old(ofl, sdp));
18107c478bd9Sstevel@tonic-gate 		if ((sym = wkp->wk_symtab) != 0) {
18117c478bd9Sstevel@tonic-gate 			sym = wkp->wk_symtab;
18127c478bd9Sstevel@tonic-gate 			sym->st_value = _sym->st_value;
18137c478bd9Sstevel@tonic-gate 			sym->st_size = _sym->st_size;
18147c478bd9Sstevel@tonic-gate 			sym->st_other = _sym->st_other;
18157c478bd9Sstevel@tonic-gate 			sym->st_shndx = _sym->st_shndx;
18167c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(bind,
18177c478bd9Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info));
18187c478bd9Sstevel@tonic-gate 			__sym = sym;
18197c478bd9Sstevel@tonic-gate 		}
18207c478bd9Sstevel@tonic-gate 		if ((sym = wkp->wk_dynsym) != 0) {
18217c478bd9Sstevel@tonic-gate 			sym = wkp->wk_dynsym;
18227c478bd9Sstevel@tonic-gate 			sym->st_value = _sym->st_value;
18237c478bd9Sstevel@tonic-gate 			sym->st_size = _sym->st_size;
18247c478bd9Sstevel@tonic-gate 			sym->st_other = _sym->st_other;
18257c478bd9Sstevel@tonic-gate 			sym->st_shndx = _sym->st_shndx;
18267c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(bind,
18277c478bd9Sstevel@tonic-gate 			    ELF_ST_TYPE(sym->st_info));
18287c478bd9Sstevel@tonic-gate 			__sym = sym;
18297c478bd9Sstevel@tonic-gate 		}
18305aefb655Srie 		DBG_CALL(Dbg_syms_new(ofl, __sym, sdp));
18317c478bd9Sstevel@tonic-gate 	}
18327c478bd9Sstevel@tonic-gate 
18337c478bd9Sstevel@tonic-gate 	/*
18345aefb655Srie 	 * Now display GOT debugging information if required.
18357c478bd9Sstevel@tonic-gate 	 */
1836d326b23bSrie 	DBG_CALL(Dbg_got_display(ofl, 0, 0));
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 	/*
18399039eeafSab 	 * Update the section headers information. sh_info is
18409039eeafSab 	 * supposed to contain the offset at which the first
18419039eeafSab 	 * global symbol resides in the symbol table, while
18429039eeafSab 	 * sh_link contains the section index of the associated
18439039eeafSab 	 * string table.
18447c478bd9Sstevel@tonic-gate 	 */
18457c478bd9Sstevel@tonic-gate 	if (symtab) {
184660758829Srie 		Shdr	*shdr = ofl->ofl_ossymtab->os_shdr;
18477c478bd9Sstevel@tonic-gate 
18487c478bd9Sstevel@tonic-gate 		shdr->sh_info = ofl->ofl_shdrcnt + ofl->ofl_locscnt +
1849d840867fSab 		    ofl->ofl_scopecnt + 2;
18507c478bd9Sstevel@tonic-gate 		/* LINTED */
18517c478bd9Sstevel@tonic-gate 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osstrtab->os_scn);
18527c478bd9Sstevel@tonic-gate 		if (symshndx) {
18537c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_ossymshndx->os_shdr;
18547c478bd9Sstevel@tonic-gate 			shdr->sh_link =
1855d840867fSab 			    (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn);
18567c478bd9Sstevel@tonic-gate 		}
18577c478bd9Sstevel@tonic-gate 	}
18587c478bd9Sstevel@tonic-gate 	if (dynsym) {
185960758829Srie 		Shdr	*shdr = ofl->ofl_osdynsym->os_shdr;
18607c478bd9Sstevel@tonic-gate 
18619039eeafSab 		shdr->sh_info = 1 + ofl->ofl_dynshdrcnt + ofl->ofl_lregsymcnt;
18627c478bd9Sstevel@tonic-gate 		/* LINTED */
18637c478bd9Sstevel@tonic-gate 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
18647c478bd9Sstevel@tonic-gate 
18657c478bd9Sstevel@tonic-gate 		ofl->ofl_oshash->os_shdr->sh_link =
18667c478bd9Sstevel@tonic-gate 		    /* LINTED */
18677c478bd9Sstevel@tonic-gate 		    (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn);
18687c478bd9Sstevel@tonic-gate 		if (dynshndx) {
18697c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osdynshndx->os_shdr;
18707c478bd9Sstevel@tonic-gate 			shdr->sh_link =
1871d840867fSab 			    (Word)elf_ndxscn(ofl->ofl_osdynsym->os_scn);
18727c478bd9Sstevel@tonic-gate 		}
18737c478bd9Sstevel@tonic-gate 	}
18749039eeafSab 	if (ldynsym) {
187560758829Srie 		Shdr	*shdr = ofl->ofl_osldynsym->os_shdr;
18769039eeafSab 
18779039eeafSab 		/* ldynsym has no globals, so give index one past the end */
18789039eeafSab 		shdr->sh_info = ldynsym_ndx;
18799039eeafSab 
18809039eeafSab 		/*
18819039eeafSab 		 * The ldynsym and dynsym must be adjacent. The
18829039eeafSab 		 * idea is that rtld should be able to start with
18839039eeafSab 		 * the ldynsym and march straight through the end
18849039eeafSab 		 * of dynsym, seeing them as a single symbol table,
18859039eeafSab 		 * despite the fact that they are in distinct sections.
18869039eeafSab 		 * Ensure that this happened correctly.
18879039eeafSab 		 *
18889039eeafSab 		 * Note that I use ldynsym_ndx here instead of the
18899039eeafSab 		 * computation I used to set the section size
1890d579eb63Sab 		 * (found in ldynsym_cnt). The two will agree, unless
1891d579eb63Sab 		 * we somehow miscounted symbols or failed to insert them
1892d579eb63Sab 		 * all. Using ldynsym_ndx here catches that error in
1893d579eb63Sab 		 * addition to checking for adjacency.
18949039eeafSab 		 */
18959039eeafSab 		assert(dynsym == (ldynsym + ldynsym_ndx));
18969039eeafSab 
18979039eeafSab 
18989039eeafSab 		/* LINTED */
18999039eeafSab 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
19009039eeafSab 
19019039eeafSab 		if (ldynshndx) {
19029039eeafSab 			shdr = ofl->ofl_osldynshndx->os_shdr;
19039039eeafSab 			shdr->sh_link =
1904d840867fSab 			    (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn);
19059039eeafSab 		}
1906d579eb63Sab 
1907d579eb63Sab 		/*
1908d579eb63Sab 		 * The presence of .SUNW_ldynsym means that there may be
1909d579eb63Sab 		 * associated sort sections, one for regular symbols
1910d579eb63Sab 		 * and the other for TLS. Each sort section needs the
1911d579eb63Sab 		 * following done:
1912d579eb63Sab 		 *	- Section header link references .SUNW_ldynsym
1913d579eb63Sab 		 *	- Should have received the expected # of items
1914d579eb63Sab 		 *	- Sorted by increasing address
1915d579eb63Sab 		 */
1916d579eb63Sab 		if (ofl->ofl_osdynsymsort) {	/* .SUNW_dynsymsort */
1917d579eb63Sab 			ofl->ofl_osdynsymsort->os_shdr->sh_link =
1918d579eb63Sab 			    (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn);
1919d579eb63Sab 			assert(ofl->ofl_dynsymsortcnt == dynsymsort_ndx);
192060758829Srie 
1921d579eb63Sab 			if (dynsymsort_ndx > 1) {
1922d579eb63Sab 				dynsort_compare_syms = ldynsym;
1923d579eb63Sab 				qsort(dynsymsort, dynsymsort_ndx,
1924d579eb63Sab 				    sizeof (*dynsymsort), dynsort_compare);
1925a194faf8Srie 				dynsort_dupwarn(ofl, ldynsym,
1926a194faf8Srie 				    st_getstrbuf(dynstr),
1927d579eb63Sab 				    dynsymsort, dynsymsort_ndx,
1928d579eb63Sab 				    MSG_ORIG(MSG_SCN_DYNSYMSORT));
1929d579eb63Sab 			}
1930d579eb63Sab 		}
1931d579eb63Sab 		if (ofl->ofl_osdyntlssort) {	/* .SUNW_dyntlssort */
1932d579eb63Sab 			ofl->ofl_osdyntlssort->os_shdr->sh_link =
1933d579eb63Sab 			    (Word)elf_ndxscn(ofl->ofl_osldynsym->os_scn);
1934d579eb63Sab 			assert(ofl->ofl_dyntlssortcnt == dyntlssort_ndx);
193560758829Srie 
1936d579eb63Sab 			if (dyntlssort_ndx > 1) {
1937d579eb63Sab 				dynsort_compare_syms = ldynsym;
1938d579eb63Sab 				qsort(dyntlssort, dyntlssort_ndx,
1939d579eb63Sab 				    sizeof (*dyntlssort), dynsort_compare);
1940a194faf8Srie 				dynsort_dupwarn(ofl, ldynsym,
1941a194faf8Srie 				    st_getstrbuf(dynstr),
1942d579eb63Sab 				    dyntlssort, dyntlssort_ndx,
1943d579eb63Sab 				    MSG_ORIG(MSG_SCN_DYNTLSSORT));
1944d579eb63Sab 			}
1945d579eb63Sab 		}
19469039eeafSab 	}
19477c478bd9Sstevel@tonic-gate 
19487c478bd9Sstevel@tonic-gate 	/*
19497c478bd9Sstevel@tonic-gate 	 * Used by ld.so.1 only.
19507c478bd9Sstevel@tonic-gate 	 */
19517c478bd9Sstevel@tonic-gate 	return (etext);
1952d579eb63Sab 
1953d579eb63Sab #undef ADD_TO_DYNSORT
19547c478bd9Sstevel@tonic-gate }
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate /*
19577c478bd9Sstevel@tonic-gate  * Build the dynamic section.
19587c478bd9Sstevel@tonic-gate  */
19595aefb655Srie static int
19607c478bd9Sstevel@tonic-gate update_odynamic(Ofl_desc *ofl)
19617c478bd9Sstevel@tonic-gate {
19627c478bd9Sstevel@tonic-gate 	Listnode	*lnp;
19637c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
19647c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
19657c478bd9Sstevel@tonic-gate 	Shdr		*shdr;
19667c478bd9Sstevel@tonic-gate 	Dyn		*_dyn = (Dyn *)ofl->ofl_osdynamic->os_outdata->d_buf;
19677c478bd9Sstevel@tonic-gate 	Dyn		*dyn;
19687c478bd9Sstevel@tonic-gate 	Str_tbl		*dynstr;
1969*cce0e03bSab 	size_t		stoff;
19707c478bd9Sstevel@tonic-gate 	Word		flags = ofl->ofl_flags;
19713244bcaaSab 	Word		cnt;
19727c478bd9Sstevel@tonic-gate 
19737c478bd9Sstevel@tonic-gate 	dynstr = ofl->ofl_dynstrtab;
19747c478bd9Sstevel@tonic-gate 	ofl->ofl_osdynamic->os_shdr->sh_link =
19757c478bd9Sstevel@tonic-gate 	    /* LINTED */
19767c478bd9Sstevel@tonic-gate 	    (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
19777c478bd9Sstevel@tonic-gate 
19787c478bd9Sstevel@tonic-gate 	dyn = _dyn;
19797c478bd9Sstevel@tonic-gate 
19807c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_sos, lnp, ifl)) {
19817c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_flags &
19827c478bd9Sstevel@tonic-gate 		    (FLG_IF_IGNORE | FLG_IF_DEPREQD)) == FLG_IF_IGNORE)
19837c478bd9Sstevel@tonic-gate 			continue;
19847c478bd9Sstevel@tonic-gate 
19857c478bd9Sstevel@tonic-gate 		/*
19867c478bd9Sstevel@tonic-gate 		 * Create and set up the DT_POSFLAG_1 entry here if required.
19877c478bd9Sstevel@tonic-gate 		 */
19887c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_flags & (FLG_IF_LAZYLD|FLG_IF_GRPPRM)) &&
19897c478bd9Sstevel@tonic-gate 		    (ifl->ifl_flags & (FLG_IF_NEEDED))) {
19907c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_POSFLAG_1;
19917c478bd9Sstevel@tonic-gate 			if (ifl->ifl_flags & FLG_IF_LAZYLD)
19927c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = DF_P1_LAZYLOAD;
19937c478bd9Sstevel@tonic-gate 			if (ifl->ifl_flags & FLG_IF_GRPPRM)
19947c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val |= DF_P1_GROUPPERM;
19957c478bd9Sstevel@tonic-gate 			dyn++;
19967c478bd9Sstevel@tonic-gate 		}
19977c478bd9Sstevel@tonic-gate 
19987c478bd9Sstevel@tonic-gate 		if (ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR))
19997c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_NEEDED;
20007c478bd9Sstevel@tonic-gate 		else
20017c478bd9Sstevel@tonic-gate 			continue;
20027c478bd9Sstevel@tonic-gate 
20037c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ifl->ifl_soname, &stoff);
20047c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20057c478bd9Sstevel@tonic-gate 		/* LINTED */
20067c478bd9Sstevel@tonic-gate 		ifl->ifl_neededndx = (Half)(((uintptr_t)dyn - (uintptr_t)_dyn) /
20077c478bd9Sstevel@tonic-gate 		    sizeof (Dyn));
20087c478bd9Sstevel@tonic-gate 		dyn++;
20097c478bd9Sstevel@tonic-gate 	}
20107c478bd9Sstevel@tonic-gate 
2011*cce0e03bSab 	if (ofl->ofl_dtsfltrs != NULL) {
2012*cce0e03bSab 		Dfltr_desc	*dftp;
2013*cce0e03bSab 		Aliste		idx;
20147c478bd9Sstevel@tonic-gate 
2015*cce0e03bSab 		for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, idx, dftp)) {
20167c478bd9Sstevel@tonic-gate 			if (dftp->dft_flag == FLG_SY_AUXFLTR)
20177c478bd9Sstevel@tonic-gate 				dyn->d_tag = DT_SUNW_AUXILIARY;
20187c478bd9Sstevel@tonic-gate 			else
20197c478bd9Sstevel@tonic-gate 				dyn->d_tag = DT_SUNW_FILTER;
20207c478bd9Sstevel@tonic-gate 
20217c478bd9Sstevel@tonic-gate 			(void) st_setstring(dynstr, dftp->dft_str, &stoff);
20227c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = stoff;
20237c478bd9Sstevel@tonic-gate 			dftp->dft_ndx = (Half)(((uintptr_t)dyn -
20247c478bd9Sstevel@tonic-gate 			    (uintptr_t)_dyn) / sizeof (Dyn));
20257c478bd9Sstevel@tonic-gate 			dyn++;
20267c478bd9Sstevel@tonic-gate 		}
20277c478bd9Sstevel@tonic-gate 	}
20285aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U),
20295b59e4caSab 	    SYM_NOHASH, 0, ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) &&
20305b59e4caSab 	    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
20317c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_INIT;
20327c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = sdp->sd_sym->st_value;
20337c478bd9Sstevel@tonic-gate 		dyn++;
20347c478bd9Sstevel@tonic-gate 	}
20355aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U),
20365b59e4caSab 	    SYM_NOHASH, 0, ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) &&
20375b59e4caSab 	    (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
20387c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_FINI;
20397c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = sdp->sd_sym->st_value;
20407c478bd9Sstevel@tonic-gate 		dyn++;
20417c478bd9Sstevel@tonic-gate 	}
20427c478bd9Sstevel@tonic-gate 	if (ofl->ofl_soname) {
20437c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_SONAME;
20447c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ofl->ofl_soname, &stoff);
20457c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20467c478bd9Sstevel@tonic-gate 		dyn++;
20477c478bd9Sstevel@tonic-gate 	}
20487c478bd9Sstevel@tonic-gate 	if (ofl->ofl_filtees) {
20497c478bd9Sstevel@tonic-gate 		if (flags & FLG_OF_AUX) {
20507c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_AUXILIARY;
20517c478bd9Sstevel@tonic-gate 		} else {
20527c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_FILTER;
20537c478bd9Sstevel@tonic-gate 		}
20547c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ofl->ofl_filtees, &stoff);
20557c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20567c478bd9Sstevel@tonic-gate 		dyn++;
20577c478bd9Sstevel@tonic-gate 	}
20587c478bd9Sstevel@tonic-gate 	if (ofl->ofl_rpath) {
20597c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ofl->ofl_rpath, &stoff);
20607c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_RUNPATH;
20617c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20627c478bd9Sstevel@tonic-gate 		dyn++;
20637c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_RPATH;
20647c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20657c478bd9Sstevel@tonic-gate 		dyn++;
20667c478bd9Sstevel@tonic-gate 	}
20677c478bd9Sstevel@tonic-gate 	if (ofl->ofl_config) {
20687c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_CONFIG;
20697c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ofl->ofl_config, &stoff);
20707c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20717c478bd9Sstevel@tonic-gate 		dyn++;
20727c478bd9Sstevel@tonic-gate 	}
20737c478bd9Sstevel@tonic-gate 	if (ofl->ofl_depaudit) {
20747c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_DEPAUDIT;
20757c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ofl->ofl_depaudit, &stoff);
20767c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20777c478bd9Sstevel@tonic-gate 		dyn++;
20787c478bd9Sstevel@tonic-gate 	}
20797c478bd9Sstevel@tonic-gate 	if (ofl->ofl_audit) {
20807c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_AUDIT;
20817c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ofl->ofl_audit, &stoff);
20827c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = stoff;
20837c478bd9Sstevel@tonic-gate 		dyn++;
20847c478bd9Sstevel@tonic-gate 	}
20857c478bd9Sstevel@tonic-gate 
20867c478bd9Sstevel@tonic-gate 	/*
20877c478bd9Sstevel@tonic-gate 	 * The following DT_* entries do not apply to relocatable objects.
20887c478bd9Sstevel@tonic-gate 	 */
20897c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_RELOBJ)) {
20907c478bd9Sstevel@tonic-gate 
20917c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_HASH;
20927c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = ofl->ofl_oshash->os_shdr->sh_addr;
20937c478bd9Sstevel@tonic-gate 		dyn++;
20947c478bd9Sstevel@tonic-gate 
20957c478bd9Sstevel@tonic-gate 		shdr = ofl->ofl_osdynstr->os_shdr;
20967c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_STRTAB;
20977c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_addr;
20987c478bd9Sstevel@tonic-gate 		dyn++;
20997c478bd9Sstevel@tonic-gate 
21007c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_STRSZ;
21017c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_size;
21027c478bd9Sstevel@tonic-gate 		dyn++;
21037c478bd9Sstevel@tonic-gate 
21047c478bd9Sstevel@tonic-gate 		shdr = ofl->ofl_osdynsym->os_shdr;
21057c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_SYMTAB;
21067c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_addr;
21077c478bd9Sstevel@tonic-gate 		dyn++;
21087c478bd9Sstevel@tonic-gate 
21097c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_SYMENT;
21107c478bd9Sstevel@tonic-gate 		dyn->d_un.d_ptr = shdr->sh_entsize;
21117c478bd9Sstevel@tonic-gate 		dyn++;
21127c478bd9Sstevel@tonic-gate 
21139039eeafSab 		if (ofl->ofl_osldynsym) {
21149039eeafSab 			/*
21159039eeafSab 			 * We have arranged for the .SUNW_ldynsym data to be
21169039eeafSab 			 * immediately in front of the .dynsym data.
21179039eeafSab 			 * This means that you could start at the top
21189039eeafSab 			 * of .SUNW_ldynsym and see the data for both tables
21199039eeafSab 			 * without a break. This is the view we want to
21209039eeafSab 			 * provide for DT_SUNW_SYMTAB, which is why we
21219039eeafSab 			 * add the lengths together.
21229039eeafSab 			 */
21239039eeafSab 			Shdr *lshdr = ofl->ofl_osldynsym->os_shdr;
21249039eeafSab 			dyn->d_tag = DT_SUNW_SYMTAB;
21259039eeafSab 			dyn->d_un.d_ptr = lshdr->sh_addr;
21269039eeafSab 			dyn++;
21279039eeafSab 
21289039eeafSab 			dyn->d_tag = DT_SUNW_SYMSZ;
21299039eeafSab 			dyn->d_un.d_val = lshdr->sh_size + shdr->sh_size;
21309039eeafSab 			dyn++;
21319039eeafSab 		}
21329039eeafSab 
2133d579eb63Sab 		if (ofl->ofl_osdynsymsort || ofl->ofl_osdyntlssort) {
2134d579eb63Sab 			dyn->d_tag = DT_SUNW_SORTENT;
2135d579eb63Sab 			dyn->d_un.d_val = sizeof (Word);
2136d579eb63Sab 			dyn++;
2137d579eb63Sab 		}
2138d579eb63Sab 
2139d579eb63Sab 		if (ofl->ofl_osdynsymsort) {
2140d579eb63Sab 			dyn->d_tag = DT_SUNW_SYMSORT;
2141d579eb63Sab 			dyn->d_un.d_ptr =
2142d579eb63Sab 			    ofl->ofl_osdynsymsort->os_shdr->sh_addr;
2143d579eb63Sab 			dyn++;
2144d579eb63Sab 
2145d579eb63Sab 			dyn->d_tag = DT_SUNW_SYMSORTSZ;
2146d579eb63Sab 			dyn->d_un.d_val =
2147d579eb63Sab 			    ofl->ofl_osdynsymsort->os_shdr->sh_size;
2148d579eb63Sab 			dyn++;
2149d579eb63Sab 		}
2150d579eb63Sab 
2151d579eb63Sab 		if (ofl->ofl_osdyntlssort) {
2152d579eb63Sab 			dyn->d_tag = DT_SUNW_TLSSORT;
2153d579eb63Sab 			dyn->d_un.d_ptr =
2154d579eb63Sab 			    ofl->ofl_osdyntlssort->os_shdr->sh_addr;
2155d579eb63Sab 			dyn++;
2156d579eb63Sab 
2157d579eb63Sab 			dyn->d_tag = DT_SUNW_TLSSORTSZ;
2158d579eb63Sab 			dyn->d_un.d_val =
2159d579eb63Sab 			    ofl->ofl_osdyntlssort->os_shdr->sh_size;
2160d579eb63Sab 			dyn++;
2161d579eb63Sab 		}
2162d579eb63Sab 
21637c478bd9Sstevel@tonic-gate 		/*
21647c478bd9Sstevel@tonic-gate 		 * Reserve the DT_CHECKSUM entry.  Its value will be filled in
21657c478bd9Sstevel@tonic-gate 		 * after the complete image is built.
21667c478bd9Sstevel@tonic-gate 		 */
21677c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_CHECKSUM;
21687c478bd9Sstevel@tonic-gate 		ofl->ofl_checksum = &dyn->d_un.d_val;
21697c478bd9Sstevel@tonic-gate 		dyn++;
21707c478bd9Sstevel@tonic-gate 
2171d840867fSab 		/*
2172d840867fSab 		 * Versioning sections: DT_VERDEF and DT_VERNEED.
2173d840867fSab 		 *
2174d840867fSab 		 * The Solaris ld does not produce DT_VERSYM, but the GNU ld
2175d840867fSab 		 * does, in order to support their style of versioning, which
2176d840867fSab 		 * differs from ours:
2177d840867fSab 		 *
2178d840867fSab 		 *	- The top bit of the 16-bit Versym index is
2179d840867fSab 		 *		not part of the version, but is interpreted
2180d840867fSab 		 *		as a "hidden bit".
2181d840867fSab 		 *
2182d840867fSab 		 *	- External (SHN_UNDEF) symbols can have non-zero
2183d840867fSab 		 *		Versym values, which specify versions in
2184d840867fSab 		 *		referenced objects, via the Verneed section.
2185d840867fSab 		 *
2186d840867fSab 		 *	- The vna_other field of the Vernaux structures
2187d840867fSab 		 *		found in the Verneed section are not zero as
2188d840867fSab 		 *		with Solaris, but instead contain the version
2189d840867fSab 		 *		index to be used by Versym indices to reference
2190d840867fSab 		 *		the given external version.
2191d840867fSab 		 *
2192d840867fSab 		 * The Solaris ld, rtld, and elfdump programs all interpret the
2193d840867fSab 		 * presence of DT_VERSYM as meaning that GNU versioning rules
2194d840867fSab 		 * apply to the given file. If DT_VERSYM is not present,
2195d840867fSab 		 * then Solaris versioning rules apply. If we should ever need
2196d840867fSab 		 * to change our ld so that it does issue DT_VERSYM, then
2197d840867fSab 		 * this rule for detecting GNU versioning will no longer work.
2198d840867fSab 		 * In that case, we will have to invent a way to explicitly
2199d840867fSab 		 * specify the style of versioning in use, perhaps via a
2200d840867fSab 		 * new dynamic entry named something like DT_SUNW_VERSIONSTYLE,
2201d840867fSab 		 * where the d_un.d_val value specifies which style is to be
2202d840867fSab 		 * used.
2203d840867fSab 		 */
22047c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) ==
22057c478bd9Sstevel@tonic-gate 		    FLG_OF_VERDEF) {
22067c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osverdef->os_shdr;
22077c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERDEF;
22087c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22097c478bd9Sstevel@tonic-gate 			dyn++;
22107c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERDEFNUM;
22117c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_info;
22127c478bd9Sstevel@tonic-gate 			dyn++;
22137c478bd9Sstevel@tonic-gate 		}
22147c478bd9Sstevel@tonic-gate 		if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) ==
22157c478bd9Sstevel@tonic-gate 		    FLG_OF_VERNEED) {
22167c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osverneed->os_shdr;
22177c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERNEED;
22187c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22197c478bd9Sstevel@tonic-gate 			dyn++;
22207c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_VERNEEDNUM;
22217c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_info;
22227c478bd9Sstevel@tonic-gate 			dyn++;
22237c478bd9Sstevel@tonic-gate 		}
2224d840867fSab 
2225e38a713aSrie 		if ((ofl->ofl_flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt) {
22267c478bd9Sstevel@tonic-gate 			dyn->d_tag = M_REL_DT_COUNT;
22277c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = ofl->ofl_relocrelcnt;
22287c478bd9Sstevel@tonic-gate 			dyn++;
22297c478bd9Sstevel@tonic-gate 		}
22307c478bd9Sstevel@tonic-gate 		if (flags & FLG_OF_TEXTREL) {
22317c478bd9Sstevel@tonic-gate 			/*
22327c478bd9Sstevel@tonic-gate 			 * Only the presence of this entry is used in this
22337c478bd9Sstevel@tonic-gate 			 * implementation, not the value stored.
22347c478bd9Sstevel@tonic-gate 			 */
22357c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_TEXTREL;
22367c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = 0;
22377c478bd9Sstevel@tonic-gate 			dyn++;
22387c478bd9Sstevel@tonic-gate 		}
22397c478bd9Sstevel@tonic-gate 
22407c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osfiniarray) {
22417c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osfiniarray->os_shdr;
22427c478bd9Sstevel@tonic-gate 
22437c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_FINI_ARRAY;
22447c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22457c478bd9Sstevel@tonic-gate 			dyn++;
22467c478bd9Sstevel@tonic-gate 
22477c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_FINI_ARRAYSZ;
22487c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
22497c478bd9Sstevel@tonic-gate 			dyn++;
22507c478bd9Sstevel@tonic-gate 		}
22517c478bd9Sstevel@tonic-gate 
22527c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osinitarray) {
22537c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_osinitarray->os_shdr;
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_INIT_ARRAY;
22567c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22577c478bd9Sstevel@tonic-gate 			dyn++;
22587c478bd9Sstevel@tonic-gate 
22597c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_INIT_ARRAYSZ;
22607c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
22617c478bd9Sstevel@tonic-gate 			dyn++;
22627c478bd9Sstevel@tonic-gate 		}
22637c478bd9Sstevel@tonic-gate 
22647c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ospreinitarray) {
22657c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_ospreinitarray->os_shdr;
22667c478bd9Sstevel@tonic-gate 
22677c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PREINIT_ARRAY;
22687c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22697c478bd9Sstevel@tonic-gate 			dyn++;
22707c478bd9Sstevel@tonic-gate 
22717c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PREINIT_ARRAYSZ;
22727c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
22737c478bd9Sstevel@tonic-gate 			dyn++;
22747c478bd9Sstevel@tonic-gate 		}
22757c478bd9Sstevel@tonic-gate 
22767c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltcnt) {
22777c478bd9Sstevel@tonic-gate 			shdr =  ofl->ofl_osplt->os_relosdesc->os_shdr;
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTRELSZ;
22807c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_size;
22817c478bd9Sstevel@tonic-gate 			dyn++;
22827c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTREL;
22837c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = M_REL_DT_TYPE;
22847c478bd9Sstevel@tonic-gate 			dyn++;
22857c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_JMPREL;
22867c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
22877c478bd9Sstevel@tonic-gate 			dyn++;
22887c478bd9Sstevel@tonic-gate 		}
22897c478bd9Sstevel@tonic-gate 		if (ofl->ofl_pltpad) {
22907c478bd9Sstevel@tonic-gate 			shdr =  ofl->ofl_osplt->os_shdr;
22917c478bd9Sstevel@tonic-gate 
22927c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTPAD;
229360758829Srie 			if (ofl->ofl_pltcnt) {
22947c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = shdr->sh_addr +
2295d840867fSab 				    M_PLT_RESERVSZ +
2296d840867fSab 				    ofl->ofl_pltcnt * M_PLT_ENTSIZE;
229760758829Srie 			} else
22987c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = shdr->sh_addr;
22997c478bd9Sstevel@tonic-gate 			dyn++;
23007c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_PLTPADSZ;
2301d840867fSab 			dyn->d_un.d_val = ofl->ofl_pltpad * M_PLT_ENTSIZE;
23027c478bd9Sstevel@tonic-gate 			dyn++;
23037c478bd9Sstevel@tonic-gate 		}
23047c478bd9Sstevel@tonic-gate 		if (ofl->ofl_relocsz) {
23057c478bd9Sstevel@tonic-gate 			dyn->d_tag = M_REL_DT_TYPE;
23067c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = ofl->ofl_osrelhead->os_shdr->sh_addr;
23077c478bd9Sstevel@tonic-gate 			dyn++;
23087c478bd9Sstevel@tonic-gate 			dyn->d_tag = M_REL_DT_SIZE;
23097c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = ofl->ofl_relocsz;
23107c478bd9Sstevel@tonic-gate 			dyn++;
23117c478bd9Sstevel@tonic-gate 			dyn->d_tag = M_REL_DT_ENT;
23127c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osrelhead->os_shdr->sh_type == SHT_REL)
23137c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = sizeof (Rel);
23147c478bd9Sstevel@tonic-gate 			else
23157c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = sizeof (Rela);
23167c478bd9Sstevel@tonic-gate 			dyn++;
23177c478bd9Sstevel@tonic-gate 		}
23187c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ossyminfo) {
23197c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_ossyminfo->os_shdr;
23207c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SYMINFO;
23217c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = shdr->sh_addr;
23227c478bd9Sstevel@tonic-gate 			dyn++;
23237c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SYMINSZ;
23247c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = shdr->sh_size;
23257c478bd9Sstevel@tonic-gate 			dyn++;
23267c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SYMINENT;
23277c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = sizeof (Syminfo);
23287c478bd9Sstevel@tonic-gate 			dyn++;
23297c478bd9Sstevel@tonic-gate 		}
23307c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osmove) {
23317c478bd9Sstevel@tonic-gate 			Os_desc *	osp;
23327c478bd9Sstevel@tonic-gate 
23337c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_MOVEENT;
23347c478bd9Sstevel@tonic-gate 			osp = ofl->ofl_osmove;
23357c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = osp->os_shdr->sh_entsize;
23367c478bd9Sstevel@tonic-gate 			dyn++;
23377c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_MOVESZ;
23387c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = osp->os_shdr->sh_size;
23397c478bd9Sstevel@tonic-gate 			dyn++;
23407c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_MOVETAB;
23417c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = osp->os_shdr->sh_addr;
23427c478bd9Sstevel@tonic-gate 			dyn++;
23437c478bd9Sstevel@tonic-gate 		}
23447c478bd9Sstevel@tonic-gate 		if (ofl->ofl_regsymcnt) {
23457c478bd9Sstevel@tonic-gate 			int	ndx;
23467c478bd9Sstevel@tonic-gate 
23477c478bd9Sstevel@tonic-gate 			for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
23487c478bd9Sstevel@tonic-gate 				if ((sdp = ofl->ofl_regsyms[ndx]) == 0)
23497c478bd9Sstevel@tonic-gate 					continue;
23507c478bd9Sstevel@tonic-gate 
23517c478bd9Sstevel@tonic-gate 				dyn->d_tag = M_DT_REGISTER;
23527c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = sdp->sd_symndx;
23537c478bd9Sstevel@tonic-gate 				dyn++;
23547c478bd9Sstevel@tonic-gate 			}
23557c478bd9Sstevel@tonic-gate 		}
23567c478bd9Sstevel@tonic-gate 
23577c478bd9Sstevel@tonic-gate 		for (LIST_TRAVERSE(&ofl->ofl_rtldinfo, lnp, sdp)) {
23587c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SUNW_RTLDINF;
23597c478bd9Sstevel@tonic-gate 			dyn->d_un.d_ptr = sdp->sd_sym->st_value;
23607c478bd9Sstevel@tonic-gate 			dyn++;
23617c478bd9Sstevel@tonic-gate 		}
23627c478bd9Sstevel@tonic-gate 
23637c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynamic->os_sgdesc &&
23647c478bd9Sstevel@tonic-gate 		    (ofl->ofl_osdynamic->os_sgdesc->sg_phdr.p_flags & PF_W)) {
23657c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osinterp) {
23667c478bd9Sstevel@tonic-gate 				dyn->d_tag = DT_DEBUG;
23677c478bd9Sstevel@tonic-gate 				dyn->d_un.d_ptr = 0;
23687c478bd9Sstevel@tonic-gate 				dyn++;
23697c478bd9Sstevel@tonic-gate 			}
23707c478bd9Sstevel@tonic-gate 
23717c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_FEATURE_1;
23727c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osmove)
23737c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = 0;
23747c478bd9Sstevel@tonic-gate 			else
23757c478bd9Sstevel@tonic-gate 				dyn->d_un.d_val = DTF_1_PARINIT;
23767c478bd9Sstevel@tonic-gate 			dyn++;
23777c478bd9Sstevel@tonic-gate 		}
23787c478bd9Sstevel@tonic-gate 
23797c478bd9Sstevel@tonic-gate 		if (ofl->ofl_oscap) {
23807c478bd9Sstevel@tonic-gate 			dyn->d_tag = DT_SUNW_CAP;
23817c478bd9Sstevel@tonic-gate 			dyn->d_un.d_val = ofl->ofl_oscap->os_shdr->sh_addr;
23827c478bd9Sstevel@tonic-gate 			dyn++;
23837c478bd9Sstevel@tonic-gate 		}
23847c478bd9Sstevel@tonic-gate 	}
23857c478bd9Sstevel@tonic-gate 
23867c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_SYMBOLIC) {
23877c478bd9Sstevel@tonic-gate 		dyn->d_tag = DT_SYMBOLIC;
23887c478bd9Sstevel@tonic-gate 		dyn->d_un.d_val = 0;
23897c478bd9Sstevel@tonic-gate 		dyn++;
23907c478bd9Sstevel@tonic-gate 	}
23917c478bd9Sstevel@tonic-gate 	dyn->d_tag = DT_FLAGS;
23927c478bd9Sstevel@tonic-gate 	dyn->d_un.d_val = ofl->ofl_dtflags;
23937c478bd9Sstevel@tonic-gate 	dyn++;
23947c478bd9Sstevel@tonic-gate 
23957c478bd9Sstevel@tonic-gate 	/*
23967c478bd9Sstevel@tonic-gate 	 * If -Bdirect was specified, but some NODIRECT symbols were specified
23977c478bd9Sstevel@tonic-gate 	 * via a mapfile, or -znodirect was used on the command line, then
23987c478bd9Sstevel@tonic-gate 	 * clear the DF_1_DIRECT flag.  The resultant object will use per-symbol
23997c478bd9Sstevel@tonic-gate 	 * direct bindings rather than be enabled for global direct bindings.
24007c478bd9Sstevel@tonic-gate 	 */
240160758829Srie 	if (ofl->ofl_flags1 & FLG_OF1_NDIRECT) {
24027c478bd9Sstevel@tonic-gate 		ofl->ofl_dtflags_1 &= ~DF_1_DIRECT;
240360758829Srie 		ofl->ofl_dtflags_1 |= DF_1_NODIRECT;
240460758829Srie 	}
24057c478bd9Sstevel@tonic-gate 
24067c478bd9Sstevel@tonic-gate 	dyn->d_tag = DT_FLAGS_1;
24077c478bd9Sstevel@tonic-gate 	dyn->d_un.d_val = ofl->ofl_dtflags_1;
24087c478bd9Sstevel@tonic-gate 	dyn++;
24097c478bd9Sstevel@tonic-gate 
24103244bcaaSab 	dyn->d_tag = DT_SUNW_STRPAD;
24113244bcaaSab 	dyn->d_un.d_val = DYNSTR_EXTRA_PAD;
24123244bcaaSab 	dyn++;
24133244bcaaSab 
24145aefb655Srie 	ld_mach_update_odynamic(ofl, &dyn);
24157c478bd9Sstevel@tonic-gate 
24163244bcaaSab 	for (cnt = 1 + DYNAMIC_EXTRA_ELTS; cnt--; dyn++) {
24173244bcaaSab 		dyn->d_tag = DT_NULL;
24183244bcaaSab 		dyn->d_un.d_val = 0;
24193244bcaaSab 	}
24207c478bd9Sstevel@tonic-gate 
24215b59e4caSab 	/*
24225b59e4caSab 	 * Ensure that we wrote the right number of entries. If not,
24235b59e4caSab 	 * we either miscounted in make_dynamic(), or we did something wrong
24245b59e4caSab 	 * in this function.
24255b59e4caSab 	 */
24265b59e4caSab 	assert((ofl->ofl_osdynamic->os_shdr->sh_size /
24275b59e4caSab 	    ofl->ofl_osdynamic->os_shdr->sh_entsize) ==
24283244bcaaSab 	    ((uintptr_t)dyn - (uintptr_t)_dyn) / sizeof (*dyn));
24295b59e4caSab 
24307c478bd9Sstevel@tonic-gate 	return (1);
24317c478bd9Sstevel@tonic-gate }
24327c478bd9Sstevel@tonic-gate 
24337c478bd9Sstevel@tonic-gate /*
24347c478bd9Sstevel@tonic-gate  * Build the version definition section
24357c478bd9Sstevel@tonic-gate  */
24365aefb655Srie static int
24377c478bd9Sstevel@tonic-gate update_overdef(Ofl_desc *ofl)
24387c478bd9Sstevel@tonic-gate {
24397c478bd9Sstevel@tonic-gate 	Listnode	*lnp1, *lnp2;
24407c478bd9Sstevel@tonic-gate 	Ver_desc	*vdp, *_vdp;
24417c478bd9Sstevel@tonic-gate 	Verdef		*vdf, *_vdf;
24427c478bd9Sstevel@tonic-gate 	int		num = 0;
24437c478bd9Sstevel@tonic-gate 	Os_desc		*strosp, *symosp;
24447c478bd9Sstevel@tonic-gate 
24457c478bd9Sstevel@tonic-gate 	/*
24467c478bd9Sstevel@tonic-gate 	 * Traverse the version descriptors and update the version structures
24477c478bd9Sstevel@tonic-gate 	 * to point to the dynstr name in preparation for building the version
24487c478bd9Sstevel@tonic-gate 	 * section structure.
24497c478bd9Sstevel@tonic-gate 	 */
24507c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_verdesc, lnp1, vdp)) {
24517c478bd9Sstevel@tonic-gate 		Sym_desc *	sdp;
24527c478bd9Sstevel@tonic-gate 
24537c478bd9Sstevel@tonic-gate 		if (vdp->vd_flags & VER_FLG_BASE) {
24547c478bd9Sstevel@tonic-gate 			const char	*name = vdp->vd_name;
2455*cce0e03bSab 			size_t		stoff;
24567c478bd9Sstevel@tonic-gate 
24577c478bd9Sstevel@tonic-gate 			/*
24587c478bd9Sstevel@tonic-gate 			 * Create a new string table entry to represent the base
24597c478bd9Sstevel@tonic-gate 			 * version name (there is no corresponding symbol for
24607c478bd9Sstevel@tonic-gate 			 * this).
24617c478bd9Sstevel@tonic-gate 			 */
24627c478bd9Sstevel@tonic-gate 			if (!(ofl->ofl_flags & FLG_OF_DYNAMIC)) {
24637c478bd9Sstevel@tonic-gate 				(void) st_setstring(ofl->ofl_strtab,
2464d840867fSab 				    name, &stoff);
24657c478bd9Sstevel@tonic-gate 				/* LINTED */
2466*cce0e03bSab 				vdp->vd_name = (const char *)stoff;
24677c478bd9Sstevel@tonic-gate 			} else {
24687c478bd9Sstevel@tonic-gate 				(void) st_setstring(ofl->ofl_dynstrtab,
2469d840867fSab 				    name, &stoff);
24707c478bd9Sstevel@tonic-gate 				/* LINTED */
2471*cce0e03bSab 				vdp->vd_name = (const char *)stoff;
24727c478bd9Sstevel@tonic-gate 			}
24737c478bd9Sstevel@tonic-gate 		} else {
24745aefb655Srie 			sdp = ld_sym_find(vdp->vd_name, vdp->vd_hash, 0, ofl);
24757c478bd9Sstevel@tonic-gate 			/* LINTED */
24767c478bd9Sstevel@tonic-gate 			vdp->vd_name = (const char *)
2477d840867fSab 			    (uintptr_t)sdp->sd_sym->st_name;
24787c478bd9Sstevel@tonic-gate 		}
24797c478bd9Sstevel@tonic-gate 	}
24807c478bd9Sstevel@tonic-gate 
24817c478bd9Sstevel@tonic-gate 	_vdf = vdf = (Verdef *)ofl->ofl_osverdef->os_outdata->d_buf;
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate 	/*
24847c478bd9Sstevel@tonic-gate 	 * Traverse the version descriptors and update the version section to
24857c478bd9Sstevel@tonic-gate 	 * reflect each version and its associated dependencies.
24867c478bd9Sstevel@tonic-gate 	 */
24877c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_verdesc, lnp1, vdp)) {
24887c478bd9Sstevel@tonic-gate 		Half		cnt = 1;
24897c478bd9Sstevel@tonic-gate 		Verdaux *	vdap, * _vdap;
24907c478bd9Sstevel@tonic-gate 
24917c478bd9Sstevel@tonic-gate 		_vdap = vdap = (Verdaux *)(vdf + 1);
24927c478bd9Sstevel@tonic-gate 
24937c478bd9Sstevel@tonic-gate 		vdf->vd_version = VER_DEF_CURRENT;
24947c478bd9Sstevel@tonic-gate 		vdf->vd_flags	= vdp->vd_flags & MSK_VER_USER;
24957c478bd9Sstevel@tonic-gate 		vdf->vd_ndx	= vdp->vd_ndx;
24967c478bd9Sstevel@tonic-gate 		vdf->vd_hash	= vdp->vd_hash;
24977c478bd9Sstevel@tonic-gate 
24987c478bd9Sstevel@tonic-gate 		/* LINTED */
24997c478bd9Sstevel@tonic-gate 		vdap->vda_name = (uintptr_t)vdp->vd_name;
25007c478bd9Sstevel@tonic-gate 		vdap++;
25017c478bd9Sstevel@tonic-gate 		/* LINTED */
25027c478bd9Sstevel@tonic-gate 		_vdap->vda_next = (Word)((uintptr_t)vdap - (uintptr_t)_vdap);
25037c478bd9Sstevel@tonic-gate 
25047c478bd9Sstevel@tonic-gate 		/*
25057c478bd9Sstevel@tonic-gate 		 * Traverse this versions dependency list generating the
25067c478bd9Sstevel@tonic-gate 		 * appropriate version dependency entries.
25077c478bd9Sstevel@tonic-gate 		 */
25087c478bd9Sstevel@tonic-gate 		for (LIST_TRAVERSE(&vdp->vd_deps, lnp2, _vdp)) {
25097c478bd9Sstevel@tonic-gate 			/* LINTED */
25107c478bd9Sstevel@tonic-gate 			vdap->vda_name = (uintptr_t)_vdp->vd_name;
25117c478bd9Sstevel@tonic-gate 			_vdap = vdap;
25127c478bd9Sstevel@tonic-gate 			vdap++, cnt++;
25137c478bd9Sstevel@tonic-gate 			/* LINTED */
25147c478bd9Sstevel@tonic-gate 			_vdap->vda_next = (Word)((uintptr_t)vdap -
25157c478bd9Sstevel@tonic-gate 			    (uintptr_t)_vdap);
25167c478bd9Sstevel@tonic-gate 		}
25177c478bd9Sstevel@tonic-gate 		_vdap->vda_next = 0;
25187c478bd9Sstevel@tonic-gate 
25197c478bd9Sstevel@tonic-gate 		/*
25207c478bd9Sstevel@tonic-gate 		 * Record the versions auxiliary array offset and the associated
25217c478bd9Sstevel@tonic-gate 		 * dependency count.
25227c478bd9Sstevel@tonic-gate 		 */
25237c478bd9Sstevel@tonic-gate 		/* LINTED */
25247c478bd9Sstevel@tonic-gate 		vdf->vd_aux = (Word)((uintptr_t)(vdf + 1) - (uintptr_t)vdf);
25257c478bd9Sstevel@tonic-gate 		vdf->vd_cnt = cnt;
25267c478bd9Sstevel@tonic-gate 
25277c478bd9Sstevel@tonic-gate 		/*
25287c478bd9Sstevel@tonic-gate 		 * Record the next versions offset and update the version
25297c478bd9Sstevel@tonic-gate 		 * pointer.  Remember the previous version offset as the very
25307c478bd9Sstevel@tonic-gate 		 * last structures next pointer should be null.
25317c478bd9Sstevel@tonic-gate 		 */
25327c478bd9Sstevel@tonic-gate 		_vdf = vdf;
25337c478bd9Sstevel@tonic-gate 		vdf = (Verdef *)vdap, num++;
25347c478bd9Sstevel@tonic-gate 		/* LINTED */
25357c478bd9Sstevel@tonic-gate 		_vdf->vd_next = (Word)((uintptr_t)vdf - (uintptr_t)_vdf);
25367c478bd9Sstevel@tonic-gate 	}
25377c478bd9Sstevel@tonic-gate 	_vdf->vd_next = 0;
25387c478bd9Sstevel@tonic-gate 
25397c478bd9Sstevel@tonic-gate 	/*
25407c478bd9Sstevel@tonic-gate 	 * Record the string table association with the version definition
25417c478bd9Sstevel@tonic-gate 	 * section, and the symbol table associated with the version symbol
25427c478bd9Sstevel@tonic-gate 	 * table (the actual contents of the version symbol table are filled
25437c478bd9Sstevel@tonic-gate 	 * in during symbol update).
25447c478bd9Sstevel@tonic-gate 	 */
25457c478bd9Sstevel@tonic-gate 	if ((ofl->ofl_flags & FLG_OF_RELOBJ) ||
25467c478bd9Sstevel@tonic-gate 	    (ofl->ofl_flags & FLG_OF_STATIC)) {
25477c478bd9Sstevel@tonic-gate 		strosp = ofl->ofl_osstrtab;
25487c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_ossymtab;
25497c478bd9Sstevel@tonic-gate 	} else {
25507c478bd9Sstevel@tonic-gate 		strosp = ofl->ofl_osdynstr;
25517c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_osdynsym;
25527c478bd9Sstevel@tonic-gate 	}
25537c478bd9Sstevel@tonic-gate 	/* LINTED */
25547c478bd9Sstevel@tonic-gate 	ofl->ofl_osverdef->os_shdr->sh_link = (Word)elf_ndxscn(strosp->os_scn);
25557c478bd9Sstevel@tonic-gate 	/* LINTED */
25567c478bd9Sstevel@tonic-gate 	ofl->ofl_osversym->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn);
25577c478bd9Sstevel@tonic-gate 
25587c478bd9Sstevel@tonic-gate 	/*
25597c478bd9Sstevel@tonic-gate 	 * The version definition sections `info' field is used to indicate the
25607c478bd9Sstevel@tonic-gate 	 * number of entries in this section.
25617c478bd9Sstevel@tonic-gate 	 */
25627c478bd9Sstevel@tonic-gate 	ofl->ofl_osverdef->os_shdr->sh_info = num;
25637c478bd9Sstevel@tonic-gate 
25647c478bd9Sstevel@tonic-gate 	return (1);
25657c478bd9Sstevel@tonic-gate }
25667c478bd9Sstevel@tonic-gate 
25677c478bd9Sstevel@tonic-gate /*
25687c478bd9Sstevel@tonic-gate  * Build the version needed section
25697c478bd9Sstevel@tonic-gate  */
25705aefb655Srie static int
25717c478bd9Sstevel@tonic-gate update_overneed(Ofl_desc *ofl)
25727c478bd9Sstevel@tonic-gate {
25737c478bd9Sstevel@tonic-gate 	Listnode	*lnp;
25747c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
25757c478bd9Sstevel@tonic-gate 	Verneed		*vnd, *_vnd;
25767c478bd9Sstevel@tonic-gate 	Str_tbl		*dynstr;
25777c478bd9Sstevel@tonic-gate 	Word		num = 0, cnt = 0;
25787c478bd9Sstevel@tonic-gate 
25797c478bd9Sstevel@tonic-gate 	dynstr = ofl->ofl_dynstrtab;
25807c478bd9Sstevel@tonic-gate 	_vnd = vnd = (Verneed *)ofl->ofl_osverneed->os_outdata->d_buf;
25817c478bd9Sstevel@tonic-gate 
25827c478bd9Sstevel@tonic-gate 	/*
25837c478bd9Sstevel@tonic-gate 	 * Traverse the shared object list looking for dependencies that have
25847c478bd9Sstevel@tonic-gate 	 * versions defined within them.
25857c478bd9Sstevel@tonic-gate 	 */
25867c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_sos, lnp, ifl)) {
25877c478bd9Sstevel@tonic-gate 		Half		_cnt;
25887c478bd9Sstevel@tonic-gate 		Vernaux		*_vnap, *vnap;
25897c478bd9Sstevel@tonic-gate 		Sdf_desc	*sdf = ifl->ifl_sdfdesc;
2590*cce0e03bSab 		size_t		stoff;
25917c478bd9Sstevel@tonic-gate 
25927c478bd9Sstevel@tonic-gate 		if (!(ifl->ifl_flags & FLG_IF_VERNEED))
25937c478bd9Sstevel@tonic-gate 			continue;
25947c478bd9Sstevel@tonic-gate 
25957c478bd9Sstevel@tonic-gate 		vnd->vn_version = VER_NEED_CURRENT;
25967c478bd9Sstevel@tonic-gate 
25977c478bd9Sstevel@tonic-gate 		(void) st_setstring(dynstr, ifl->ifl_soname, &stoff);
25987c478bd9Sstevel@tonic-gate 		vnd->vn_file = stoff;
25997c478bd9Sstevel@tonic-gate 
26007c478bd9Sstevel@tonic-gate 		_vnap = vnap = (Vernaux *)(vnd + 1);
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate 		if (sdf && (sdf->sdf_flags & FLG_SDF_SPECVER)) {
260360758829Srie 			Sdv_desc	*sdv;
260460758829Srie 			Listnode	*lnp2;
26057c478bd9Sstevel@tonic-gate 
26067c478bd9Sstevel@tonic-gate 			/*
26077c478bd9Sstevel@tonic-gate 			 * If version needed definitions were specified in
26087c478bd9Sstevel@tonic-gate 			 * a mapfile ($VERSION=*) then record those
26097c478bd9Sstevel@tonic-gate 			 * definitions.
26107c478bd9Sstevel@tonic-gate 			 */
26117c478bd9Sstevel@tonic-gate 			for (LIST_TRAVERSE(&sdf->sdf_verneed, lnp2, sdv)) {
2612d840867fSab 				(void) st_setstring(dynstr, sdv->sdv_name,
2613d840867fSab 				    &stoff);
26147c478bd9Sstevel@tonic-gate 				vnap->vna_name = stoff;
26157c478bd9Sstevel@tonic-gate 				/* LINTED */
26167c478bd9Sstevel@tonic-gate 				vnap->vna_hash = (Word)elf_hash(sdv->sdv_name);
26177c478bd9Sstevel@tonic-gate 				vnap->vna_flags = 0;
26187c478bd9Sstevel@tonic-gate 				vnap->vna_other = 0;
26197c478bd9Sstevel@tonic-gate 				_vnap = vnap;
26207c478bd9Sstevel@tonic-gate 				vnap++;
26217c478bd9Sstevel@tonic-gate 				cnt++;
26227c478bd9Sstevel@tonic-gate 				/* LINTED */
26237c478bd9Sstevel@tonic-gate 				_vnap->vna_next = (Word)((uintptr_t)vnap -
26247c478bd9Sstevel@tonic-gate 				    (uintptr_t)_vnap);
26257c478bd9Sstevel@tonic-gate 			}
26267c478bd9Sstevel@tonic-gate 		} else {
26277c478bd9Sstevel@tonic-gate 
26287c478bd9Sstevel@tonic-gate 			/*
26297c478bd9Sstevel@tonic-gate 			 * Traverse the version index list recording
26307c478bd9Sstevel@tonic-gate 			 * each version as a needed dependency.
26317c478bd9Sstevel@tonic-gate 			 */
26327c478bd9Sstevel@tonic-gate 			for (cnt = _cnt = 0; _cnt <= ifl->ifl_vercnt;
26337c478bd9Sstevel@tonic-gate 			    _cnt++) {
263460758829Srie 				Ver_index	*vip = &ifl->ifl_verndx[_cnt];
26357c478bd9Sstevel@tonic-gate 
26367c478bd9Sstevel@tonic-gate 				if (vip->vi_flags & FLG_VER_REFER) {
26377c478bd9Sstevel@tonic-gate 					(void) st_setstring(dynstr,
2638d840867fSab 					    vip->vi_name, &stoff);
26397c478bd9Sstevel@tonic-gate 					vnap->vna_name = stoff;
264060758829Srie 
26417c478bd9Sstevel@tonic-gate 					if (vip->vi_desc) {
2642d840867fSab 						vnap->vna_hash =
2643d840867fSab 						    vip->vi_desc->vd_hash;
2644d840867fSab 						vnap->vna_flags =
2645d840867fSab 						    vip->vi_desc->vd_flags;
26467c478bd9Sstevel@tonic-gate 					} else {
2647d840867fSab 						vnap->vna_hash = 0;
2648d840867fSab 						vnap->vna_flags = 0;
26497c478bd9Sstevel@tonic-gate 					}
26507c478bd9Sstevel@tonic-gate 					vnap->vna_other = 0;
26517c478bd9Sstevel@tonic-gate 
26527c478bd9Sstevel@tonic-gate 					_vnap = vnap;
26537c478bd9Sstevel@tonic-gate 					vnap++, cnt++;
26547c478bd9Sstevel@tonic-gate 					_vnap->vna_next =
2655d840867fSab 					    /* LINTED */
2656d840867fSab 					    (Word)((uintptr_t)vnap -
2657d840867fSab 					    (uintptr_t)_vnap);
26587c478bd9Sstevel@tonic-gate 				}
26597c478bd9Sstevel@tonic-gate 			}
26607c478bd9Sstevel@tonic-gate 		}
26617c478bd9Sstevel@tonic-gate 		_vnap->vna_next = 0;
26627c478bd9Sstevel@tonic-gate 
26637c478bd9Sstevel@tonic-gate 		/*
26647c478bd9Sstevel@tonic-gate 		 * Record the versions auxiliary array offset and
26657c478bd9Sstevel@tonic-gate 		 * the associated dependency count.
26667c478bd9Sstevel@tonic-gate 		 */
26677c478bd9Sstevel@tonic-gate 		/* LINTED */
26687c478bd9Sstevel@tonic-gate 		vnd->vn_aux = (Word)((uintptr_t)(vnd + 1) - (uintptr_t)vnd);
26697c478bd9Sstevel@tonic-gate 		/* LINTED */
26707c478bd9Sstevel@tonic-gate 		vnd->vn_cnt = (Half)cnt;
26717c478bd9Sstevel@tonic-gate 
26727c478bd9Sstevel@tonic-gate 		/*
26737c478bd9Sstevel@tonic-gate 		 * Record the next versions offset and update the version
26747c478bd9Sstevel@tonic-gate 		 * pointer.  Remember the previous version offset as the very
26757c478bd9Sstevel@tonic-gate 		 * last structures next pointer should be null.
26767c478bd9Sstevel@tonic-gate 		 */
26777c478bd9Sstevel@tonic-gate 		_vnd = vnd;
26787c478bd9Sstevel@tonic-gate 		vnd = (Verneed *)vnap, num++;
26797c478bd9Sstevel@tonic-gate 		/* LINTED */
26807c478bd9Sstevel@tonic-gate 		_vnd->vn_next = (Word)((uintptr_t)vnd - (uintptr_t)_vnd);
26817c478bd9Sstevel@tonic-gate 	}
26827c478bd9Sstevel@tonic-gate 	_vnd->vn_next = 0;
26837c478bd9Sstevel@tonic-gate 
26847c478bd9Sstevel@tonic-gate 	/*
26857c478bd9Sstevel@tonic-gate 	 * Record association on string table section and use the
26867c478bd9Sstevel@tonic-gate 	 * `info' field to indicate the number of entries in this
26877c478bd9Sstevel@tonic-gate 	 * section.
26887c478bd9Sstevel@tonic-gate 	 */
26897c478bd9Sstevel@tonic-gate 	ofl->ofl_osverneed->os_shdr->sh_link =
26907c478bd9Sstevel@tonic-gate 	    /* LINTED */
26917c478bd9Sstevel@tonic-gate 	    (Word)elf_ndxscn(ofl->ofl_osdynstr->os_scn);
26927c478bd9Sstevel@tonic-gate 	ofl->ofl_osverneed->os_shdr->sh_info = num;
26937c478bd9Sstevel@tonic-gate 
26947c478bd9Sstevel@tonic-gate 	return (1);
26957c478bd9Sstevel@tonic-gate }
26967c478bd9Sstevel@tonic-gate 
26977c478bd9Sstevel@tonic-gate 
26987c478bd9Sstevel@tonic-gate /*
26997c478bd9Sstevel@tonic-gate  * Update syminfo section.
27007c478bd9Sstevel@tonic-gate  */
27015aefb655Srie static uintptr_t
27027c478bd9Sstevel@tonic-gate update_osyminfo(Ofl_desc * ofl)
27037c478bd9Sstevel@tonic-gate {
27047c478bd9Sstevel@tonic-gate 	Os_desc *	symosp, * infosp = ofl->ofl_ossyminfo;
27057c478bd9Sstevel@tonic-gate 	Syminfo *	sip = infosp->os_outdata->d_buf;
27067c478bd9Sstevel@tonic-gate 	Shdr *		shdr = infosp->os_shdr;
27077c478bd9Sstevel@tonic-gate 	char		*strtab;
27087c478bd9Sstevel@tonic-gate 	Listnode *	lnp;
27097c478bd9Sstevel@tonic-gate 	Sym_desc *	sdp;
2710*cce0e03bSab 	Aliste		idx;
27117c478bd9Sstevel@tonic-gate 	Sfltr_desc *	sftp;
27127c478bd9Sstevel@tonic-gate 
27137c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_RELOBJ) {
27147c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_ossymtab;
27157c478bd9Sstevel@tonic-gate 		strtab = ofl->ofl_osstrtab->os_outdata->d_buf;
27167c478bd9Sstevel@tonic-gate 	} else {
27177c478bd9Sstevel@tonic-gate 		symosp = ofl->ofl_osdynsym;
27187c478bd9Sstevel@tonic-gate 		strtab = ofl->ofl_osdynstr->os_outdata->d_buf;
27197c478bd9Sstevel@tonic-gate 	}
27207c478bd9Sstevel@tonic-gate 
27217c478bd9Sstevel@tonic-gate 	/* LINTED */
27227c478bd9Sstevel@tonic-gate 	infosp->os_shdr->sh_link = (Word)elf_ndxscn(symosp->os_scn);
27237c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osdynamic)
27247c478bd9Sstevel@tonic-gate 		infosp->os_shdr->sh_info =
27257c478bd9Sstevel@tonic-gate 		    /* LINTED */
27267c478bd9Sstevel@tonic-gate 		    (Word)elf_ndxscn(ofl->ofl_osdynamic->os_scn);
27277c478bd9Sstevel@tonic-gate 
27287c478bd9Sstevel@tonic-gate 	/*
27297c478bd9Sstevel@tonic-gate 	 * Update any references with the index into the dynamic table.
27307c478bd9Sstevel@tonic-gate 	 */
27317c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_syminfsyms, lnp, sdp)) {
27327c478bd9Sstevel@tonic-gate 		Ifl_desc *	ifl;
27337c478bd9Sstevel@tonic-gate 		if (sdp->sd_aux && sdp->sd_aux->sa_bindto)
27347c478bd9Sstevel@tonic-gate 			ifl = sdp->sd_aux->sa_bindto;
27357c478bd9Sstevel@tonic-gate 		else
27367c478bd9Sstevel@tonic-gate 			ifl = sdp->sd_file;
27377c478bd9Sstevel@tonic-gate 		sip[sdp->sd_symndx].si_boundto = ifl->ifl_neededndx;
27387c478bd9Sstevel@tonic-gate 	}
27397c478bd9Sstevel@tonic-gate 
27407c478bd9Sstevel@tonic-gate 	/*
27417c478bd9Sstevel@tonic-gate 	 * Update any filtee references with the index into the dynamic table.
27427c478bd9Sstevel@tonic-gate 	 */
2743*cce0e03bSab 	for (ALIST_TRAVERSE(ofl->ofl_symfltrs, idx, sftp)) {
2744*cce0e03bSab 		Dfltr_desc	*dftp;
27457c478bd9Sstevel@tonic-gate 
2746*cce0e03bSab 		dftp = alist_item(ofl->ofl_dtsfltrs, sftp->sft_idx);
27477c478bd9Sstevel@tonic-gate 		sip[sftp->sft_sdp->sd_symndx].si_boundto = dftp->dft_ndx;
27487c478bd9Sstevel@tonic-gate 	}
27497c478bd9Sstevel@tonic-gate 
27507c478bd9Sstevel@tonic-gate 	/*
27517c478bd9Sstevel@tonic-gate 	 * Display debugging information about section.
27527c478bd9Sstevel@tonic-gate 	 */
27535aefb655Srie 	DBG_CALL(Dbg_syminfo_title(ofl->ofl_lml));
27545aefb655Srie 	if (DBG_ENABLED) {
27555aefb655Srie 		Word	_cnt, cnt = shdr->sh_size / shdr->sh_entsize;
27567c478bd9Sstevel@tonic-gate 		Sym *	symtab = symosp->os_outdata->d_buf;
27577c478bd9Sstevel@tonic-gate 		Dyn *	dyn;
27587c478bd9Sstevel@tonic-gate 
27597c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynamic)
27607c478bd9Sstevel@tonic-gate 			dyn = ofl->ofl_osdynamic->os_outdata->d_buf;
27617c478bd9Sstevel@tonic-gate 		else
27627c478bd9Sstevel@tonic-gate 			dyn = 0;
27637c478bd9Sstevel@tonic-gate 
27647c478bd9Sstevel@tonic-gate 		for (_cnt = 1; _cnt < cnt; _cnt++) {
27657c478bd9Sstevel@tonic-gate 			if (sip[_cnt].si_flags || sip[_cnt].si_boundto)
27667c478bd9Sstevel@tonic-gate 				/* LINTED */
27675aefb655Srie 				DBG_CALL(Dbg_syminfo_entry(ofl->ofl_lml, _cnt,
27687c478bd9Sstevel@tonic-gate 				    &sip[_cnt], &symtab[_cnt], strtab, dyn));
27697c478bd9Sstevel@tonic-gate 		}
27707c478bd9Sstevel@tonic-gate 	}
27717c478bd9Sstevel@tonic-gate 	return (1);
27727c478bd9Sstevel@tonic-gate }
27737c478bd9Sstevel@tonic-gate 
27747c478bd9Sstevel@tonic-gate /*
27757c478bd9Sstevel@tonic-gate  * Build the output elf header.
27767c478bd9Sstevel@tonic-gate  */
27775aefb655Srie static uintptr_t
27787c478bd9Sstevel@tonic-gate update_oehdr(Ofl_desc * ofl)
27797c478bd9Sstevel@tonic-gate {
27805aefb655Srie 	Ehdr	*ehdr = ofl->ofl_nehdr;
27817c478bd9Sstevel@tonic-gate 
27827c478bd9Sstevel@tonic-gate 	/*
27837c478bd9Sstevel@tonic-gate 	 * If an entry point symbol has already been established (refer
27847c478bd9Sstevel@tonic-gate 	 * sym_validate()) simply update the elf header entry point with the
27857c478bd9Sstevel@tonic-gate 	 * symbols value.  If no entry point is defined it will have been filled
27867c478bd9Sstevel@tonic-gate 	 * with the start address of the first section within the text segment
27877c478bd9Sstevel@tonic-gate 	 * (refer update_outfile()).
27887c478bd9Sstevel@tonic-gate 	 */
27897c478bd9Sstevel@tonic-gate 	if (ofl->ofl_entry)
27907c478bd9Sstevel@tonic-gate 		ehdr->e_entry =
2791d840867fSab 		    ((Sym_desc *)(ofl->ofl_entry))->sd_sym->st_value;
27927c478bd9Sstevel@tonic-gate 
27937c478bd9Sstevel@tonic-gate 	/*
27947c478bd9Sstevel@tonic-gate 	 * Note. it may be necessary to update the `e_flags' field in the
27957c478bd9Sstevel@tonic-gate 	 * machine dependent section.
27967c478bd9Sstevel@tonic-gate 	 */
27977c478bd9Sstevel@tonic-gate 	ehdr->e_ident[EI_DATA] = M_DATA;
27985aefb655Srie 	ehdr->e_machine = ofl->ofl_dehdr->e_machine;
27995aefb655Srie 	ehdr->e_flags = ofl->ofl_dehdr->e_flags;
28005aefb655Srie 	ehdr->e_version = ofl->ofl_dehdr->e_version;
28015aefb655Srie 
28025aefb655Srie 	if (ehdr->e_machine != M_MACH) {
28035aefb655Srie 		if (ehdr->e_machine != M_MACHPLUS)
28047c478bd9Sstevel@tonic-gate 			return (S_ERROR);
28055aefb655Srie 		if ((ehdr->e_flags & M_FLAGSPLUS) == 0)
28067c478bd9Sstevel@tonic-gate 			return (S_ERROR);
28077c478bd9Sstevel@tonic-gate 	}
28087c478bd9Sstevel@tonic-gate 
28097c478bd9Sstevel@tonic-gate 	if (ofl->ofl_flags & FLG_OF_SHAROBJ)
28107c478bd9Sstevel@tonic-gate 		ehdr->e_type = ET_DYN;
28117c478bd9Sstevel@tonic-gate 	else if (ofl->ofl_flags & FLG_OF_RELOBJ)
28127c478bd9Sstevel@tonic-gate 		ehdr->e_type = ET_REL;
28137c478bd9Sstevel@tonic-gate 	else
28147c478bd9Sstevel@tonic-gate 		ehdr->e_type = ET_EXEC;
28157c478bd9Sstevel@tonic-gate 
28167c478bd9Sstevel@tonic-gate 	return (1);
28177c478bd9Sstevel@tonic-gate }
28187c478bd9Sstevel@tonic-gate 
28197c478bd9Sstevel@tonic-gate /*
28207c478bd9Sstevel@tonic-gate  * Perform move table expansion.
28217c478bd9Sstevel@tonic-gate  */
28227c478bd9Sstevel@tonic-gate static uintptr_t
28237c478bd9Sstevel@tonic-gate expand_move(Ofl_desc *ofl, Sym_desc *sdp, Move *u1)
28247c478bd9Sstevel@tonic-gate {
28257c478bd9Sstevel@tonic-gate 	Move		*mv;
28267c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
28277c478bd9Sstevel@tonic-gate 	unsigned char	*taddr, *taddr0;
28287c478bd9Sstevel@tonic-gate 	Sxword		offset;
28297c478bd9Sstevel@tonic-gate 	int		i;
28307c478bd9Sstevel@tonic-gate 	Addr		base1;
28317c478bd9Sstevel@tonic-gate 	unsigned int	stride;
28327c478bd9Sstevel@tonic-gate 
28337c478bd9Sstevel@tonic-gate 	osp = ofl->ofl_issunwdata1->is_osdesc;
28347c478bd9Sstevel@tonic-gate 	base1 = (Addr)(osp->os_shdr->sh_addr +
2835d840867fSab 	    ofl->ofl_issunwdata1->is_indata->d_off);
28367c478bd9Sstevel@tonic-gate 	taddr0 = taddr = osp->os_outdata->d_buf;
28377c478bd9Sstevel@tonic-gate 	mv = u1;
28387c478bd9Sstevel@tonic-gate 
28397c478bd9Sstevel@tonic-gate 	offset = sdp->sd_sym->st_value - base1;
28407c478bd9Sstevel@tonic-gate 	taddr += offset;
28417c478bd9Sstevel@tonic-gate 	taddr = taddr + mv->m_poffset;
28427c478bd9Sstevel@tonic-gate 	for (i = 0; i < mv->m_repeat; i++) {
28437c478bd9Sstevel@tonic-gate 		/* LINTED */
28445aefb655Srie 		DBG_CALL(Dbg_move_expand(ofl->ofl_lml, mv,
28455aefb655Srie 		    (Addr)(taddr - taddr0)));
28467c478bd9Sstevel@tonic-gate 		stride = (unsigned int)mv->m_stride + 1;
28477c478bd9Sstevel@tonic-gate 		/* LINTED */
28487c478bd9Sstevel@tonic-gate 		switch (ELF_M_SIZE(mv->m_info)) {
28497c478bd9Sstevel@tonic-gate 		case 1:
28507c478bd9Sstevel@tonic-gate 			/* LINTED */
28517c478bd9Sstevel@tonic-gate 			*taddr = (unsigned char)mv->m_value;
28527c478bd9Sstevel@tonic-gate 			taddr += stride;
28537c478bd9Sstevel@tonic-gate 			break;
28547c478bd9Sstevel@tonic-gate 		case 2:
28557c478bd9Sstevel@tonic-gate 			/* LINTED */
28567c478bd9Sstevel@tonic-gate 			*((Half *)taddr) = (Half)mv->m_value;
28577c478bd9Sstevel@tonic-gate 			taddr += 2*stride;
28587c478bd9Sstevel@tonic-gate 			break;
28597c478bd9Sstevel@tonic-gate 		case 4:
28607c478bd9Sstevel@tonic-gate 			/* LINTED */
28617c478bd9Sstevel@tonic-gate 			*((Word *)taddr) = (Word)mv->m_value;
28627c478bd9Sstevel@tonic-gate 			taddr += 4*stride;
28637c478bd9Sstevel@tonic-gate 			break;
28647c478bd9Sstevel@tonic-gate 		case 8:
28657c478bd9Sstevel@tonic-gate 			/* LINTED */
2866d840867fSab 			*((unsigned long long *)taddr) = mv->m_value;
28677c478bd9Sstevel@tonic-gate 			taddr += 8*stride;
28687c478bd9Sstevel@tonic-gate 			break;
28697c478bd9Sstevel@tonic-gate 		default:
28707c478bd9Sstevel@tonic-gate 			/*
28717c478bd9Sstevel@tonic-gate 			 * Should never come here since this is already
28727c478bd9Sstevel@tonic-gate 			 * checked at sunwmove_preprocess().
28737c478bd9Sstevel@tonic-gate 			 */
28747c478bd9Sstevel@tonic-gate 			return (S_ERROR);
28757c478bd9Sstevel@tonic-gate 		}
28767c478bd9Sstevel@tonic-gate 	}
28777c478bd9Sstevel@tonic-gate 	return (1);
28787c478bd9Sstevel@tonic-gate }
28797c478bd9Sstevel@tonic-gate 
28807c478bd9Sstevel@tonic-gate /*
28817c478bd9Sstevel@tonic-gate  * Update Move sections.
28827c478bd9Sstevel@tonic-gate  */
28835aefb655Srie static uintptr_t
28847c478bd9Sstevel@tonic-gate update_move(Ofl_desc *ofl)
28857c478bd9Sstevel@tonic-gate {
28867c478bd9Sstevel@tonic-gate 	Word		ndx = 0;
28877c478bd9Sstevel@tonic-gate 	Is_desc *	isp;
28887c478bd9Sstevel@tonic-gate 	Word		flags = ofl->ofl_flags;
28897c478bd9Sstevel@tonic-gate 	Move *		mv1, * mv2;
28907c478bd9Sstevel@tonic-gate 	Listnode *	lnp1;
28917c478bd9Sstevel@tonic-gate 	Psym_info *	psym;
28927c478bd9Sstevel@tonic-gate 
28937c478bd9Sstevel@tonic-gate 	/*
28947c478bd9Sstevel@tonic-gate 	 * Determine the index of the symbol table that will be referenced by
28957c478bd9Sstevel@tonic-gate 	 * the relocation entries.
28967c478bd9Sstevel@tonic-gate 	 */
28979039eeafSab 	if (OFL_ALLOW_DYNSYM(ofl))
28987c478bd9Sstevel@tonic-gate 		/* LINTED */
28997c478bd9Sstevel@tonic-gate 		ndx = (Word) elf_ndxscn(ofl->ofl_osdynsym->os_scn);
29007c478bd9Sstevel@tonic-gate 	else if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ))
29017c478bd9Sstevel@tonic-gate 		/* LINTED */
29027c478bd9Sstevel@tonic-gate 		ndx = (Word) elf_ndxscn(ofl->ofl_ossymtab->os_scn);
29037c478bd9Sstevel@tonic-gate 
29047c478bd9Sstevel@tonic-gate 	/*
29057c478bd9Sstevel@tonic-gate 	 * update sh_link and mv pointer for updating move table.
29067c478bd9Sstevel@tonic-gate 	 */
29077c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osmove) {
29087c478bd9Sstevel@tonic-gate 		ofl->ofl_osmove->os_shdr->sh_link = ndx;
29097c478bd9Sstevel@tonic-gate 		mv1 = (Move *) ofl->ofl_osmove->os_outdata->d_buf;
29107c478bd9Sstevel@tonic-gate 	}
29117c478bd9Sstevel@tonic-gate 
29127c478bd9Sstevel@tonic-gate 	/*
29137c478bd9Sstevel@tonic-gate 	 * Update symbol entry index
29147c478bd9Sstevel@tonic-gate 	 */
29157c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_parsym, lnp1, psym)) {
29167c478bd9Sstevel@tonic-gate 		Listnode *	lnp2;
29177c478bd9Sstevel@tonic-gate 		Mv_itm *	mvp;
29187c478bd9Sstevel@tonic-gate 		Sym_desc 	*sdp;
29197c478bd9Sstevel@tonic-gate 
29207c478bd9Sstevel@tonic-gate 		/*
29217c478bd9Sstevel@tonic-gate 		 * Expand move table
29227c478bd9Sstevel@tonic-gate 		 */
29237c478bd9Sstevel@tonic-gate 		if (psym->psym_symd->sd_flags & FLG_SY_PAREXPN) {
29247c478bd9Sstevel@tonic-gate 			const char	*s;
29257c478bd9Sstevel@tonic-gate 
29267c478bd9Sstevel@tonic-gate 			if (ofl->ofl_flags & FLG_OF_STATIC)
29277c478bd9Sstevel@tonic-gate 				s = MSG_INTL(MSG_PSYM_EXPREASON1);
29287c478bd9Sstevel@tonic-gate 			else if (ofl->ofl_flags1 & FLG_OF1_NOPARTI)
29297c478bd9Sstevel@tonic-gate 				s = MSG_INTL(MSG_PSYM_EXPREASON2);
29307c478bd9Sstevel@tonic-gate 			else
29317c478bd9Sstevel@tonic-gate 				s = MSG_INTL(MSG_PSYM_EXPREASON3);
29325aefb655Srie 			DBG_CALL(Dbg_move_parexpn(ofl->ofl_lml,
29335aefb655Srie 			    psym->psym_symd->sd_name, s));
29347c478bd9Sstevel@tonic-gate 			for (LIST_TRAVERSE(&(psym->psym_mvs), lnp2, mvp)) {
29357c478bd9Sstevel@tonic-gate 				if ((mvp->mv_flag & FLG_MV_OUTSECT) == 0)
29367c478bd9Sstevel@tonic-gate 					continue;
29377c478bd9Sstevel@tonic-gate 				mv2 = mvp->mv_ientry;
29387c478bd9Sstevel@tonic-gate 				sdp = psym->psym_symd;
29395aefb655Srie 				DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0,
29405aefb655Srie 				    mv2, sdp));
29417c478bd9Sstevel@tonic-gate 				(void) expand_move(ofl, sdp, mv2);
29427c478bd9Sstevel@tonic-gate 			}
29437c478bd9Sstevel@tonic-gate 			continue;
29447c478bd9Sstevel@tonic-gate 		}
29457c478bd9Sstevel@tonic-gate 
29467c478bd9Sstevel@tonic-gate 		/*
29477c478bd9Sstevel@tonic-gate 		 * Process move table
29487c478bd9Sstevel@tonic-gate 		 */
29495aefb655Srie 		DBG_CALL(Dbg_move_outmove(ofl->ofl_lml,
29505aefb655Srie 		    psym->psym_symd->sd_name));
29517c478bd9Sstevel@tonic-gate 		for (LIST_TRAVERSE(&(psym->psym_mvs), lnp2, mvp)) {
29527c478bd9Sstevel@tonic-gate 			int	idx = 1;
295360758829Srie 			Sym	*sym;
295460758829Srie 
29557c478bd9Sstevel@tonic-gate 			if ((mvp->mv_flag & FLG_MV_OUTSECT) == 0)
29567c478bd9Sstevel@tonic-gate 				continue;
295760758829Srie 
29587c478bd9Sstevel@tonic-gate 			isp = mvp->mv_isp;
29597c478bd9Sstevel@tonic-gate 			mv2 = mvp->mv_ientry;
2960d840867fSab 			sdp = isp->is_file->ifl_oldndx[ELF_M_SYM(mv2->m_info)];
296160758829Srie 			sym = sdp->sd_sym;
29627c478bd9Sstevel@tonic-gate 
29635aefb655Srie 			DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 0, mv2, sdp));
296460758829Srie 
29657c478bd9Sstevel@tonic-gate 			*mv1 = *mv2;
29667c478bd9Sstevel@tonic-gate 			if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) {
296760758829Srie 				if (ELF_ST_BIND(sym->st_info) == STB_LOCAL) {
296860758829Srie 					Half	symbssndx = ofl->ofl_isbss->
2969d840867fSab 					    is_osdesc->os_scnsymndx;
297060758829Srie 
2971d840867fSab 					mv1->m_info =
2972d840867fSab 					    /* LINTED */
2973d840867fSab 					    ELF_M_INFO(symbssndx, mv2->m_info);
297460758829Srie 
297560758829Srie 					if (ELF_ST_TYPE(sym->st_info) !=
2976d840867fSab 					    STT_SECTION) {
297760758829Srie 						mv1->m_poffset = sym->st_value -
297860758829Srie 						    ofl->ofl_isbss->is_osdesc->
297960758829Srie 						    os_shdr->sh_addr +
298060758829Srie 						    mv2->m_poffset;
2981d840867fSab 					}
29827c478bd9Sstevel@tonic-gate 				} else {
2983d840867fSab 					mv1->m_info =
2984d840867fSab 					    /* LINTED */
2985d840867fSab 					    ELF_M_INFO(sdp->sd_symndx,
2986d840867fSab 					    mv2->m_info);
29877c478bd9Sstevel@tonic-gate 				}
29887c478bd9Sstevel@tonic-gate 			} else {
29897c478bd9Sstevel@tonic-gate 				Boolean 	isredloc = FALSE;
29907c478bd9Sstevel@tonic-gate 
299160758829Srie 				if ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) &&
29927c478bd9Sstevel@tonic-gate 				    (ofl->ofl_flags1 & FLG_OF1_REDLSYM))
29937c478bd9Sstevel@tonic-gate 					isredloc = TRUE;
29947c478bd9Sstevel@tonic-gate 
29957c478bd9Sstevel@tonic-gate 				if (isredloc && !(sdp->sd_psyminfo)) {
299660758829Srie 					Word	symndx = sdp->sd_isc->
299760758829Srie 					    is_osdesc->os_scnsymndx;
299860758829Srie 
29997c478bd9Sstevel@tonic-gate 					mv1->m_info =
3000d840867fSab 					    /* LINTED */
3001d840867fSab 					    ELF_M_INFO(symndx, mv2->m_info);
300260758829Srie 					mv1->m_poffset += sym->st_value;
30037c478bd9Sstevel@tonic-gate 				} else {
30047c478bd9Sstevel@tonic-gate 					if (isredloc)
3005d840867fSab 						DBG_CALL(Dbg_syms_reduce(ofl,
3006d840867fSab 						    DBG_SYM_REDUCE_RETAIN, sdp,
3007d840867fSab 						    idx,
3008d840867fSab 						    ofl->ofl_osmove->os_name));
30097c478bd9Sstevel@tonic-gate 
30107c478bd9Sstevel@tonic-gate 					mv1->m_info =
3011d840867fSab 					    /* LINTED */
3012d840867fSab 					    ELF_M_INFO(sdp->sd_symndx,
3013d840867fSab 					    mv2->m_info);
30147c478bd9Sstevel@tonic-gate 				}
30157c478bd9Sstevel@tonic-gate 			}
30165aefb655Srie 			DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 1, mv1, sdp));
30177c478bd9Sstevel@tonic-gate 			mv1++;
30187c478bd9Sstevel@tonic-gate 			idx++;
30197c478bd9Sstevel@tonic-gate 		}
30207c478bd9Sstevel@tonic-gate 	}
30217c478bd9Sstevel@tonic-gate 	return (1);
30227c478bd9Sstevel@tonic-gate }
30237c478bd9Sstevel@tonic-gate 
30247c478bd9Sstevel@tonic-gate 
30257c478bd9Sstevel@tonic-gate /*
30267c478bd9Sstevel@tonic-gate  * Scan through the SHT_GROUP output sections.  Update their
30277c478bd9Sstevel@tonic-gate  * sh_link/sh_info fields as well as the section contents.
30287c478bd9Sstevel@tonic-gate  */
30295aefb655Srie static uintptr_t
30307c478bd9Sstevel@tonic-gate update_ogroup(Ofl_desc * ofl)
30317c478bd9Sstevel@tonic-gate {
30327c478bd9Sstevel@tonic-gate 	Listnode	*lnp;
30337c478bd9Sstevel@tonic-gate 	Os_desc		*osp;
30347c478bd9Sstevel@tonic-gate 	uintptr_t	error = 0;
30357c478bd9Sstevel@tonic-gate 
30367c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_osgroups, lnp, osp)) {
30377c478bd9Sstevel@tonic-gate 		Is_desc		*isp;
30387c478bd9Sstevel@tonic-gate 		Ifl_desc	*ifl;
30397c478bd9Sstevel@tonic-gate 		Shdr		*shdr = osp->os_shdr;
30407c478bd9Sstevel@tonic-gate 		Sym_desc	*sdp;
30417c478bd9Sstevel@tonic-gate 		Xword		i, grpcnt;
30427c478bd9Sstevel@tonic-gate 		Word		*gdata;
30437c478bd9Sstevel@tonic-gate 
30447c478bd9Sstevel@tonic-gate 		/*
30457c478bd9Sstevel@tonic-gate 		 * Since input GROUP sections always create unique
30467c478bd9Sstevel@tonic-gate 		 * output GROUP sections - we know there is only one
30477c478bd9Sstevel@tonic-gate 		 * item on the list.
30487c478bd9Sstevel@tonic-gate 		 */
30497c478bd9Sstevel@tonic-gate 		isp = (Is_desc *)osp->os_isdescs.head->data;
30507c478bd9Sstevel@tonic-gate 
30517c478bd9Sstevel@tonic-gate 		ifl = isp->is_file;
30527c478bd9Sstevel@tonic-gate 		sdp = ifl->ifl_oldndx[isp->is_shdr->sh_info];
30537c478bd9Sstevel@tonic-gate 		shdr->sh_link = (Word)elf_ndxscn(ofl->ofl_ossymtab->os_scn);
30547c478bd9Sstevel@tonic-gate 		shdr->sh_info = sdp->sd_symndx;
30557c478bd9Sstevel@tonic-gate 
30567c478bd9Sstevel@tonic-gate 		/*
30577c478bd9Sstevel@tonic-gate 		 * Scan through the group data section and update
30587c478bd9Sstevel@tonic-gate 		 * all of the links to new values.
30597c478bd9Sstevel@tonic-gate 		 */
30607c478bd9Sstevel@tonic-gate 		grpcnt = shdr->sh_size / shdr->sh_entsize;
30617c478bd9Sstevel@tonic-gate 		gdata = (Word *)osp->os_outdata->d_buf;
30627c478bd9Sstevel@tonic-gate 		for (i = 1; i < grpcnt; i++) {
30637c478bd9Sstevel@tonic-gate 			Is_desc	*	_isp;
30647c478bd9Sstevel@tonic-gate 			Os_desc	*	_osp;
30657c478bd9Sstevel@tonic-gate 
30667c478bd9Sstevel@tonic-gate 			/*
30677c478bd9Sstevel@tonic-gate 			 * Perform a sanity check that the section index
30687c478bd9Sstevel@tonic-gate 			 * stored in the SHT_GROUP section is valid
30697c478bd9Sstevel@tonic-gate 			 * for the file it came from.
30707c478bd9Sstevel@tonic-gate 			 */
30717c478bd9Sstevel@tonic-gate 			if (gdata[i] >= ifl->ifl_shnum) {
30725aefb655Srie 				eprintf(ofl->ofl_lml, ERR_FATAL,
30735aefb655Srie 				    MSG_INTL(MSG_GRP_INVALNDX), isp->is_name,
30745aefb655Srie 				    ifl->ifl_name, i, gdata[i]);
30757c478bd9Sstevel@tonic-gate 				error = S_ERROR;
30767c478bd9Sstevel@tonic-gate 				gdata[i] = 0;
30777c478bd9Sstevel@tonic-gate 				continue;
30787c478bd9Sstevel@tonic-gate 			}
30797c478bd9Sstevel@tonic-gate 
30807c478bd9Sstevel@tonic-gate 			_isp = ifl->ifl_isdesc[gdata[i]];
30817c478bd9Sstevel@tonic-gate 
30827c478bd9Sstevel@tonic-gate 			/*
30837c478bd9Sstevel@tonic-gate 			 * If the referenced section didn't make it to the
30847c478bd9Sstevel@tonic-gate 			 * output file - just zero out the entry.
30857c478bd9Sstevel@tonic-gate 			 */
30867c478bd9Sstevel@tonic-gate 			if ((_osp = _isp->is_osdesc) == 0)
30877c478bd9Sstevel@tonic-gate 				gdata[i] = 0;
30887c478bd9Sstevel@tonic-gate 			else
30897c478bd9Sstevel@tonic-gate 				gdata[i] = (Word)elf_ndxscn(_osp->os_scn);
30907c478bd9Sstevel@tonic-gate 		}
30917c478bd9Sstevel@tonic-gate 	}
30927c478bd9Sstevel@tonic-gate 	return (error);
30937c478bd9Sstevel@tonic-gate }
30947c478bd9Sstevel@tonic-gate 
30955aefb655Srie static void
30963244bcaaSab update_ostrtab(Os_desc *osp, Str_tbl *stp, uint_t extra)
30977c478bd9Sstevel@tonic-gate {
30987c478bd9Sstevel@tonic-gate 	Elf_Data	*data;
30993244bcaaSab 
31007c478bd9Sstevel@tonic-gate 	if (osp == 0)
31017c478bd9Sstevel@tonic-gate 		return;
31027c478bd9Sstevel@tonic-gate 
31037c478bd9Sstevel@tonic-gate 	data = osp->os_outdata;
31043244bcaaSab 	assert(data->d_size == (st_getstrtab_sz(stp) + extra));
3105*cce0e03bSab 	(void) st_setstrbuf(stp, data->d_buf, data->d_size - extra);
31063244bcaaSab 	/* If leaving an extra hole at the end, zero it */
31073244bcaaSab 	if (extra > 0)
31083244bcaaSab 		(void) memset((char *)data->d_buf + data->d_size - extra,
31093244bcaaSab 		    0x0, extra);
31107c478bd9Sstevel@tonic-gate }
31117c478bd9Sstevel@tonic-gate 
31127c478bd9Sstevel@tonic-gate /*
31137c478bd9Sstevel@tonic-gate  * Translate the shdr->sh_{link, info} from its input section value to that
31147c478bd9Sstevel@tonic-gate  * of the corresponding shdr->sh_{link, info} output section value.
31157c478bd9Sstevel@tonic-gate  */
31165aefb655Srie static Word
31175aefb655Srie translate_link(Ofl_desc *ofl, Os_desc *osp, Word link, const char *msg)
31187c478bd9Sstevel@tonic-gate {
31197c478bd9Sstevel@tonic-gate 	Is_desc *	isp;
31207c478bd9Sstevel@tonic-gate 	Ifl_desc *	ifl;
31217c478bd9Sstevel@tonic-gate 
31227c478bd9Sstevel@tonic-gate 	/*
31237c478bd9Sstevel@tonic-gate 	 * Don't translate the special section numbers.
31247c478bd9Sstevel@tonic-gate 	 */
31257c478bd9Sstevel@tonic-gate 	if (link >= SHN_LORESERVE)
31267c478bd9Sstevel@tonic-gate 		return (link);
31277c478bd9Sstevel@tonic-gate 
31287c478bd9Sstevel@tonic-gate 	/*
31297c478bd9Sstevel@tonic-gate 	 * Does this output section translate back to an input file.  If not
31307c478bd9Sstevel@tonic-gate 	 * then there is no translation to do.  In this case we will assume that
31317c478bd9Sstevel@tonic-gate 	 * if sh_link has a value, it's the right value.
31327c478bd9Sstevel@tonic-gate 	 */
31337c478bd9Sstevel@tonic-gate 	isp = (Is_desc *)osp->os_isdescs.head->data;
31347c478bd9Sstevel@tonic-gate 	if ((ifl = isp->is_file) == NULL)
31357c478bd9Sstevel@tonic-gate 		return (link);
31367c478bd9Sstevel@tonic-gate 
31377c478bd9Sstevel@tonic-gate 	/*
31387c478bd9Sstevel@tonic-gate 	 * Sanity check to make sure that the sh_{link, info} value
31397c478bd9Sstevel@tonic-gate 	 * is within range for the input file.
31407c478bd9Sstevel@tonic-gate 	 */
31417c478bd9Sstevel@tonic-gate 	if (link >= ifl->ifl_shnum) {
31425aefb655Srie 		eprintf(ofl->ofl_lml, ERR_WARNING, msg, ifl->ifl_name,
31437c478bd9Sstevel@tonic-gate 		    isp->is_name, EC_XWORD(link));
31447c478bd9Sstevel@tonic-gate 		return (link);
31457c478bd9Sstevel@tonic-gate 	}
31467c478bd9Sstevel@tonic-gate 
31477c478bd9Sstevel@tonic-gate 	/*
31487c478bd9Sstevel@tonic-gate 	 * Follow the link to the input section.
31497c478bd9Sstevel@tonic-gate 	 */
31507c478bd9Sstevel@tonic-gate 	if ((isp = ifl->ifl_isdesc[link]) == 0)
31517c478bd9Sstevel@tonic-gate 		return (0);
31527c478bd9Sstevel@tonic-gate 	if ((osp = isp->is_osdesc) == 0)
31537c478bd9Sstevel@tonic-gate 		return (0);
31547c478bd9Sstevel@tonic-gate 
31557c478bd9Sstevel@tonic-gate 	/* LINTED */
31567c478bd9Sstevel@tonic-gate 	return ((Word)elf_ndxscn(osp->os_scn));
31577c478bd9Sstevel@tonic-gate }
31587c478bd9Sstevel@tonic-gate 
31597c478bd9Sstevel@tonic-gate /*
31607c478bd9Sstevel@tonic-gate  * Having created all of the necessary sections, segments, and associated
31617c478bd9Sstevel@tonic-gate  * headers, fill in the program headers and update any other data in the
31627c478bd9Sstevel@tonic-gate  * output image.  Some general rules:
31637c478bd9Sstevel@tonic-gate  *
316470d3e49eSrie  *  o	If an interpreter is required always generate a PT_PHDR entry as
31657c478bd9Sstevel@tonic-gate  *	well.  It is this entry that triggers the kernel into passing the
316670d3e49eSrie  *	interpreter an aux vector instead of just a file descriptor.
31677c478bd9Sstevel@tonic-gate  *
31687c478bd9Sstevel@tonic-gate  *  o	When generating an image that will be interpreted (ie. a dynamic
31697c478bd9Sstevel@tonic-gate  *	executable, a shared object, or a static executable that has been
317070d3e49eSrie  *	provided with an interpreter - weird, but possible), make the initial
31717c478bd9Sstevel@tonic-gate  *	loadable segment include both the ehdr and phdr[].  Both of these
317270d3e49eSrie  *	tables are used by the interpreter therefore it seems more intuitive
31737c478bd9Sstevel@tonic-gate  *	to explicitly defined them as part of the mapped image rather than
317470d3e49eSrie  *	relying on page rounding by the interpreter to allow their access.
31757c478bd9Sstevel@tonic-gate  *
317670d3e49eSrie  *  o	When generating a static image that does not require an interpreter
31777c478bd9Sstevel@tonic-gate  *	have the first loadable segment indicate the address of the first
31787c478bd9Sstevel@tonic-gate  *	.section as the start address (things like /kernel/unix and ufsboot
31797c478bd9Sstevel@tonic-gate  *	expect this behavior).
31807c478bd9Sstevel@tonic-gate  */
31817c478bd9Sstevel@tonic-gate uintptr_t
31825aefb655Srie ld_update_outfile(Ofl_desc *ofl)
31837c478bd9Sstevel@tonic-gate {
31847c478bd9Sstevel@tonic-gate 	Addr		size, etext, vaddr = ofl->ofl_segorigin;
31857c478bd9Sstevel@tonic-gate 	Listnode	*lnp1, *lnp2;
3186d1827f25Srie 	Sg_desc		*sgp, *dtracesgp = 0, *capsgp = 0;
3187*cce0e03bSab 	Os_desc		*osp;
3188d1827f25Srie 	int		phdrndx = 0, segndx = -1, secndx;
3189d1827f25Srie 	int		dtracepndx, dtracesndx, cappndx, capsndx;
31905aefb655Srie 	Ehdr		*ehdr = ofl->ofl_nehdr;
31917c478bd9Sstevel@tonic-gate 	Shdr		*hshdr;
3192d1827f25Srie 	Phdr		*_phdr = 0;
3193d1827f25Srie 	Word		phdrsz = (ehdr->e_phnum * ehdr->e_phentsize), shscnndx;
31947c478bd9Sstevel@tonic-gate 	Word		flags = ofl->ofl_flags, ehdrsz = ehdr->e_ehsize;
31957c478bd9Sstevel@tonic-gate 	Boolean		nobits;
31967c478bd9Sstevel@tonic-gate 	Off		offset;
3197*cce0e03bSab 	Aliste		idx;
31987c478bd9Sstevel@tonic-gate 
31997c478bd9Sstevel@tonic-gate 	/*
32007c478bd9Sstevel@tonic-gate 	 * Loop through the segment descriptors and pick out what we need.
32017c478bd9Sstevel@tonic-gate 	 */
32025aefb655Srie 	DBG_CALL(Dbg_seg_title(ofl->ofl_lml));
32037c478bd9Sstevel@tonic-gate 	for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) {
3204d1827f25Srie 		Phdr	*phdr = &(sgp->sg_phdr);
32057c478bd9Sstevel@tonic-gate 		Xword 	p_align;
32067c478bd9Sstevel@tonic-gate 
32077c478bd9Sstevel@tonic-gate 		segndx++;
32087c478bd9Sstevel@tonic-gate 
32097c478bd9Sstevel@tonic-gate 		/*
32107c478bd9Sstevel@tonic-gate 		 * If an interpreter is required generate a PT_INTERP and
32117c478bd9Sstevel@tonic-gate 		 * PT_PHDR program header entry.  The PT_PHDR entry describes
32127c478bd9Sstevel@tonic-gate 		 * the program header table itself.  This information will be
32137c478bd9Sstevel@tonic-gate 		 * passed via the aux vector to the interpreter (ld.so.1).
32147c478bd9Sstevel@tonic-gate 		 * The program header array is actually part of the first
32157c478bd9Sstevel@tonic-gate 		 * loadable segment (and the PT_PHDR entry is the first entry),
32167c478bd9Sstevel@tonic-gate 		 * therefore its virtual address isn't known until the first
32177c478bd9Sstevel@tonic-gate 		 * loadable segment is processed.
32187c478bd9Sstevel@tonic-gate 		 */
32197c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_PHDR) {
32207c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osinterp) {
32217c478bd9Sstevel@tonic-gate 				phdr->p_offset = ehdr->e_phoff;
32227c478bd9Sstevel@tonic-gate 				phdr->p_filesz = phdr->p_memsz = phdrsz;
3223d1827f25Srie 
32245aefb655Srie 				DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
32257c478bd9Sstevel@tonic-gate 				ofl->ofl_phdr[phdrndx++] = *phdr;
32267c478bd9Sstevel@tonic-gate 			}
32277c478bd9Sstevel@tonic-gate 			continue;
32287c478bd9Sstevel@tonic-gate 		}
32297c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_INTERP) {
32307c478bd9Sstevel@tonic-gate 			if (ofl->ofl_osinterp) {
3231d1827f25Srie 				Shdr	*shdr = ofl->ofl_osinterp->os_shdr;
32327c478bd9Sstevel@tonic-gate 
32337c478bd9Sstevel@tonic-gate 				phdr->p_vaddr = phdr->p_memsz = 0;
32347c478bd9Sstevel@tonic-gate 				phdr->p_offset = shdr->sh_offset;
32357c478bd9Sstevel@tonic-gate 				phdr->p_filesz = shdr->sh_size;
3236d1827f25Srie 
32375aefb655Srie 				DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
32387c478bd9Sstevel@tonic-gate 				ofl->ofl_phdr[phdrndx++] = *phdr;
32397c478bd9Sstevel@tonic-gate 			}
32407c478bd9Sstevel@tonic-gate 			continue;
32417c478bd9Sstevel@tonic-gate 		}
32427c478bd9Sstevel@tonic-gate 
32437c478bd9Sstevel@tonic-gate 		/*
3244d1827f25Srie 		 * If we are creating a PT_SUNWDTRACE segment, remember where
3245d1827f25Srie 		 * the program header is.  The header values are assigned after
3246d1827f25Srie 		 * update_osym() has completed and the symbol table addresses
3247d1827f25Srie 		 * have been udpated.
32487c478bd9Sstevel@tonic-gate 		 */
32497c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_SUNWDTRACE) {
32507c478bd9Sstevel@tonic-gate 			if ((ofl->ofl_dtracesym) &&
32517c478bd9Sstevel@tonic-gate 			    ((flags & FLG_OF_RELOBJ) == 0)) {
3252d1827f25Srie 				dtracesgp = sgp;
3253d1827f25Srie 				dtracesndx = segndx;
3254d1827f25Srie 				dtracepndx = phdrndx++;
32557c478bd9Sstevel@tonic-gate 			}
32567c478bd9Sstevel@tonic-gate 			continue;
32577c478bd9Sstevel@tonic-gate 		}
32587c478bd9Sstevel@tonic-gate 
32597c478bd9Sstevel@tonic-gate 		/*
32607c478bd9Sstevel@tonic-gate 		 * If a hardware/software capabilities section is required,
32617c478bd9Sstevel@tonic-gate 		 * generate the PT_SUNWCAP header.  Note, as this comes before
32627c478bd9Sstevel@tonic-gate 		 * the first loadable segment, we don't yet know its real
32637c478bd9Sstevel@tonic-gate 		 * virtual address.  This is updated later.
32647c478bd9Sstevel@tonic-gate 		 */
32657c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_SUNWCAP) {
32667c478bd9Sstevel@tonic-gate 			if (ofl->ofl_oscap) {
3267d1827f25Srie 				capsgp = sgp;
3268d1827f25Srie 				capsndx = segndx;
3269d1827f25Srie 				cappndx = phdrndx++;
32707c478bd9Sstevel@tonic-gate 			}
32717c478bd9Sstevel@tonic-gate 			continue;
32727c478bd9Sstevel@tonic-gate 		}
32737c478bd9Sstevel@tonic-gate 
32747c478bd9Sstevel@tonic-gate 		/*
32757c478bd9Sstevel@tonic-gate 		 * As the dynamic program header occurs after the loadable
32767c478bd9Sstevel@tonic-gate 		 * headers in the segment descriptor table, all the address
32777c478bd9Sstevel@tonic-gate 		 * information for the .dynamic output section will have been
32787c478bd9Sstevel@tonic-gate 		 * figured out by now.
32797c478bd9Sstevel@tonic-gate 		 */
32807c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_DYNAMIC) {
32819039eeafSab 			if (OFL_ALLOW_DYNSYM(ofl)) {
3282d1827f25Srie 				Shdr	*shdr = ofl->ofl_osdynamic->os_shdr;
32837c478bd9Sstevel@tonic-gate 
32847c478bd9Sstevel@tonic-gate 				phdr->p_vaddr = shdr->sh_addr;
32857c478bd9Sstevel@tonic-gate 				phdr->p_offset = shdr->sh_offset;
32867c478bd9Sstevel@tonic-gate 				phdr->p_filesz = shdr->sh_size;
32877c478bd9Sstevel@tonic-gate 				phdr->p_flags = M_DATASEG_PERM;
3288d1827f25Srie 
32895aefb655Srie 				DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
32907c478bd9Sstevel@tonic-gate 				ofl->ofl_phdr[phdrndx++] = *phdr;
32917c478bd9Sstevel@tonic-gate 			}
32927c478bd9Sstevel@tonic-gate 			continue;
32937c478bd9Sstevel@tonic-gate 		}
3294d1827f25Srie 
3295d1827f25Srie 		/*
3296d1827f25Srie 		 * As the AMD unwind program header occurs after the loadable
3297d1827f25Srie 		 * headers in the segment descriptor table, all the address
3298d1827f25Srie 		 * information for the .eh_frame output section will have been
3299d1827f25Srie 		 * figured out by now.
3300d1827f25Srie 		 */
330102ca3e02Srie #if	(defined(__i386) || defined(__amd64)) && defined(_ELF64)
33027c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_SUNW_UNWIND) {
33037c478bd9Sstevel@tonic-gate 			Shdr	    *shdr;
3304d1827f25Srie 
33057c478bd9Sstevel@tonic-gate 			if (ofl->ofl_unwindhdr == 0)
33067c478bd9Sstevel@tonic-gate 				continue;
3307d1827f25Srie 
33087c478bd9Sstevel@tonic-gate 			shdr = ofl->ofl_unwindhdr->os_shdr;
33097c478bd9Sstevel@tonic-gate 
33107c478bd9Sstevel@tonic-gate 			phdr->p_flags = PF_R;
33117c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = shdr->sh_addr;
33127c478bd9Sstevel@tonic-gate 			phdr->p_memsz = shdr->sh_size;
33137c478bd9Sstevel@tonic-gate 			phdr->p_filesz = shdr->sh_size;
33147c478bd9Sstevel@tonic-gate 			phdr->p_offset = shdr->sh_offset;
33157c478bd9Sstevel@tonic-gate 			phdr->p_align = shdr->sh_addralign;
33167c478bd9Sstevel@tonic-gate 			phdr->p_paddr = 0;
33177c478bd9Sstevel@tonic-gate 			ofl->ofl_phdr[phdrndx++] = *phdr;
33187c478bd9Sstevel@tonic-gate 			continue;
33197c478bd9Sstevel@tonic-gate 		}
33207c478bd9Sstevel@tonic-gate #endif
3321d1827f25Srie 		/*
3322d1827f25Srie 		 * As the TLS program header occurs after the loadable
3323d1827f25Srie 		 * headers in the segment descriptor table, all the address
3324d1827f25Srie 		 * information for the .tls output section will have been
3325d1827f25Srie 		 * figured out by now.
3326d1827f25Srie 		 */
33277c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_TLS) {
3328dd94ecefSrie 			Os_desc	*tlsosp;
3329f79d60b6Srie 			Shdr	*firstshdr = 0, *lastfileshdr = 0, *lastshdr;
33307c478bd9Sstevel@tonic-gate 
3331dd94ecefSrie 			if (ofl->ofl_ostlsseg.head == NULL)
33327c478bd9Sstevel@tonic-gate 				continue;
3333dd94ecefSrie 
3334f79d60b6Srie 			/*
3335f79d60b6Srie 			 * Scan through the sections that have contributed TLS.
3336f79d60b6Srie 			 * Remember the first and last so as to determine the
3337f79d60b6Srie 			 * TLS memory size requirement.  Remember the last
3338f79d60b6Srie 			 * non-nobits section to determine the TLS data
3339f79d60b6Srie 			 * contribution, which determines the TLS file size.
3340f79d60b6Srie 			 */
3341dd94ecefSrie 			for (LIST_TRAVERSE(&ofl->ofl_ostlsseg, lnp2, tlsosp)) {
3342dd94ecefSrie 				Shdr	*tlsshdr = tlsosp->os_shdr;
3343dd94ecefSrie 
3344f79d60b6Srie 				if (firstshdr == 0)
3345f79d60b6Srie 					firstshdr = tlsshdr;
3346f79d60b6Srie 				if (tlsshdr->sh_type != SHT_NOBITS)
3347f79d60b6Srie 					lastfileshdr = tlsshdr;
3348f79d60b6Srie 				lastshdr = tlsshdr;
33497c478bd9Sstevel@tonic-gate 			}
3350dd94ecefSrie 
3351dd94ecefSrie 			phdr->p_flags = PF_R | PF_W;
33527c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = firstshdr->sh_addr;
33537c478bd9Sstevel@tonic-gate 			phdr->p_offset = firstshdr->sh_offset;
3354dd94ecefSrie 			phdr->p_align = firstshdr->sh_addralign;
3355f79d60b6Srie 
3356f79d60b6Srie 			if (lastfileshdr)
3357f79d60b6Srie 				phdr->p_filesz = lastfileshdr->sh_offset +
3358f79d60b6Srie 				    lastfileshdr->sh_size - phdr->p_offset;
3359f79d60b6Srie 			else
3360f79d60b6Srie 				phdr->p_filesz = 0;
3361f79d60b6Srie 
3362f79d60b6Srie 			phdr->p_memsz = lastshdr->sh_offset +
3363f79d60b6Srie 			    lastshdr->sh_size - phdr->p_offset;
3364dd94ecefSrie 
33655aefb655Srie 			DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
3366d1827f25Srie 			ofl->ofl_phdr[phdrndx] = *phdr;
3367d1827f25Srie 			ofl->ofl_tlsphdr = &ofl->ofl_phdr[phdrndx++];
33687c478bd9Sstevel@tonic-gate 			continue;
33697c478bd9Sstevel@tonic-gate 		}
33707c478bd9Sstevel@tonic-gate 
33717c478bd9Sstevel@tonic-gate 		/*
33727c478bd9Sstevel@tonic-gate 		 * If this is an empty segment declaration, it will occur after
3373d1827f25Srie 		 * all other loadable segments.  As empty segments can be
3374d1827f25Srie 		 * defind with fixed addresses, make sure that no loadable
3375d1827f25Srie 		 * segments overlap.  This might occur as the object evolves
3376d1827f25Srie 		 * and the loadable segments grow, thus encroaching upon an
3377d1827f25Srie 		 * existing segment reservation.
3378d1827f25Srie 		 *
3379d1827f25Srie 		 * Segments are only created for dynamic objects, thus this
3380d1827f25Srie 		 * checking can be skipped when building a relocatable object.
33817c478bd9Sstevel@tonic-gate 		 */
33827c478bd9Sstevel@tonic-gate 		if (!(ofl->ofl_flags & FLG_OF_RELOBJ) &&
33837c478bd9Sstevel@tonic-gate 		    (sgp->sg_flags & FLG_SG_EMPTY)) {
3384d1827f25Srie 			int	i;
33857c478bd9Sstevel@tonic-gate 			Addr	v_e;
33867c478bd9Sstevel@tonic-gate 
33877c478bd9Sstevel@tonic-gate 			vaddr = phdr->p_vaddr;
33887c478bd9Sstevel@tonic-gate 			phdr->p_memsz = sgp->sg_length;
33895aefb655Srie 			DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
33907c478bd9Sstevel@tonic-gate 			ofl->ofl_phdr[phdrndx++] = *phdr;
33917c478bd9Sstevel@tonic-gate 
33927c478bd9Sstevel@tonic-gate 			if (phdr->p_type != PT_LOAD)
33937c478bd9Sstevel@tonic-gate 				continue;
33947c478bd9Sstevel@tonic-gate 
33957c478bd9Sstevel@tonic-gate 			v_e = vaddr + phdr->p_memsz;
3396d1827f25Srie 
33977c478bd9Sstevel@tonic-gate 			/*
33987c478bd9Sstevel@tonic-gate 			 * Check overlaps
33997c478bd9Sstevel@tonic-gate 			 */
34007c478bd9Sstevel@tonic-gate 			for (i = 0; i < phdrndx - 1; i++) {
34017c478bd9Sstevel@tonic-gate 				Addr 	p_s = (ofl->ofl_phdr[i]).p_vaddr;
34027c478bd9Sstevel@tonic-gate 				Addr 	p_e;
34037c478bd9Sstevel@tonic-gate 
34047c478bd9Sstevel@tonic-gate 				if ((ofl->ofl_phdr[i]).p_type != PT_LOAD)
34057c478bd9Sstevel@tonic-gate 					continue;
34067c478bd9Sstevel@tonic-gate 
34077c478bd9Sstevel@tonic-gate 				p_e = p_s + (ofl->ofl_phdr[i]).p_memsz;
34087c478bd9Sstevel@tonic-gate 				if (((p_s <= vaddr) && (p_e > vaddr)) ||
34097c478bd9Sstevel@tonic-gate 				    ((vaddr <= p_s) && (v_e > p_s)))
34105aefb655Srie 					eprintf(ofl->ofl_lml, ERR_WARNING,
34117c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_UPD_SEGOVERLAP),
34125aefb655Srie 					    ofl->ofl_name, EC_ADDR(p_e),
34135aefb655Srie 					    sgp->sg_name, EC_ADDR(vaddr));
34147c478bd9Sstevel@tonic-gate 			}
34157c478bd9Sstevel@tonic-gate 			continue;
34167c478bd9Sstevel@tonic-gate 		}
34177c478bd9Sstevel@tonic-gate 
34187c478bd9Sstevel@tonic-gate 		/*
34197c478bd9Sstevel@tonic-gate 		 * Having processed any of the special program headers any
34207c478bd9Sstevel@tonic-gate 		 * remaining headers will be built to express individual
34217c478bd9Sstevel@tonic-gate 		 * segments.  Segments are only built if they have output
34227c478bd9Sstevel@tonic-gate 		 * section descriptors associated with them (ie. some form of
34237c478bd9Sstevel@tonic-gate 		 * input section has been matched to this segment).
34247c478bd9Sstevel@tonic-gate 		 */
34250bc07c75Srie 		if (sgp->sg_osdescs == NULL)
34267c478bd9Sstevel@tonic-gate 			continue;
34277c478bd9Sstevel@tonic-gate 
34287c478bd9Sstevel@tonic-gate 		/*
34297c478bd9Sstevel@tonic-gate 		 * Determine the segments offset and size from the section
34307c478bd9Sstevel@tonic-gate 		 * information provided from elf_update().
34317c478bd9Sstevel@tonic-gate 		 * Allow for multiple NOBITS sections.
34327c478bd9Sstevel@tonic-gate 		 */
3433*cce0e03bSab 		osp = sgp->sg_osdescs->apl_data[0];
343454d82594Sseizo 		hshdr = osp->os_shdr;
34357c478bd9Sstevel@tonic-gate 
34367c478bd9Sstevel@tonic-gate 		phdr->p_filesz = 0;
34377c478bd9Sstevel@tonic-gate 		phdr->p_memsz = 0;
34387c478bd9Sstevel@tonic-gate 		phdr->p_offset = offset = hshdr->sh_offset;
34390bc07c75Srie 
344054d82594Sseizo 		nobits = ((hshdr->sh_type == SHT_NOBITS) &&
34410bc07c75Srie 		    ((sgp->sg_flags & FLG_SG_PHREQ) == 0));
34420bc07c75Srie 
3443*cce0e03bSab 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) {
3444*cce0e03bSab 			Shdr	*shdr = osp->os_shdr;
34457c478bd9Sstevel@tonic-gate 
34467c478bd9Sstevel@tonic-gate 			p_align = 0;
34477c478bd9Sstevel@tonic-gate 			if (shdr->sh_addralign > p_align)
34487c478bd9Sstevel@tonic-gate 				p_align = shdr->sh_addralign;
34490bc07c75Srie 
34507c478bd9Sstevel@tonic-gate 			offset = (Off)S_ROUND(offset, shdr->sh_addralign);
34517c478bd9Sstevel@tonic-gate 			offset += shdr->sh_size;
34520bc07c75Srie 
34537c478bd9Sstevel@tonic-gate 			if (shdr->sh_type != SHT_NOBITS) {
34547c478bd9Sstevel@tonic-gate 				if (nobits) {
34555aefb655Srie 					eprintf(ofl->ofl_lml, ERR_FATAL,
34567c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_UPD_NOBITS));
34577c478bd9Sstevel@tonic-gate 					return (S_ERROR);
34587c478bd9Sstevel@tonic-gate 				}
34597c478bd9Sstevel@tonic-gate 				phdr->p_filesz = offset - phdr->p_offset;
346054d82594Sseizo 			} else if ((sgp->sg_flags & FLG_SG_PHREQ) == 0)
34617c478bd9Sstevel@tonic-gate 				nobits = TRUE;
34627c478bd9Sstevel@tonic-gate 		}
34637c478bd9Sstevel@tonic-gate 		phdr->p_memsz = offset - hshdr->sh_offset;
34647c478bd9Sstevel@tonic-gate 
34657c478bd9Sstevel@tonic-gate 		/*
34667c478bd9Sstevel@tonic-gate 		 * If this is PT_SUNWBSS, set alignment
34677c478bd9Sstevel@tonic-gate 		 */
34687c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_SUNWBSS)
34697c478bd9Sstevel@tonic-gate 			phdr->p_align = p_align;
34707c478bd9Sstevel@tonic-gate 
34717c478bd9Sstevel@tonic-gate 		/*
34727c478bd9Sstevel@tonic-gate 		 * If this is the first loadable segment of a dynamic object,
347370d3e49eSrie 		 * or an interpreter has been specified (a static object built
347470d3e49eSrie 		 * with an interpreter will still be given a PT_HDR entry), then
34757c478bd9Sstevel@tonic-gate 		 * compensate for the elf header and program header array.  Both
34767c478bd9Sstevel@tonic-gate 		 * of these are actually part of the loadable segment as they
347770d3e49eSrie 		 * may be inspected by the interpreter.  Adjust the segments
34787c478bd9Sstevel@tonic-gate 		 * size and offset accordingly.
34797c478bd9Sstevel@tonic-gate 		 */
34807c478bd9Sstevel@tonic-gate 		if ((_phdr == 0) && (phdr->p_type == PT_LOAD) &&
34817c478bd9Sstevel@tonic-gate 		    ((ofl->ofl_osinterp) || (flags & FLG_OF_DYNAMIC)) &&
34824899432aSab 		    (!(ofl->ofl_dtflags_1 & DF_1_NOHDR))) {
34837c478bd9Sstevel@tonic-gate 			size = (Addr)S_ROUND((phdrsz + ehdrsz),
34847c478bd9Sstevel@tonic-gate 			    hshdr->sh_addralign);
34857c478bd9Sstevel@tonic-gate 			phdr->p_offset -= size;
34867c478bd9Sstevel@tonic-gate 			phdr->p_filesz += size;
34877c478bd9Sstevel@tonic-gate 			phdr->p_memsz += size;
34887c478bd9Sstevel@tonic-gate 		}
34897c478bd9Sstevel@tonic-gate 
34907c478bd9Sstevel@tonic-gate 		/*
34917c478bd9Sstevel@tonic-gate 		 * If a segment size symbol is required (specified via a
34927c478bd9Sstevel@tonic-gate 		 * mapfile) update its value.
34937c478bd9Sstevel@tonic-gate 		 */
34947c478bd9Sstevel@tonic-gate 		if (sgp->sg_sizesym != NULL)
34957c478bd9Sstevel@tonic-gate 			sgp->sg_sizesym->sd_sym->st_value = phdr->p_memsz;
34967c478bd9Sstevel@tonic-gate 
34977c478bd9Sstevel@tonic-gate 		/*
34987c478bd9Sstevel@tonic-gate 		 * If no file content has been assigned to this segment (it
34997c478bd9Sstevel@tonic-gate 		 * only contains no-bits sections), then reset the offset for
35007c478bd9Sstevel@tonic-gate 		 * consistency.
35017c478bd9Sstevel@tonic-gate 		 */
35027c478bd9Sstevel@tonic-gate 		if (phdr->p_filesz == 0)
35037c478bd9Sstevel@tonic-gate 			phdr->p_offset = 0;
35047c478bd9Sstevel@tonic-gate 
35057c478bd9Sstevel@tonic-gate 		/*
35067c478bd9Sstevel@tonic-gate 		 * If a virtual address has been specified for this segment
35077c478bd9Sstevel@tonic-gate 		 * (presumably from a map file) use it and make sure the
35087c478bd9Sstevel@tonic-gate 		 * previous segment does not run into this segment.
35097c478bd9Sstevel@tonic-gate 		 */
35107c478bd9Sstevel@tonic-gate 		if ((phdr->p_type == PT_LOAD) ||
35117c478bd9Sstevel@tonic-gate 		    (phdr->p_type == PT_SUNWBSS)) {
35127c478bd9Sstevel@tonic-gate 			if ((sgp->sg_flags & FLG_SG_VADDR)) {
35137c478bd9Sstevel@tonic-gate 				if (_phdr && (vaddr > phdr->p_vaddr) &&
35147c478bd9Sstevel@tonic-gate 				    (phdr->p_type == PT_LOAD))
35155aefb655Srie 					eprintf(ofl->ofl_lml, ERR_WARNING,
35167c478bd9Sstevel@tonic-gate 					    MSG_INTL(MSG_UPD_SEGOVERLAP),
35177c478bd9Sstevel@tonic-gate 					    ofl->ofl_name, EC_ADDR(vaddr),
35187c478bd9Sstevel@tonic-gate 					    sgp->sg_name,
35197c478bd9Sstevel@tonic-gate 					    EC_ADDR(phdr->p_vaddr));
35207c478bd9Sstevel@tonic-gate 				vaddr = phdr->p_vaddr;
35217c478bd9Sstevel@tonic-gate 				phdr->p_align = 0;
35227c478bd9Sstevel@tonic-gate 			} else {
35237c478bd9Sstevel@tonic-gate 				vaddr = phdr->p_vaddr =
35247c478bd9Sstevel@tonic-gate 				    (Addr)S_ROUND(vaddr, phdr->p_align);
35257c478bd9Sstevel@tonic-gate 			}
35267c478bd9Sstevel@tonic-gate 		}
35277c478bd9Sstevel@tonic-gate 
35287c478bd9Sstevel@tonic-gate 		/*
35297c478bd9Sstevel@tonic-gate 		 * Adjust the address offset and p_align if needed.
35307c478bd9Sstevel@tonic-gate 		 */
35313906e0c2Srie 		if (((sgp->sg_flags & FLG_SG_VADDR) == 0) &&
35323906e0c2Srie 		    ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0)) {
35337c478bd9Sstevel@tonic-gate 			if (phdr->p_align != 0)
35347c478bd9Sstevel@tonic-gate 				vaddr += phdr->p_offset % phdr->p_align;
35357c478bd9Sstevel@tonic-gate 			else
35367c478bd9Sstevel@tonic-gate 				vaddr += phdr->p_offset;
35377c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = vaddr;
35387c478bd9Sstevel@tonic-gate 		}
35397c478bd9Sstevel@tonic-gate 
35407c478bd9Sstevel@tonic-gate 		/*
35417c478bd9Sstevel@tonic-gate 		 * If an interpreter is required set the virtual address of the
35427c478bd9Sstevel@tonic-gate 		 * PT_PHDR program header now that we know the virtual address
35437c478bd9Sstevel@tonic-gate 		 * of the loadable segment that contains it.  Update the
35447c478bd9Sstevel@tonic-gate 		 * PT_SUNWCAP header similarly.
35457c478bd9Sstevel@tonic-gate 		 */
35467c478bd9Sstevel@tonic-gate 		if ((_phdr == 0) && (phdr->p_type == PT_LOAD)) {
35477c478bd9Sstevel@tonic-gate 			_phdr = phdr;
35487c478bd9Sstevel@tonic-gate 
3549d1827f25Srie 			if ((ofl->ofl_dtflags_1 & DF_1_NOHDR) == 0) {
35507c478bd9Sstevel@tonic-gate 				if (ofl->ofl_osinterp)
35517c478bd9Sstevel@tonic-gate 					ofl->ofl_phdr[0].p_vaddr =
35527c478bd9Sstevel@tonic-gate 					    vaddr + ehdrsz;
35537c478bd9Sstevel@tonic-gate 
35547c478bd9Sstevel@tonic-gate 				/*
35557c478bd9Sstevel@tonic-gate 				 * Finally, if we're creating a dynamic object
355670d3e49eSrie 				 * (or a static object in which an interpreter
35577c478bd9Sstevel@tonic-gate 				 * is specified) update the vaddr to reflect
35587c478bd9Sstevel@tonic-gate 				 * the address of the first section within this
35597c478bd9Sstevel@tonic-gate 				 * segment.
35607c478bd9Sstevel@tonic-gate 				 */
35617c478bd9Sstevel@tonic-gate 				if ((ofl->ofl_osinterp) ||
35627c478bd9Sstevel@tonic-gate 				    (flags & FLG_OF_DYNAMIC))
35637c478bd9Sstevel@tonic-gate 					vaddr += size;
35647c478bd9Sstevel@tonic-gate 			} else {
35657c478bd9Sstevel@tonic-gate 				/*
3566d1827f25Srie 				 * If the DF_1_NOHDR flag was set, and an
3567d1827f25Srie 				 * interpreter is being generated, the PT_PHDR
35687c478bd9Sstevel@tonic-gate 				 * will not be part of any loadable segment.
35697c478bd9Sstevel@tonic-gate 				 */
3570d1827f25Srie 				if (ofl->ofl_osinterp) {
3571d1827f25Srie 					ofl->ofl_phdr[0].p_vaddr = 0;
3572d1827f25Srie 					ofl->ofl_phdr[0].p_memsz = 0;
3573d1827f25Srie 					ofl->ofl_phdr[0].p_flags = 0;
3574d1827f25Srie 				}
35757c478bd9Sstevel@tonic-gate 			}
35767c478bd9Sstevel@tonic-gate 		}
35777c478bd9Sstevel@tonic-gate 
35787c478bd9Sstevel@tonic-gate 		/*
3579c1c6f601Srie 		 * Ensure the ELF entry point defaults to zero.  Typically, this
3580c1c6f601Srie 		 * value is overridden in update_oehdr() to one of the standard
3581c1c6f601Srie 		 * entry points.  Historically, this default was set to the
3582c1c6f601Srie 		 * address of first executable section, but this has since been
3583c1c6f601Srie 		 * found to be more confusing than it is helpful.
35847c478bd9Sstevel@tonic-gate 		 */
3585c1c6f601Srie 		ehdr->e_entry = 0;
35867c478bd9Sstevel@tonic-gate 
35875aefb655Srie 		DBG_CALL(Dbg_seg_entry(ofl, segndx, sgp));
35887c478bd9Sstevel@tonic-gate 
35897c478bd9Sstevel@tonic-gate 		/*
35907c478bd9Sstevel@tonic-gate 		 * Traverse the output section descriptors for this segment so
35917c478bd9Sstevel@tonic-gate 		 * that we can update the section headers addresses.  We've
35927c478bd9Sstevel@tonic-gate 		 * calculated the virtual address of the initial section within
35937c478bd9Sstevel@tonic-gate 		 * this segment, so each successive section can be calculated
35947c478bd9Sstevel@tonic-gate 		 * based on their offsets from each other.
35957c478bd9Sstevel@tonic-gate 		 */
35967c478bd9Sstevel@tonic-gate 		secndx = 0;
35977c478bd9Sstevel@tonic-gate 		hshdr = 0;
3598*cce0e03bSab 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) {
3599*cce0e03bSab 			Shdr	*shdr = osp->os_shdr;
36007c478bd9Sstevel@tonic-gate 
36017c478bd9Sstevel@tonic-gate 			if (shdr->sh_link)
360260758829Srie 				shdr->sh_link = translate_link(ofl, osp,
360360758829Srie 				    shdr->sh_link, MSG_INTL(MSG_FIL_INVSHLINK));
36047c478bd9Sstevel@tonic-gate 
36057c478bd9Sstevel@tonic-gate 			if (shdr->sh_info && (shdr->sh_flags & SHF_INFO_LINK))
360660758829Srie 				shdr->sh_info = translate_link(ofl, osp,
360760758829Srie 				    shdr->sh_info, MSG_INTL(MSG_FIL_INVSHINFO));
36087c478bd9Sstevel@tonic-gate 
36097c478bd9Sstevel@tonic-gate 			if (!(flags & FLG_OF_RELOBJ) &&
36107c478bd9Sstevel@tonic-gate 			    (phdr->p_type == PT_LOAD) ||
36117c478bd9Sstevel@tonic-gate 			    (phdr->p_type == PT_SUNWBSS)) {
36127c478bd9Sstevel@tonic-gate 				if (hshdr)
36137c478bd9Sstevel@tonic-gate 					vaddr += (shdr->sh_offset -
36147c478bd9Sstevel@tonic-gate 					    hshdr->sh_offset);
36157c478bd9Sstevel@tonic-gate 
36167c478bd9Sstevel@tonic-gate 				shdr->sh_addr = vaddr;
36177c478bd9Sstevel@tonic-gate 				hshdr = shdr;
36187c478bd9Sstevel@tonic-gate 			}
36197c478bd9Sstevel@tonic-gate 
36207c478bd9Sstevel@tonic-gate 			DBG_CALL(Dbg_seg_os(ofl, osp, secndx));
36217c478bd9Sstevel@tonic-gate 			secndx++;
36227c478bd9Sstevel@tonic-gate 		}
36237c478bd9Sstevel@tonic-gate 
36247c478bd9Sstevel@tonic-gate 		/*
36257c478bd9Sstevel@tonic-gate 		 * Establish the virtual address of the end of the last section
36267c478bd9Sstevel@tonic-gate 		 * in this segment so that the next segments offset can be
36277c478bd9Sstevel@tonic-gate 		 * calculated from this.
36287c478bd9Sstevel@tonic-gate 		 */
36297c478bd9Sstevel@tonic-gate 		if (hshdr)
36307c478bd9Sstevel@tonic-gate 			vaddr += hshdr->sh_size;
36317c478bd9Sstevel@tonic-gate 
36327c478bd9Sstevel@tonic-gate 		/*
36337c478bd9Sstevel@tonic-gate 		 * Output sections for this segment complete.  Adjust the
36347c478bd9Sstevel@tonic-gate 		 * virtual offset for the last sections size, and make sure we
36357c478bd9Sstevel@tonic-gate 		 * haven't exceeded any maximum segment length specification.
36367c478bd9Sstevel@tonic-gate 		 */
36377c478bd9Sstevel@tonic-gate 		if ((sgp->sg_length != 0) && (sgp->sg_length < phdr->p_memsz)) {
36385aefb655Srie 			eprintf(ofl->ofl_lml, ERR_FATAL,
36395aefb655Srie 			    MSG_INTL(MSG_UPD_LARGSIZE), ofl->ofl_name,
36405aefb655Srie 			    sgp->sg_name, EC_XWORD(phdr->p_memsz),
36417c478bd9Sstevel@tonic-gate 			    EC_XWORD(sgp->sg_length));
36427c478bd9Sstevel@tonic-gate 			return (S_ERROR);
36437c478bd9Sstevel@tonic-gate 		}
36447c478bd9Sstevel@tonic-gate 
36457c478bd9Sstevel@tonic-gate 		if (phdr->p_type == PT_NOTE) {
36467c478bd9Sstevel@tonic-gate 			phdr->p_vaddr = 0;
36477c478bd9Sstevel@tonic-gate 			phdr->p_paddr = 0;
36487c478bd9Sstevel@tonic-gate 			phdr->p_align = 0;
36497c478bd9Sstevel@tonic-gate 			phdr->p_memsz = 0;
36507c478bd9Sstevel@tonic-gate 		}
3651d1827f25Srie 
36527c478bd9Sstevel@tonic-gate 		if ((phdr->p_type != PT_NULL) && !(flags & FLG_OF_RELOBJ))
36537c478bd9Sstevel@tonic-gate 			ofl->ofl_phdr[phdrndx++] = *phdr;
36547c478bd9Sstevel@tonic-gate 	}
36557c478bd9Sstevel@tonic-gate 
36567c478bd9Sstevel@tonic-gate 	/*
36577c478bd9Sstevel@tonic-gate 	 * Update any new output sections.  When building the initial output
36587c478bd9Sstevel@tonic-gate 	 * image, a number of sections were created but left uninitialized (eg.
36597c478bd9Sstevel@tonic-gate 	 * .dynsym, .dynstr, .symtab, .symtab, etc.).  Here we update these
36607c478bd9Sstevel@tonic-gate 	 * sections with the appropriate data.  Other sections may still be
36617c478bd9Sstevel@tonic-gate 	 * modified via reloc_process().
36627c478bd9Sstevel@tonic-gate 	 *
366370d3e49eSrie 	 * Copy the interpreter name into the .interp section.
36647c478bd9Sstevel@tonic-gate 	 */
36657c478bd9Sstevel@tonic-gate 	if (ofl->ofl_interp)
36667c478bd9Sstevel@tonic-gate 		(void) strcpy((char *)ofl->ofl_osinterp->os_outdata->d_buf,
36677c478bd9Sstevel@tonic-gate 		    ofl->ofl_interp);
36687c478bd9Sstevel@tonic-gate 
36697c478bd9Sstevel@tonic-gate 	/*
36707c478bd9Sstevel@tonic-gate 	 * Update the .shstrtab, .strtab and .dynstr sections.
36717c478bd9Sstevel@tonic-gate 	 */
36723244bcaaSab 	update_ostrtab(ofl->ofl_osshstrtab, ofl->ofl_shdrsttab, 0);
36733244bcaaSab 	update_ostrtab(ofl->ofl_osstrtab, ofl->ofl_strtab, 0);
36743244bcaaSab 	update_ostrtab(ofl->ofl_osdynstr, ofl->ofl_dynstrtab, DYNSTR_EXTRA_PAD);
36757c478bd9Sstevel@tonic-gate 
36767c478bd9Sstevel@tonic-gate 	/*
36777c478bd9Sstevel@tonic-gate 	 * Build any output symbol tables, the symbols information is copied
36787c478bd9Sstevel@tonic-gate 	 * and updated into the new output image.
36797c478bd9Sstevel@tonic-gate 	 */
36807c478bd9Sstevel@tonic-gate 	if ((etext = update_osym(ofl)) == (Addr)S_ERROR)
36817c478bd9Sstevel@tonic-gate 		return (S_ERROR);
36827c478bd9Sstevel@tonic-gate 
36837c478bd9Sstevel@tonic-gate 	/*
36847c478bd9Sstevel@tonic-gate 	 * If we have a PT_SUNWDTRACE phdr, update it now with the address of
36857c478bd9Sstevel@tonic-gate 	 * the symbol.  It's only now been updated via update_sym().
36867c478bd9Sstevel@tonic-gate 	 */
3687d1827f25Srie 	if (dtracesgp && ofl->ofl_dtracesym) {
3688d1827f25Srie 		Phdr		*aphdr, *phdr = &(dtracesgp->sg_phdr);
36897c478bd9Sstevel@tonic-gate 		Sym_desc	*sdp = ofl->ofl_dtracesym;
36907c478bd9Sstevel@tonic-gate 
3691d1827f25Srie 		phdr->p_vaddr = sdp->sd_sym->st_value;
3692d1827f25Srie 		phdr->p_memsz = sdp->sd_sym->st_size;
36937c478bd9Sstevel@tonic-gate 
36947c478bd9Sstevel@tonic-gate 		/*
36957c478bd9Sstevel@tonic-gate 		 * Take permisions of the segment the symbol is associated with.
36967c478bd9Sstevel@tonic-gate 		 */
3697d1827f25Srie 		aphdr = &sdp->sd_isc->is_osdesc->os_sgdesc->sg_phdr;
3698d1827f25Srie 		assert(aphdr);
3699d1827f25Srie 		phdr->p_flags = aphdr->p_flags;
3700d1827f25Srie 
3701d1827f25Srie 		DBG_CALL(Dbg_seg_entry(ofl, dtracesndx, dtracesgp));
3702d1827f25Srie 		ofl->ofl_phdr[dtracepndx] = *phdr;
3703d1827f25Srie 	}
3704d1827f25Srie 
3705d1827f25Srie 	/*
3706d1827f25Srie 	 * If we have a PT_SUNWCAP phdr, update it now from the associated
3707d1827f25Srie 	 * section information.
3708d1827f25Srie 	 */
3709d1827f25Srie 	if (capsgp && ofl->ofl_oscap) {
3710d1827f25Srie 		Phdr	*phdr = &(capsgp->sg_phdr);
3711d1827f25Srie 		Shdr	*shdr = ofl->ofl_oscap->os_shdr;
3712d1827f25Srie 
3713d1827f25Srie 		phdr->p_vaddr = shdr->sh_addr;
3714d1827f25Srie 		phdr->p_offset = shdr->sh_offset;
3715d1827f25Srie 		phdr->p_filesz = shdr->sh_size;
3716d1827f25Srie 		phdr->p_flags = PF_R;
3717d1827f25Srie 
3718d1827f25Srie 		DBG_CALL(Dbg_seg_entry(ofl, capsndx, capsgp));
3719d1827f25Srie 		ofl->ofl_phdr[cappndx] = *phdr;
37207c478bd9Sstevel@tonic-gate 	}
37217c478bd9Sstevel@tonic-gate 
37227c478bd9Sstevel@tonic-gate 	/*
37237c478bd9Sstevel@tonic-gate 	 * Update the GROUP sections.
37247c478bd9Sstevel@tonic-gate 	 */
37257c478bd9Sstevel@tonic-gate 	if (update_ogroup(ofl) == S_ERROR)
37267c478bd9Sstevel@tonic-gate 		return (S_ERROR);
37277c478bd9Sstevel@tonic-gate 
37287c478bd9Sstevel@tonic-gate 	/*
37297c478bd9Sstevel@tonic-gate 	 * Update Move Table.
37307c478bd9Sstevel@tonic-gate 	 */
37317c478bd9Sstevel@tonic-gate 	if (ofl->ofl_osmove || ofl->ofl_issunwdata1) {
37327c478bd9Sstevel@tonic-gate 		if (update_move(ofl) == S_ERROR)
37337c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37347c478bd9Sstevel@tonic-gate 	}
37357c478bd9Sstevel@tonic-gate 
37367c478bd9Sstevel@tonic-gate 	/*
37377c478bd9Sstevel@tonic-gate 	 * Build any output headers, version information, dynamic structure and
37387c478bd9Sstevel@tonic-gate 	 * syminfo structure.
37397c478bd9Sstevel@tonic-gate 	 */
37407c478bd9Sstevel@tonic-gate 	if (update_oehdr(ofl) == S_ERROR)
37417c478bd9Sstevel@tonic-gate 		return (S_ERROR);
37427c478bd9Sstevel@tonic-gate 	if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) == FLG_OF_VERDEF)
37437c478bd9Sstevel@tonic-gate 		if (update_overdef(ofl) == S_ERROR)
37447c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37457c478bd9Sstevel@tonic-gate 	if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) == FLG_OF_VERNEED)
37467c478bd9Sstevel@tonic-gate 		if (update_overneed(ofl) == S_ERROR)
37477c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37487c478bd9Sstevel@tonic-gate 	if (flags & FLG_OF_DYNAMIC) {
37497c478bd9Sstevel@tonic-gate 		if (update_odynamic(ofl) == S_ERROR)
37507c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37517c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ossyminfo)
37527c478bd9Sstevel@tonic-gate 			if (update_osyminfo(ofl) == S_ERROR)
37537c478bd9Sstevel@tonic-gate 				return (S_ERROR);
37547c478bd9Sstevel@tonic-gate 	}
37557c478bd9Sstevel@tonic-gate 
37567c478bd9Sstevel@tonic-gate 	/*
37577c478bd9Sstevel@tonic-gate 	 * Emit Strtab diagnostics.
37587c478bd9Sstevel@tonic-gate 	 */
37595aefb655Srie 	DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osshstrtab,
37605aefb655Srie 	    ofl->ofl_shdrsttab));
37615aefb655Srie 	DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osstrtab,
37625aefb655Srie 	    ofl->ofl_strtab));
37635aefb655Srie 	DBG_CALL(Dbg_sec_strtab(ofl->ofl_lml, ofl->ofl_osdynstr,
37645aefb655Srie 	    ofl->ofl_dynstrtab));
37657c478bd9Sstevel@tonic-gate 
37667c478bd9Sstevel@tonic-gate 	/*
37677c478bd9Sstevel@tonic-gate 	 * Initialize the section headers string table index within the elf
37687c478bd9Sstevel@tonic-gate 	 * header.
37697c478bd9Sstevel@tonic-gate 	 */
37707c478bd9Sstevel@tonic-gate 	/* LINTED */
37717c478bd9Sstevel@tonic-gate 	if ((shscnndx = elf_ndxscn(ofl->ofl_osshstrtab->os_scn)) <
37727c478bd9Sstevel@tonic-gate 	    SHN_LORESERVE) {
37735aefb655Srie 		ofl->ofl_nehdr->e_shstrndx =
37747c478bd9Sstevel@tonic-gate 		    /* LINTED */
37757c478bd9Sstevel@tonic-gate 		    (Half)shscnndx;
37767c478bd9Sstevel@tonic-gate 	} else {
37777c478bd9Sstevel@tonic-gate 		/*
37787c478bd9Sstevel@tonic-gate 		 * If the STRTAB section index doesn't fit into
37797c478bd9Sstevel@tonic-gate 		 * e_shstrndx, then we store it in 'shdr[0].st_link'.
37807c478bd9Sstevel@tonic-gate 		 */
37817c478bd9Sstevel@tonic-gate 		Elf_Scn	*scn;
37827c478bd9Sstevel@tonic-gate 		Shdr	*shdr0;
37835aefb655Srie 
37847c478bd9Sstevel@tonic-gate 		if ((scn = elf_getscn(ofl->ofl_elf, 0)) == NULL) {
37855aefb655Srie 			eprintf(ofl->ofl_lml, ERR_ELF,
37865aefb655Srie 			    MSG_INTL(MSG_ELF_GETSCN), ofl->ofl_name);
37877c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37887c478bd9Sstevel@tonic-gate 		}
37897c478bd9Sstevel@tonic-gate 		if ((shdr0 = elf_getshdr(scn)) == NULL) {
37905aefb655Srie 			eprintf(ofl->ofl_lml, ERR_ELF,
37915aefb655Srie 			    MSG_INTL(MSG_ELF_GETSHDR), ofl->ofl_name);
37927c478bd9Sstevel@tonic-gate 			return (S_ERROR);
37937c478bd9Sstevel@tonic-gate 		}
37945aefb655Srie 		ofl->ofl_nehdr->e_shstrndx = SHN_XINDEX;
37957c478bd9Sstevel@tonic-gate 		shdr0->sh_link = shscnndx;
37967c478bd9Sstevel@tonic-gate 	}
37977c478bd9Sstevel@tonic-gate 
37987c478bd9Sstevel@tonic-gate 	return ((uintptr_t)etext);
37997c478bd9Sstevel@tonic-gate }
3800