xref: /onnv-gate/usr/src/cmd/sgs/libld/common/resolve.c (revision 13074:787bf65954d0)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51618Srie  * Common Development and Distribution License (the "License").
61618Srie  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211618Srie 
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  *	Copyright (c) 1988 AT&T
240Sstevel@tonic-gate  *	  All Rights Reserved
250Sstevel@tonic-gate  *
26*13074SAli.Bahrami@Oracle.COM  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Symbol table resolution
310Sstevel@tonic-gate  */
326206Sab196087 #define	ELF_TARGET_AMD64
336206Sab196087 
340Sstevel@tonic-gate #include	<stdio.h>
351618Srie #include	<debug.h>
360Sstevel@tonic-gate #include	"msg.h"
370Sstevel@tonic-gate #include	"_libld.h"
380Sstevel@tonic-gate 
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * Categorize the symbol types that are applicable to the resolution process.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate typedef	enum {
440Sstevel@tonic-gate 	SYM_DEFINED,		/* Defined symbol (SHN_ABS or shndx != 0) */
450Sstevel@tonic-gate 	SYM_UNDEFINED,		/* Undefined symbol (SHN_UNDEF) */
460Sstevel@tonic-gate 	SYM_TENTATIVE,		/* Tentative symbol (SHN_COMMON) */
470Sstevel@tonic-gate 	SYM_NUM			/* the number of symbol types */
480Sstevel@tonic-gate } Symtype;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * Do nothing.
520Sstevel@tonic-gate  */
530Sstevel@tonic-gate /* ARGSUSED0 */
540Sstevel@tonic-gate static void
sym_null(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)550Sstevel@tonic-gate sym_null(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
5610792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate }
590Sstevel@tonic-gate 
605220Srie static void
sym_visibility_diag(Error err,Sym_desc * sdp,Sym * osym,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl)615220Srie sym_visibility_diag(Error err, Sym_desc *sdp, Sym *osym, Sym *nsym,
625220Srie     Ifl_desc *ifl, Ofl_desc *ofl)
635220Srie {
645220Srie 	Conv_inv_buf_t	inv_obuf, inv_nbuf;
655220Srie 
6611993SAli.Bahrami@Sun.COM 	/* Warnings are only issued when -z verbose is specified */
6711993SAli.Bahrami@Sun.COM 	if (!(ofl->ofl_flags & FLG_OF_VERBOSE) && (err != ERR_FATAL))
6811993SAli.Bahrami@Sun.COM 		return;
6911993SAli.Bahrami@Sun.COM 
70*13074SAli.Bahrami@Oracle.COM 	ld_eprintf(ofl, err, MSG_INTL(MSG_SYM_CONFVIS), demangle(sdp->sd_name));
71*13074SAli.Bahrami@Oracle.COM 	ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_VISTYPES),
725220Srie 	    sdp->sd_file->ifl_name, conv_sym_other(osym->st_other, &inv_obuf),
735220Srie 	    ifl->ifl_name, conv_sym_other(nsym->st_other, &inv_nbuf));
745220Srie 
75*13074SAli.Bahrami@Oracle.COM 	if (err != ERR_FATAL)
76*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
775220Srie 		    ifl->ifl_name);
785220Srie }
795220Srie 
805220Srie /*
815220Srie  * STV_VISIBILITY rules for STV_DEFAULT/INTERNAL/HIDDEN/PROTECTED say that the
825220Srie  * most restrictive visibility value should be taken.  The precedence is:
835220Srie  *
845220Srie  *    (most restrictive) INTERNAL -> HIDDEN -> PROTECTED -> DEFAULT  (least)
855220Srie  *
865220Srie  * The STV_EXPORT and STV_SINGLETON visibilities are slightly different, in that
875220Srie  * the visibility must remain global and can not be reduced in any way.
885220Srie  *
895220Srie  * Resolution of different visibilities between two relocatable objects can
905220Srie  * take the following actions:
915220Srie  *
925220Srie  *  i.     if applicable, the most restrictive action is silently taken.
935220Srie  *  ii.    if a mapfile visibility definition competes with a more restrictive
945220Srie  *         relocatable object definition, then a warning is generated, but the
955220Srie  *         the more restrictive visibility is taken.
965220Srie  *  iii.   in the case of conflicts with an EXPORTED or SINGLETON symbol with
975220Srie  *	   any type of visibility between relocatable objects, the combination
985220Srie  *	   is deemed fatal.
995220Srie  *
1005220Srie  *                                  new visibility
1015220Srie  *                    D        I         H         P         X         S
1025220Srie  *                 ------------------------------------------------------------
1035220Srie  *              D |   D        I(mw)     H(mw)     P         X         S
1045220Srie  *   original   I |   I        I         I         I         X(mw/of)  S(mw/of)
1055220Srie  *  visibility  H |   H        I(mw)     H         H         X(mw/of)  S(mw/of)
1065220Srie  *              P |   P        I(mw)     H(mw)     P         X(mw/of)  S(mw/of)
1075220Srie  *              X |   X        I(mw/of)  H(mw/of)  P(mw/of)  X         S
1085220Srie  *              S |   S        I(mw/of)  H(mw/of)  P(mw/of)  S         S
1095220Srie  * where:
1105220Srie  *
1115220Srie  *  mw -  mapfile warning: if the original symbol originates from a mapfile
1125220Srie  *        then warn the user that their scope definition is being overridden.
1135220Srie  *  of -  object definitions are fatal: any combination of relocatable object
1145220Srie  *        visibilities that conflict with a SINGLETON and EXPORTED are fatal.
1155220Srie  *
1165220Srie  * Note, an eliminate symbol (STV_ELIMINATE) is treated as hidden (STV_HIDDEN)
1175220Srie  * for processing through this state table.
1185220Srie  */
1195220Srie static Half
sym_visibility(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl)1205220Srie sym_visibility(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl)
1215220Srie {
1225220Srie 	Sym	*osym = sdp->sd_sym;
1235220Srie 	uchar_t	wovis, ovis;
1245220Srie 	uchar_t	wnvis, nvis;
1255220Srie 
1265220Srie 	wovis = ovis = ELF_ST_VISIBILITY(osym->st_other);
1275220Srie 	wnvis = nvis = ELF_ST_VISIBILITY(nsym->st_other);
1285220Srie 
1295220Srie 	/*
1305220Srie 	 * If the original visibilities are eliminate, assign them hidden for
1315220Srie 	 * the state table processing.  The original visibility, rather than
1325220Srie 	 * the working visibility, will be returned to the caller.
1335220Srie 	 */
1345220Srie 	if (wovis == STV_ELIMINATE)
1355220Srie 		wovis = STV_HIDDEN;
1365220Srie 	if (wnvis == STV_ELIMINATE)
1375220Srie 		wnvis = STV_HIDDEN;
1385220Srie 
1395220Srie 	/*
1405220Srie 	 * The most complex visibility resolution is between two relocatable
1415220Srie 	 * objects.  However, in the case of SINGLETONS we also want to catch
1425220Srie 	 * any singleton definitions within shared objects.  Relocatable objects
1435220Srie 	 * that bind to these symbols inherit the singleton visibility as this
1445220Srie 	 * efficiently triggers ld.so.1 into carrying out the appropriate
1455220Srie 	 * runtime symbol search.  Any other resolution between a relocatable
1465220Srie 	 * object and a shared object will retain the relocatable objects
1475220Srie 	 * visibility.
1485220Srie 	 */
1495220Srie 	if ((sdp->sd_ref == REF_REL_NEED) &&
1505220Srie 	    (ifl->ifl_ehdr->e_type == ET_DYN)) {
1515220Srie 		if ((sdp->sd_sym->st_shndx == SHN_UNDEF) &&
1525220Srie 		    (nsym->st_shndx != SHN_UNDEF) && (wnvis == STV_SINGLETON))
1535220Srie 			return (STV_SINGLETON);
1545220Srie 		else
1555220Srie 			return (ovis);
1565220Srie 	}
1575220Srie 	if ((sdp->sd_ref != REF_REL_NEED) &&
1585220Srie 	    (ifl->ifl_ehdr->e_type == ET_REL)) {
1595220Srie 		if ((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
1605220Srie 		    (nsym->st_shndx == SHN_UNDEF) && (wovis == STV_SINGLETON))
1615220Srie 			return (STV_SINGLETON);
1625220Srie 		else
1635220Srie 			return (nvis);
1645220Srie 	}
1655220Srie 
1665220Srie 	/*
1675220Srie 	 * If the visibilities are the same, we're done.  If the working
1685220Srie 	 * visibilities differ from the original, then one must have been
1695220Srie 	 * STV_HIDDEN and the other STV_ELIMINATE.
1705220Srie 	 */
1715220Srie 	if (wovis == wnvis) {
1725220Srie 		if (ovis == nvis)
1735220Srie 			return (nvis);
1745220Srie 		else
1755220Srie 			return (STV_ELIMINATE);
1765220Srie 	}
1775220Srie 
1785220Srie 	/*
1795220Srie 	 * An EXPORTED symbol or SINGLETON symbol can not be demoted, any
1805220Srie 	 * conflicting visibility from another object is fatal.  A conflicting
1815220Srie 	 * visibility from a mapfile produces a warning, as the mapfile
1825220Srie 	 * definition can be overridden.
1835220Srie 	 */
1845220Srie 	if ((wnvis == STV_EXPORTED) || (wnvis == STV_SINGLETON)) {
1855220Srie 		if ((wovis != STV_DEFAULT) && (wovis != STV_EXPORTED) &&
1865220Srie 		    (wovis != STV_SINGLETON)) {
18710792SRod.Evans@Sun.COM 			if (sdp->sd_flags & FLG_SY_MAPFILE) {
1885220Srie 				sym_visibility_diag(ERR_WARNING, sdp, osym,
1895220Srie 				    nsym, ifl, ofl);
1905220Srie 			} else {
1915220Srie 				sym_visibility_diag(ERR_FATAL, sdp, osym,
1925220Srie 				    nsym, ifl, ofl);
1935220Srie 			}
1945220Srie 		}
1955220Srie 		return (nvis);
1965220Srie 	}
1975220Srie 	if (wovis == STV_SINGLETON) {
1985220Srie 		if ((wnvis == STV_EXPORTED) || (wnvis == STV_DEFAULT))
1995220Srie 			return (STV_SINGLETON);
20010792SRod.Evans@Sun.COM 		if (sdp->sd_flags & FLG_SY_MAPFILE) {
2015220Srie 			sym_visibility_diag(ERR_WARNING, sdp, osym,
2025220Srie 			    nsym, ifl, ofl);
2035220Srie 		} else {
2045220Srie 			sym_visibility_diag(ERR_FATAL, sdp, osym,
2055220Srie 			    nsym, ifl, ofl);
2065220Srie 		}
2075220Srie 		return (nvis);
2085220Srie 	}
2095220Srie 	if (wovis == STV_EXPORTED) {
2105220Srie 		if (wnvis == STV_SINGLETON)
2115220Srie 			return (STV_SINGLETON);
2125220Srie 		if (wnvis == STV_DEFAULT)
2135220Srie 			return (STV_EXPORTED);
21410792SRod.Evans@Sun.COM 		if (sdp->sd_flags & FLG_SY_MAPFILE) {
2155220Srie 			sym_visibility_diag(ERR_WARNING, sdp, osym,
2165220Srie 			    nsym, ifl, ofl);
2175220Srie 		} else {
2185220Srie 			sym_visibility_diag(ERR_FATAL, sdp, osym,
2195220Srie 			    nsym, ifl, ofl);
2205220Srie 		}
2215220Srie 		return (nvis);
2225220Srie 	}
2235220Srie 
2245220Srie 	/*
2255220Srie 	 * Now that symbols with the same visibility, and all instances of
2265220Srie 	 * SINGLETON's have been dealt with, we're left with visibilities that
2275220Srie 	 * differ, but can be dealt with in the order of how restrictive the
2285220Srie 	 * visibilities are.  When a differing visibility originates from a
2295220Srie 	 * mapfile definition, produces a warning, as the mapfile definition
2305220Srie 	 * can be overridden by the relocatable object.
2315220Srie 	 */
2325220Srie 	if ((wnvis == STV_INTERNAL) || (wovis == STV_INTERNAL)) {
2335220Srie 		if ((wnvis == STV_INTERNAL) &&
23410792SRod.Evans@Sun.COM 		    (sdp->sd_flags & FLG_SY_MAPFILE)) {
2355220Srie 			sym_visibility_diag(ERR_WARNING, sdp, osym, nsym,
2365220Srie 			    ifl, ofl);
2375220Srie 		}
2385220Srie 		return (STV_INTERNAL);
2395220Srie 
2405220Srie 	} else if ((wnvis == STV_HIDDEN) || (wovis == STV_HIDDEN)) {
2415220Srie 		if ((wnvis == STV_HIDDEN) &&
24210792SRod.Evans@Sun.COM 		    (sdp->sd_flags & FLG_SY_MAPFILE)) {
2435220Srie 			sym_visibility_diag(ERR_WARNING, sdp, osym, nsym,
2445220Srie 			    ifl, ofl);
2455220Srie 		}
2465220Srie 
2475220Srie 		/*
2485220Srie 		 * In the case of STV_ELIMINATE and STV_HIDDEN, the working
2495220Srie 		 * visibility can differ from the original visibility, so make
2505220Srie 		 * sure to return the original visibility.
2515220Srie 		 */
2525220Srie 		if ((ovis == STV_ELIMINATE) || (nvis == STV_ELIMINATE))
2535220Srie 			return (STV_ELIMINATE);
2545220Srie 		else
2555220Srie 			return (STV_HIDDEN);
2565220Srie 
2575220Srie 	} else if ((wnvis == STV_PROTECTED) || (wovis == STV_PROTECTED))
2585220Srie 		return (STV_PROTECTED);
2595220Srie 
2605220Srie 	return (STV_DEFAULT);
2615220Srie }
2625220Srie 
2630Sstevel@tonic-gate /*
2640Sstevel@tonic-gate  * Check if two symbols types are compatible
2650Sstevel@tonic-gate  */
2660Sstevel@tonic-gate /*ARGSUSED4*/
2670Sstevel@tonic-gate static void
sym_typecheck(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)2680Sstevel@tonic-gate sym_typecheck(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
26910792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
2700Sstevel@tonic-gate {
2714734Sab196087 	uchar_t		otype = ELF_ST_TYPE(sdp->sd_sym->st_info);
2724734Sab196087 	uchar_t		ntype = ELF_ST_TYPE(nsym->st_info);
2734734Sab196087 	Conv_inv_buf_t	inv_buf1, inv_buf2;
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	/*
2760Sstevel@tonic-gate 	 * Perform any machine specific type checking.
2770Sstevel@tonic-gate 	 */
2786206Sab196087 	if ((ld_targ.t_ms.ms_mach_sym_typecheck != NULL) &&
2796206Sab196087 	    (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym, ifl, ofl))
2800Sstevel@tonic-gate 		return;
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	/*
2835220Srie 	 * NOTYPE's can be combined with other types, only give an error if
2845220Srie 	 * combining two differing types without NOTYPE.
2850Sstevel@tonic-gate 	 */
2860Sstevel@tonic-gate 	if ((otype == ntype) || (otype == STT_NOTYPE) || (ntype == STT_NOTYPE))
2870Sstevel@tonic-gate 		return;
2880Sstevel@tonic-gate 
289*13074SAli.Bahrami@Oracle.COM 	ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
2900Sstevel@tonic-gate 	    demangle(sdp->sd_name));
291*13074SAli.Bahrami@Oracle.COM 	ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
2921618Srie 	    sdp->sd_file->ifl_name,
2934734Sab196087 	    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype, 0, &inv_buf1),
2941976Sab196087 	    ifl->ifl_name,
2954734Sab196087 	    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype, 0, &inv_buf2));
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate /*ARGSUSED4*/
2990Sstevel@tonic-gate static void
sym_mach_check(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)3000Sstevel@tonic-gate sym_mach_check(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
30110792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate 	/*
3040Sstevel@tonic-gate 	 * Perform any machine specific type checking.
3050Sstevel@tonic-gate 	 */
3066206Sab196087 	if (ld_targ.t_ms.ms_mach_sym_typecheck != NULL)
3076206Sab196087 		(void) (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym,
3086206Sab196087 		    ifl, ofl);
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate /*
3120Sstevel@tonic-gate  * Promote the symbols reference.
3130Sstevel@tonic-gate  */
3140Sstevel@tonic-gate static void
3150Sstevel@tonic-gate /* ARGSUSED4 */
sym_promote(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)3160Sstevel@tonic-gate sym_promote(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
31710792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
3180Sstevel@tonic-gate {
3191682Srie 	Word	shndx = nsym->st_shndx;
3201682Srie 
32110792SRod.Evans@Sun.COM 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	/*
3240Sstevel@tonic-gate 	 * If the old symbol is from a shared object and the new symbol is a
3250Sstevel@tonic-gate 	 * reference from a relocatable object, promote the old symbols
3260Sstevel@tonic-gate 	 * reference.
3270Sstevel@tonic-gate 	 */
3280Sstevel@tonic-gate 	if ((sdp->sd_ref == REF_DYN_SEEN) &&
3290Sstevel@tonic-gate 	    (ifl->ifl_ehdr->e_type == ET_REL)) {
3300Sstevel@tonic-gate 		sdp->sd_ref = REF_DYN_NEED;
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 		/*
3330Sstevel@tonic-gate 		 * If this is an undefined symbol it must be a relocatable
3340Sstevel@tonic-gate 		 * object overriding a shared object.  In this case also
3350Sstevel@tonic-gate 		 * override the reference name so that any undefined symbol
3360Sstevel@tonic-gate 		 * diagnostics will refer to the relocatable object name.
3370Sstevel@tonic-gate 		 */
3381682Srie 		if (shndx == SHN_UNDEF)
3390Sstevel@tonic-gate 			sdp->sd_aux->sa_rfile = ifl->ifl_name;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 		/*
3420Sstevel@tonic-gate 		 * If this symbol is an undefined, or common, determine whether
3430Sstevel@tonic-gate 		 * it is a global or weak reference (see build_osym(), where
3440Sstevel@tonic-gate 		 * REF_DYN_NEED definitions are returned back to undefines).
3450Sstevel@tonic-gate 		 */
34610792SRod.Evans@Sun.COM 		if (((shndx == SHN_UNDEF) || ((nsdflags & FLG_SY_SPECSEC) &&
3471682Srie 		    (shndx == SHN_COMMON))) &&
3480Sstevel@tonic-gate 		    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
3490Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_GLOBREF;
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate /*
3550Sstevel@tonic-gate  * Override a symbol.
3560Sstevel@tonic-gate  */
3570Sstevel@tonic-gate static void
sym_override(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)3580Sstevel@tonic-gate sym_override(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
35910792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
3600Sstevel@tonic-gate {
3615220Srie 	Sym	*osym = sdp->sd_sym;
3625220Srie 	Word	link;
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	/*
3650Sstevel@tonic-gate 	 * In the case of a WEAK UNDEF symbol don't let a symbol from an
3660Sstevel@tonic-gate 	 * unavailable object override the symbol definition.  This is because
3670Sstevel@tonic-gate 	 * this symbol *may* not be present in a future object and by promoting
3680Sstevel@tonic-gate 	 * this symbol we are actually causing bindings (PLTS) to be formed
3690Sstevel@tonic-gate 	 * to this symbol.  Instead let the 'generic' weak binding take place.
3700Sstevel@tonic-gate 	 */
3710Sstevel@tonic-gate 	if ((ELF_ST_BIND(osym->st_info) == STB_WEAK) &&
3721682Srie 	    (sdp->sd_sym->st_shndx == SHN_UNDEF) &&
3731682Srie 	    ((ifl->ifl_flags & FLG_IF_NEEDED) == 0))
3740Sstevel@tonic-gate 		return;
3750Sstevel@tonic-gate 
37610792SRod.Evans@Sun.COM 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/*
3790Sstevel@tonic-gate 	 * This symbol has already been compared to an SO definition,
3800Sstevel@tonic-gate 	 * as per the runtime behavior, ignore extra definitions.
3810Sstevel@tonic-gate 	 */
3820Sstevel@tonic-gate 	if ((sdp->sd_flags & FLG_SY_SOFOUND) &&
3830Sstevel@tonic-gate 	    (ifl->ifl_ehdr->e_type == ET_DYN))
3840Sstevel@tonic-gate 		return;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	/*
3870Sstevel@tonic-gate 	 * Mark the symbol as available and copy the new symbols contents.
3880Sstevel@tonic-gate 	 */
3890Sstevel@tonic-gate 	sdp->sd_flags &= ~FLG_SY_NOTAVAIL;
3900Sstevel@tonic-gate 	*osym = *nsym;
3910Sstevel@tonic-gate 	sdp->sd_shndx = nshndx;
3920Sstevel@tonic-gate 	sdp->sd_flags &= ~FLG_SY_SPECSEC;
39310792SRod.Evans@Sun.COM 	sdp->sd_flags |= (nsdflags & (FLG_SY_SPECSEC | FLG_SY_TENTSYM));
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 	/*
3960Sstevel@tonic-gate 	 * If the new symbol has PROTECTED visibility, mark it.  If a PROTECTED
3975220Srie 	 * symbol is copy relocated, a warning message will be printed.  See
3980Sstevel@tonic-gate 	 * reloc_exec().
3990Sstevel@tonic-gate 	 */
4000Sstevel@tonic-gate 	if (ELF_ST_VISIBILITY(nsym->st_other) == STV_PROTECTED)
4010Sstevel@tonic-gate 		sdp->sd_flags |= FLG_SY_PROT;
4020Sstevel@tonic-gate 	else
4030Sstevel@tonic-gate 		sdp->sd_flags &= ~FLG_SY_PROT;
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	/*
4060Sstevel@tonic-gate 	 * Establish the symbols reference.  If the new symbol originates from a
4070Sstevel@tonic-gate 	 * relocatable object then this reference becomes needed, otherwise
4080Sstevel@tonic-gate 	 * the new symbol must be from a shared object.  In this case only
4090Sstevel@tonic-gate 	 * promote the symbol to needed if we presently have a reference from a
4100Sstevel@tonic-gate 	 * relocatable object.
4110Sstevel@tonic-gate 	 */
4120Sstevel@tonic-gate 	if (ifl->ifl_ehdr->e_type == ET_REL) {
4130Sstevel@tonic-gate 		sdp->sd_ref = REF_REL_NEED;
4140Sstevel@tonic-gate 
4151682Srie 		if (nsym->st_shndx == SHN_UNDEF) {
4160Sstevel@tonic-gate 			/*
41711827SRod.Evans@Sun.COM 			 * If this is an undefined symbol, then we can only be
41811827SRod.Evans@Sun.COM 			 * attempting to override an existing undefined symbol.
41911827SRod.Evans@Sun.COM 			 * The original symbol is either:
42011827SRod.Evans@Sun.COM 			 *
42111827SRod.Evans@Sun.COM 			 *  -	a mapfile definition
42211827SRod.Evans@Sun.COM 			 *  -	a previous relocatable object whose visibility
42311827SRod.Evans@Sun.COM 			 *	or type should be overridden by this new symbol
42411827SRod.Evans@Sun.COM 			 *  -	a previous shared object
42511827SRod.Evans@Sun.COM 			 *
42611827SRod.Evans@Sun.COM 			 * If the original undefined symbol stems from a mapfile
42711827SRod.Evans@Sun.COM 			 * then don't alter the reference file name.  Should we
42811827SRod.Evans@Sun.COM 			 * end up with some form of 'undefined' symbol error,
42911827SRod.Evans@Sun.COM 			 * the characteristics of that error are most likely to
43011827SRod.Evans@Sun.COM 			 * have originated from a mapfile.
43111827SRod.Evans@Sun.COM 			 *
43211827SRod.Evans@Sun.COM 			 * Otherwise, update the reference file name to indicate
43311827SRod.Evans@Sun.COM 			 * this symbol.
4340Sstevel@tonic-gate 			 */
43511827SRod.Evans@Sun.COM 			if ((sdp->sd_flags & FLG_SY_MAPREF) == 0)
43611827SRod.Evans@Sun.COM 				sdp->sd_aux->sa_rfile = ifl->ifl_name;
4370Sstevel@tonic-gate 		} else {
4380Sstevel@tonic-gate 			/*
4393466Srie 			 * Under -Bnodirect, all exported interfaces that have
4403466Srie 			 * not explicitly been defined protected or directly
4413466Srie 			 * bound to, are tagged to prevent direct binding.
4420Sstevel@tonic-gate 			 */
4430Sstevel@tonic-gate 			if ((ofl->ofl_flags1 & FLG_OF1_ALNODIR) &&
44410792SRod.Evans@Sun.COM 			    ((sdp->sd_flags &
44510792SRod.Evans@Sun.COM 			    (FLG_SY_PROTECT | FLG_SY_DIR)) == 0))
44610792SRod.Evans@Sun.COM 				sdp->sd_flags |= FLG_SY_NDIR;
4470Sstevel@tonic-gate 		}
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 		/*
4500Sstevel@tonic-gate 		 * If this symbol is an undefined, or common, determine whether
4510Sstevel@tonic-gate 		 * it is a global or weak reference (see build_osym(), where
4520Sstevel@tonic-gate 		 * REF_DYN_NEED definitions are returned back to undefines).
4530Sstevel@tonic-gate 		 */
4541682Srie 		if (((nsym->st_shndx == SHN_UNDEF) ||
45510792SRod.Evans@Sun.COM 		    ((nsdflags & FLG_SY_SPECSEC) &&
4561682Srie 		    (nsym->st_shndx == SHN_COMMON))) &&
4570Sstevel@tonic-gate 		    (ELF_ST_BIND(nsym->st_info) == STB_GLOBAL))
4580Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_GLOBREF;
4590Sstevel@tonic-gate 		else
4600Sstevel@tonic-gate 			sdp->sd_flags &= ~FLG_SY_GLOBREF;
4610Sstevel@tonic-gate 	} else {
4620Sstevel@tonic-gate 		if (sdp->sd_ref == REF_REL_NEED)
4630Sstevel@tonic-gate 			sdp->sd_ref = REF_DYN_NEED;
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 		/*
4660Sstevel@tonic-gate 		 * Determine the symbols availability.  A symbol is determined
4670Sstevel@tonic-gate 		 * to be unavailable if it belongs to a version of a shared
4680Sstevel@tonic-gate 		 * object that this user does not wish to use, or if it belongs
4690Sstevel@tonic-gate 		 * to an implicit shared object.
4700Sstevel@tonic-gate 		 */
4710Sstevel@tonic-gate 		if (ifl->ifl_vercnt) {
4725220Srie 			Ver_index	*vip;
4730Sstevel@tonic-gate 			Half		vndx = ifl->ifl_versym[ndx];
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 			sdp->sd_aux->sa_dverndx = vndx;
4760Sstevel@tonic-gate 			vip = &ifl->ifl_verndx[vndx];
4770Sstevel@tonic-gate 			if (!(vip->vi_flags & FLG_VER_AVAIL)) {
4780Sstevel@tonic-gate 				sdp->sd_flags |= FLG_SY_NOTAVAIL;
4790Sstevel@tonic-gate 				/*
4805220Srie 				 * If this is the first occurrence of an
4810Sstevel@tonic-gate 				 * unavailable symbol record it for possible
4820Sstevel@tonic-gate 				 * use in later error diagnostics
4830Sstevel@tonic-gate 				 * (see sym_undef).
4840Sstevel@tonic-gate 				 */
4850Sstevel@tonic-gate 				if (!(sdp->sd_aux->sa_vfile))
4860Sstevel@tonic-gate 					sdp->sd_aux->sa_vfile = ifl->ifl_name;
4870Sstevel@tonic-gate 			}
4880Sstevel@tonic-gate 		}
4890Sstevel@tonic-gate 		if (!(ifl->ifl_flags & FLG_IF_NEEDED))
4900Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_NOTAVAIL;
4910Sstevel@tonic-gate 	}
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	/*
4940Sstevel@tonic-gate 	 * Make sure any symbol association maintained by the original symbol
4950Sstevel@tonic-gate 	 * is cleared and then update the symbols file reference.
4960Sstevel@tonic-gate 	 */
4970Sstevel@tonic-gate 	if ((link = sdp->sd_aux->sa_linkndx) != 0) {
4980Sstevel@tonic-gate 		Sym_desc *	_sdp;
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 		_sdp = sdp->sd_file->ifl_oldndx[link];
5010Sstevel@tonic-gate 		_sdp->sd_aux->sa_linkndx = 0;
5020Sstevel@tonic-gate 		sdp->sd_aux->sa_linkndx = 0;
5030Sstevel@tonic-gate 	}
5040Sstevel@tonic-gate 	sdp->sd_file = ifl;
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	/*
5070Sstevel@tonic-gate 	 * Update the input section descriptor to that of the new input file
5080Sstevel@tonic-gate 	 */
50910792SRod.Evans@Sun.COM 	if (((nsdflags & FLG_SY_SPECSEC) == 0) &&
510*13074SAli.Bahrami@Oracle.COM 	    (nsym->st_shndx != SHN_UNDEF) &&
511*13074SAli.Bahrami@Oracle.COM 	    ((sdp->sd_isc = ifl->ifl_isdesc[nshndx]) == NULL))
512*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_NOSECDEF),
513*13074SAli.Bahrami@Oracle.COM 		    demangle(sdp->sd_name), ifl->ifl_name);
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate /*
5170Sstevel@tonic-gate  * Resolve two undefines (only called for two relocatable objects).
5180Sstevel@tonic-gate  */
5190Sstevel@tonic-gate static void
sym_twoundefs(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)5200Sstevel@tonic-gate sym_twoundefs(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
52110792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
5220Sstevel@tonic-gate {
5233731Srie 	Sym	*osym = sdp->sd_sym;
5243731Srie 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
52511827SRod.Evans@Sun.COM 	uchar_t	otype = ELF_ST_TYPE(osym->st_info);
5263731Srie 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
52711827SRod.Evans@Sun.COM 	uchar_t	ntype = ELF_ST_TYPE(nsym->st_info);
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	/*
5300Sstevel@tonic-gate 	 * If two relocatable objects define a weak and non-weak undefined
5310Sstevel@tonic-gate 	 * reference, take the non-weak definition.
5320Sstevel@tonic-gate 	 *
5330Sstevel@tonic-gate 	 *		-- or --
5340Sstevel@tonic-gate 	 *
5350Sstevel@tonic-gate 	 * If two relocatable objects define a NOTYPE & another, then
5360Sstevel@tonic-gate 	 * take the other.
5370Sstevel@tonic-gate 	 */
5380Sstevel@tonic-gate 	if (((obind == STB_WEAK) && (nbind != STB_WEAK)) ||
53911827SRod.Evans@Sun.COM 	    (otype == STT_NOTYPE) && (ntype != STT_NOTYPE)) {
54010792SRod.Evans@Sun.COM 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
5410Sstevel@tonic-gate 		return;
5420Sstevel@tonic-gate 	}
54310792SRod.Evans@Sun.COM 	sym_typecheck(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate /*
5470Sstevel@tonic-gate  * Resolve two real definitions.
5480Sstevel@tonic-gate  */
5490Sstevel@tonic-gate static void
sym_tworeals(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)5500Sstevel@tonic-gate sym_tworeals(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
55110792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
5520Sstevel@tonic-gate {
5534734Sab196087 	Conv_inv_buf_t inv_buf1, inv_buf2;
5543731Srie 	Sym	*osym = sdp->sd_sym;
5553731Srie 	uchar_t	otype = ELF_ST_TYPE(osym->st_info);
5563731Srie 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
5573731Srie 	uchar_t	ntype = ELF_ST_TYPE(nsym->st_info);
5583731Srie 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
5593731Srie 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
5603731Srie 	Half	nfile = ifl->ifl_ehdr->e_type;
5613731Srie 	int	warn = 0;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	/*
5640Sstevel@tonic-gate 	 * If both definitions are from relocatable objects, and have non-weak
5650Sstevel@tonic-gate 	 * binding then this is a fatal condition.
5660Sstevel@tonic-gate 	 */
5670Sstevel@tonic-gate 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind != STB_WEAK) &&
5680Sstevel@tonic-gate 	    (nbind != STB_WEAK) && (!(ofl->ofl_flags & FLG_OF_MULDEFS))) {
569*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
5700Sstevel@tonic-gate 		    demangle(sdp->sd_name));
571*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
5720Sstevel@tonic-gate 		    sdp->sd_file->ifl_name,
5734734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
5744734Sab196087 		    0, &inv_buf1), ifl->ifl_name,
5754734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
5764734Sab196087 		    0, &inv_buf2));
5770Sstevel@tonic-gate 		return;
5780Sstevel@tonic-gate 	}
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	/*
5810Sstevel@tonic-gate 	 * Perform any machine specific type checking.
5820Sstevel@tonic-gate 	 */
5836206Sab196087 	if ((ld_targ.t_ms.ms_mach_sym_typecheck != NULL) &&
5846206Sab196087 	    (*ld_targ.t_ms.ms_mach_sym_typecheck)(sdp, nsym, ifl, ofl))
5850Sstevel@tonic-gate 		return;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	/*
5880Sstevel@tonic-gate 	 * Check the symbols type and size.
5890Sstevel@tonic-gate 	 */
5900Sstevel@tonic-gate 	if (otype != ntype) {
591*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
5920Sstevel@tonic-gate 		    demangle(sdp->sd_name));
593*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
5940Sstevel@tonic-gate 		    sdp->sd_file->ifl_name,
5954734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
5964734Sab196087 		    0, &inv_buf1), ifl->ifl_name,
5974734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
5984734Sab196087 		    0, &inv_buf2));
5990Sstevel@tonic-gate 		warn++;
6000Sstevel@tonic-gate 	} else if ((otype == STT_OBJECT) && (osym->st_size != nsym->st_size)) {
6010Sstevel@tonic-gate 		if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
602*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_WARNING,
6031618Srie 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
6041618Srie 			    MSG_INTL(MSG_STR_SIZES), sdp->sd_file->ifl_name,
6051618Srie 			    EC_XWORD(osym->st_size), ifl->ifl_name,
6061618Srie 			    EC_XWORD(nsym->st_size));
6070Sstevel@tonic-gate 			warn++;
6080Sstevel@tonic-gate 		}
6090Sstevel@tonic-gate 	}
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	/*
6120Sstevel@tonic-gate 	 * Having provided the user with any necessary warnings, take the
6130Sstevel@tonic-gate 	 * appropriate symbol:
6140Sstevel@tonic-gate 	 *
61510167SRod.Evans@Sun.COM 	 *  -	if one symbol is from a shared object and the other is from a
6160Sstevel@tonic-gate 	 *	relocatable object, take the relocatable objects symbol (the
6170Sstevel@tonic-gate 	 *	run-time linker is always going to find the relocatable object
6180Sstevel@tonic-gate 	 *	symbol regardless of the binding), else
6190Sstevel@tonic-gate 	 *
62010167SRod.Evans@Sun.COM 	 *  -	if both symbols are from relocatable objects and one symbol is
6210Sstevel@tonic-gate 	 *	weak take the non-weak symbol (two non-weak symbols would have
6220Sstevel@tonic-gate 	 *	generated the fatal error condition above unless -z muldefs is
6230Sstevel@tonic-gate 	 *	in effect), else
6240Sstevel@tonic-gate 	 *
62510167SRod.Evans@Sun.COM 	 *  -	take the first symbol definition encountered.
6260Sstevel@tonic-gate 	 */
6270Sstevel@tonic-gate 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
6280Sstevel@tonic-gate 		if (warn)
629*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
630*13074SAli.Bahrami@Oracle.COM 			    sdp->sd_file->ifl_name);
6310Sstevel@tonic-gate 		return;
6320Sstevel@tonic-gate 	} else if ((nfile == ET_REL) && ((ofile == ET_DYN) ||
6330Sstevel@tonic-gate 	    ((obind == STB_WEAK) && (nbind != STB_WEAK)))) {
6340Sstevel@tonic-gate 		if (warn)
635*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
636*13074SAli.Bahrami@Oracle.COM 			    ifl->ifl_name);
63710792SRod.Evans@Sun.COM 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
6380Sstevel@tonic-gate 		return;
6390Sstevel@tonic-gate 	} else {
6400Sstevel@tonic-gate 		if (warn)
641*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
642*13074SAli.Bahrami@Oracle.COM 			    sdp->sd_file->ifl_name);
64310792SRod.Evans@Sun.COM 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
6440Sstevel@tonic-gate 		return;
6450Sstevel@tonic-gate 	}
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate /*
6490Sstevel@tonic-gate  * Resolve a real and tentative definition.
6500Sstevel@tonic-gate  */
6510Sstevel@tonic-gate static void
sym_realtent(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)6520Sstevel@tonic-gate sym_realtent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
65310792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
6540Sstevel@tonic-gate {
6554734Sab196087 	Conv_inv_buf_t inv_buf1, inv_buf2;
6563731Srie 	Sym	*osym = sdp->sd_sym;
6573731Srie 	uchar_t otype = ELF_ST_TYPE(osym->st_info);
6583731Srie 	uchar_t obind = ELF_ST_BIND(osym->st_info);
6593731Srie 	uchar_t ntype = ELF_ST_TYPE(nsym->st_info);
6603731Srie 	uchar_t nbind = ELF_ST_BIND(nsym->st_info);
6613731Srie 	Boolean	otent = FALSE, ntent = FALSE;
6623731Srie 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
6633731Srie 	Half	nfile = ifl->ifl_ehdr->e_type;
6643731Srie 	int	warn = 0;
6655220Srie 	uchar_t	ovis = ELF_ST_VISIBILITY(osym->st_other);
6665220Srie 	uchar_t	nvis = ELF_ST_VISIBILITY(nsym->st_other);
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 	/*
6690Sstevel@tonic-gate 	 * Special rules for functions.
6700Sstevel@tonic-gate 	 *
67110167SRod.Evans@Sun.COM 	 *  -	If both definitions are from relocatable objects, have the same
6720Sstevel@tonic-gate 	 *	binding (ie. two weaks or two non-weaks), and the real
6730Sstevel@tonic-gate 	 *	definition is a function (the other must be tentative), treat
6740Sstevel@tonic-gate 	 *	this as a multiply defined symbol error, else
6750Sstevel@tonic-gate 	 *
67610167SRod.Evans@Sun.COM 	 *  -	if the real symbol definition is a function within a shared
6770Sstevel@tonic-gate 	 *	library and the tentative symbol is a relocatable object, and
6780Sstevel@tonic-gate 	 *	the tentative is not weak and the function real, then retain the
6790Sstevel@tonic-gate 	 *	tentative definition.
6800Sstevel@tonic-gate 	 */
6810Sstevel@tonic-gate 	if ((ofile == ET_REL) && (nfile == ET_REL) && (obind == nbind) &&
6820Sstevel@tonic-gate 	    ((otype == STT_FUNC) || (ntype == STT_FUNC))) {
6830Sstevel@tonic-gate 		if (ofl->ofl_flags & FLG_OF_MULDEFS) {
684*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
685*13074SAli.Bahrami@Oracle.COM 			    demangle(sdp->sd_name));
6860Sstevel@tonic-gate 			sym_promote(sdp, nsym, ifl, ofl, ndx,
68710792SRod.Evans@Sun.COM 			    nshndx, nsdflags);
6880Sstevel@tonic-gate 		} else {
689*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_MULDEF),
690*13074SAli.Bahrami@Oracle.COM 			    demangle(sdp->sd_name));
6910Sstevel@tonic-gate 		}
692*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
6930Sstevel@tonic-gate 		    sdp->sd_file->ifl_name,
6944734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
6954734Sab196087 		    0, &inv_buf1), ifl->ifl_name,
6964734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
6974734Sab196087 		    0, &inv_buf2));
6980Sstevel@tonic-gate 		return;
6990Sstevel@tonic-gate 	} else if (ofile != nfile) {
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 		if ((ofile == ET_DYN) && (otype == STT_FUNC)) {
7030Sstevel@tonic-gate 			if ((otype != STB_WEAK) && (ntype == STB_WEAK))
7040Sstevel@tonic-gate 				return;
7050Sstevel@tonic-gate 			else {
7060Sstevel@tonic-gate 				sym_override(sdp, nsym, ifl, ofl, ndx,
70710792SRod.Evans@Sun.COM 				    nshndx, nsdflags);
7080Sstevel@tonic-gate 				return;
7090Sstevel@tonic-gate 			}
7100Sstevel@tonic-gate 		}
7110Sstevel@tonic-gate 		if ((nfile == ET_DYN) && (ntype == STT_FUNC)) {
7120Sstevel@tonic-gate 			if ((ntype != STB_WEAK) && (otype == STB_WEAK)) {
7130Sstevel@tonic-gate 				sym_override(sdp, nsym, ifl, ofl, ndx,
71410792SRod.Evans@Sun.COM 				    nshndx, nsdflags);
7150Sstevel@tonic-gate 				return;
7160Sstevel@tonic-gate 			} else
7170Sstevel@tonic-gate 				return;
7180Sstevel@tonic-gate 		}
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	if (sdp->sd_flags & FLG_SY_TENTSYM)
7220Sstevel@tonic-gate 		otent = TRUE;
72310792SRod.Evans@Sun.COM 	if (nsdflags & FLG_SY_TENTSYM)
7240Sstevel@tonic-gate 		ntent = TRUE;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	/*
7280Sstevel@tonic-gate 	 * Check the symbols type and size.
7290Sstevel@tonic-gate 	 */
7300Sstevel@tonic-gate 	if (otype != ntype) {
731*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFTYPE),
7320Sstevel@tonic-gate 		    demangle(sdp->sd_name));
733*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_FILETYPES),
7340Sstevel@tonic-gate 		    sdp->sd_file->ifl_name,
7354734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, otype,
7364734Sab196087 		    0, &inv_buf1), ifl->ifl_name,
7374734Sab196087 		    conv_sym_info_type(ofl->ofl_dehdr->e_machine, ntype,
7384734Sab196087 		    0, &inv_buf2));
7390Sstevel@tonic-gate 		warn++;
7400Sstevel@tonic-gate 	} else if (osym->st_size != nsym->st_size) {
7410Sstevel@tonic-gate 		/*
7420Sstevel@tonic-gate 		 * If both definitions are from relocatable objects we have a
7430Sstevel@tonic-gate 		 * potential fatal error condition.  If the tentative is larger
7440Sstevel@tonic-gate 		 * than the real definition treat this as a multiple definition.
7450Sstevel@tonic-gate 		 * Note that if only one symbol is weak, the non-weak will be
7460Sstevel@tonic-gate 		 * taken.
7470Sstevel@tonic-gate 		 */
7480Sstevel@tonic-gate 		if (((ofile == ET_REL) && (nfile == ET_REL) &&
7490Sstevel@tonic-gate 		    (obind == nbind)) &&
7500Sstevel@tonic-gate 		    ((otent && (osym->st_size > nsym->st_size)) ||
7510Sstevel@tonic-gate 		    (ntent && (osym->st_size < nsym->st_size)))) {
752*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_SYM_DIFFATTR),
753*13074SAli.Bahrami@Oracle.COM 			    demangle(sdp->sd_name), MSG_INTL(MSG_STR_SIZES),
754*13074SAli.Bahrami@Oracle.COM 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_size),
755*13074SAli.Bahrami@Oracle.COM 			    ifl->ifl_name, EC_XWORD(nsym->st_size));
756*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_TENTERR));
7570Sstevel@tonic-gate 		} else {
7580Sstevel@tonic-gate 			if (!(ofl->ofl_flags & FLG_OF_NOWARN)) {
759*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_WARNING,
7601618Srie 				    MSG_INTL(MSG_SYM_DIFFATTR),
7610Sstevel@tonic-gate 				    demangle(sdp->sd_name),
7620Sstevel@tonic-gate 				    MSG_INTL(MSG_STR_SIZES),
7630Sstevel@tonic-gate 				    sdp->sd_file->ifl_name,
7640Sstevel@tonic-gate 				    EC_XWORD(osym->st_size),
7650Sstevel@tonic-gate 				    ifl->ifl_name, EC_XWORD(nsym->st_size));
7660Sstevel@tonic-gate 				warn++;
7670Sstevel@tonic-gate 			}
7680Sstevel@tonic-gate 		}
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	/*
7720Sstevel@tonic-gate 	 * Having provided the user with any necessary warnings, take the
7730Sstevel@tonic-gate 	 * appropriate symbol:
7740Sstevel@tonic-gate 	 *
77510167SRod.Evans@Sun.COM 	 *  -	if the original symbol is from relocatable file and it is
7760Sstevel@tonic-gate 	 *	a protected tentative symbol, take the original one.
7770Sstevel@tonic-gate 	 *
77810167SRod.Evans@Sun.COM 	 *  -	if the original symbol is from shared object and the new
7790Sstevel@tonic-gate 	 *	symbol is a protected tentative symbol from a relocatable file,
7800Sstevel@tonic-gate 	 *	take the new one.
7810Sstevel@tonic-gate 	 *
78210167SRod.Evans@Sun.COM 	 *  -	if the original symbol is tentative, and providing the original
7830Sstevel@tonic-gate 	 *	symbol isn't strong and the new symbol weak, take the real
7840Sstevel@tonic-gate 	 *	symbol, else
7850Sstevel@tonic-gate 	 *
78610167SRod.Evans@Sun.COM 	 *  -	if the original symbol is weak and the new tentative symbol is
7870Sstevel@tonic-gate 	 *	strong take the new symbol.
7880Sstevel@tonic-gate 	 *
7890Sstevel@tonic-gate 	 * Refer to the System V ABI Page 4-27 for a description of the binding
7900Sstevel@tonic-gate 	 * requirements of tentative and weak symbols.
7910Sstevel@tonic-gate 	 */
7920Sstevel@tonic-gate 	if ((ofile == ET_REL) && (nfile == ET_DYN) && (otent == TRUE) &&
7935220Srie 	    (ovis == STV_PROTECTED)) {
7940Sstevel@tonic-gate 		return;
7950Sstevel@tonic-gate 	}
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 	if ((ofile == ET_DYN) && (nfile == ET_REL) && (ntent == TRUE) &&
7985220Srie 	    (nvis == STV_PROTECTED)) {
79910792SRod.Evans@Sun.COM 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
8000Sstevel@tonic-gate 		return;
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
8040Sstevel@tonic-gate 		if (warn)
805*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
806*13074SAli.Bahrami@Oracle.COM 			    sdp->sd_file->ifl_name);
8070Sstevel@tonic-gate 		return;
8080Sstevel@tonic-gate 	}
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	if (((otent) && (!((obind != STB_WEAK) && (nbind == STB_WEAK)))) ||
8110Sstevel@tonic-gate 	    ((obind == STB_WEAK) && (nbind != STB_WEAK))) {
8120Sstevel@tonic-gate 		if (warn)
813*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
814*13074SAli.Bahrami@Oracle.COM 			    ifl->ifl_name);
81510792SRod.Evans@Sun.COM 		sym_override(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
8160Sstevel@tonic-gate 		return;
8170Sstevel@tonic-gate 	} else {
8180Sstevel@tonic-gate 		if (warn)
819*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_SYM_DEFTAKEN),
820*13074SAli.Bahrami@Oracle.COM 			    sdp->sd_file->ifl_name);
82110792SRod.Evans@Sun.COM 		sym_promote(sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
8220Sstevel@tonic-gate 		return;
8230Sstevel@tonic-gate 	}
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate /*
8270Sstevel@tonic-gate  * Resolve two tentative symbols.
8280Sstevel@tonic-gate  */
8290Sstevel@tonic-gate static void
sym_twotent(Sym_desc * sdp,Sym * nsym,Ifl_desc * ifl,Ofl_desc * ofl,int ndx,Word nshndx,sd_flag_t nsdflags)8300Sstevel@tonic-gate sym_twotent(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl,
83110792SRod.Evans@Sun.COM     int ndx, Word nshndx, sd_flag_t nsdflags)
8320Sstevel@tonic-gate {
8333731Srie 	Sym	*osym = sdp->sd_sym;
8343731Srie 	uchar_t	obind = ELF_ST_BIND(osym->st_info);
8353731Srie 	uchar_t	nbind = ELF_ST_BIND(nsym->st_info);
8363731Srie 	Half	ofile = sdp->sd_file->ifl_ehdr->e_type;
8373731Srie 	Half	nfile = ifl->ifl_ehdr->e_type;
8383731Srie 	size_t	size = 0;
8393731Srie 	Xword	value = 0;
8400Sstevel@tonic-gate 
8416206Sab196087 #if	defined(_ELF64)
8426206Sab196087 	if (ld_targ.t_m.m_mach == EM_AMD64) {
843574Sseizo 		/*
8446206Sab196087 		 * If the original and new symbols are both COMMON, but of
8456206Sab196087 		 * a different size model, take the small one.
846574Sseizo 		 */
8476206Sab196087 		if ((sdp->sd_sym->st_shndx == SHN_COMMON) &&
8486206Sab196087 		    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
8496206Sab196087 			/*
8506206Sab196087 			 * Take the original symbol.
8516206Sab196087 			 */
8526206Sab196087 			return;
8531682Srie 
8546206Sab196087 		} else if ((sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
8556206Sab196087 		    (nsym->st_shndx == SHN_COMMON)) {
8566206Sab196087 			/*
8576206Sab196087 			 * Take the new symbol.
8586206Sab196087 			 */
8596206Sab196087 			sym_override(sdp, nsym, ifl, ofl, ndx, nshndx,
86010792SRod.Evans@Sun.COM 			    nsdflags);
8616206Sab196087 			return;
8626206Sab196087 		}
863574Sseizo 	}
864574Sseizo #endif
865574Sseizo 
8660Sstevel@tonic-gate 	/*
8670Sstevel@tonic-gate 	 * Check the alignment of the symbols.  This can only be tested for if
8680Sstevel@tonic-gate 	 * the symbols are not real definitions to a SHT_NOBITS section (ie.
8690Sstevel@tonic-gate 	 * they were originally tentative), as in this case the symbol would
8700Sstevel@tonic-gate 	 * have a displacement value rather than an alignment.  In other words
8710Sstevel@tonic-gate 	 * we can only test this for two relocatable objects.
8720Sstevel@tonic-gate 	 */
8734734Sab196087 	/* BEGIN CSTYLED */
8740Sstevel@tonic-gate 	if ((osym->st_value != nsym->st_value) &&
8750Sstevel@tonic-gate 	    ((sdp->sd_flags & FLG_SY_SPECSEC) &&
8761682Srie 	    (sdp->sd_sym->st_shndx == SHN_COMMON) &&
87710792SRod.Evans@Sun.COM 	    (nsdflags & FLG_SY_SPECSEC) &&
8786206Sab196087 #if	defined(_ELF64)
8791682Srie 	    (nsym->st_shndx == SHN_COMMON)) ||
8806206Sab196087 	    ((ld_targ.t_m.m_mach == EM_AMD64) &&
8816206Sab196087 	    (sdp->sd_flags & FLG_SY_SPECSEC) &&
8821682Srie 	    (sdp->sd_sym->st_shndx == SHN_X86_64_LCOMMON) &&
88310792SRod.Evans@Sun.COM 	    (nsdflags & FLG_SY_SPECSEC) &&
8841682Srie 	    (nsym->st_shndx == SHN_X86_64_LCOMMON))) {
885574Sseizo #else
8861682Srie 	    (nsym->st_shndx == SHN_COMMON))) {
887574Sseizo #endif
8884734Sab196087 	/* END CSTYLED */
8894734Sab196087 
8900Sstevel@tonic-gate 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
8910Sstevel@tonic-gate 		const char	*file;
8920Sstevel@tonic-gate 		Xword		salign;
8930Sstevel@tonic-gate 		Xword		balign;
8940Sstevel@tonic-gate 		uint_t		alignscompliment;
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate 		if (osym->st_value < nsym->st_value) {
8970Sstevel@tonic-gate 			salign = osym->st_value;
8980Sstevel@tonic-gate 			balign = nsym->st_value;
8990Sstevel@tonic-gate 		} else {
9000Sstevel@tonic-gate 			salign = nsym->st_value;
9010Sstevel@tonic-gate 			balign = osym->st_value;
9020Sstevel@tonic-gate 		}
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 		/*
9050Sstevel@tonic-gate 		 * If the smaller alignment fits smoothly into the
9060Sstevel@tonic-gate 		 * larger alignment - we take it with no warning.
9070Sstevel@tonic-gate 		 */
9080Sstevel@tonic-gate 		if (S_ALIGN(balign, salign) == balign)
9090Sstevel@tonic-gate 			alignscompliment = 1;
9100Sstevel@tonic-gate 		else
9110Sstevel@tonic-gate 			alignscompliment = 0;
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
914*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_WARNING,
9151618Srie 			    MSG_INTL(MSG_SYM_DIFFATTR), demangle(sdp->sd_name),
9160Sstevel@tonic-gate 			    MSG_INTL(MSG_STR_ALIGNMENTS),
9170Sstevel@tonic-gate 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_value),
9180Sstevel@tonic-gate 			    ifl->ifl_name, EC_XWORD(nsym->st_value));
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 		/*
9210Sstevel@tonic-gate 		 * Having provided the necessary warning indicate which
9220Sstevel@tonic-gate 		 * relocatable object we are going to take.
9230Sstevel@tonic-gate 		 *
92410167SRod.Evans@Sun.COM 		 *  -	if one symbol is weak and the other is non-weak
9250Sstevel@tonic-gate 		 *	take the non-weak symbol, else
9260Sstevel@tonic-gate 		 *
92710167SRod.Evans@Sun.COM 		 *  -	take the largest alignment (as we still have to check
9280Sstevel@tonic-gate 		 *	the symbols size simply save the largest value for
9290Sstevel@tonic-gate 		 *	updating later).
9300Sstevel@tonic-gate 		 */
9310Sstevel@tonic-gate 		if ((obind == STB_WEAK) && (nbind != STB_WEAK))
9320Sstevel@tonic-gate 			file = ifl->ifl_name;
9330Sstevel@tonic-gate 		else if (obind != nbind)
9340Sstevel@tonic-gate 			file = sdp->sd_file->ifl_name;
9350Sstevel@tonic-gate 		else {
9360Sstevel@tonic-gate 			emsg = MSG_INTL(MSG_SYM_LARGER);
9370Sstevel@tonic-gate 			value = balign;
9380Sstevel@tonic-gate 		}
9390Sstevel@tonic-gate 		if (!(ofl->ofl_flags & FLG_OF_NOWARN) && !alignscompliment)
940*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, emsg, file);
9410Sstevel@tonic-gate 	}
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 	/*
9440Sstevel@tonic-gate 	 * Check the size of the symbols.
9450Sstevel@tonic-gate 	 */
9460Sstevel@tonic-gate 	if (osym->st_size != nsym->st_size) {
9470Sstevel@tonic-gate 		const char	*emsg = MSG_INTL(MSG_SYM_DEFTAKEN);
9480Sstevel@tonic-gate 		const char	*file;
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
951*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_SYM_DIFFATTR),
952*13074SAli.Bahrami@Oracle.COM 			    demangle(sdp->sd_name), MSG_INTL(MSG_STR_SIZES),
953*13074SAli.Bahrami@Oracle.COM 			    sdp->sd_file->ifl_name, EC_XWORD(osym->st_size),
954*13074SAli.Bahrami@Oracle.COM 			    ifl->ifl_name, EC_XWORD(nsym->st_size));
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 		/*
9580Sstevel@tonic-gate 		 * This symbol has already been compared to an SO definition,
9590Sstevel@tonic-gate 		 * as per the runtime behavior, ignore extra definitions.
9600Sstevel@tonic-gate 		 */
9610Sstevel@tonic-gate 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN)) {
9620Sstevel@tonic-gate 			if (!(ofl->ofl_flags & FLG_OF_NOWARN))
963*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_NONE, emsg,
9640Sstevel@tonic-gate 				    sdp->sd_file->ifl_name);
9650Sstevel@tonic-gate 			return;
9660Sstevel@tonic-gate 		}
9670Sstevel@tonic-gate 
9680Sstevel@tonic-gate 		/*
9690Sstevel@tonic-gate 		 * Having provided the necessary warning indicate what course
9700Sstevel@tonic-gate 		 * of action we are going to take.
9710Sstevel@tonic-gate 		 *
97210167SRod.Evans@Sun.COM 		 *  -	if the file types differ, take the relocatable object
9730Sstevel@tonic-gate 		 *	and apply the largest symbol size, else
97410167SRod.Evans@Sun.COM 		 *  -	if one symbol is weak and the other is non-weak, take
9750Sstevel@tonic-gate 		 *	the non-weak symbol, else
97610167SRod.Evans@Sun.COM 		 *  -	simply take the largest symbol reference.
9770Sstevel@tonic-gate 		 */
9780Sstevel@tonic-gate 		if (nfile != ofile) {
9790Sstevel@tonic-gate 			if (nfile == ET_REL) {
9800Sstevel@tonic-gate 				file = ifl->ifl_name;
9810Sstevel@tonic-gate 				if (osym->st_size > nsym->st_size) {
9820Sstevel@tonic-gate 					size = (size_t)osym->st_size;
9830Sstevel@tonic-gate 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
9840Sstevel@tonic-gate 				}
9850Sstevel@tonic-gate 				sym_override(sdp, nsym, ifl, ofl, ndx,
98610792SRod.Evans@Sun.COM 				    nshndx, nsdflags);
9870Sstevel@tonic-gate 			} else {
9880Sstevel@tonic-gate 				file = sdp->sd_file->ifl_name;
9890Sstevel@tonic-gate 				if (osym->st_size < nsym->st_size) {
9900Sstevel@tonic-gate 					size = (size_t)nsym->st_size;
9910Sstevel@tonic-gate 					emsg = MSG_INTL(MSG_SYM_DEFUPDATE);
9920Sstevel@tonic-gate 				}
9930Sstevel@tonic-gate 				sym_promote(sdp, nsym, ifl, ofl, ndx,
99410792SRod.Evans@Sun.COM 				    nshndx, nsdflags);
9950Sstevel@tonic-gate 			}
9960Sstevel@tonic-gate 		} else if (obind != nbind) {
9970Sstevel@tonic-gate 			if ((obind == STB_WEAK) && (nbind != STB_WEAK)) {
9980Sstevel@tonic-gate 				sym_override(sdp, nsym, ifl, ofl, ndx,
99910792SRod.Evans@Sun.COM 				    nshndx, nsdflags);
10000Sstevel@tonic-gate 				file = ifl->ifl_name;
10010Sstevel@tonic-gate 			} else
10020Sstevel@tonic-gate 				file = sdp->sd_file->ifl_name;
10030Sstevel@tonic-gate 		} else {
10040Sstevel@tonic-gate 			if (osym->st_size < nsym->st_size) {
10050Sstevel@tonic-gate 				sym_override(sdp, nsym, ifl, ofl, ndx,
100610792SRod.Evans@Sun.COM 				    nshndx, nsdflags);
10070Sstevel@tonic-gate 				file = ifl->ifl_name;
10080Sstevel@tonic-gate 			} else
10090Sstevel@tonic-gate 				file = sdp->sd_file->ifl_name;
10100Sstevel@tonic-gate 		}
10110Sstevel@tonic-gate 		if (!(ofl->ofl_flags & FLG_OF_NOWARN))
1012*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, emsg, file);
10130Sstevel@tonic-gate 		if (size)
10140Sstevel@tonic-gate 			sdp->sd_sym->st_size = (Xword)size;
10150Sstevel@tonic-gate 	} else {
10160Sstevel@tonic-gate 		/*
10170Sstevel@tonic-gate 		 * If the sizes are the same
10180Sstevel@tonic-gate 		 *
101910167SRod.Evans@Sun.COM 		 *  -	if the file types differ, take the relocatable object,
10200Sstevel@tonic-gate 		 *	else
10210Sstevel@tonic-gate 		 *
102210167SRod.Evans@Sun.COM 		 *  -	if one symbol is weak and the other is non-weak, take
10230Sstevel@tonic-gate 		 *	the non-weak symbol, else
10240Sstevel@tonic-gate 		 *
102510167SRod.Evans@Sun.COM 		 *  -	take the first reference.
10260Sstevel@tonic-gate 		 */
10270Sstevel@tonic-gate 		if ((sdp->sd_flags & FLG_SY_SOFOUND) && (nfile == ET_DYN))
10280Sstevel@tonic-gate 			return;
10290Sstevel@tonic-gate 		else if (((ofile != nfile) && (nfile == ET_REL)) ||
10300Sstevel@tonic-gate 		    (((obind == STB_WEAK) && (nbind != STB_WEAK)) &&
10310Sstevel@tonic-gate 		    (!((ofile != nfile) && (ofile == ET_REL)))))
10320Sstevel@tonic-gate 			sym_override(sdp, nsym, ifl, ofl, ndx,
103310792SRod.Evans@Sun.COM 			    nshndx, nsdflags);
10340Sstevel@tonic-gate 		else
10350Sstevel@tonic-gate 			sym_promote(sdp, nsym, ifl, ofl, ndx,
103610792SRod.Evans@Sun.COM 			    nshndx, nsdflags);
10370Sstevel@tonic-gate 	}
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	/*
10400Sstevel@tonic-gate 	 * Enforce the largest alignment if necessary.
10410Sstevel@tonic-gate 	 */
10420Sstevel@tonic-gate 	if (value)
10430Sstevel@tonic-gate 		sdp->sd_sym->st_value = value;
10440Sstevel@tonic-gate }
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate /*
10470Sstevel@tonic-gate  * Symbol resolution state table.  `Action' describes the required
10480Sstevel@tonic-gate  * procedure to be called (if any).
10490Sstevel@tonic-gate  */
10500Sstevel@tonic-gate static void (*Action[REF_NUM * SYM_NUM * 2][SYM_NUM])(Sym_desc *,
105110792SRod.Evans@Sun.COM     Sym *, Ifl_desc *, Ofl_desc *, int, Word, sd_flag_t) = {
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate /*				defined		undef		tent	*/
10540Sstevel@tonic-gate /*				ET_REL		ET_REL		ET_REL	*/
10550Sstevel@tonic-gate 
10560Sstevel@tonic-gate /*  0 defined REF_DYN_SEEN */	sym_tworeals,	sym_promote,	sym_realtent,
10570Sstevel@tonic-gate /*  1   undef REF_DYN_SEEN */	sym_override,	sym_override,	sym_override,
10580Sstevel@tonic-gate /*  2    tent REF_DYN_SEEN */	sym_realtent,	sym_promote,	sym_twotent,
10590Sstevel@tonic-gate /*  3 defined REF_DYN_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
10600Sstevel@tonic-gate /*  4   undef REF_DYN_NEED */	sym_override,	sym_override,	sym_override,
10610Sstevel@tonic-gate /*  5    tent REF_DYN_NEED */	sym_realtent,	sym_typecheck,	sym_twotent,
10620Sstevel@tonic-gate /*  6 defined REF_REL_NEED */	sym_tworeals,	sym_typecheck,	sym_realtent,
10630Sstevel@tonic-gate /*  7   undef REF_REL_NEED */	sym_override,	sym_twoundefs,	sym_override,
10640Sstevel@tonic-gate /*  8    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent,
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate /*				defined		undef		tent	*/
10670Sstevel@tonic-gate /*				ET_DYN		ET_DYN		ET_DYN	*/
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate /*  9 defined REF_DYN_SEEN */	sym_tworeals,	sym_null,	sym_realtent,
10700Sstevel@tonic-gate /* 10   undef REF_DYN_SEEN */	sym_override,	sym_mach_check,	sym_override,
10710Sstevel@tonic-gate /* 11    tent REF_DYN_SEEN */	sym_realtent,	sym_null,	sym_twotent,
10720Sstevel@tonic-gate /* 12 defined REF_DYN_NEED */	sym_tworeals,	sym_null,	sym_realtent,
10730Sstevel@tonic-gate /* 13   undef REF_DYN_NEED */	sym_override,	sym_null,	sym_override,
10740Sstevel@tonic-gate /* 14    tent REF_DYN_NEED */	sym_realtent,	sym_null,	sym_twotent,
10750Sstevel@tonic-gate /* 15 defined REF_REL_NEED */	sym_tworeals,	sym_null,	sym_realtent,
10760Sstevel@tonic-gate /* 16   undef REF_REL_NEED */	sym_override,	sym_mach_check,	sym_override,
10770Sstevel@tonic-gate /* 17    tent REF_REL_NEED */	sym_realtent,	sym_null,	sym_twotent
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate };
10800Sstevel@tonic-gate 
10810Sstevel@tonic-gate uintptr_t
10821618Srie ld_sym_resolve(Sym_desc *sdp, Sym *nsym, Ifl_desc *ifl, Ofl_desc *ofl, int ndx,
108310792SRod.Evans@Sun.COM     Word nshndx, sd_flag_t nsdflags)
10840Sstevel@tonic-gate {
10850Sstevel@tonic-gate 	int		row, column;		/* State table coordinates */
10860Sstevel@tonic-gate 	Sym		*osym = sdp->sd_sym;
108711827SRod.Evans@Sun.COM 	sd_flag_t	osdflags = sdp->sd_flags;
10880Sstevel@tonic-gate 	Is_desc		*isp;
10895220Srie 	Half		vis = 0, nfile = ifl->ifl_ehdr->e_type;
10905220Srie 	Half		oref = sdp->sd_ref;
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 	/*
10930Sstevel@tonic-gate 	 * Determine the original symbols definition (defines row in Action[]).
10940Sstevel@tonic-gate 	 */
109511827SRod.Evans@Sun.COM 	if (osdflags & FLG_SY_TENTSYM)
10960Sstevel@tonic-gate 		row = SYM_TENTATIVE;
10971682Srie 	else if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
10981682Srie 	    (sdp->sd_sym->st_shndx == SHN_SUNW_IGNORE))
10990Sstevel@tonic-gate 		row = SYM_UNDEFINED;
11000Sstevel@tonic-gate 	else
11010Sstevel@tonic-gate 		row = SYM_DEFINED;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	/*
11040Sstevel@tonic-gate 	 * If the input file is an implicit shared object then we don't need
11050Sstevel@tonic-gate 	 * to bind to any symbols within it other than to verify that any
11060Sstevel@tonic-gate 	 * undefined references will be closed (implicit shared objects are only
11070Sstevel@tonic-gate 	 * processed when no undefined symbols are required as a result of the
11080Sstevel@tonic-gate 	 * link-edit (see process_dynamic())).
11090Sstevel@tonic-gate 	 */
11100Sstevel@tonic-gate 	if ((nfile == ET_DYN) && !(ifl->ifl_flags & FLG_IF_NEEDED) &&
11110Sstevel@tonic-gate 	    (row != SYM_UNDEFINED))
11120Sstevel@tonic-gate 		return (1);
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 	/*
11150Sstevel@tonic-gate 	 * Finish computing the Action[] row by applying the symbols reference
11160Sstevel@tonic-gate 	 * together with the input files type.
11170Sstevel@tonic-gate 	 */
11180Sstevel@tonic-gate 	row = row + (REF_NUM * sdp->sd_ref);
11190Sstevel@tonic-gate 	if (nfile == ET_DYN)
11200Sstevel@tonic-gate 		row += (REF_NUM * SYM_NUM);
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	/*
11235220Srie 	 * If either the original or new symbol originates from a relocatable
11245220Srie 	 * object, determine the appropriate visibility for the resolved symbol.
11255220Srie 	 */
11265220Srie 	if ((oref == REF_REL_NEED) || (nfile == ET_REL))
11275220Srie 		vis = sym_visibility(sdp, nsym, ifl, ofl);
11285220Srie 
11295220Srie 	/*
11300Sstevel@tonic-gate 	 * Determine the new symbols definition (defines column in Action[]).
11310Sstevel@tonic-gate 	 */
113210792SRod.Evans@Sun.COM 	if ((nsdflags & FLG_SY_SPECSEC) &&
11331682Srie 	    (nsym->st_shndx == SHN_COMMON)) {
11340Sstevel@tonic-gate 		column = SYM_TENTATIVE;
113510792SRod.Evans@Sun.COM 		nsdflags |= FLG_SY_TENTSYM;
11366206Sab196087 #if	defined(_ELF64)
11376206Sab196087 	} else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
113810792SRod.Evans@Sun.COM 	    (nsdflags & FLG_SY_SPECSEC) &&
11391682Srie 	    (nsym->st_shndx == SHN_X86_64_LCOMMON)) {
1140574Sseizo 		column = SYM_TENTATIVE;
114110792SRod.Evans@Sun.COM 		nsdflags |= FLG_SY_TENTSYM;
1142574Sseizo #endif
11431682Srie 	} else if ((nsym->st_shndx == SHN_UNDEF) ||
11441682Srie 	    (nsym->st_shndx == SHN_SUNW_IGNORE)) {
11450Sstevel@tonic-gate 		column = SYM_UNDEFINED;
11460Sstevel@tonic-gate 		nshndx = SHN_UNDEF;
11470Sstevel@tonic-gate 	} else {
11480Sstevel@tonic-gate 		column = SYM_DEFINED;
11490Sstevel@tonic-gate 		/*
11500Sstevel@tonic-gate 		 * If the new symbol is from a shared library and it is
11510Sstevel@tonic-gate 		 * associated with a SHT_NOBITS section then this symbol
11520Sstevel@tonic-gate 		 * originated from a tentative symbol.
11530Sstevel@tonic-gate 		 */
115410792SRod.Evans@Sun.COM 		if (((nsdflags & FLG_SY_SPECSEC) == 0) && (nfile == ET_DYN)) {
11550Sstevel@tonic-gate 			isp = ifl->ifl_isdesc[nshndx];
11560Sstevel@tonic-gate 			if (isp && (isp->is_shdr->sh_type == SHT_NOBITS)) {
11570Sstevel@tonic-gate 				column = SYM_TENTATIVE;
115810792SRod.Evans@Sun.COM 				nsdflags |= FLG_SY_TENTSYM;
11590Sstevel@tonic-gate 			}
11600Sstevel@tonic-gate 		}
11610Sstevel@tonic-gate 	}
11620Sstevel@tonic-gate 
11631618Srie 	DBG_CALL(Dbg_syms_resolving(ofl, ndx, sdp->sd_name, row, column,
11641618Srie 	    osym, nsym, sdp, ifl));
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 	/*
11670Sstevel@tonic-gate 	 * Record the input filename on the defined files list for possible
11680Sstevel@tonic-gate 	 * later diagnostics.  The `sa_dfiles' list is used to maintain the list
11690Sstevel@tonic-gate 	 * of shared objects that define the same symbol.  This list is only
11700Sstevel@tonic-gate 	 * generated when the -m option is in effect and is used to list
11710Sstevel@tonic-gate 	 * multiple (interposed) definitions of a symbol (refer to ldmap_out()).
11720Sstevel@tonic-gate 	 */
11731682Srie 	if ((ofl->ofl_flags & FLG_OF_GENMAP) && (nsym->st_shndx != SHN_UNDEF) &&
117410792SRod.Evans@Sun.COM 	    ((nsdflags & FLG_SY_SPECSEC) == 0))
11759131SRod.Evans@Sun.COM 		if (aplist_append(&sdp->sd_aux->sa_dfiles, ifl->ifl_name,
11769131SRod.Evans@Sun.COM 		    AL_CNT_SDP_DFILES) == NULL)
11770Sstevel@tonic-gate 			return (S_ERROR);
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 	/*
11800Sstevel@tonic-gate 	 * Perform the required resolution.
11810Sstevel@tonic-gate 	 */
118210792SRod.Evans@Sun.COM 	Action[row][column](sdp, nsym, ifl, ofl, ndx, nshndx, nsdflags);
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	/*
11855220Srie 	 * Apply any visibility requirements.  If a SINGLETON has been
11865220Srie 	 * established, make sure no symbol reduction indicators remain
11875220Srie 	 * associated with the symbol, and indicate that the symbol can not
11885220Srie 	 * be directly bound to.
11895220Srie 	 */
11905220Srie 	if ((oref == REF_REL_NEED) || (nfile == ET_REL)) {
11915220Srie 		if ((vis == STV_EXPORTED) || (vis == STV_SINGLETON)) {
119210792SRod.Evans@Sun.COM 			sdp->sd_flags &= ~MSK_SY_LOCAL;
11935220Srie 
11945220Srie 			if (vis == STV_EXPORTED)
119510792SRod.Evans@Sun.COM 				sdp->sd_flags |= FLG_SY_EXPORT;
11965220Srie 			else {
119710792SRod.Evans@Sun.COM 				sdp->sd_flags |= (FLG_SY_NDIR | FLG_SY_SINGLE);
11985220Srie 
119910167SRod.Evans@Sun.COM 				if (sdp->sd_ref == REF_REL_NEED) {
120010167SRod.Evans@Sun.COM 					ofl->ofl_flags1 |=
120110167SRod.Evans@Sun.COM 					    (FLG_OF1_NDIRECT | FLG_OF1_NGLBDIR);
120210167SRod.Evans@Sun.COM 				}
12035220Srie 			}
12045220Srie 		} else if (vis == STV_PROTECTED) {
120510792SRod.Evans@Sun.COM 			sdp->sd_flags |= FLG_SY_PROTECT;
12065220Srie 		} else if ((vis == STV_INTERNAL) || (vis == STV_HIDDEN)) {
120710792SRod.Evans@Sun.COM 			sdp->sd_flags |= FLG_SY_HIDDEN;
12085220Srie 		} else if (vis == STV_ELIMINATE) {
120910792SRod.Evans@Sun.COM 			sdp->sd_flags |= (FLG_SY_HIDDEN | FLG_SY_ELIM);
12105220Srie 		}
12115220Srie 
12125220Srie 		sdp->sd_sym->st_other =
12135220Srie 		    (sdp->sd_sym->st_other & ~MSK_SYM_VISIBILITY) | vis;
12145220Srie 	}
12155220Srie 
12165220Srie 	/*
12170Sstevel@tonic-gate 	 * If the symbol has been resolved to the new input file, and this is
12180Sstevel@tonic-gate 	 * a versioned relocatable object, then the version information of the
12190Sstevel@tonic-gate 	 * new symbol must be promoted to the versioning of the output file.
12200Sstevel@tonic-gate 	 */
12210Sstevel@tonic-gate 	if ((sdp->sd_file == ifl) && (nfile == ET_REL) && (ifl->ifl_versym) &&
12221682Srie 	    (nsym->st_shndx != SHN_UNDEF))
12231618Srie 		ld_vers_promote(sdp, ndx, ifl, ofl);
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	/*
12260Sstevel@tonic-gate 	 * Determine whether a mapfile reference has been satisfied.  Mapfile
12270Sstevel@tonic-gate 	 * symbol references augment symbols that should be contributed from
12280Sstevel@tonic-gate 	 * the relocatable objects used to build the output image.  If a
12290Sstevel@tonic-gate 	 * relocatable object doesn't provide one of the mapfile symbol
12300Sstevel@tonic-gate 	 * references then somethings amiss, and will be flagged during symbol
12310Sstevel@tonic-gate 	 * validation.
12320Sstevel@tonic-gate 	 */
12330Sstevel@tonic-gate 	if ((nfile == ET_REL) && ((sdp->sd_flags &
12340Sstevel@tonic-gate 	    (FLG_SY_MAPREF | FLG_SY_MAPUSED)) == FLG_SY_MAPREF)) {
12350Sstevel@tonic-gate 		/*
12360Sstevel@tonic-gate 		 * Extern and parent references are satisfied by references from
12370Sstevel@tonic-gate 		 * a relocatable object.  Note that we let *any* symbol type
12380Sstevel@tonic-gate 		 * satisfy this reference, to be as flexible as possible with
12390Sstevel@tonic-gate 		 * user written mapfiles.  It could be questionable, for
12400Sstevel@tonic-gate 		 * example, if what a user expects to be an extern reference is
12410Sstevel@tonic-gate 		 * actually found to be a definition in a relocatable object.
12420Sstevel@tonic-gate 		 *
12430Sstevel@tonic-gate 		 * Any other mapfile reference (typically for versioning
12440Sstevel@tonic-gate 		 * information) simply augments a relocatables definition.
12450Sstevel@tonic-gate 		 */
12460Sstevel@tonic-gate 		if ((sdp->sd_flags & (FLG_SY_EXTERN | FLG_SY_PARENT)) ||
12471682Srie 		    ((sdp->sd_sym->st_shndx != SHN_UNDEF) &&
12480Sstevel@tonic-gate 		    (sdp->sd_ref == REF_REL_NEED)))
12490Sstevel@tonic-gate 			sdp->sd_flags |= FLG_SY_MAPUSED;
12500Sstevel@tonic-gate 	}
12510Sstevel@tonic-gate 
125211827SRod.Evans@Sun.COM 	/*
125311827SRod.Evans@Sun.COM 	 * Make sure any special symbol requirements are carried over.
125411827SRod.Evans@Sun.COM 	 */
125511827SRod.Evans@Sun.COM 	if ((osdflags & FLG_SY_CAP) || (nsdflags & FLG_SY_CAP))
125611827SRod.Evans@Sun.COM 		sdp->sd_flags |= FLG_SY_CAP;
125711827SRod.Evans@Sun.COM 
12581618Srie 	DBG_CALL(Dbg_syms_resolved(ofl, sdp));
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 	return (1);
12610Sstevel@tonic-gate }
1262