xref: /illumos-gate/usr/src/cmd/sgs/libld/common/update.c (revision a196c3ff)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
215aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate  *	  All Rights Reserved
257c478bd9Sstevel@tonic-gate  *
26f441771bSRod Evans  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate  * Update the new output file image, perform virtual address, offset and
317c478bd9Sstevel@tonic-gate  * displacement calculations on the program headers and sections headers,
327c478bd9Sstevel@tonic-gate  * and generate any new output section information.
337c478bd9Sstevel@tonic-gate  */
34ba2be530Sab 
35ba2be530Sab #define	ELF_TARGET_AMD64
36ba2be530Sab 
377c478bd9Sstevel@tonic-gate #include	<stdio.h>
387c478bd9Sstevel@tonic-gate #include	<string.h>
39fdf855a7Sseizo #include	<unistd.h>
405aefb655Srie #include	<debug.h>
417c478bd9Sstevel@tonic-gate #include	"msg.h"
427c478bd9Sstevel@tonic-gate #include	"_libld.h"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
459039eeafSab  * Comparison routine used by qsort() for sorting of the global symbol list
467c478bd9Sstevel@tonic-gate  * based off of the hashbuckets the symbol will eventually be deposited in.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate static int
sym_hash_compare(Sym_s_list * s1,Sym_s_list * s2)497c478bd9Sstevel@tonic-gate sym_hash_compare(Sym_s_list * s1, Sym_s_list * s2)
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate 	return (s1->sl_hval - s2->sl_hval);
527c478bd9Sstevel@tonic-gate }
537c478bd9Sstevel@tonic-gate 
54d579eb63Sab /*
55d579eb63Sab  * Comparison routine used by qsort() for sorting of dyn[sym|tls]sort section
56d579eb63Sab  * indices based on the address of the symbols they reference. The
57d579eb63Sab  * use of the global dynsort_compare_syms variable is needed because
58d579eb63Sab  * we need to examine the symbols the indices reference. It is safe, because
59d579eb63Sab  * the linker is single threaded.
60d579eb63Sab  */
61ae940584SToomas Soome static Sym *dynsort_compare_syms;
62d579eb63Sab 
63d579eb63Sab static int
dynsort_compare(const void * idx1,const void * idx2)64d579eb63Sab dynsort_compare(const void *idx1, const void *idx2)
65d579eb63Sab {
66d579eb63Sab 	Sym *s1 = dynsort_compare_syms + *((const Word *) idx1);
67d579eb63Sab 	Sym *s2 = dynsort_compare_syms + *((const Word *) idx2);
68d579eb63Sab 
69d579eb63Sab 	/*
70d579eb63Sab 	 * Note: the logical computation for this is
71d579eb63Sab 	 *	(st_value1 - st_value2)
72d579eb63Sab 	 * However, that is only correct if the address type is smaller
73d579eb63Sab 	 * than a pointer. Writing it this way makes it immune to the
74d579eb63Sab 	 * class (32 or 64-bit) of the linker.
75d579eb63Sab 	 */
76d579eb63Sab 	return ((s1->st_value < s2->st_value) ? -1 :
77d579eb63Sab 	    (s1->st_value > s2->st_value));
78d579eb63Sab }
79d579eb63Sab 
80d579eb63Sab /*
81d579eb63Sab  * Scan the sorted symbols, and issue warnings if there are any duplicate
82d579eb63Sab  * values in the list. We only do this if -zverbose is set, or we are
83d579eb63Sab  * running with LD_DEBUG defined
84d579eb63Sab  *
85d579eb63Sab  * entry:
86d579eb63Sab  *	ofl - Output file descriptor
87d579eb63Sab  *	ldynsym - Pointer to start of .SUNW_ldynsym section that the
88d579eb63Sab  *		sort section indexes reference.
89d579eb63Sab  *	symsort - Pointer to start of .SUNW_dynsymsort or .SUNW_dyntlssort
90d579eb63Sab  *		section.
91d579eb63Sab  *	n - # of indices in symsort array
92d579eb63Sab  *	secname - Name of the symsort section.
93d579eb63Sab  *
94d579eb63Sab  * exit:
95d579eb63Sab  *	If the symsort section contains indexes to more than one
96d579eb63Sab  *	symbol with the same address value, a warning is issued.
97d579eb63Sab  */
98d579eb63Sab static void
dynsort_dupwarn(Ofl_desc * ofl,Sym * ldynsym,const char * str,Word * symsort,Word n,const char * secname)99d579eb63Sab dynsort_dupwarn(Ofl_desc *ofl, Sym *ldynsym, const char *str,
100d579eb63Sab     Word *symsort, Word n, const char *secname)
101d579eb63Sab {
102d579eb63Sab 	int zverbose = (ofl->ofl_flags & FLG_OF_VERBOSE) != 0;
103d579eb63Sab 	Word ndx, cmp_ndx;
104d579eb63Sab 	Addr addr, cmp_addr;
105d579eb63Sab 
106d579eb63Sab 	/* Nothing to do if -zverbose or LD_DEBUG are not active */
107d579eb63Sab 	if (!(zverbose || DBG_ENABLED))
108d579eb63Sab 		return;
109d579eb63Sab 
110d579eb63Sab 	cmp_ndx = 0;
111d579eb63Sab 	cmp_addr = ldynsym[symsort[cmp_ndx]].st_value;
112d579eb63Sab 	for (ndx = 1; ndx < n; ndx++) {
113d579eb63Sab 		addr = ldynsym[symsort[ndx]].st_value;
114d579eb63Sab 		if (cmp_addr == addr) {
115d579eb63Sab 			if (zverbose)
1161007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
117d579eb63Sab 				    MSG_INTL(MSG_SYM_DUPSORTADDR), secname,
118d579eb63Sab 				    str + ldynsym[symsort[cmp_ndx]].st_name,
119d579eb63Sab 				    str + ldynsym[symsort[ndx]].st_name,
120d579eb63Sab 				    EC_ADDR(addr));
121d579eb63Sab 			DBG_CALL(Dbg_syms_dup_sort_addr(ofl->ofl_lml, secname,
122d579eb63Sab 			    str + ldynsym[symsort[cmp_ndx]].st_name,
123d579eb63Sab 			    str + ldynsym[symsort[ndx]].st_name,
124d579eb63Sab 			    EC_ADDR(addr)));
125d579eb63Sab 		} else {	/* Not a dup. Move reference up */
126d579eb63Sab 			cmp_ndx = ndx;
127d579eb63Sab 			cmp_addr = addr;
128d579eb63Sab 		}
129d579eb63Sab 	}
130d579eb63Sab }
131d579eb63Sab 
1328222814eSRichard Lowe static inline Boolean
ass_enabled(Ass_desc * ma,uint_t ass)1338222814eSRichard Lowe ass_enabled(Ass_desc *ma, uint_t ass)
1348222814eSRichard Lowe {
1358222814eSRichard Lowe 	return ((ma->ass_enabled & ass) != 0);
1368222814eSRichard Lowe }
1378222814eSRichard Lowe 
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate  * Build and update any output symbol tables.  Here we work on all the symbol
1407c478bd9Sstevel@tonic-gate  * tables at once to reduce the duplication of symbol and string manipulation.
1417c478bd9Sstevel@tonic-gate  * Symbols and their associated strings are copied from the read-only input
1427c478bd9Sstevel@tonic-gate  * file images to the output image and their values and index's updated in the
1437c478bd9Sstevel@tonic-gate  * output image.
1447c478bd9Sstevel@tonic-gate  */
1455aefb655Srie static Addr
update_osym(Ofl_desc * ofl)1467c478bd9Sstevel@tonic-gate update_osym(Ofl_desc *ofl)
1477c478bd9Sstevel@tonic-gate {
148d579eb63Sab 	/*
149d579eb63Sab 	 * There are several places in this function where we wish
150d579eb63Sab 	 * to insert a symbol index to the combined .SUNW_ldynsym/.dynsym
151d579eb63Sab 	 * symbol table into one of the two sort sections (.SUNW_dynsymsort
152d579eb63Sab 	 * or .SUNW_dyntlssort), if that symbol has the right attributes.
153d579eb63Sab 	 * This macro is used to generate the necessary code from a single
154d579eb63Sab 	 * specification.
155d579eb63Sab 	 *
156d579eb63Sab 	 * entry:
157d579eb63Sab 	 *	_sdp, _sym, _type - As per DYNSORT_COUNT. See _libld.h
158d579eb63Sab 	 *	_sym_ndx - Index that _sym will have in the combined
159d579eb63Sab 	 *		.SUNW_ldynsym/.dynsym symbol table.
160d579eb63Sab 	 */
161d579eb63Sab #define	ADD_TO_DYNSORT(_sdp, _sym, _type, _sym_ndx) \
162d579eb63Sab 	{ \
163d579eb63Sab 		Word *_dynsort_arr, *_dynsort_ndx; \
164d579eb63Sab 		\
165d579eb63Sab 		if (dynsymsort_symtype[_type]) { \
166d579eb63Sab 			_dynsort_arr = dynsymsort; \
167d579eb63Sab 			_dynsort_ndx = &dynsymsort_ndx; \
168d579eb63Sab 		} else if (_type == STT_TLS) { \
169d579eb63Sab 			_dynsort_arr = dyntlssort; \
170d579eb63Sab 			_dynsort_ndx = &dyntlssort_ndx; \
171d579eb63Sab 		} else { \
172d579eb63Sab 			_dynsort_arr = NULL; \
173d579eb63Sab 		} \
174d579eb63Sab 		if ((_dynsort_arr != NULL) && DYNSORT_TEST_ATTR(_sdp, _sym)) \
17508278a5eSRod Evans 		    _dynsort_arr[(*_dynsort_ndx)++] = _sym_ndx; \
176d579eb63Sab 	}
177d579eb63Sab 
1787c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
1797c478bd9Sstevel@tonic-gate 	Sym_avlnode	*sav;
18057ef7aa9SRod Evans 	Sg_desc		*sgp, *tsgp = NULL, *dsgp = NULL, *esgp = NULL;
18157ef7aa9SRod Evans 	Os_desc		*osp, *iosp = NULL, *fosp = NULL;
18257ef7aa9SRod Evans 	Is_desc		*isc;
1837c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl;
1847c478bd9Sstevel@tonic-gate 	Word		bssndx, etext_ndx, edata_ndx = 0, end_ndx, start_ndx;
1857c478bd9Sstevel@tonic-gate 	Word		end_abs = 0, etext_abs = 0, edata_abs;
18635450702SAli Bahrami 	Word		tlsbssndx = 0, parexpnndx;
187ba2be530Sab #if	defined(_ELF64)
18854d82594Sseizo 	Word		lbssndx = 0;
18954d82594Sseizo 	Addr		lbssaddr = 0;
19054d82594Sseizo #endif
1917c478bd9Sstevel@tonic-gate 	Addr		bssaddr, etext = 0, edata = 0, end = 0, start = 0;
1927c478bd9Sstevel@tonic-gate 	Addr		tlsbssaddr = 0;
193c524b4feSRichard Lowe 	Addr		parexpnbase, parexpnaddr;
1947c478bd9Sstevel@tonic-gate 	int		start_set = 0;
19557ef7aa9SRod Evans 	Sym		_sym = {0}, *sym, *symtab = NULL;
19657ef7aa9SRod Evans 	Sym		*dynsym = NULL, *ldynsym = NULL;
197635216b6SRod Evans 	Word		symtab_ndx = 0;		/* index into .symtab */
198ca4eed8bSAli Bahrami 	Word		symtab_gbl_bndx;	/* .symtab ndx 1st global */
1999039eeafSab 	Word		ldynsym_ndx = 0;	/* index into .SUNW_ldynsym */
2009039eeafSab 	Word		dynsym_ndx = 0;		/* index into .dynsym */
201635216b6SRod Evans 	Word		scopesym_ndx = 0;	/* index into scoped symbols */
202ca4eed8bSAli Bahrami 	Word		scopesym_bndx = 0;	/* .symtab ndx 1st scoped sym */
203635216b6SRod Evans 	Word		ldynscopesym_ndx = 0;	/* index to ldynsym scoped */
204635216b6SRod Evans 						/*	symbols */
205635216b6SRod Evans 	Word		*dynsymsort = NULL;	/* SUNW_dynsymsort index */
206635216b6SRod Evans 						/*	vector */
207635216b6SRod Evans 	Word		*dyntlssort = NULL;	/* SUNW_dyntlssort index */
208635216b6SRod Evans 						/*	vector */
209d579eb63Sab 	Word		dynsymsort_ndx;		/* index dynsymsort array */
210d579eb63Sab 	Word		dyntlssort_ndx;		/* index dyntlssort array */
211635216b6SRod Evans 	Word		*symndx;		/* symbol index (for */
212635216b6SRod Evans 						/*	relocation use) */
21357ef7aa9SRod Evans 	Word		*symshndx = NULL;	/* .symtab_shndx table */
21457ef7aa9SRod Evans 	Word		*dynshndx = NULL;	/* .dynsym_shndx table */
21557ef7aa9SRod Evans 	Word		*ldynshndx = NULL;	/* .SUNW_ldynsym_shndx table */
216fb8f92baSToomas Soome 	Word		ldynsym_cnt = 0;	/* number of items in */
217635216b6SRod Evans 						/*	.SUNW_ldynsym */
2187c478bd9Sstevel@tonic-gate 	Str_tbl		*shstrtab;
2197c478bd9Sstevel@tonic-gate 	Str_tbl		*strtab;
2207c478bd9Sstevel@tonic-gate 	Str_tbl		*dynstr;
2217c478bd9Sstevel@tonic-gate 	Word		*hashtab;	/* hash table pointer */
2227c478bd9Sstevel@tonic-gate 	Word		*hashbkt;	/* hash table bucket pointer */
2237c478bd9Sstevel@tonic-gate 	Word		*hashchain;	/* hash table chain pointer */
2247c478bd9Sstevel@tonic-gate 	Wk_desc		*wkp;
22557ef7aa9SRod Evans 	Alist		*weak = NULL;
2261d9df23bSab 	ofl_flag_t	flags = ofl->ofl_flags;
2277c478bd9Sstevel@tonic-gate 	Versym		*versym;
2287c478bd9Sstevel@tonic-gate 	Gottable	*gottable;	/* used for display got debugging */
2297c478bd9Sstevel@tonic-gate 					/*	information */
2307c478bd9Sstevel@tonic-gate 	Syminfo		*syminfo;
2317c478bd9Sstevel@tonic-gate 	Sym_s_list	*sorted_syms;	/* table to hold sorted symbols */
2327c478bd9Sstevel@tonic-gate 	Word		ssndx;		/* global index into sorted_syms */
2337c478bd9Sstevel@tonic-gate 	Word		scndx;		/* scoped index into sorted_syms */
234cce0e03bSab 	size_t		stoff;		/* string offset */
23557ef7aa9SRod Evans 	Aliste		idx1;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/*
2387c478bd9Sstevel@tonic-gate 	 * Initialize pointers to the symbol table entries and the symbol
2397c478bd9Sstevel@tonic-gate 	 * table strings.  Skip the first symbol entry and the first string
2407c478bd9Sstevel@tonic-gate 	 * table byte.  Note that if we are not generating any output symbol
241e64d0ff9SAli Bahrami 	 * tables we must still generate and update internal copies so
2427c478bd9Sstevel@tonic-gate 	 * that the relocation phase has the correct information.
2437c478bd9Sstevel@tonic-gate 	 */
2447c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) ||
2457c478bd9Sstevel@tonic-gate 	    ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) {
2467c478bd9Sstevel@tonic-gate 		symtab = (Sym *)ofl->ofl_ossymtab->os_outdata->d_buf;
2477c478bd9Sstevel@tonic-gate 		symtab[symtab_ndx++] = _sym;
2487c478bd9Sstevel@tonic-gate 		if (ofl->ofl_ossymshndx)
249d840867fSab 			symshndx =
250d840867fSab 			    (Word *)ofl->ofl_ossymshndx->os_outdata->d_buf;
2517c478bd9Sstevel@tonic-gate 	}
2529039eeafSab 	if (OFL_ALLOW_DYNSYM(ofl)) {
2537c478bd9Sstevel@tonic-gate 		dynsym = (Sym *)ofl->ofl_osdynsym->os_outdata->d_buf;
2547c478bd9Sstevel@tonic-gate 		dynsym[dynsym_ndx++] = _sym;
2559039eeafSab 		/*
2569039eeafSab 		 * If we are also constructing a .SUNW_ldynsym section
2579039eeafSab 		 * to contain local function symbols, then set it up too.
2589039eeafSab 		 */
2599039eeafSab 		if (ofl->ofl_osldynsym) {
2609039eeafSab 			ldynsym = (Sym *)ofl->ofl_osldynsym->os_outdata->d_buf;
2619039eeafSab 			ldynsym[ldynsym_ndx++] = _sym;
262d579eb63Sab 			ldynsym_cnt = 1 + ofl->ofl_dynlocscnt +
263d579eb63Sab 			    ofl->ofl_dynscopecnt;
264d579eb63Sab 
265d579eb63Sab 			/*
266d579eb63Sab 			 * If there is a SUNW_ldynsym, then there may also
267d579eb63Sab 			 * be a .SUNW_dynsymsort and/or .SUNW_dyntlssort
268d579eb63Sab 			 * sections, used to collect indices of function
269d579eb63Sab 			 * and data symbols sorted by address order.
270d579eb63Sab 			 */
271d579eb63Sab 			if (ofl->ofl_osdynsymsort) {	/* .SUNW_dynsymsort */
272d579eb63Sab 				dynsymsort = (Word *)
273d579eb63Sab 				    ofl->ofl_osdynsymsort->os_outdata->d_buf;
274d579eb63Sab 				dynsymsort_ndx = 0;
275d579eb63Sab 			}
276d579eb63Sab 			if (ofl->ofl_osdyntlssort) {	/* .SUNW_dyntlssort */
277d579eb63Sab 				dyntlssort = (Word *)
278d579eb63Sab 				    ofl->ofl_osdyntlssort->os_outdata->d_buf;
279d579eb63Sab 				dyntlssort_ndx = 0;
280d579eb63Sab 			}
2819039eeafSab 		}
2829039eeafSab 
2837c478bd9Sstevel@tonic-gate 		/*
2847c478bd9Sstevel@tonic-gate 		 * Initialize the hash table.
2857c478bd9Sstevel@tonic-gate 		 */
2867c478bd9Sstevel@tonic-gate 		hashtab = (Word *)(ofl->ofl_oshash->os_outdata->d_buf);
2877c478bd9Sstevel@tonic-gate 		hashbkt = &hashtab[2];
2887c478bd9Sstevel@tonic-gate 		hashchain = &hashtab[2 + ofl->ofl_hashbkts];
2897c478bd9Sstevel@tonic-gate 		hashtab[0] = ofl->ofl_hashbkts;
290635216b6SRod Evans 		hashtab[1] = DYNSYM_ALL_CNT(ofl);
2917c478bd9Sstevel@tonic-gate 		if (ofl->ofl_osdynshndx)
292d840867fSab 			dynshndx =
293d840867fSab 			    (Word *)ofl->ofl_osdynshndx->os_outdata->d_buf;
2949039eeafSab 		if (ofl->ofl_osldynshndx)
295d840867fSab 			ldynshndx =
296d840867fSab 			    (Word *)ofl->ofl_osldynshndx->os_outdata->d_buf;
2977c478bd9Sstevel@tonic-gate 	}
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	/*
3007c478bd9Sstevel@tonic-gate 	 * symndx is the symbol index to be used for relocation processing.  It
3017c478bd9Sstevel@tonic-gate 	 * points to the relevant symtab's (.dynsym or .symtab) symbol ndx.
3027c478bd9Sstevel@tonic-gate 	 */
3037c478bd9Sstevel@tonic-gate 	if (dynsym)
3047c478bd9Sstevel@tonic-gate 		symndx = &dynsym_ndx;
3057c478bd9Sstevel@tonic-gate 	else
3067c478bd9Sstevel@tonic-gate 		symndx = &symtab_ndx;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	/*
3097c478bd9Sstevel@tonic-gate 	 * If we have version definitions initialize the version symbol index
3107c478bd9Sstevel@tonic-gate 	 * table.  There is one entry for each symbol which contains the symbols
3117c478bd9Sstevel@tonic-gate 	 * version index.
3127c478bd9Sstevel@tonic-gate 	 */
313090a8d9eSAli Bahrami 	if (!(flags & FLG_OF_NOVERSEC) &&
314090a8d9eSAli Bahrami 	    (flags & (FLG_OF_VERNEED | FLG_OF_VERDEF))) {
3157c478bd9Sstevel@tonic-gate 		versym = (Versym *)ofl->ofl_osversym->os_outdata->d_buf;
316fb8f92baSToomas Soome 		versym[0] = 0;
3177c478bd9Sstevel@tonic-gate 	} else
31828bda19cSRod Evans 		versym = NULL;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/*
3217c478bd9Sstevel@tonic-gate 	 * If syminfo section exists be prepared to fill it in.
3227c478bd9Sstevel@tonic-gate 	 */
3237c478bd9Sstevel@tonic-gate 	if (ofl->ofl_ossyminfo) {
3247c478bd9Sstevel@tonic-gate 		syminfo = ofl->ofl_ossyminfo->os_outdata->d_buf;
3257c478bd9Sstevel@tonic-gate 		syminfo[0].si_flags = SYMINFO_CURRENT;
3267c478bd9Sstevel@tonic-gate 	} else
32728bda19cSRod Evans 		syminfo = NULL;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	/*
3307c478bd9Sstevel@tonic-gate 	 * Setup our string tables.
3317c478bd9Sstevel@tonic-gate 	 */
3327c478bd9Sstevel@tonic-gate 	shstrtab = ofl->ofl_shdrsttab;
3337c478bd9Sstevel@tonic-gate 	strtab = ofl->ofl_strtab;
3347c478bd9Sstevel@tonic-gate 	dynstr = ofl->ofl_dynstrtab;
3357c478bd9Sstevel@tonic-gate 
3365aefb655Srie 	DBG_CALL(Dbg_syms_sec_title(ofl->ofl_lml));
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	/*
3399039eeafSab 	 * Put output file name to the first .symtab and .SUNW_ldynsym symbol.
3407c478bd9Sstevel@tonic-gate 	 */
3417c478bd9Sstevel@tonic-gate 	if (symtab) {
3427c478bd9Sstevel@tonic-gate 		(void) st_setstring(strtab, ofl->ofl_name, &stoff);
3437c478bd9Sstevel@tonic-gate 		sym = &symtab[symtab_ndx++];
3447c478bd9Sstevel@tonic-gate 		/* LINTED */
3457c478bd9Sstevel@tonic-gate 		sym->st_name = stoff;
3467c478bd9Sstevel@tonic-gate 		sym->st_value = 0;
3477c478bd9Sstevel@tonic-gate 		sym->st_size = 0;
3487c478bd9Sstevel@tonic-gate 		sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE);
3497c478bd9Sstevel@tonic-gate 		sym->st_other = 0;
3507c478bd9Sstevel@tonic-gate 		sym->st_shndx = SHN_ABS;
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 		if (versym && !dynsym)
3537c478bd9Sstevel@tonic-gate 			versym[1] = 0;
3547c478bd9Sstevel@tonic-gate 	}
355d579eb63Sab 	if (ldynsym) {
3569039eeafSab 		(void) st_setstring(dynstr, ofl->ofl_name, &stoff);
3579039eeafSab 		sym = &ldynsym[ldynsym_ndx];
3589039eeafSab 		/* LINTED */
3599039eeafSab 		sym->st_name = stoff;
3609039eeafSab 		sym->st_value = 0;
3619039eeafSab 		sym->st_size = 0;
3629039eeafSab 		sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE);
3639039eeafSab 		sym->st_other = 0;
3649039eeafSab 		sym->st_shndx = SHN_ABS;
3659039eeafSab 
3669039eeafSab 		/* Scoped symbols get filled in global loop below */
3679039eeafSab 		ldynscopesym_ndx = ldynsym_ndx + 1;
3689039eeafSab 		ldynsym_ndx += ofl->ofl_dynscopecnt;
3699039eeafSab 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	/*
3727c478bd9Sstevel@tonic-gate 	 * If we are to display GOT summary information, then allocate
3737c478bd9Sstevel@tonic-gate 	 * the buffer to 'cache' the GOT symbols into now.
3747c478bd9Sstevel@tonic-gate 	 */
3755aefb655Srie 	if (DBG_ENABLED) {
376d326b23bSrie 		if ((ofl->ofl_gottable = gottable =
37757ef7aa9SRod Evans 		    libld_calloc(ofl->ofl_gotcnt, sizeof (Gottable))) == NULL)
37808278a5eSRod Evans 			return ((Addr)S_ERROR);
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	/*
3827c478bd9Sstevel@tonic-gate 	 * Traverse the program headers.  Determine the last executable segment
3837c478bd9Sstevel@tonic-gate 	 * and the last data segment so that we can update etext and edata. If
3847c478bd9Sstevel@tonic-gate 	 * we have empty segments (reservations) record them for setting _end.
3857c478bd9Sstevel@tonic-gate 	 */
38657ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
3870bc07c75Srie 		Phdr	*phd = &(sgp->sg_phdr);
388cce0e03bSab 		Os_desc	*osp;
38957ef7aa9SRod Evans 		Aliste	idx2;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 		if (phd->p_type == PT_LOAD) {
3928b891ae8SRichard Lowe 			if (aplist_nitems(sgp->sg_osdescs) != 0) {
393d840867fSab 				Word	_flags = phd->p_flags & (PF_W | PF_R);
3940bc07c75Srie 
395d840867fSab 				if (_flags == PF_R)
396d840867fSab 					tsgp = sgp;
397d840867fSab 				else if (_flags == (PF_W | PF_R))
398d840867fSab 					dsgp = sgp;
3997c478bd9Sstevel@tonic-gate 			} else if (sgp->sg_flags & FLG_SG_EMPTY)
400d840867fSab 				esgp = sgp;
4017c478bd9Sstevel@tonic-gate 		}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 		/*
4047c478bd9Sstevel@tonic-gate 		 * Generate a section symbol for each output section.
4057c478bd9Sstevel@tonic-gate 		 */
40657ef7aa9SRod Evans 		for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
4077c478bd9Sstevel@tonic-gate 			Word	sectndx;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 			sym = &_sym;
4107c478bd9Sstevel@tonic-gate 			sym->st_value = osp->os_shdr->sh_addr;
4117c478bd9Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION);
4127c478bd9Sstevel@tonic-gate 			/* LINTED */
4137c478bd9Sstevel@tonic-gate 			sectndx = elf_ndxscn(osp->os_scn);
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 			if (symtab) {
4167c478bd9Sstevel@tonic-gate 				if (sectndx >= SHN_LORESERVE) {
4177c478bd9Sstevel@tonic-gate 					symshndx[symtab_ndx] = sectndx;
4187c478bd9Sstevel@tonic-gate 					sym->st_shndx = SHN_XINDEX;
4197c478bd9Sstevel@tonic-gate 				} else {
4207c478bd9Sstevel@tonic-gate 					/* LINTED */
4217c478bd9Sstevel@tonic-gate 					sym->st_shndx = (Half)sectndx;
4227c478bd9Sstevel@tonic-gate 				}
4237c478bd9Sstevel@tonic-gate 				symtab[symtab_ndx++] = *sym;
4247c478bd9Sstevel@tonic-gate 			}
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 			if (dynsym && (osp->os_flags & FLG_OS_OUTREL))
4277c478bd9Sstevel@tonic-gate 				dynsym[dynsym_ndx++] = *sym;
4287c478bd9Sstevel@tonic-gate 
42957ef7aa9SRod Evans 			if ((dynsym == NULL) ||
43057ef7aa9SRod Evans 			    (osp->os_flags & FLG_OS_OUTREL)) {
4317c478bd9Sstevel@tonic-gate 				if (versym)
4327c478bd9Sstevel@tonic-gate 					versym[*symndx - 1] = 0;
43357ef7aa9SRod Evans 				osp->os_identndx = *symndx - 1;
4345aefb655Srie 				DBG_CALL(Dbg_syms_sec_entry(ofl->ofl_lml,
43557ef7aa9SRod Evans 				    osp->os_identndx, sgp, osp));
4367c478bd9Sstevel@tonic-gate 			}
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 			/*
4397c478bd9Sstevel@tonic-gate 			 * Generate the .shstrtab for this section.
4407c478bd9Sstevel@tonic-gate 			 */
4417c478bd9Sstevel@tonic-gate 			(void) st_setstring(shstrtab, osp->os_name, &stoff);
4427c478bd9Sstevel@tonic-gate 			osp->os_shdr->sh_name = (Word)stoff;
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 			/*
4457c478bd9Sstevel@tonic-gate 			 * Find the section index for our special symbols.
4467c478bd9Sstevel@tonic-gate 			 */
4477c478bd9Sstevel@tonic-gate 			if (sgp == tsgp) {
4487c478bd9Sstevel@tonic-gate 				/* LINTED */
4497c478bd9Sstevel@tonic-gate 				etext_ndx = elf_ndxscn(osp->os_scn);
4507c478bd9Sstevel@tonic-gate 			} else if (dsgp == sgp) {
4517c478bd9Sstevel@tonic-gate 				if (osp->os_shdr->sh_type != SHT_NOBITS) {
4527c478bd9Sstevel@tonic-gate 					/* LINTED */
4537c478bd9Sstevel@tonic-gate 					edata_ndx = elf_ndxscn(osp->os_scn);
4547c478bd9Sstevel@tonic-gate 				}
4557c478bd9Sstevel@tonic-gate 			}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 			if (start_set == 0) {
4587c478bd9Sstevel@tonic-gate 				start = sgp->sg_phdr.p_vaddr;
4597c478bd9Sstevel@tonic-gate 				/* LINTED */
4607c478bd9Sstevel@tonic-gate 				start_ndx = elf_ndxscn(osp->os_scn);
4617c478bd9Sstevel@tonic-gate 				start_set++;
4627c478bd9Sstevel@tonic-gate 			}
463c1c6f601Srie 
464c1c6f601Srie 			/*
465c1c6f601Srie 			 * While we're here, determine whether a .init or .fini
466c1c6f601Srie 			 * section exist.
467c1c6f601Srie 			 */
46857ef7aa9SRod Evans 			if ((iosp == NULL) && (strcmp(osp->os_name,
469c1c6f601Srie 			    MSG_ORIG(MSG_SCN_INIT)) == 0))
470c1c6f601Srie 				iosp = osp;
47157ef7aa9SRod Evans 			if ((fosp == NULL) && (strcmp(osp->os_name,
472c1c6f601Srie 			    MSG_ORIG(MSG_SCN_FINI)) == 0))
473c1c6f601Srie 				fosp = osp;
4747c478bd9Sstevel@tonic-gate 		}
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	/*
4787c478bd9Sstevel@tonic-gate 	 * Add local register symbols to the .dynsym.  These are required as
4797c478bd9Sstevel@tonic-gate 	 * DT_REGISTER .dynamic entries must have a symbol to reference.
4807c478bd9Sstevel@tonic-gate 	 */
4817c478bd9Sstevel@tonic-gate 	if (ofl->ofl_regsyms && dynsym) {
4827c478bd9Sstevel@tonic-gate 		int	ndx;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 		for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
48557ef7aa9SRod Evans 			Sym_desc	*rsdp;
4867c478bd9Sstevel@tonic-gate 
48757ef7aa9SRod Evans 			if ((rsdp = ofl->ofl_regsyms[ndx]) == NULL)
4887c478bd9Sstevel@tonic-gate 				continue;
4897c478bd9Sstevel@tonic-gate 
49008278a5eSRod Evans 			if (!SYM_IS_HIDDEN(rsdp) &&
4917c478bd9Sstevel@tonic-gate 			    (ELF_ST_BIND(rsdp->sd_sym->st_info) != STB_LOCAL))
4927c478bd9Sstevel@tonic-gate 				continue;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 			dynsym[dynsym_ndx] = *(rsdp->sd_sym);
4957c478bd9Sstevel@tonic-gate 			rsdp->sd_symndx = *symndx;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 			if (dynsym[dynsym_ndx].st_name) {
4987c478bd9Sstevel@tonic-gate 				(void) st_setstring(dynstr, rsdp->sd_name,
4997c478bd9Sstevel@tonic-gate 				    &stoff);
5007c478bd9Sstevel@tonic-gate 				dynsym[dynsym_ndx].st_name = stoff;
5017c478bd9Sstevel@tonic-gate 			}
5027c478bd9Sstevel@tonic-gate 			dynsym_ndx++;
5037c478bd9Sstevel@tonic-gate 		}
5047c478bd9Sstevel@tonic-gate 	}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	/*
5077c478bd9Sstevel@tonic-gate 	 * Having traversed all the output segments, warn the user if the
5087c478bd9Sstevel@tonic-gate 	 * traditional text or data segments don't exist.  Otherwise from these
5097c478bd9Sstevel@tonic-gate 	 * segments establish the values for `etext', `edata', `end', `END',
5107c478bd9Sstevel@tonic-gate 	 * and `START'.
5117c478bd9Sstevel@tonic-gate 	 */
5127c478bd9Sstevel@tonic-gate 	if (!(flags & FLG_OF_RELOBJ)) {
51357ef7aa9SRod Evans 		Sg_desc	*sgp;
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 		if (tsgp)
5167c478bd9Sstevel@tonic-gate 			etext = tsgp->sg_phdr.p_vaddr + tsgp->sg_phdr.p_filesz;
5177c478bd9Sstevel@tonic-gate 		else {
5187c478bd9Sstevel@tonic-gate 			etext = (Addr)0;
5197c478bd9Sstevel@tonic-gate 			etext_ndx = SHN_ABS;
5207c478bd9Sstevel@tonic-gate 			etext_abs = 1;
5211d9df23bSab 			if (flags & FLG_OF_VERBOSE)
5221007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
5237c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_UPD_NOREADSEG));
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 		if (dsgp) {
5267c478bd9Sstevel@tonic-gate 			edata = dsgp->sg_phdr.p_vaddr + dsgp->sg_phdr.p_filesz;
5277c478bd9Sstevel@tonic-gate 		} else {
5287c478bd9Sstevel@tonic-gate 			edata = (Addr)0;
5297c478bd9Sstevel@tonic-gate 			edata_ndx = SHN_ABS;
5307c478bd9Sstevel@tonic-gate 			edata_abs = 1;
5311d9df23bSab 			if (flags & FLG_OF_VERBOSE)
5321007fd6fSAli Bahrami 				ld_eprintf(ofl, ERR_WARNING,
5337c478bd9Sstevel@tonic-gate 				    MSG_INTL(MSG_UPD_NORDWRSEG));
5347c478bd9Sstevel@tonic-gate 		}
5357c478bd9Sstevel@tonic-gate 
53657ef7aa9SRod Evans 		if (dsgp == NULL) {
5377c478bd9Sstevel@tonic-gate 			if (tsgp)
5387c478bd9Sstevel@tonic-gate 				sgp = tsgp;
5397c478bd9Sstevel@tonic-gate 			else
5407c478bd9Sstevel@tonic-gate 				sgp = 0;
54157ef7aa9SRod Evans 		} else if (tsgp == NULL)
5427c478bd9Sstevel@tonic-gate 			sgp = dsgp;
5437c478bd9Sstevel@tonic-gate 		else if (dsgp->sg_phdr.p_vaddr > tsgp->sg_phdr.p_vaddr)
5447c478bd9Sstevel@tonic-gate 			sgp = dsgp;
5457c478bd9Sstevel@tonic-gate 		else if (dsgp->sg_phdr.p_vaddr < tsgp->sg_phdr.p_vaddr)
5467c478bd9Sstevel@tonic-gate 			sgp = tsgp;
5477c478bd9Sstevel@tonic-gate 		else {
5487c478bd9Sstevel@tonic-gate 			/*
5497c478bd9Sstevel@tonic-gate 			 * One of the segments must be of zero size.
5507c478bd9Sstevel@tonic-gate 			 */
5517c478bd9Sstevel@tonic-gate 			if (tsgp->sg_phdr.p_memsz)
5527c478bd9Sstevel@tonic-gate 				sgp = tsgp;
5537c478bd9Sstevel@tonic-gate 			else
5547c478bd9Sstevel@tonic-gate 				sgp = dsgp;
5557c478bd9Sstevel@tonic-gate 		}
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 		if (esgp && (esgp->sg_phdr.p_vaddr > sgp->sg_phdr.p_vaddr))
5587c478bd9Sstevel@tonic-gate 			sgp = esgp;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 		if (sgp) {
5617c478bd9Sstevel@tonic-gate 			end = sgp->sg_phdr.p_vaddr + sgp->sg_phdr.p_memsz;
5627c478bd9Sstevel@tonic-gate 
563fdf855a7Sseizo 			/*
564fdf855a7Sseizo 			 * If the last loadable segment is a read-only segment,
565fdf855a7Sseizo 			 * then the application which uses the symbol _end to
566fdf855a7Sseizo 			 * find the beginning of writable heap area may cause
567fdf855a7Sseizo 			 * segmentation violation. We adjust the value of the
568fdf855a7Sseizo 			 * _end to skip to the next page boundary.
569fdf855a7Sseizo 			 *
570fdf855a7Sseizo 			 * 6401812 System interface which returs beginning
571fdf855a7Sseizo 			 *	   heap would be nice.
572fdf855a7Sseizo 			 * When the above RFE is implemented, the changes below
573fdf855a7Sseizo 			 * could be changed in a better way.
574fdf855a7Sseizo 			 */
575fdf855a7Sseizo 			if ((sgp->sg_phdr.p_flags & PF_W) == 0)
57660758829Srie 				end = (Addr)S_ROUND(end, sysconf(_SC_PAGESIZE));
577fdf855a7Sseizo 
5787c478bd9Sstevel@tonic-gate 			/*
5797c478bd9Sstevel@tonic-gate 			 * If we're dealing with a memory reservation there are
5807c478bd9Sstevel@tonic-gate 			 * no sections to establish an index for _end, so assign
5817c478bd9Sstevel@tonic-gate 			 * it as an absolute.
5827c478bd9Sstevel@tonic-gate 			 */
5838b891ae8SRichard Lowe 			if (aplist_nitems(sgp->sg_osdescs) != 0) {
5840bc07c75Srie 				/*
5850bc07c75Srie 				 * Determine the last section for this segment.
5860bc07c75Srie 				 */
587cce0e03bSab 				Os_desc	*osp = sgp->sg_osdescs->apl_data
588cce0e03bSab 				    [sgp->sg_osdescs->apl_nitems - 1];
589cce0e03bSab 
5900bc07c75Srie 				/* LINTED */
591cce0e03bSab 				end_ndx = elf_ndxscn(osp->os_scn);
5927c478bd9Sstevel@tonic-gate 			} else {
5937c478bd9Sstevel@tonic-gate 				end_ndx = SHN_ABS;
5947c478bd9Sstevel@tonic-gate 				end_abs = 1;
5957c478bd9Sstevel@tonic-gate 			}
5967c478bd9Sstevel@tonic-gate 		} else {
5977c478bd9Sstevel@tonic-gate 			end = (Addr) 0;
5987c478bd9Sstevel@tonic-gate 			end_ndx = SHN_ABS;
5997c478bd9Sstevel@tonic-gate 			end_abs = 1;
6001007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_UPD_NOSEG));
6017c478bd9Sstevel@tonic-gate 		}
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	/*
6057c478bd9Sstevel@tonic-gate 	 * Initialize the scoped symbol table entry point.  This is for all
6067c478bd9Sstevel@tonic-gate 	 * the global symbols that have been scoped to locals and will be
6077c478bd9Sstevel@tonic-gate 	 * filled in during global symbol processing so that we don't have
6087c478bd9Sstevel@tonic-gate 	 * to traverse the globals symbol hash array more than once.
6097c478bd9Sstevel@tonic-gate 	 */
6107c478bd9Sstevel@tonic-gate 	if (symtab) {
611ca4eed8bSAli Bahrami 		scopesym_bndx = symtab_ndx;
612ca4eed8bSAli Bahrami 		scopesym_ndx = scopesym_bndx;
6137c478bd9Sstevel@tonic-gate 		symtab_ndx += ofl->ofl_scopecnt;
6147c478bd9Sstevel@tonic-gate 	}
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	/*
61735450702SAli Bahrami 	 * If expanding partially expanded symbols under '-z nopartial',
61835450702SAli Bahrami 	 * prepare to do that.
6197c478bd9Sstevel@tonic-gate 	 */
62035450702SAli Bahrami 	if (ofl->ofl_isparexpn) {
62135450702SAli Bahrami 		osp = ofl->ofl_isparexpn->is_osdesc;
622b26cc8daSAli Bahrami 		parexpnbase = parexpnaddr = (Addr)(osp->os_shdr->sh_addr +
62335450702SAli Bahrami 		    ofl->ofl_isparexpn->is_indata->d_off);
6247c478bd9Sstevel@tonic-gate 		/* LINTED */
62535450702SAli Bahrami 		parexpnndx = elf_ndxscn(osp->os_scn);
62657ef7aa9SRod Evans 		ofl->ofl_parexpnndx = osp->os_identndx;
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 	/*
6307c478bd9Sstevel@tonic-gate 	 * If we are generating a .symtab collect all the local symbols,
6317c478bd9Sstevel@tonic-gate 	 * assigning a new virtual address or displacement (value).
6327c478bd9Sstevel@tonic-gate 	 */
63357ef7aa9SRod Evans 	for (APLIST_TRAVERSE(ofl->ofl_objs, idx1, ifl)) {
63408278a5eSRod Evans 		Xword		lndx, local = ifl->ifl_locscnt;
63508278a5eSRod Evans 		Cap_desc	*cdp = ifl->ifl_caps;
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 		for (lndx = 1; lndx < local; lndx++) {
6387c478bd9Sstevel@tonic-gate 			Gotndx		*gnp;
639d579eb63Sab 			uchar_t		type;
6407c478bd9Sstevel@tonic-gate 			Word		*_symshndx;
6419039eeafSab 			int		enter_in_symtab, enter_in_ldynsym;
6429039eeafSab 			int		update_done;
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 			sdp = ifl->ifl_oldndx[lndx];
6457c478bd9Sstevel@tonic-gate 			sym = sdp->sd_sym;
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 			/*
6487c478bd9Sstevel@tonic-gate 			 * Assign a got offset if necessary.
6497c478bd9Sstevel@tonic-gate 			 */
650ba2be530Sab 			if ((ld_targ.t_mr.mr_assign_got != NULL) &&
651ba2be530Sab 			    (*ld_targ.t_mr.mr_assign_got)(ofl, sdp) == S_ERROR)
6527c478bd9Sstevel@tonic-gate 				return ((Addr)S_ERROR);
653ba2be530Sab 
6545aefb655Srie 			if (DBG_ENABLED) {
65557ef7aa9SRod Evans 				Aliste	idx2;
65657ef7aa9SRod Evans 
65757ef7aa9SRod Evans 				for (ALIST_TRAVERSE(sdp->sd_GOTndxs,
65857ef7aa9SRod Evans 				    idx2, gnp)) {
659d840867fSab 					gottable->gt_sym = sdp;
660d840867fSab 					gottable->gt_gndx.gn_gotndx =
661d840867fSab 					    gnp->gn_gotndx;
662d840867fSab 					gottable->gt_gndx.gn_addend =
663d840867fSab 					    gnp->gn_addend;
664d840867fSab 					gottable++;
665d840867fSab 				}
6667c478bd9Sstevel@tonic-gate 			}
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 			if ((type = ELF_ST_TYPE(sym->st_info)) == STT_SECTION)
6697c478bd9Sstevel@tonic-gate 				continue;
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 			/*
6727c478bd9Sstevel@tonic-gate 			 * Ignore any symbols that have been marked as invalid
6737c478bd9Sstevel@tonic-gate 			 * during input processing.  Providing these aren't used
6747c478bd9Sstevel@tonic-gate 			 * for relocation they'll just be dropped from the
6757c478bd9Sstevel@tonic-gate 			 * output image.
6767c478bd9Sstevel@tonic-gate 			 */
6777c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_INVALID)
6787c478bd9Sstevel@tonic-gate 				continue;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 			/*
6817c478bd9Sstevel@tonic-gate 			 * If the section that this symbol was associated
6827c478bd9Sstevel@tonic-gate 			 * with has been discarded - then we discard
6837c478bd9Sstevel@tonic-gate 			 * the local symbol along with it.
6847c478bd9Sstevel@tonic-gate 			 */
6857c478bd9Sstevel@tonic-gate 			if (sdp->sd_flags & FLG_SY_ISDISC)
6867c478bd9Sstevel@tonic-gate 				continue;
6877c478bd9Sstevel@tonic-gate 
688ca4eed8bSAli Bahrami 			/*
689ca4eed8bSAli Bahrami 			 * If this symbol is from a different file
690ca4eed8bSAli Bahrami 			 * than the input descriptor we are processing,
691ca4eed8bSAli Bahrami 			 * treat it as if it has FLG_SY_ISDISC set.
692ca4eed8bSAli Bahrami 			 * This happens when sloppy_comdat_reloc()
693ca4eed8bSAli Bahrami 			 * replaces a symbol to a discarded comdat section
694ca4eed8bSAli Bahrami 			 * with an equivalent symbol from a different
695ca4eed8bSAli Bahrami 			 * file. We only want to enter such a symbol
696ca4eed8bSAli Bahrami 			 * once --- as part of the file that actually
697ca4eed8bSAli Bahrami 			 * supplies it.
698ca4eed8bSAli Bahrami 			 */
699ca4eed8bSAli Bahrami 			if (ifl != sdp->sd_file)
700ca4eed8bSAli Bahrami 				continue;
701ca4eed8bSAli Bahrami 
7027c478bd9Sstevel@tonic-gate 			/*
7037c478bd9Sstevel@tonic-gate 			 * Generate an output symbol to represent this input
7047c478bd9Sstevel@tonic-gate 			 * symbol.  Even if the symbol table is to be stripped
7057c478bd9Sstevel@tonic-gate 			 * we still need to update any local symbols that are
7067c478bd9Sstevel@tonic-gate 			 * used during relocation.
7077c478bd9Sstevel@tonic-gate 			 */
7089039eeafSab 			enter_in_symtab = symtab &&
70944bac77bSrie 			    (!(ofl->ofl_flags & FLG_OF_REDLSYM) ||
71057ef7aa9SRod Evans 			    sdp->sd_move);
711f980a4bbSRichard Lowe 			enter_in_ldynsym = ldynsym &&
712f980a4bbSRichard Lowe 			    ((sym->st_name != 0) || (type == STT_FILE)) &&
713d579eb63Sab 			    ldynsym_symtype[type] &&
71444bac77bSrie 			    !(ofl->ofl_flags & FLG_OF_REDLSYM);
715f980a4bbSRichard Lowe 
71657ef7aa9SRod Evans 			_symshndx = NULL;
71757ef7aa9SRod Evans 
7189039eeafSab 			if (enter_in_symtab) {
7197c478bd9Sstevel@tonic-gate 				if (!dynsym)
7207c478bd9Sstevel@tonic-gate 					sdp->sd_symndx = *symndx;
7217c478bd9Sstevel@tonic-gate 				symtab[symtab_ndx] = *sym;
72208278a5eSRod Evans 
7237c478bd9Sstevel@tonic-gate 				/*
7247c478bd9Sstevel@tonic-gate 				 * Provided this isn't an unnamed register
7257c478bd9Sstevel@tonic-gate 				 * symbol, update its name.
7267c478bd9Sstevel@tonic-gate 				 */
7277c478bd9Sstevel@tonic-gate 				if (((sdp->sd_flags & FLG_SY_REGSYM) == 0) ||
7287c478bd9Sstevel@tonic-gate 				    symtab[symtab_ndx].st_name) {
7297c478bd9Sstevel@tonic-gate 					(void) st_setstring(strtab,
7307c478bd9Sstevel@tonic-gate 					    sdp->sd_name, &stoff);
7317c478bd9Sstevel@tonic-gate 					symtab[symtab_ndx].st_name = stoff;
7327c478bd9Sstevel@tonic-gate 				}
7337c478bd9Sstevel@tonic-gate 				sdp->sd_flags &= ~FLG_SY_CLEAN;
7347c478bd9Sstevel@tonic-gate 				if (symshndx)
7357c478bd9Sstevel@tonic-gate 					_symshndx = &symshndx[symtab_ndx];
7367c478bd9Sstevel@tonic-gate 				sdp->sd_sym = sym = &symtab[symtab_ndx++];
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 				if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
7399039eeafSab 				    (sym->st_shndx == SHN_ABS) &&
7409039eeafSab 				    !enter_in_ldynsym)
7417c478bd9Sstevel@tonic-gate 					continue;
7429039eeafSab 			} else if (enter_in_ldynsym) {
7439039eeafSab 				/*
7449039eeafSab 				 * Not using symtab, but we do have ldynsym
7459039eeafSab 				 * available.
7469039eeafSab 				 */
7479039eeafSab 				ldynsym[ldynsym_ndx] = *sym;
7489039eeafSab 				(void) st_setstring(dynstr, sdp->sd_name,
749d840867fSab 				    &stoff);
7509039eeafSab 				ldynsym[ldynsym_ndx].st_name = stoff;
7519039eeafSab 
7529039eeafSab 				sdp->sd_flags &= ~FLG_SY_CLEAN;
7539039eeafSab 				if (ldynshndx)
7549039eeafSab 					_symshndx = &ldynshndx[ldynsym_ndx];
755d579eb63Sab 				sdp->sd_sym = sym = &ldynsym[ldynsym_ndx];
756d579eb63Sab 				/* Add it to sort section if it qualifies */
757d579eb63Sab 				ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx);
758d579eb63Sab 				ldynsym_ndx++;
7599039eeafSab 			} else {	/* Not using symtab or ldynsym */
7607c478bd9Sstevel@tonic-gate 				/*
7617c478bd9Sstevel@tonic-gate 				 * If this symbol requires modifying to provide
7627c478bd9Sstevel@tonic-gate 				 * for a relocation or move table update, make
7637c478bd9Sstevel@tonic-gate 				 * a copy of it.
7647c478bd9Sstevel@tonic-gate 				 */
7657c478bd9Sstevel@tonic-gate 				if (!(sdp->sd_flags & FLG_SY_UPREQD) &&
76657ef7aa9SRod Evans 				    !(sdp->sd_move))
7677c478bd9Sstevel@tonic-gate 					continue;
7687c478bd9Sstevel@tonic-gate 				if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
7697c478bd9Sstevel@tonic-gate 				    (sym->st_shndx == SHN_ABS))
7707c478bd9Sstevel@tonic-gate 					continue;
7717c478bd9Sstevel@tonic-gate 
7725aefb655Srie 				if (ld_sym_copy(sdp) == S_ERROR)
7737c478bd9Sstevel@tonic-gate 					return ((Addr)S_ERROR);
7747c478bd9Sstevel@tonic-gate 				sym = sdp->sd_sym;
7757c478bd9Sstevel@tonic-gate 			}
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 			/*
7787c478bd9Sstevel@tonic-gate 			 * Update the symbols contents if necessary.
7797c478bd9Sstevel@tonic-gate 			 */
7809039eeafSab 			update_done = 0;
7817c478bd9Sstevel@tonic-gate 			if (type == STT_FILE) {
7827c478bd9Sstevel@tonic-gate 				sdp->sd_shndx = sym->st_shndx = SHN_ABS;
7837c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_SPECSEC;
7849039eeafSab 				update_done = 1;
7857c478bd9Sstevel@tonic-gate 			}
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 			/*
7887c478bd9Sstevel@tonic-gate 			 * If we are expanding the locally bound partially
7897c478bd9Sstevel@tonic-gate 			 * initialized symbols, then update the address here.
7907c478bd9Sstevel@tonic-gate 			 */
79135450702SAli Bahrami 			if (ofl->ofl_isparexpn &&
7929039eeafSab 			    (sdp->sd_flags & FLG_SY_PAREXPN) && !update_done) {
79335450702SAli Bahrami 				sym->st_shndx = parexpnndx;
79435450702SAli Bahrami 				sdp->sd_isc = ofl->ofl_isparexpn;
795b26cc8daSAli Bahrami 				sym->st_value = parexpnaddr;
79635450702SAli Bahrami 				parexpnaddr += sym->st_size;
797b26cc8daSAli Bahrami 				if ((flags & FLG_OF_RELOBJ) == 0)
798b26cc8daSAli Bahrami 					sym->st_value -= parexpnbase;
7997c478bd9Sstevel@tonic-gate 			}
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 			/*
8027c478bd9Sstevel@tonic-gate 			 * If this isn't an UNDEF symbol (ie. an input section
8037c478bd9Sstevel@tonic-gate 			 * is associated), update the symbols value and index.
8047c478bd9Sstevel@tonic-gate 			 */
80508278a5eSRod Evans 			if (((isc = sdp->sd_isc) != NULL) && !update_done) {
8067c478bd9Sstevel@tonic-gate 				Word	sectndx;
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate 				osp = isc->is_osdesc;
8097c478bd9Sstevel@tonic-gate 				/* LINTED */
8107c478bd9Sstevel@tonic-gate 				sym->st_value +=
8117c478bd9Sstevel@tonic-gate 				    (Off)_elf_getxoff(isc->is_indata);
812635216b6SRod Evans 				if ((flags & FLG_OF_RELOBJ) == 0) {
8137c478bd9Sstevel@tonic-gate 					sym->st_value += osp->os_shdr->sh_addr;
8147c478bd9Sstevel@tonic-gate 					/*
8157c478bd9Sstevel@tonic-gate 					 * TLS symbols are relative to
8167c478bd9Sstevel@tonic-gate 					 * the TLS segment.
8177c478bd9Sstevel@tonic-gate 					 */
818d579eb63Sab 					if ((type == STT_TLS) &&
819d579eb63Sab 					    (ofl->ofl_tlsphdr)) {
8207c478bd9Sstevel@tonic-gate 						sym->st_value -=
8217c478bd9Sstevel@tonic-gate 						    ofl->ofl_tlsphdr->p_vaddr;
8229039eeafSab 					}
8237c478bd9Sstevel@tonic-gate 				}
8247c478bd9Sstevel@tonic-gate 				/* LINTED */
8257c478bd9Sstevel@tonic-gate 				if ((sdp->sd_shndx = sectndx =
8267c478bd9Sstevel@tonic-gate 				    elf_ndxscn(osp->os_scn)) >= SHN_LORESERVE) {
8277c478bd9Sstevel@tonic-gate 					if (_symshndx) {
8287c478bd9Sstevel@tonic-gate 						*_symshndx = sectndx;
8297c478bd9Sstevel@tonic-gate 					}
8307c478bd9Sstevel@tonic-gate 					sym->st_shndx = SHN_XINDEX;
8317c478bd9Sstevel@tonic-gate 				} else {
8327c478bd9Sstevel@tonic-gate 					/* LINTED */
8337c478bd9Sstevel@tonic-gate 					sym->st_shndx = sectndx;
8347c478bd9Sstevel@tonic-gate 				}
8357c478bd9Sstevel@tonic-gate 			}
8369039eeafSab 
8379039eeafSab 			/*
8389039eeafSab 			 * If entering the symbol in both the symtab and the
8399039eeafSab 			 * ldynsym, then the one in symtab needs to be
8409039eeafSab 			 * copied to ldynsym. If it is only in the ldynsym,
8419039eeafSab 			 * then the code above already set it up and we have
8429039eeafSab 			 * nothing more to do here.
8439039eeafSab 			 */
8449039eeafSab 			if (enter_in_symtab && enter_in_ldynsym) {
8459039eeafSab 				ldynsym[ldynsym_ndx] = *sym;
8469039eeafSab 				(void) st_setstring(dynstr, sdp->sd_name,
847d840867fSab 				    &stoff);
8489039eeafSab 				ldynsym[ldynsym_ndx].st_name = stoff;
8499039eeafSab 
8509039eeafSab 				if (_symshndx && ldynshndx)
8519039eeafSab 					ldynshndx[ldynsym_ndx] = *_symshndx;
8529039eeafSab 
853d579eb63Sab 				/* Add it to sort section if it qualifies */
854d579eb63Sab 				ADD_TO_DYNSORT(sdp, sym, type, ldynsym_ndx);
855d579eb63Sab 
8569039eeafSab 				ldynsym_ndx++;
8579039eeafSab 			}
8587c478bd9Sstevel@tonic-gate 		}
85908278a5eSRod Evans 
86008278a5eSRod Evans 		/*
86108278a5eSRod Evans 		 * If this input file has undergone object to symbol
86208278a5eSRod Evans 		 * capabilities conversion, supply any new capabilities symbols.
86308278a5eSRod Evans 		 * These symbols are copies of the original global symbols, and
86408278a5eSRod Evans 		 * follow the existing local symbols that are supplied from this
86508278a5eSRod Evans 		 * input file (which are identified with a preceding STT_FILE).
86608278a5eSRod Evans 		 */
86708278a5eSRod Evans 		if (symtab && cdp && cdp->ca_syms) {
86808278a5eSRod Evans 			Aliste		idx2;
86908278a5eSRod Evans 			Cap_sym		*csp;
87008278a5eSRod Evans 
87108278a5eSRod Evans 			for (APLIST_TRAVERSE(cdp->ca_syms, idx2, csp)) {
87208278a5eSRod Evans 				Is_desc	*isp;
87308278a5eSRod Evans 
87408278a5eSRod Evans 				sdp = csp->cs_sdp;
87508278a5eSRod Evans 				sym = sdp->sd_sym;
87608278a5eSRod Evans 
87708278a5eSRod Evans 				if ((isp = sdp->sd_isc) != NULL) {
87808278a5eSRod Evans 					Os_desc	*osp = isp->is_osdesc;
87908278a5eSRod Evans 
88008278a5eSRod Evans 					/*
88108278a5eSRod Evans 					 * Update the symbols value.
88208278a5eSRod Evans 					 */
88308278a5eSRod Evans 					/* LINTED */
88408278a5eSRod Evans 					sym->st_value +=
88508278a5eSRod Evans 					    (Off)_elf_getxoff(isp->is_indata);
88608278a5eSRod Evans 					if ((flags & FLG_OF_RELOBJ) == 0)
88708278a5eSRod Evans 						sym->st_value +=
88808278a5eSRod Evans 						    osp->os_shdr->sh_addr;
88908278a5eSRod Evans 
89008278a5eSRod Evans 					/*
89108278a5eSRod Evans 					 * Update the symbols section index.
89208278a5eSRod Evans 					 */
89308278a5eSRod Evans 					sdp->sd_shndx = sym->st_shndx =
89408278a5eSRod Evans 					    elf_ndxscn(osp->os_scn);
89508278a5eSRod Evans 				}
89608278a5eSRod Evans 
89708278a5eSRod Evans 				symtab[symtab_ndx] = *sym;
89808278a5eSRod Evans 				(void) st_setstring(strtab, sdp->sd_name,
89908278a5eSRod Evans 				    &stoff);
90008278a5eSRod Evans 				symtab[symtab_ndx].st_name = stoff;
90108278a5eSRod Evans 				sdp->sd_symndx = symtab_ndx++;
90208278a5eSRod Evans 			}
90308278a5eSRod Evans 		}
9047c478bd9Sstevel@tonic-gate 	}
90508278a5eSRod Evans 
906ca4eed8bSAli Bahrami 	symtab_gbl_bndx = symtab_ndx;	/* .symtab index of 1st global entry */
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	/*
9097c478bd9Sstevel@tonic-gate 	 * Two special symbols are `_init' and `_fini'.  If these are supplied
9107c478bd9Sstevel@tonic-gate 	 * by crti.o then they are used to represent the total concatenation of
911c1c6f601Srie 	 * the `.init' and `.fini' sections.
912c1c6f601Srie 	 *
913635216b6SRod Evans 	 * Determine whether any .init or .fini sections exist.  If these
914635216b6SRod Evans 	 * sections exist and a dynamic object is being built, but no `_init'
915635216b6SRod Evans 	 * or `_fini' symbols are found, then the user is probably building
916635216b6SRod Evans 	 * this object directly from ld(1) rather than using a compiler driver
917635216b6SRod Evans 	 * that provides the symbols via crt's.
918c1c6f601Srie 	 *
919c1c6f601Srie 	 * If the .init or .fini section exist, and their associated symbols,
920c1c6f601Srie 	 * determine the size of the sections and updated the symbols value
921c1c6f601Srie 	 * accordingly.
9227c478bd9Sstevel@tonic-gate 	 */
9235aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U), SYM_NOHASH, 0,
9247c478bd9Sstevel@tonic-gate 	    ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc &&
925c1c6f601Srie 	    (sdp->sd_isc->is_osdesc == iosp)) {
9265aefb655Srie 		if (ld_sym_copy(sdp) == S_ERROR)
9277c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
92860758829Srie 		sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size;
92960758829Srie 
930c1c6f601Srie 	} else if (iosp && !(flags & FLG_OF_RELOBJ)) {
9311007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT),
932c1c6f601Srie 		    MSG_ORIG(MSG_SYM_INIT_U), MSG_ORIG(MSG_SCN_INIT));
9337c478bd9Sstevel@tonic-gate 	}
934c1c6f601Srie 
9355aefb655Srie 	if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U), SYM_NOHASH, 0,
9367c478bd9Sstevel@tonic-gate 	    ofl)) != NULL) && (sdp->sd_ref == REF_REL_NEED) && sdp->sd_isc &&
937c1c6f601Srie 	    (sdp->sd_isc->is_osdesc == fosp)) {
9385aefb655Srie 		if (ld_sym_copy(sdp) == S_ERROR)
9397c478bd9Sstevel@tonic-gate 			return ((Addr)S_ERROR);
94060758829Srie 		sdp->sd_sym->st_size = sdp->sd_isc->is_osdesc->os_shdr->sh_size;
94160758829Srie 
942c1c6f601Srie 	} else if (fosp && !(flags & FLG_OF_RELOBJ)) {
9431007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_NOCRT),
944c1c6f601Srie 		    MSG_ORIG(MSG_SYM_FINI_U), MSG_ORIG(MSG_SCN_FINI));
9457c478bd9Sstevel@tonic-gate 	}
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	/*
9487c478bd9Sstevel@tonic-gate 	 * Assign .bss information for use with updating COMMON symbols.
9497c478bd9Sstevel@tonic-gate 	 */
9507c478bd9Sstevel@tonic-gate 	if (ofl->ofl_isbss) {
95157ef7aa9SRod Evans 		isc = ofl->ofl_isbss;
95257ef7aa9SRod Evans 		osp = isc->is_osdesc;
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 		bssaddr = osp->os_shdr->sh_addr +
95557ef7aa9SRod Evans 		    (Off)_elf_getxoff(isc->is_indata);
9567c478bd9Sstevel@tonic-gate 		/* LINTED */
9577c478bd9Sstevel@tonic-gate 		bssndx = elf_ndxscn(osp->os_scn);
9587c478bd9Sstevel@tonic-gate 	}
9597c478bd9Sstevel@tonic-gate 
960ba2be530Sab #if	defined(_ELF64)
96154d82594Sseizo 	/*
962ba2be530Sab 	 * For amd64 target, assign .lbss information for use
963ba2be530Sab 	 * with updating LCOMMON symbols.
96454d82594Sseizo 	 */
965ba2be530Sab 	if ((ld_targ.t_m.m_mach == EM_AMD64) && ofl->ofl_islbss) {
96654d82594Sseizo 		osp = ofl->ofl_islbss->is_osdesc;
96754d82594Sseizo 
96854d82594Sseizo 		lbssaddr = osp->os_shdr->sh_addr +
969d840867fSab 		    (Off)_elf_getxoff(ofl->ofl_islbss->is_indata);
97054d82594Sseizo 		/* LINTED */
97154d82594Sseizo 		lbssndx = elf_ndxscn(osp->os_scn);
97254d82594Sseizo 	}
97354d82594Sseizo #endif
9747c478bd9Sstevel@tonic-gate 	/*
9757c478bd9Sstevel@tonic-gate 	 * Assign .tlsbss information for use with updating COMMON symbols.
9767c478bd9Sstevel@tonic-gate 	 */
9777c478bd9Sstevel@tonic-gate 	if (ofl->ofl_istlsbss) {
9787c478bd9Sstevel@tonic-gate 		osp = ofl->ofl_istlsbss->is_osdesc;
9797c478bd9Sstevel@tonic-gate 		tlsbssaddr = osp->os_shdr->sh_addr +
980d840867fSab 		    (Off)_elf_getxoff(ofl->ofl_istlsbss->is_indata);
9817c478bd9Sstevel@tonic-gate 		/* LINTED */
9827c478bd9Sstevel@tonic-gate 		tlsbssndx = elf_ndxscn(osp->os_scn);
9837c478bd9Sstevel@tonic-gate 	}
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	if ((sorted_syms = libld_calloc(ofl->ofl_globcnt +
98657ef7aa9SRod Evans