xref: /illumos-gate/usr/src/cmd/sgs/libld/common/syms.c (revision fb12490a)
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  *
267c478bd9Sstevel@tonic-gate  *
27bf994817SAli Bahrami  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Symbol table management routines
327c478bd9Sstevel@tonic-gate  */
33ba2be530Sab 
34ba2be530Sab #define	ELF_TARGET_AMD64
35ba2be530Sab 
36a8facf26SRichard Lowe /* We deliberately choose a locale unaware ctype */
37a8facf26SRichard Lowe #include	<sys/ctype.h>
38a8facf26SRichard Lowe 
397c478bd9Sstevel@tonic-gate #include	<stdio.h>
407c478bd9Sstevel@tonic-gate #include	<string.h>
415aefb655Srie #include	<debug.h>
427c478bd9Sstevel@tonic-gate #include	"msg.h"
437c478bd9Sstevel@tonic-gate #include	"_libld.h"
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * AVL tree comparator function:
477c478bd9Sstevel@tonic-gate  *
486b3ba5bdSAli Bahrami  * The primary key is the symbol name hash with a secondary key of the symbol
496b3ba5bdSAli Bahrami  * name itself.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate int
ld_sym_avl_comp(const void * elem1,const void * elem2)525aefb655Srie ld_sym_avl_comp(const void *elem1, const void *elem2)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	Sym_avlnode	*sav1 = (Sym_avlnode *)elem1;
557c478bd9Sstevel@tonic-gate 	Sym_avlnode	*sav2 = (Sym_avlnode *)elem2;
566b3ba5bdSAli Bahrami 	int		res;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	res = sav1->sav_hash - sav2->sav_hash;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	if (res < 0)
617c478bd9Sstevel@tonic-gate 		return (-1);
627c478bd9Sstevel@tonic-gate 	if (res > 0)
637c478bd9Sstevel@tonic-gate 		return (1);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	/*
667c478bd9Sstevel@tonic-gate 	 * Hash is equal - now compare name
677c478bd9Sstevel@tonic-gate 	 */
687c478bd9Sstevel@tonic-gate 	res = strcmp(sav1->sav_name, sav2->sav_name);
697c478bd9Sstevel@tonic-gate 	if (res == 0)
707c478bd9Sstevel@tonic-gate 		return (0);
717c478bd9Sstevel@tonic-gate 	if (res > 0)
727c478bd9Sstevel@tonic-gate 		return (1);
737c478bd9Sstevel@tonic-gate 	return (-1);
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate  * Focal point for verifying symbol names.
787c478bd9Sstevel@tonic-gate  */
79a194faf8Srie inline static const char *
string(Ofl_desc * ofl,Ifl_desc * ifl,Sym * sym,const char * strs,size_t strsize,int symndx,Word shndx,Word symsecndx,const char * symsecname,const char * strsecname,sd_flag_t * flags)805aefb655Srie string(Ofl_desc *ofl, Ifl_desc *ifl, Sym *sym, const char *strs, size_t strsize,
814a8d0ea7SAli Bahrami     int symndx, Word shndx, Word symsecndx, const char *symsecname,
82635216b6SRod Evans     const char *strsecname, sd_flag_t *flags)
837c478bd9Sstevel@tonic-gate {
846b3ba5bdSAli Bahrami 	Word	name = sym->st_name;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	if (name) {
877c478bd9Sstevel@tonic-gate 		if ((ifl->ifl_flags & FLG_IF_HSTRTAB) == 0) {
881007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_FIL_NOSTRTABLE),
891007fd6fSAli Bahrami 			    ifl->ifl_name, EC_WORD(symsecndx), symsecname,
901007fd6fSAli Bahrami 			    symndx, EC_XWORD(name));
916b3ba5bdSAli Bahrami 			return (NULL);
927c478bd9Sstevel@tonic-gate 		}
937c478bd9Sstevel@tonic-gate 		if (name >= (Word)strsize) {
941007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL,
955aefb655Srie 			    MSG_INTL(MSG_FIL_EXCSTRTABLE), ifl->ifl_name,
964a8d0ea7SAli Bahrami 			    EC_WORD(symsecndx), symsecname, symndx,
974a8d0ea7SAli Bahrami 			    EC_XWORD(name), strsecname, EC_XWORD(strsize));
986b3ba5bdSAli Bahrami 			return (NULL);
997c478bd9Sstevel@tonic-gate 		}
1007c478bd9Sstevel@tonic-gate 	}
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	/*
1037c478bd9Sstevel@tonic-gate 	 * Determine if we're dealing with a register and if so validate it.
1047c478bd9Sstevel@tonic-gate 	 * If it's a scratch register, a fabricated name will be returned.
1057c478bd9Sstevel@tonic-gate 	 */
106ba2be530Sab 	if (ld_targ.t_ms.ms_is_regsym != NULL) {
107ba2be530Sab 		const char *regname = (*ld_targ.t_ms.ms_is_regsym)(ofl, ifl,
108ba2be530Sab 		    sym, strs, symndx, shndx, symsecname, flags);
109ba2be530Sab 
110ba2be530Sab 		if (regname == (const char *)S_ERROR) {
1116b3ba5bdSAli Bahrami 			return (NULL);
112ba2be530Sab 		}
113ba2be530Sab 		if (regname)
114ba2be530Sab 			return (regname);
1157c478bd9Sstevel@tonic-gate 	}
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	/*
1187c478bd9Sstevel@tonic-gate 	 * If this isn't a register, but we have a global symbol with a null
1197c478bd9Sstevel@tonic-gate 	 * name, we're not going to be able to hash this, search for it, or
1207c478bd9Sstevel@tonic-gate 	 * do anything interesting.  However, we've been accepting a symbol of
1217c478bd9Sstevel@tonic-gate 	 * this kind for ages now, so give the user a warning (rather than a
1227c478bd9Sstevel@tonic-gate 	 * fatal error), just in case this instance exists somewhere in the
1237c478bd9Sstevel@tonic-gate 	 * world and hasn't, as yet, been a problem.
1247c478bd9Sstevel@tonic-gate 	 */
1257c478bd9Sstevel@tonic-gate 	if ((name == 0) && (ELF_ST_BIND(sym->st_info) != STB_LOCAL)) {
1261007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_FIL_NONAMESYM),
1274a8d0ea7SAli Bahrami 		    ifl->ifl_name, EC_WORD(symsecndx), symsecname, symndx,
1284a8d0ea7SAli Bahrami 		    EC_XWORD(name));
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 	return (strs + name);
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
133ba2be530Sab /*
134ba2be530Sab  * For producing symbol names strings to use in error messages.
135ba2be530Sab  * If the symbol has a non-null name, then the string returned by
136ba2be530Sab  * this function is the output from demangle(), surrounded by
137ba2be530Sab  * single quotes. For null names, a descriptive string giving
138ba2be530Sab  * the symbol section and index is generated.
139ba2be530Sab  *
140ba2be530Sab  * This function uses an internal static buffer to hold the resulting
141ba2be530Sab  * string. The value returned is usable by the caller until the next
142ba2be530Sab  * call, at which point it is overwritten.
143ba2be530Sab  */
144ba2be530Sab static const char *
demangle_symname(const char * name,const char * symtab_name,Word symndx)145ba2be530Sab demangle_symname(const char *name, const char *symtab_name, Word symndx)
146ba2be530Sab {
147ba2be530Sab #define	INIT_BUFSIZE 256
148ba2be530Sab 
1496b3ba5bdSAli Bahrami 	static char	*buf;
1506b3ba5bdSAli Bahrami 	static size_t	bufsize = 0;
151ba2be530Sab 	size_t		len;
152ba2be530Sab 	int		use_name;
153ba2be530Sab 
154ba2be530Sab 	use_name = (name != NULL) && (*name != '\0');
155ba2be530Sab 
156ba2be530Sab 	if (use_name) {
157ba2be530Sab 		name = demangle(name);
158ba2be530Sab 		len = strlen(name) + 2;   /* Include room for quotes */
159ba2be530Sab 	} else {
160ba2be530Sab 		name = MSG_ORIG(MSG_STR_EMPTY);
1614f680cc6SAli Bahrami 		len = strlen(symtab_name) + 2 + CONV_INV_BUFSIZE;
162ba2be530Sab 	}
163ba2be530Sab 	len++;			/* Null termination */
164ba2be530Sab 
165ba2be530Sab 	/* If our buffer is too small, double it until it is big enough */
166ba2be530Sab 	if (len > bufsize) {
167ba2be530Sab 		size_t	new_bufsize = bufsize;
168ba2be530Sab 		char	*new_buf;
169ba2be530Sab 
170ba2be530Sab 		if (new_bufsize == 0)
171ba2be530Sab 			new_bufsize = INIT_BUFSIZE;
172ba2be530Sab 		while (len > new_bufsize)
173ba2be530Sab 			new_bufsize *= 2;
1746b3ba5bdSAli Bahrami 		if ((new_buf = libld_malloc(new_bufsize)) == NULL)
175ba2be530Sab 			return (name);
176ba2be530Sab 		buf = new_buf;
177ba2be530Sab 		bufsize = new_bufsize;
178ba2be530Sab 	}
179ba2be530Sab 
180ba2be530Sab 	if (use_name) {
181ba2be530Sab 		(void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_SYMNAM), name);
182ba2be530Sab 	} else {
183ba2be530Sab 		(void) snprintf(buf, bufsize, MSG_ORIG(MSG_FMT_NULLSYMNAM),
184ba2be530Sab 		    symtab_name, EC_WORD(symndx));
185ba2be530Sab 	}
186ba2be530Sab 
187ba2be530Sab 	return (buf);
188ba2be530Sab 
189ba2be530Sab #undef INIT_BUFSIZE
190ba2be530Sab }
191ba2be530Sab 
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate  * Shared objects can be built that define specific symbols that can not be
1947c478bd9Sstevel@tonic-gate  * directly bound to.  These objects have a syminfo section (and an associated
1957c478bd9Sstevel@tonic-gate  * DF_1_NODIRECT dynamic flags entry).  Scan this table looking for symbols
1967c478bd9Sstevel@tonic-gate  * that can't be bound to directly, and if this files symbol is presently
1977c478bd9Sstevel@tonic-gate  * referenced, mark it so that we don't directly bind to it.
1987c478bd9Sstevel@tonic-gate  */
1997c478bd9Sstevel@tonic-gate uintptr_t
ld_sym_nodirect(Is_desc * isp,Ifl_desc * ifl,Ofl_desc * ofl)2009a411307Srie ld_sym_nodirect(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl)
2017c478bd9Sstevel@tonic-gate {
2027c478bd9Sstevel@tonic-gate 	Shdr		*sifshdr, *symshdr;
2037c478bd9Sstevel@tonic-gate 	Syminfo		*sifdata;
2047c478bd9Sstevel@tonic-gate 	Sym		*symdata;
2057c478bd9Sstevel@tonic-gate 	char		*strdata;
2067c478bd9Sstevel@tonic-gate 	ulong_t		cnt, _cnt;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	/*
2097c478bd9Sstevel@tonic-gate 	 * Get the syminfo data, and determine the number of entries.
2107c478bd9Sstevel@tonic-gate 	 */
2117c478bd9Sstevel@tonic-gate 	sifshdr = isp->is_shdr;
2127c478bd9Sstevel@tonic-gate 	sifdata = (Syminfo *)isp->is_indata->d_buf;
2137c478bd9Sstevel@tonic-gate 	cnt =  sifshdr->sh_size / sifshdr->sh_entsize;
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	/*
2167c478bd9Sstevel@tonic-gate 	 * Get the associated symbol table.
2177c478bd9Sstevel@tonic-gate 	 */
21828bda19cSRod Evans 	if ((sifshdr->sh_link == 0) || (sifshdr->sh_link >= ifl->ifl_shnum)) {
21928bda19cSRod Evans 		/*
22028bda19cSRod Evans 		 * Broken input file
22128bda19cSRod Evans 		 */
2221007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_FIL_INVSHINFO),
22328bda19cSRod Evans 		    ifl->ifl_name, isp->is_name, EC_XWORD(sifshdr->sh_link));
22428bda19cSRod Evans 		return (0);
22528bda19cSRod Evans 	}
2267c478bd9Sstevel@tonic-gate 	symshdr = ifl->ifl_isdesc[sifshdr->sh_link]->is_shdr;
2277c478bd9Sstevel@tonic-gate 	symdata = ifl->ifl_isdesc[sifshdr->sh_link]->is_indata->d_buf;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	/*
2307c478bd9Sstevel@tonic-gate 	 * Get the string table associated with the symbol table.
2317c478bd9Sstevel@tonic-gate 	 */
2327c478bd9Sstevel@tonic-gate 	strdata = ifl->ifl_isdesc[symshdr->sh_link]->is_indata->d_buf;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	/*
2357c478bd9Sstevel@tonic-gate 	 * Traverse the syminfo data for symbols that can't be directly
2367c478bd9Sstevel@tonic-gate 	 * bound to.
2377c478bd9Sstevel@tonic-gate 	 */
2387c478bd9Sstevel@tonic-gate 	for (_cnt = 1, sifdata++; _cnt < cnt; _cnt++, sifdata++) {
2397c478bd9Sstevel@tonic-gate 		Sym		*sym;
2407c478bd9Sstevel@tonic-gate 		char		*str;
2417c478bd9Sstevel@tonic-gate 		Sym_desc	*sdp;
2427c478bd9Sstevel@tonic-gate 
2433c4993fbSrie 		if ((sifdata->si_flags & SYMINFO_FLG_NOEXTDIRECT) == 0)
2447c478bd9Sstevel@tonic-gate 			continue;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 		sym = (Sym *)(symdata + _cnt);
2477c478bd9Sstevel@tonic-gate 		str = (char *)(strdata + sym->st_name);
2487c478bd9Sstevel@tonic-gate 
24928bda19cSRod Evans 		if ((sdp = ld_sym_find(str, SYM_NOHASH, NULL, ofl)) != NULL) {
2507c478bd9Sstevel@tonic-gate 			if (ifl != sdp->sd_file)
2517c478bd9Sstevel@tonic-gate 				continue;
2527c478bd9Sstevel@tonic-gate 
253635216b6SRod Evans 			sdp->sd_flags &= ~FLG_SY_DIR;
254635216b6SRod Evans 			sdp->sd_flags |= FLG_SY_NDIR;
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 	return (0);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /*
2617c478bd9Sstevel@tonic-gate  * If, during symbol processing, it is necessary to update a local symbols
2627c478bd9Sstevel@tonic-gate  * contents before we have generated the symbol tables in the output image,
2637c478bd9Sstevel@tonic-gate  * create a new symbol structure and copy the original symbol contents.  While
2647c478bd9Sstevel@tonic-gate  * we are processing the input files, their local symbols are part of the
2657c478bd9Sstevel@tonic-gate  * read-only mapped image.  Commonly, these symbols are copied to the new output
2667c478bd9Sstevel@tonic-gate  * file image and then updated to reflect their new address and any change in
2677c478bd9Sstevel@tonic-gate  * attributes.  However, sometimes during relocation counting, it is necessary
2687c478bd9Sstevel@tonic-gate  * to adjust the symbols information.  This routine provides for the generation
2697c478bd9Sstevel@tonic-gate  * of a new symbol image so that this update can be performed.
2707c478bd9Sstevel@tonic-gate  * All global symbols are copied to an internal symbol table to improve locality
2717c478bd9Sstevel@tonic-gate  * of reference and hence performance, and thus this copying is not necessary.
2727c478bd9Sstevel@tonic-gate  */
2737c478bd9Sstevel@tonic-gate uintptr_t
ld_sym_copy(Sym_desc * sdp)2745aefb655Srie ld_sym_copy(Sym_desc *sdp)
2757c478bd9Sstevel@tonic-gate {
2767c478bd9Sstevel@tonic-gate 	Sym	*nsym;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	if (sdp->sd_flags & FLG_SY_CLEAN) {
2796b3ba5bdSAli Bahrami 		if ((nsym = libld_malloc(sizeof (Sym))) == NULL)
2807c478bd9Sstevel@tonic-gate 			return (S_ERROR);
2817c478bd9Sstevel@tonic-gate 		*nsym = *(sdp->sd_sym);
2827c478bd9Sstevel@tonic-gate 		sdp->sd_sym = nsym;
2837c478bd9Sstevel@tonic-gate 		sdp->sd_flags &= ~FLG_SY_CLEAN;
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 	return (1);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate /*
2897c478bd9Sstevel@tonic-gate  * Finds a given name in the link editors internal symbol table.  If no
2907c478bd9Sstevel@tonic-gate  * hash value is specified it is calculated.  A pointer to the located
2917c478bd9Sstevel@tonic-gate  * Sym_desc entry is returned, or NULL if the symbol is not found.
2927c478bd9Sstevel@tonic-gate  */
2937c478bd9Sstevel@tonic-gate Sym_desc *
ld_sym_find(const char * name,Word hash,avl_index_t * where,Ofl_desc * ofl)2945aefb655Srie ld_sym_find(const char *name, Word hash, avl_index_t *where, Ofl_desc *ofl)
2957c478bd9Sstevel@tonic-gate {
2966b3ba5bdSAli Bahrami 	Sym_avlnode	qsav, *sav;
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	if (hash == SYM_NOHASH)
2997c478bd9Sstevel@tonic-gate 		/* LINTED */
3007c478bd9Sstevel@tonic-gate 		hash = (Word)elf_hash((const char *)name);
3017c478bd9Sstevel@tonic-gate 	qsav.sav_hash = hash;
3027c478bd9Sstevel@tonic-gate 	qsav.sav_name = name;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	/*
3057c478bd9Sstevel@tonic-gate 	 * Perform search for symbol in AVL tree.  Note that the 'where' field
3067c478bd9Sstevel@tonic-gate 	 * is passed in from the caller.  If a 'where' is present, it can be
307a194faf8Srie 	 * used in subsequent 'ld_sym_enter()' calls if required.
3087c478bd9Sstevel@tonic-gate 	 */
3097c478bd9Sstevel@tonic-gate 	sav = avl_find(&ofl->ofl_symavl, &qsav, where);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	/*
3127c478bd9Sstevel@tonic-gate 	 * If symbol was not found in the avl tree, return null to show that.
3137c478bd9Sstevel@tonic-gate 	 */
3146b3ba5bdSAli Bahrami 	if (sav == NULL)
3156b3ba5bdSAli Bahrami 		return (NULL);
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	/*
3187c478bd9Sstevel@tonic-gate 	 * Return symbol found.
3197c478bd9Sstevel@tonic-gate 	 */
320635216b6SRod Evans 	return (sav->sav_sdp);
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate 
323a8facf26SRichard Lowe /*
324a8facf26SRichard Lowe  * GCC sometimes emits local aliases for otherwise global symbols, such that
325a8facf26SRichard Lowe  * it has a guaranteed way to refer to a symbol from the current object
326a8facf26SRichard Lowe  * regardless of interposition.
327a8facf26SRichard Lowe  *
328a8facf26SRichard Lowe  * The only way we can match on these aliases is by them ending either
329a8facf26SRichard Lowe  * ".localalias" or ".localalias.N" where N is any integer.
330a8facf26SRichard Lowe  */
331a8facf26SRichard Lowe static inline Boolean
is_gcc_localalias(Sym_desc * sdp)332a8facf26SRichard Lowe is_gcc_localalias(Sym_desc *sdp)
333a8facf26SRichard Lowe {
334a8facf26SRichard Lowe 	char *p;
335a8facf26SRichard Lowe 
336a8facf26SRichard Lowe 	if (ELF_ST_BIND(sdp->sd_sym->st_info) != STB_LOCAL)
337a8facf26SRichard Lowe 		return (FALSE);
338a8facf26SRichard Lowe 
339a8facf26SRichard Lowe 	if ((p = strstr(sdp->sd_name, MSG_ORIG(MSG_SYM_LOCALALIAS))) != NULL) {
340a8facf26SRichard Lowe 		p += MSG_SYM_LOCALALIAS_SIZE;
341a8facf26SRichard Lowe 		switch (*p++) {
342a8facf26SRichard Lowe 		case '\0':			/* unnumbered */
343a8facf26SRichard Lowe 			return (TRUE);
344a8facf26SRichard Lowe 		case '.':			/* numbered? */
345a8facf26SRichard Lowe 			if (*p == '\0')		/* no integer */
346a8facf26SRichard Lowe 				return (FALSE);
347a8facf26SRichard Lowe 			while (ISDIGIT(*p))	/* skip integer */
348a8facf26SRichard Lowe 				p++;
349a8facf26SRichard Lowe 			if (*p != '\0')		/* non-integer chars */
350a8facf26SRichard Lowe 				return (FALSE);
351a8facf26SRichard Lowe 			return (TRUE);
352a8facf26SRichard Lowe 		}
353a8facf26SRichard Lowe 	}
354a8facf26SRichard Lowe 
355a8facf26SRichard Lowe 	return (FALSE);
356a8facf26SRichard Lowe }
357a8facf26SRichard Lowe 
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate  * Enter a new symbol into the link editors internal symbol table.
3607c478bd9Sstevel@tonic-gate  * If the symbol is from an input file, information regarding the input file
3617c478bd9Sstevel@tonic-gate  * and input section is also recorded.  Otherwise (file == NULL) the symbol
3627c478bd9Sstevel@tonic-gate  * has been internally generated (ie. _etext, _edata, etc.).
3637c478bd9Sstevel@tonic-gate  */
3647c478bd9Sstevel@tonic-gate Sym_desc *
ld_sym_enter(const char * name,Sym * osym,Word hash,Ifl_desc * ifl,Ofl_desc * ofl,Word ndx,Word shndx,sd_flag_t sdflags,avl_index_t * where)3655aefb655Srie ld_sym_enter(const char *name, Sym *osym, Word hash, Ifl_desc *ifl,
366635216b6SRod Evans     Ofl_desc *ofl, Word ndx, Word shndx, sd_flag_t sdflags, avl_index_t *where)
3677c478bd9Sstevel@tonic-gate {
3687c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
3697c478bd9Sstevel@tonic-gate 	Sym_aux		*sap;
3707c478bd9Sstevel@tonic-gate 	Sym_avlnode	*savl;
3717c478bd9Sstevel@tonic-gate 	char		*_name;
3727c478bd9Sstevel@tonic-gate 	Sym		*nsym;
3737c478bd9Sstevel@tonic-gate 	Half		etype;
37460758829Srie 	uchar_t		vis;
3757c478bd9Sstevel@tonic-gate 	avl_index_t	_where;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	/*
3787c478bd9Sstevel@tonic-gate 	 * Establish the file type.
3797c478bd9Sstevel@tonic-gate 	 */
3807c478bd9Sstevel@tonic-gate 	if (ifl)
3817c478bd9Sstevel@tonic-gate 		etype = ifl->ifl_ehdr->e_type;
3827c478bd9Sstevel@tonic-gate 	else
3837c478bd9Sstevel@tonic-gate 		etype = ET_NONE;
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	ofl->ofl_entercnt++;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/*
3887c478bd9Sstevel@tonic-gate 	 * Allocate a Sym Descriptor, Auxiliary Descriptor, and a Sym AVLNode -
3897c478bd9Sstevel@tonic-gate 	 * contiguously.
3907c478bd9Sstevel@tonic-gate 	 */
391*fb12490aSRichard Lowe 	if ((savl = libld_calloc(1, S_DROUND(sizeof (Sym_avlnode)) +
392635216b6SRod Evans 	    S_DROUND(sizeof (Sym_desc)) +
393*fb12490aSRichard Lowe 	    S_DROUND(sizeof (Sym_aux)))) == NULL)
3947c478bd9Sstevel@tonic-gate 		return ((Sym_desc *)S_ERROR);
395635216b6SRod Evans 	sdp = (Sym_desc *)((uintptr_t)savl +
396635216b6SRod Evans 	    S_DROUND(sizeof (Sym_avlnode)));
397635216b6SRod Evans 	sap = (Sym_aux *)((uintptr_t)sdp +
398635216b6SRod Evans 	    S_DROUND(sizeof (Sym_desc)));
3997c478bd9Sstevel@tonic-gate 
400635216b6SRod Evans 	savl->sav_sdp = sdp;
4017c478bd9Sstevel@tonic-gate 	sdp->sd_file = ifl;
4027c478bd9Sstevel@tonic-gate 	sdp->sd_aux = sap;
4037c478bd9Sstevel@tonic-gate 	savl->sav_hash = sap->sa_hash = hash;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/*
4067c478bd9Sstevel@tonic-gate 	 * Copy the symbol table entry from the input file into the internal
4077c478bd9Sstevel@tonic-gate 	 * entry and have the symbol descriptor use it.
4087c478bd9Sstevel@tonic-gate 	 */
4097c478bd9Sstevel@tonic-gate 	sdp->sd_sym = nsym = &sap->sa_sym;
4107c478bd9Sstevel@tonic-gate 	*nsym = *osym;
4117c478bd9Sstevel@tonic-gate 	sdp->sd_shndx = shndx;
4127c478bd9Sstevel@tonic-gate 	sdp->sd_flags |= sdflags;
4137c478bd9Sstevel@tonic-gate 
4146b3ba5bdSAli Bahrami 	if ((_name = libld_malloc(strlen(name) + 1)) == NULL)
4157c478bd9Sstevel@tonic-gate 		return ((Sym_desc *)S_ERROR);
4167c478bd9Sstevel@tonic-gate 	savl->sav_name = sdp->sd_name = (const char *)strcpy(_name, name);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	/*
4197c478bd9Sstevel@tonic-gate 	 * Enter Symbol in AVL tree.
4207c478bd9Sstevel@tonic-gate 	 */
4217c478bd9Sstevel@tonic-gate 	if (where == 0) {
4227c478bd9Sstevel@tonic-gate 		/* LINTED */
4237c478bd9Sstevel@tonic-gate 		Sym_avlnode	*_savl;
4247c478bd9Sstevel@tonic-gate 		/*
4255aefb655Srie 		 * If a previous ld_sym_find() hasn't initialized 'where' do it
4267c478bd9Sstevel@tonic-gate 		 * now.
4277c478bd9Sstevel@tonic-gate 		 */
4287c478bd9Sstevel@tonic-gate 		where = &_where;
4297c478bd9Sstevel@tonic-gate 		_savl = avl_find(&ofl->ofl_symavl, savl, where);
4306b3ba5bdSAli Bahrami 		assert(_savl == NULL);
4317c478bd9Sstevel@tonic-gate 	}
4327c478bd9Sstevel@tonic-gate 	avl_insert(&ofl->ofl_symavl, savl, *where);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 	/*
4357c478bd9Sstevel@tonic-gate 	 * Record the section index.  This is possible because the
4367c478bd9Sstevel@tonic-gate 	 * `ifl_isdesc' table is filled before we start symbol processing.
4377c478bd9Sstevel@tonic-gate 	 */
4380bc07c75Srie 	if ((sdflags & FLG_SY_SPECSEC) || (nsym->st_shndx == SHN_UNDEF))
4397c478bd9Sstevel@tonic-gate 		sdp->sd_isc = NULL;
4407c478bd9Sstevel@tonic-gate 	else {
4417c478bd9Sstevel@tonic-gate 		sdp->sd_isc = ifl->ifl_isdesc[shndx];
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 		/*
4447c478bd9Sstevel@tonic-gate 		 * If this symbol is from a relocatable object, make sure that
4457c478bd9Sstevel@tonic-gate 		 * it is still associated with a section.  For example, an
4467c478bd9Sstevel@tonic-gate 		 * unknown section type (SHT_NULL) would have been rejected on
4477c478bd9Sstevel@tonic-gate 		 * input with a warning.  Here, we make the use of the symbol
4487c478bd9Sstevel@tonic-gate 		 * fatal.  A symbol descriptor is still returned, so that the
4497c478bd9Sstevel@tonic-gate 		 * caller can continue processing all symbols, and hence flush
4507c478bd9Sstevel@tonic-gate 		 * out as many error conditions as possible.
4517c478bd9Sstevel@tonic-gate 		 */
4526b3ba5bdSAli Bahrami 		if ((etype == ET_REL) && (sdp->sd_isc == NULL)) {
4531007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_INVSEC),
4541007fd6fSAli Bahrami 			    name, ifl->ifl_name, EC_XWORD(shndx));
4557c478bd9Sstevel@tonic-gate 			return (sdp);
4567c478bd9Sstevel@tonic-gate 		}
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	/*
4607c478bd9Sstevel@tonic-gate 	 * Mark any COMMON symbols as 'tentative'.
4617c478bd9Sstevel@tonic-gate 	 */
46254d82594Sseizo 	if (sdflags & FLG_SY_SPECSEC) {
4630bc07c75Srie 		if (nsym->st_shndx == SHN_COMMON)
46454d82594Sseizo 			sdp->sd_flags |= FLG_SY_TENTSYM;
465ba2be530Sab #if	defined(_ELF64)
466ba2be530Sab 		else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
467ba2be530Sab 		    (nsym->st_shndx == SHN_X86_64_LCOMMON))
46854d82594Sseizo 			sdp->sd_flags |= FLG_SY_TENTSYM;
46954d82594Sseizo #endif
47054d82594Sseizo 	}
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/*
47360758829Srie 	 * Establish the symbols visibility and reference.
4747c478bd9Sstevel@tonic-gate 	 */
47560758829Srie 	vis = ELF_ST_VISIBILITY(nsym->st_other);
47660758829Srie 
4777c478bd9Sstevel@tonic-gate 	if ((etype == ET_NONE) || (etype == ET_REL)) {
47860758829Srie 		switch (vis) {
47960758829Srie 		case STV_DEFAULT:
480635216b6SRod Evans 			sdp->sd_flags |= FLG_SY_DEFAULT;
48160758829Srie 			break;
48260758829Srie 		case STV_INTERNAL:
48360758829Srie 		case STV_HIDDEN:
484635216b6SRod Evans 			sdp->sd_flags |= FLG_SY_HIDDEN;
48560758829Srie 			break;
48660758829Srie 		case STV_PROTECTED:
487635216b6SRod Evans 			sdp->sd_flags |= FLG_SY_PROTECT;
48860758829Srie 			break;
48960758829Srie 		case STV_EXPORTED:
490635216b6SRod Evans 			sdp->sd_flags |= FLG_SY_EXPORT;
49160758829Srie 			break;
49260758829Srie 		case STV_SINGLETON:
493635216b6SRod Evans 			sdp->sd_flags |= (FLG_SY_SINGLE | FLG_SY_NDIR);
49428bda19cSRod Evans 			ofl->ofl_flags1 |= (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
49560758829Srie 			break;
49660758829Srie 		case STV_ELIMINATE:
497635216b6SRod Evans 			sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
49860758829Srie 			break;
49960758829Srie 		default:
50060758829Srie 			assert(vis <= STV_ELIMINATE);
50160758829Srie 		}
50260758829Srie 
5037c478bd9Sstevel@tonic-gate 		sdp->sd_ref = REF_REL_NEED;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 		/*
5069a411307Srie 		 * Under -Bnodirect, all exported interfaces that have not
5079a411307Srie 		 * explicitly been defined protected or directly bound to, are
5089a411307Srie 		 * tagged to prevent direct binding.
5097c478bd9Sstevel@tonic-gate 		 */
5100bc07c75Srie 		if ((ofl->ofl_flags1 & FLG_OF1_ALNODIR) &&
511635216b6SRod Evans 		    ((sdp->sd_flags & (FLG_SY_PROTECT | FLG_SY_DIR)) == 0) &&
5129a411307Srie 		    (nsym->st_shndx != SHN_UNDEF)) {
513635216b6SRod Evans 			sdp->sd_flags |= FLG_SY_NDIR;
5149a411307Srie 		}
5157c478bd9Sstevel@tonic-gate 	} else {
5167c478bd9Sstevel@tonic-gate 		sdp->sd_ref = REF_DYN_SEEN;
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 		/*
51960758829Srie 		 * If this is a protected symbol, remember this.  Note, this
520635216b6SRod Evans 		 * state is different from the FLG_SY_PROTECT used to establish
52160758829Srie 		 * a symbol definitions visibility.  This state is used to warn
52260758829Srie 		 * against possible copy relocations against this referenced
52360758829Srie 		 * symbol.
5247c478bd9Sstevel@tonic-gate 		 */
52560758829Srie 		if (vis == STV_PROTECTED)
5267c478bd9Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_PROT;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 		/*
52960758829Srie 		 * If this is a SINGLETON definition, then indicate the symbol
53060758829Srie 		 * can not be directly bound to, and retain the visibility.
53160758829Srie 		 * This visibility will be inherited by any references made to
53260758829Srie 		 * this symbol.
5337c478bd9Sstevel@tonic-gate 		 */
53460758829Srie 		if ((vis == STV_SINGLETON) && (nsym->st_shndx != SHN_UNDEF))
535635216b6SRod Evans 			sdp->sd_flags |= (FLG_SY_SINGLE | FLG_SY_NDIR);
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 		/*
53860758829Srie 		 * If the new symbol is from a shared library and is associated
53960758829Srie 		 * with a SHT_NOBITS section then this symbol originated from a
54060758829Srie 		 * tentative symbol.
5417c478bd9Sstevel@tonic-gate 		 */
5427c478bd9Sstevel@tonic-gate 		if (sdp->sd_isc &&
5437c478bd9Sstevel@tonic-gate 		    (sdp->sd_isc->is_shdr->sh_type == SHT_NOBITS))
5447c478bd9Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_TENTSYM;
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	/*
5487c478bd9Sstevel@tonic-gate 	 * Reclassify any SHN_SUNW_IGNORE symbols to SHN_UNDEF so as to
5490bc07c75Srie 	 * simplify future processing.
5507c478bd9Sstevel@tonic-gate 	 */
5510bc07c75Srie 	if (nsym->st_shndx == SHN_SUNW_IGNORE) {
5527c478bd9Sstevel@tonic-gate 		sdp->sd_shndx = shndx = SHN_UNDEF;
553635216b6SRod Evans 		sdp->sd_flags |= (FLG_SY_REDUCED |
554635216b6SRod Evans 		    FLG_SY_HIDDEN | FLG_SY_IGNORE | FLG_SY_ELIM);
5557c478bd9Sstevel@tonic-gate 	}
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	/*
5587c478bd9Sstevel@tonic-gate 	 * If this is an undefined, or common symbol from a relocatable object
5597c478bd9Sstevel@tonic-gate 	 * determine whether it is a global or weak reference (see build_osym(),
5607c478bd9Sstevel@tonic-gate 	 * where REF_DYN_NEED definitions are returned back to undefines).
5617c478bd9Sstevel@tonic-gate 	 */
56254d82594Sseizo 	if ((etype == ET_REL) &&
56354d82594Sseizo 	    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL) &&
5640bc07c75Srie 	    ((nsym->st_shndx == SHN_UNDEF) || ((sdflags & FLG_SY_SPECSEC) &&
565ba2be530Sab #if	defined(_ELF64)
5660bc07c75Srie 	    ((nsym->st_shndx == SHN_COMMON) ||
567ba2be530Sab 	    ((ld_targ.t_m.m_mach == EM_AMD64) &&
568ba2be530Sab 	    (nsym->st_shndx == SHN_X86_64_LCOMMON))))))
56954d82594Sseizo #else
57033eb6ee1Sab 	/* BEGIN CSTYLED */
5710bc07c75Srie 	    (nsym->st_shndx == SHN_COMMON))))
57233eb6ee1Sab 	/* END CSTYLED */
57354d82594Sseizo #endif
5747c478bd9Sstevel@tonic-gate 		sdp->sd_flags |= FLG_SY_GLOBREF;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	/*
5777c478bd9Sstevel@tonic-gate 	 * Record the input filename on the referenced or defined files list
5787c478bd9Sstevel@tonic-gate 	 * for possible later diagnostics.  The `sa_rfile' pointer contains the
5797c478bd9Sstevel@tonic-gate 	 * name of the file that first referenced this symbol and is used to
5807c478bd9Sstevel@tonic-gate 	 * generate undefined symbol diagnostics (refer to sym_undef_entry()).
5817c478bd9Sstevel@tonic-gate 	 * Note that this entry can be overridden if a reference from a
5827c478bd9Sstevel@tonic-gate 	 * relocatable object is found after a reference from a shared object
5837c478bd9Sstevel@tonic-gate 	 * (refer to sym_override()).
5847c478bd9Sstevel@tonic-gate 	 * The `sa_dfiles' list is used to maintain the list of files that
5857c478bd9Sstevel@tonic-gate 	 * define the same symbol.  This list can be used for two reasons:
5867c478bd9Sstevel@tonic-gate 	 *
58708278a5eSRod Evans 	 *  -	To save the first definition of a symbol that is not available
5887c478bd9Sstevel@tonic-gate 	 *	for this link-edit.
5897c478bd9Sstevel@tonic-gate 	 *
59008278a5eSRod Evans 	 *  -	To save all definitions of a symbol when the -m option is in
5917c478bd9Sstevel@tonic-gate 	 *	effect.  This is optional as it is used to list multiple
5927c478bd9Sstevel@tonic-gate 	 *	(interposed) definitions of a symbol (refer to ldmap_out()),
5937c478bd9Sstevel@tonic-gate 	 *	and can be quite expensive.
5947c478bd9Sstevel@tonic-gate 	 */
5950bc07c75Srie 	if (nsym->st_shndx == SHN_UNDEF) {
5967c478bd9Sstevel@tonic-gate 		sap->sa_rfile = ifl->ifl_name;
5977c478bd9Sstevel@tonic-gate 	} else {
5987c478bd9Sstevel@tonic-gate 		if (sdp->sd_ref == REF_DYN_SEEN) {
5997c478bd9Sstevel@tonic-gate 			/*
6007c478bd9Sstevel@tonic-gate 			 * A symbol is determined to be unavailable if it
6017c478bd9Sstevel@tonic-gate 			 * belongs to a version of a shared object that this
6027c478bd9Sstevel@tonic-gate 			 * user does not wish to use, or if it belongs to an
6037c478bd9Sstevel@tonic-gate 			 * implicit shared object.
6047c478bd9Sstevel@tonic-gate 			 */
6057c478bd9Sstevel@tonic-gate 			if (ifl->ifl_vercnt) {
6069039eeafSab 				Ver_index	*vip;
6077c478bd9Sstevel@tonic-gate 				Half		vndx = ifl->ifl_versym[ndx];
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 				sap->sa_dverndx = vndx;
6107c478bd9Sstevel@tonic-gate 				vip = &ifl->ifl_verndx[vndx];
6117c478bd9Sstevel@tonic-gate 				if (!(vip->vi_flags & FLG_VER_AVAIL)) {
6127c478bd9Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_NOTAVAIL;
6137c478bd9Sstevel@tonic-gate 					sap->sa_vfile = ifl->ifl_name;
6147c478bd9Sstevel@tonic-gate 				}
6157c478bd9Sstevel@tonic-gate 			}
6167c478bd9Sstevel@tonic-gate 			if (!(ifl->ifl_flags & FLG_IF_NEEDED))
6177c478bd9Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_NOTAVAIL;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 		} else if (etype == ET_REL) {
6207c478bd9Sstevel@tonic-gate 			/*
6217c478bd9Sstevel@tonic-gate 			 * If this symbol has been obtained from a versioned
6227c478bd9Sstevel@tonic-gate 			 * input relocatable object then the new symbol must be
6237c478bd9Sstevel@tonic-gate 			 * promoted to the versioning of the output file.
6247c478bd9Sstevel@tonic-gate 			 */
6257c478bd9Sstevel@tonic-gate 			if (ifl->ifl_versym)
6265aefb655Srie 				ld_vers_promote(sdp, ndx, ifl, ofl);
6277c478bd9Sstevel@tonic-gate 		}
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate 		if ((ofl->ofl_flags & FLG_OF_GENMAP) &&
6307c478bd9Sstevel@tonic-gate 		    ((sdflags & FLG_SY_SPECSEC) == 0))
63157ef7aa9SRod Evans 			if (aplist_append(&sap->sa_dfiles, ifl->ifl_name,
63257ef7aa9SRod Evans 			    AL_CNT_SDP_DFILES) == NULL)
6337c478bd9Sstevel@tonic-gate 				return ((Sym_desc *)S_ERROR);
6347c478bd9Sstevel@tonic-gate 	}
6357c478bd9Sstevel@tonic-gate 
63660758829Srie 	/*
63760758829Srie 	 * Provided we're not processing a mapfile, diagnose the entered symbol.
63860758829Srie 	 * Mapfile processing requires the symbol to be updated with additional
63960758829Srie 	 * information, therefore the diagnosing of the symbol is deferred until
64060758829Srie 	 * later (see Dbg_map_symbol()).
64160758829Srie 	 */
6426b3ba5bdSAli Bahrami 	if ((ifl == NULL) || ((ifl->ifl_flags & FLG_IF_MAPFILE) == 0))
64360758829Srie 		DBG_CALL(Dbg_syms_entered(ofl, nsym, sdp));
644635216b6SRod Evans 
6457c478bd9Sstevel@tonic-gate 	return (sdp);
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate /*
6497c478bd9Sstevel@tonic-gate  * Add a special symbol to the symbol table.  Takes special symbol name with
6507c478bd9Sstevel@tonic-gate  * and without underscores.  This routine is called, after all other symbol
6517c478bd9Sstevel@tonic-gate  * resolution has completed, to generate a reserved absolute symbol (the
6527c478bd9Sstevel@tonic-gate  * underscore version).  Special symbols are updated with the appropriate
653dd94ecefSrie  * values in update_osym().  If the user has already defined this symbol
6547c478bd9Sstevel@tonic-gate  * issue a warning and leave the symbol as is.  If the non-underscore symbol
6557c478bd9Sstevel@tonic-gate  * is referenced then turn it into a weak alias of the underscored symbol.
6567c478bd9Sstevel@tonic-gate  *
657635216b6SRod Evans  * The bits in sdflags_u are OR'd into the flags field of the symbol for the
658635216b6SRod Evans  * underscored symbol.
659d579eb63Sab  *
6607c478bd9Sstevel@tonic-gate  * If this is a global symbol, and it hasn't explicitly been defined as being
6617c478bd9Sstevel@tonic-gate  * directly bound to, indicate that it can't be directly bound to.
6627c478bd9Sstevel@tonic-gate  * Historically, most special symbols only have meaning to the object in which
663c1c6f601Srie  * they exist, however, they've always been global.  To ensure compatibility
664c1c6f601Srie  * with any unexpected use presently in effect, ensure these symbols don't get
6657c478bd9Sstevel@tonic-gate  * directly bound to.  Note, that establishing this state here isn't sufficient
6667c478bd9Sstevel@tonic-gate  * to create a syminfo table, only if a syminfo table is being created by some
667c1c6f601Srie  * other symbol directives will the nodirect binding be recorded.  This ensures
6687c478bd9Sstevel@tonic-gate  * we don't create syminfo sections for all objects we create, as this might add
6697c478bd9Sstevel@tonic-gate  * unnecessary bloat to users who haven't explicitly requested extra symbol
6707c478bd9Sstevel@tonic-gate  * information.
6717c478bd9Sstevel@tonic-gate  */
6727c478bd9Sstevel@tonic-gate static uintptr_t
sym_add_spec(const char * name,const char * uname,Word sdaux_id,sd_flag_t sdflags_u,sd_flag_t sdflags,Ofl_desc * ofl)6737c478bd9Sstevel@tonic-gate sym_add_spec(const char *name, const char *uname, Word sdaux_id,
674635216b6SRod Evans     sd_flag_t sdflags_u, sd_flag_t sdflags, Ofl_desc *ofl)
6757c478bd9Sstevel@tonic-gate {
6767c478bd9Sstevel@tonic-gate 	Sym_desc	*sdp;
677c524b4feSRichard Lowe 	Sym_desc	*usdp;
6787c478bd9Sstevel@tonic-gate 	Sym		*sym;
6797c478bd9Sstevel@tonic-gate 	Word		hash;
6807c478bd9Sstevel@tonic-gate 	avl_index_t	where;
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	/* LINTED */
6837c478bd9Sstevel@tonic-gate 	hash = (Word)elf_hash(uname);
6845aefb655Srie 	if (usdp = ld_sym_find(uname, hash, &where, ofl)) {
6857c478bd9Sstevel@tonic-gate 		/*
6867c478bd9Sstevel@tonic-gate 		 * If the underscore symbol exists and is undefined, or was
6877c478bd9Sstevel@tonic-gate 		 * defined in a shared library, convert it to a local symbol.
6887c478bd9Sstevel@tonic-gate 		 * Otherwise leave it as is and warn the user.
6897c478bd9Sstevel@tonic-gate 		 */
6907c478bd9Sstevel@tonic-gate 		if ((usdp->sd_shndx == SHN_UNDEF) ||
6917c478bd9Sstevel@tonic-gate 		    (usdp->sd_ref != REF_REL_NEED)) {
6927c478bd9Sstevel@tonic-gate 			usdp->sd_ref = REF_REL_NEED;
6937c478bd9Sstevel@tonic-gate 			usdp->sd_shndx = usdp->sd_sym->st_shndx = SHN_ABS;
694635216b6SRod Evans 			usdp->sd_flags |= FLG_SY_SPECSEC | sdflags_u;
6957c478bd9Sstevel@tonic-gate 			usdp->sd_sym->st_info =
6967c478bd9Sstevel@tonic-gate 			    ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
6977c478bd9Sstevel@tonic-gate 			usdp->sd_isc = NULL;
6987c478bd9Sstevel@tonic-gate 			usdp->sd_sym->st_size = 0;
6997c478bd9Sstevel@tonic-gate 			usdp->sd_sym->st_value = 0;
7007c478bd9Sstevel@tonic-gate 			/* LINTED */
7017c478bd9Sstevel@tonic-gate 			usdp->sd_aux->sa_symspec = (Half)sdaux_id;
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 			/*
7049a411307Srie 			 * If a user hasn't specifically indicated that the
7059a411307Srie 			 * scope of this symbol be made local, then leave it
7069a411307Srie 			 * as global (ie. prevent automatic scoping).  The GOT
7079a411307Srie 			 * should be defined protected, whereas all other
7089a411307Srie 			 * special symbols are tagged as no-direct.
7097c478bd9Sstevel@tonic-gate 			 */
71008278a5eSRod Evans 			if (!SYM_IS_HIDDEN(usdp) &&
711635216b6SRod Evans 			    (sdflags & FLG_SY_DEFAULT)) {
71233eb6ee1Sab 				usdp->sd_aux->sa_overndx = VER_NDX_GLOBAL;
71333eb6ee1Sab 				if (sdaux_id == SDAUX_ID_GOT) {
714635216b6SRod Evans 					usdp->sd_flags &= ~FLG_SY_NDIR;
715635216b6SRod Evans 					usdp->sd_flags |= FLG_SY_PROTECT;
71633eb6ee1Sab 					usdp->sd_sym->st_other = STV_PROTECTED;
71733eb6ee1Sab 				} else if (
718635216b6SRod Evans 				    ((usdp->sd_flags & FLG_SY_DIR) == 0) &&
71933eb6ee1Sab 				    ((ofl->ofl_flags & FLG_OF_SYMBOLIC) == 0)) {
720635216b6SRod Evans 					usdp->sd_flags |= FLG_SY_NDIR;
72133eb6ee1Sab 				}
7227c478bd9Sstevel@tonic-gate 			}
723635216b6SRod Evans 			usdp->sd_flags |= sdflags;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 			/*
726c1c6f601Srie 			 * If the reference originated from a mapfile ensure
7277c478bd9Sstevel@tonic-gate 			 * we mark the symbol as used.
7287c478bd9Sstevel@tonic-gate 			 */
7297c478bd9Sstevel@tonic-gate 			if (usdp->sd_flags & FLG_SY_MAPREF)
7307c478bd9Sstevel@tonic-gate 				usdp->sd_flags |= FLG_SY_MAPUSED;
7317c478bd9Sstevel@tonic-gate 
7325aefb655Srie 			DBG_CALL(Dbg_syms_updated(ofl, usdp, uname));
733b6a0e2cdSRichard Lowe 		} else {
7341007fd6fSAli Bahrami 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_RESERVE),
7351007fd6fSAli Bahrami 			    uname, usdp->sd_file->ifl_name);
736b6a0e2cdSRichard Lowe 		}
7377c478bd9Sstevel@tonic-gate 	} else {
7387c478bd9Sstevel@tonic-gate 		/*
7397c478bd9Sstevel@tonic-gate 		 * If the symbol does not exist create it.
7407c478bd9Sstevel@tonic-gate 		 */
741*fb12490aSRichard Lowe 		if ((sym = libld_calloc(1, sizeof (Sym))) == NULL)
7427c478bd9Sstevel@tonic-gate 			return (S_ERROR);
7437c478bd9Sstevel@tonic-gate 		sym->st_shndx = SHN_ABS;
7447c478bd9Sstevel@tonic-gate 		sym->st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
7457c478bd9Sstevel@tonic-gate 		sym->st_size = 0;
7467c478bd9Sstevel@tonic-gate 		sym->st_value = 0;
7475aefb655Srie 		DBG_CALL(Dbg_syms_created(ofl->ofl_lml, uname));
7485aefb655Srie 		if ((usdp = ld_sym_enter(uname, sym, hash, (Ifl_desc *)NULL,
749635216b6SRod Evans 		    ofl, 0, SHN_ABS, (FLG_SY_SPECSEC | sdflags_u), &where)) ==
7507c478bd9Sstevel@tonic-gate 		    (Sym_desc *)S_ERROR)
7517c478bd9Sstevel@tonic-gate 			return (S_ERROR);
7527c478bd9Sstevel@tonic-gate 		usdp->sd_ref = REF_REL_NEED;
7537c478bd9Sstevel@tonic-gate 		/* LINTED */
7547c478bd9Sstevel@tonic-gate 		usdp->sd_aux->sa_symspec = (Half)sdaux_id;
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 		usdp->sd_aux->sa_overndx = VER_NDX_GLOBAL;
7579a411307Srie 
7589a411307Srie 		if (sdaux_id == SDAUX_ID_GOT) {
759635216b6SRod Evans 			usdp->sd_flags |= FLG_SY_PROTECT;
7609a411307Srie 			usdp->sd_sym->st_other = STV_PROTECTED;
761635216b6SRod Evans 		} else if ((sdflags & FLG_SY_DEFAULT) &&
7629a411307Srie 		    ((ofl->ofl_flags & FLG_OF_SYMBOLIC) == 0)) {
763635216b6SRod Evans 			usdp->sd_flags |= FLG_SY_NDIR;
7649a411307Srie 		}
765635216b6SRod Evans 		usdp->sd_flags |= sdflags;
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
76828bda19cSRod Evans 	if (name && (sdp = ld_sym_find(name, SYM_NOHASH, NULL, ofl)) &&
7690bc07c75Srie 	    (sdp->sd_sym->st_shndx == SHN_UNDEF)) {
7707c478bd9Sstevel@tonic-gate 		uchar_t	bind;
7717c478bd9Sstevel@tonic-gate 
7727c478bd9Sstevel@tonic-gate 		/*
7737c478bd9Sstevel@tonic-gate 		 * If the non-underscore symbol exists and is undefined
7747c478bd9Sstevel@tonic-gate 		 * convert it to be a local.  If the underscore has
7757c478bd9Sstevel@tonic-gate 		 * sa_symspec set (ie. it was created above) then simulate this
7767c478bd9Sstevel@tonic-gate 		 * as a weak alias.
7777c478bd9Sstevel@tonic-gate 		 */
7787c478bd9Sstevel@tonic-gate 		sdp->sd_ref = REF_REL_NEED;
7797c478bd9Sstevel@tonic-gate 		sdp->sd_shndx = sdp->sd_sym->st_shndx = SHN_ABS;
7807c478bd9Sstevel@tonic-gate 		sdp->sd_flags |= FLG_SY_SPECSEC;
7817c478bd9Sstevel@tonic-gate 		sdp->sd_isc = NULL;
7827c478bd9Sstevel@tonic-gate 		sdp->sd_sym->st_size = 0;
7837c478bd9Sstevel@tonic-gate 		sdp->sd_sym->st_value = 0;
7847c478bd9Sstevel@tonic-gate 		/* LINTED */
7857c478bd9Sstevel@tonic-gate 		sdp->sd_aux->sa_symspec = (Half)sdaux_id;
7867c478bd9Sstevel@tonic-gate 		if (usdp->sd_aux->sa_symspec) {
7877c478bd9Sstevel@tonic-gate 			usdp->sd_aux->sa_linkndx = 0;
7887c478bd9Sstevel@tonic-gate 			sdp->sd_aux->sa_linkndx = 0;
7897c478bd9Sstevel@tonic-gate 			bind = STB_WEAK;
7907c478bd9Sstevel@tonic-gate 		} else
7917c478bd9Sstevel@tonic-gate 			bind = STB_GLOBAL;
7927c478bd9Sstevel@tonic-gate 		sdp->sd_sym->st_info = ELF_ST_INFO(bind, STT_OBJECT);
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 		/*
7959a411307Srie 		 * If a user hasn't specifically indicated the scope of this
7969a411307Srie 		 * symbol be made local then leave it as global (ie. prevent
7979a411307Srie 		 * automatic scoping).  The GOT should be defined protected,
7989a411307Srie 		 * whereas all other special symbols are tagged as no-direct.
7997c478bd9Sstevel@tonic-gate 		 */
80008278a5eSRod Evans 		if (!SYM_IS_HIDDEN(sdp) &&
801635216b6SRod Evans 		    (sdflags & FLG_SY_DEFAULT)) {
8027c478bd9Sstevel@tonic-gate 			sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL;
8039a411307Srie 			if (sdaux_id == SDAUX_ID_GOT) {
804635216b6SRod Evans 				sdp->sd_flags &= ~FLG_SY_NDIR;
805635216b6SRod Evans 				sdp->sd_flags |= FLG_SY_PROTECT;
8069a411307Srie 				sdp->sd_sym->st_other = STV_PROTECTED;
807635216b6SRod Evans 			} else if (((sdp->sd_flags & FLG_SY_DIR) == 0) &&
8089a411307Srie 			    ((ofl->ofl_flags & FLG_OF_SYMBOLIC) == 0)) {
809635216b6SRod Evans 				sdp->sd_flags |= FLG_SY_NDIR;
8109a411307Srie 			}
8117c478bd9Sstevel@tonic-gate 		}
812635216b6SRod Evans 		sdp->sd_flags |= sdflags;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 		/*
815c1c6f601Srie 		 * If the reference originated from a mapfile ensure
8167c478bd9Sstevel@tonic-gate 		 * we mark the symbol as used.
8177c478bd9Sstevel@tonic-gate 		 */
8187c478bd9Sstevel@tonic-gate 		if (sdp->sd_flags & FLG_SY_MAPREF)
8197c478bd9Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_MAPUSED;
8207c478bd9Sstevel@tonic-gate 
8215aefb655Srie 		DBG_CALL(Dbg_syms_updated(ofl, sdp, name));
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 	return (1);
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate /*
8287c478bd9Sstevel@tonic-gate  * Undefined symbols can fall into one of four types:
8297c478bd9Sstevel@tonic-gate  *
8306b3ba5bdSAli Bahrami  *  -	the symbol is really undefined (SHN_UNDEF).
8317c478bd9Sstevel@tonic-gate  *
8326b3ba5bdSAli Bahrami  *  -	versioning has been enabled, however this symbol has not been assigned
8337c478bd9Sstevel@tonic-gate  *	to one of the defined versions.
8347c478bd9Sstevel@tonic-gate  *
8356b3ba5bdSAli Bahrami  *  -	the symbol has been defined by an implicitly supplied library, ie. one
8367c478bd9Sstevel@tonic-gate  *	which was encounted because it was NEEDED by another library, rather
837c524b4feSRichard Lowe  *	than from a command line supplied library which would become the only
8387c478bd9Sstevel@tonic-gate  *	dependency of the output file being produced.
8397c478bd9Sstevel@tonic-gate  *
8406b3ba5bdSAli Bahrami  *  -	the symbol has been defined by a version of a shared object that is
8417c478bd9Sstevel@tonic-gate  *	not permitted for this link-edit.
8427c478bd9Sstevel@tonic-gate  *
8437c478bd9Sstevel@tonic-gate  * In all cases the file who made the first reference to this symbol will have
8447c478bd9Sstevel@tonic-gate  * been recorded via the `sa_rfile' pointer.
8457c478bd9Sstevel@tonic-gate  */
8467c478bd9Sstevel@tonic-gate typedef enum {
8477c478bd9Sstevel@tonic-gate 	UNDEF,		NOVERSION,	IMPLICIT,	NOTAVAIL,
8487c478bd9Sstevel@tonic-gate 	BNDLOCAL
8497c478bd9Sstevel@tonic-gate } Type;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate static const Msg format[] = {
8527c478bd9Sstevel@tonic-gate 	MSG_SYM_UND_UNDEF,		/* MSG_INTL(MSG_SYM_UND_UNDEF) */
8537c478bd9Sstevel@tonic-gate 	MSG_SYM_UND_NOVER,		/* MSG_INTL(MSG_SYM_UND_NOVER) */
8547c478bd9Sstevel@tonic-gate 	MSG_SYM_UND_IMPL,		/* MSG_INTL(MSG_SYM_UND_IMPL) */
8557c478bd9Sstevel@tonic-gate 	MSG_SYM_UND_NOTA,		/* MSG_INTL(MSG_SYM_UND_NOTA) */
8567c478bd9Sstevel@tonic-gate 	MSG_SYM_UND_BNDLOCAL		/* MSG_INTL(MSG_SYM_UND_BNDLOCAL) */
8577c478bd9Sstevel@tonic-gate };
8587c478bd9Sstevel@tonic-gate 
8591007fd6fSAli Bahrami /*
8601007fd6fSAli Bahrami  * Issue an undefined symbol message for the given symbol.
8611007fd6fSAli Bahrami  *
8621007fd6fSAli Bahrami  * entry:
8631007fd6fSAli Bahrami  *	ofl - Output descriptor
8641007fd6fSAli Bahrami  *	sdp - Undefined symbol to report
8651007fd6fSAli Bahrami  *	type - Type of undefined symbol
8661007fd6fSAli Bahrami  *	ofl_flag - One of 0, FLG_OF_FATAL, or FLG_OF_WARN.
8671007fd6fSAli Bahrami  *	undef_state - Address of variable to be initialized to 0
8681007fd6fSAli Bahrami  *		before the first call to sym_undef_entry, and passed
8691007fd6fSAli Bahrami  *		to each subsequent call. A non-zero value for *undef_state
8701007fd6fSAli Bahrami  *		indicates that this is not the first call in the series.
8711007fd6fSAli Bahrami  *
8721007fd6fSAli Bahrami  * exit:
8731007fd6fSAli Bahrami  *	If *undef_state is 0, a title is issued.
8741007fd6fSAli Bahrami  *
8751007fd6fSAli Bahrami  *	A message for the undefined symbol is issued.
8761007fd6fSAli Bahrami  *
8771007fd6fSAli Bahrami  *	If ofl_flag is non-zero, its value is OR'd into *undef_state. Otherwise,
8781007fd6fSAli Bahrami  *	all bits other than FLG_OF_FATAL and FLG_OF_WARN are set, in order to
8791007fd6fSAli Bahrami  *	provide *undef_state with a non-zero value. These other bits have
8801007fd6fSAli Bahrami  *	no meaning beyond that, and serve to ensure that *undef_state is
8811007fd6fSAli Bahrami  *	non-zero if sym_undef_entry() has been called.
8821007fd6fSAli Bahrami  */
8835aefb655Srie static void
sym_undef_entry(Ofl_desc * ofl,Sym_desc * sdp,Type type,ofl_flag_t ofl_flag,ofl_flag_t * undef_state)8841007fd6fSAli Bahrami sym_undef_entry(Ofl_desc *ofl, Sym_desc *sdp, Type type, ofl_flag_t ofl_flag,
8851007fd6fSAli Bahrami     ofl_flag_t *undef_state)
8867c478bd9Sstevel@tonic-gate {
8877c478bd9Sstevel@tonic-gate 	const char	*name1, *name2, *name3;
8887c478bd9Sstevel@tonic-gate 	Ifl_desc	*ifl = sdp->sd_file;
8897c478bd9Sstevel@tonic-gate 	Sym_aux		*sap = sdp->sd_aux;
8907c478bd9Sstevel@tonic-gate 
8911007fd6fSAli Bahrami 	if (*undef_state == 0)
8921007fd6fSAli Bahrami 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FMT_UNDEF),
8931007fd6fSAli Bahrami 		    MSG_INTL(MSG_SYM_UNDEF_ITM_11),
8941007fd6fSAli Bahrami 		    MSG_INTL(MSG_SYM_UNDEF_ITM_21),
8951007fd6fSAli Bahrami 		    MSG_INTL(MSG_SYM_UNDEF_ITM_12),
8961007fd6fSAli Bahrami 		    MSG_INTL(MSG_SYM_UNDEF_ITM_22));
8971007fd6fSAli Bahrami 
8981007fd6fSAli Bahrami 	ofl->ofl_flags |= ofl_flag;
8991007fd6fSAli Bahrami 	*undef_state |= ofl_flag ? ofl_flag : ~(FLG_OF_FATAL | FLG_OF_WARN);
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	switch (