xref: /onnv-gate/usr/src/cmd/sgs/libld/common/version.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 /*
23*13074SAli.Bahrami@Oracle.COM  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include	<string.h>
270Sstevel@tonic-gate #include	<stdio.h>
281618Srie #include	<debug.h>
290Sstevel@tonic-gate #include	"msg.h"
300Sstevel@tonic-gate #include	"_libld.h"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate  * Locate a version descriptor.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate Ver_desc *
ld_vers_find(const char * name,Word hash,APlist * alp)369131SRod.Evans@Sun.COM ld_vers_find(const char *name, Word hash, APlist *alp)
370Sstevel@tonic-gate {
389131SRod.Evans@Sun.COM 	Aliste		idx;
390Sstevel@tonic-gate 	Ver_desc	*vdp;
400Sstevel@tonic-gate 
419131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(alp, idx, vdp)) {
420Sstevel@tonic-gate 		if (vdp->vd_hash != hash)
430Sstevel@tonic-gate 			continue;
440Sstevel@tonic-gate 		if (strcmp(vdp->vd_name, name) == 0)
450Sstevel@tonic-gate 			return (vdp);
460Sstevel@tonic-gate 	}
479131SRod.Evans@Sun.COM 	return (NULL);
480Sstevel@tonic-gate }
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * Add a new version descriptor to a version descriptor list.  Note, users of
520Sstevel@tonic-gate  * this are responsible for determining if the version descriptor already
530Sstevel@tonic-gate  * exists (this can reduce the need to allocate storage for descriptor names
540Sstevel@tonic-gate  * until it is determined a descriptor need be created (see map_symbol())).
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate Ver_desc *
ld_vers_desc(const char * name,Word hash,APlist ** alpp)579131SRod.Evans@Sun.COM ld_vers_desc(const char *name, Word hash, APlist **alpp)
580Sstevel@tonic-gate {
590Sstevel@tonic-gate 	Ver_desc	*vdp;
600Sstevel@tonic-gate 
619131SRod.Evans@Sun.COM 	if ((vdp = libld_calloc(sizeof (Ver_desc), 1)) == NULL)
620Sstevel@tonic-gate 		return ((Ver_desc *)S_ERROR);
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	vdp->vd_name = name;
650Sstevel@tonic-gate 	vdp->vd_hash = hash;
660Sstevel@tonic-gate 
679131SRod.Evans@Sun.COM 	if (aplist_append(alpp, vdp, AL_CNT_VERDESCS) == NULL)
680Sstevel@tonic-gate 		return ((Ver_desc *)S_ERROR);
699131SRod.Evans@Sun.COM 
709131SRod.Evans@Sun.COM 	return (vdp);
710Sstevel@tonic-gate }
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate  * Now that all explict files have been processed validate any version
750Sstevel@tonic-gate  * definitions.  Insure that any version references are available (a version
760Sstevel@tonic-gate  * has been defined when it's been assigned an index).  Also calculate the
770Sstevel@tonic-gate  * number of .version section entries that will be required to hold this
780Sstevel@tonic-gate  * information.
790Sstevel@tonic-gate  */
800Sstevel@tonic-gate #define	_NUM_OF_VERS_	40	/* twice as big as the depth for libc version */
810Sstevel@tonic-gate typedef struct {
820Sstevel@tonic-gate 	Ver_desc	**ver_stk;
830Sstevel@tonic-gate 	int 		ver_sp;
840Sstevel@tonic-gate 	int 		ver_lmt;
850Sstevel@tonic-gate } Ver_Stack;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate static uintptr_t
vers_visit_children(Ofl_desc * ofl,Ver_desc * vp,int flag)881618Srie vers_visit_children(Ofl_desc *ofl, Ver_desc *vp, int flag)
890Sstevel@tonic-gate {
909131SRod.Evans@Sun.COM 	Aliste			idx;
910Sstevel@tonic-gate 	Ver_desc		*vdp;
920Sstevel@tonic-gate 	static int		err = 0;
930Sstevel@tonic-gate 	static Ver_Stack	ver_stk = {0, 0, 0};
940Sstevel@tonic-gate 	int			tmp_sp;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	/*
970Sstevel@tonic-gate 	 * If there was any fatal error,
980Sstevel@tonic-gate 	 * just return.
990Sstevel@tonic-gate 	 */
1000Sstevel@tonic-gate 	if (err == S_ERROR)
1010Sstevel@tonic-gate 		return (err);
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	/*
1040Sstevel@tonic-gate 	 * if this is called from, ver_check_defs(), initialize sp.
1050Sstevel@tonic-gate 	 */
1060Sstevel@tonic-gate 	if (flag == 0)
1070Sstevel@tonic-gate 		ver_stk.ver_sp = 0;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	/*
1100Sstevel@tonic-gate 	 * Check if passed version pointer vp is already in the stack.
1110Sstevel@tonic-gate 	 */
1120Sstevel@tonic-gate 	for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) {
1130Sstevel@tonic-gate 		Ver_desc *v;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 		v = ver_stk.ver_stk[tmp_sp];
1160Sstevel@tonic-gate 		if (v == vp) {
1170Sstevel@tonic-gate 			/*
1180Sstevel@tonic-gate 			 * cyclic dependency.
1190Sstevel@tonic-gate 			 */
1200Sstevel@tonic-gate 			if (err == 0) {
121*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_FATAL,
1221618Srie 				    MSG_INTL(MSG_VER_CYCLIC));
1230Sstevel@tonic-gate 				err = 1;
1240Sstevel@tonic-gate 			}
1250Sstevel@tonic-gate 			for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) {
1260Sstevel@tonic-gate 				v = ver_stk.ver_stk[tmp_sp];
1270Sstevel@tonic-gate 				if ((v->vd_flags & FLG_VER_CYCLIC) == 0) {
1280Sstevel@tonic-gate 					v->vd_flags |= FLG_VER_CYCLIC;
129*13074SAli.Bahrami@Oracle.COM 					ld_eprintf(ofl, ERR_NONE,
1301618Srie 					    MSG_INTL(MSG_VER_ADDVER),
1311618Srie 					    v->vd_name);
1320Sstevel@tonic-gate 				}
1330Sstevel@tonic-gate 			}
1340Sstevel@tonic-gate 			if ((vp->vd_flags & FLG_VER_CYCLIC) == 0) {
1350Sstevel@tonic-gate 				vp->vd_flags |= FLG_VER_CYCLIC;
136*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_NONE,
1371618Srie 				    MSG_INTL(MSG_VER_ADDVER), vp->vd_name);
1380Sstevel@tonic-gate 			}
1390Sstevel@tonic-gate 			return (err);
1400Sstevel@tonic-gate 		}
1410Sstevel@tonic-gate 	}
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	/*
1440Sstevel@tonic-gate 	 * Push version on the stack.
1450Sstevel@tonic-gate 	 */
1460Sstevel@tonic-gate 	if (ver_stk.ver_sp >= ver_stk.ver_lmt) {
1470Sstevel@tonic-gate 		ver_stk.ver_lmt += _NUM_OF_VERS_;
1480Sstevel@tonic-gate 		if ((ver_stk.ver_stk = (Ver_desc **)
1490Sstevel@tonic-gate 		    libld_realloc((void *)ver_stk.ver_stk,
1500Sstevel@tonic-gate 		    ver_stk.ver_lmt * sizeof (Ver_desc *))) == NULL)
1510Sstevel@tonic-gate 			return (S_ERROR);
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate 	ver_stk.ver_stk[(ver_stk.ver_sp)++] = vp;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	/*
1560Sstevel@tonic-gate 	 * Now visit children.
1570Sstevel@tonic-gate 	 */
1589131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(vp->vd_deps, idx, vdp))
1591618Srie 		if (vers_visit_children(ofl, vdp, 1) == S_ERROR)
1600Sstevel@tonic-gate 			return (S_ERROR);
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	/*
1630Sstevel@tonic-gate 	 * Pop version from the stack.
1640Sstevel@tonic-gate 	 */
1650Sstevel@tonic-gate 	(ver_stk.ver_sp)--;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	return (err);
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate uintptr_t
ld_vers_check_defs(Ofl_desc * ofl)1711618Srie ld_vers_check_defs(Ofl_desc *ofl)
1720Sstevel@tonic-gate {
1739131SRod.Evans@Sun.COM 	Aliste		idx1;
1740Sstevel@tonic-gate 	Ver_desc	*vdp;
1750Sstevel@tonic-gate 	uintptr_t 	is_cyclic = 0;
1760Sstevel@tonic-gate 
1771618Srie 	DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, ofl->ofl_name));
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	/*
1800Sstevel@tonic-gate 	 * First check if there are any cyclic dependency
1810Sstevel@tonic-gate 	 */
1829131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp))
1831618Srie 		if ((is_cyclic = vers_visit_children(ofl, vdp, 0)) == S_ERROR)
1840Sstevel@tonic-gate 			return (S_ERROR);
18510792SRod.Evans@Sun.COM 
1860Sstevel@tonic-gate 	if (is_cyclic)
1870Sstevel@tonic-gate 		ofl->ofl_flags |= FLG_OF_FATAL;
1880Sstevel@tonic-gate 
1899131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) {
1900Sstevel@tonic-gate 		Byte		cnt;
1910Sstevel@tonic-gate 		Sym		*sym;
1920Sstevel@tonic-gate 		Sym_desc	*sdp;
1930Sstevel@tonic-gate 		const char	*name = vdp->vd_name;
19410792SRod.Evans@Sun.COM 		uchar_t		bind;
1950Sstevel@tonic-gate 		Ver_desc	*_vdp;
1960Sstevel@tonic-gate 		avl_index_t	where;
1979131SRod.Evans@Sun.COM 		Aliste		idx2;
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 		if (vdp->vd_ndx == 0) {
200*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_FATAL,
2011618Srie 			    MSG_INTL(MSG_VER_UNDEF), name, vdp->vd_ref->vd_name,
2020Sstevel@tonic-gate 			    vdp->vd_ref->vd_file->ifl_name);
2030Sstevel@tonic-gate 			continue;
2040Sstevel@tonic-gate 		}
2050Sstevel@tonic-gate 
2061618Srie 		DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, vdp));
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 		/*
2090Sstevel@tonic-gate 		 * If a version definition contains no symbols this is possibly
2100Sstevel@tonic-gate 		 * a mapfile error.
2110Sstevel@tonic-gate 		 */
2120Sstevel@tonic-gate 		if ((vdp->vd_flags &
2130Sstevel@tonic-gate 		    (VER_FLG_BASE | VER_FLG_WEAK | FLG_VER_REFER)) == 0)
2141618Srie 			DBG_CALL(Dbg_ver_nointerface(ofl->ofl_lml,
2151618Srie 			    vdp->vd_name));
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 		/*
2180Sstevel@tonic-gate 		 * Update the version entry count to account for this new
2190Sstevel@tonic-gate 		 * version descriptor (the count is the size in bytes).
2200Sstevel@tonic-gate 		 */
2210Sstevel@tonic-gate 		ofl->ofl_verdefsz += sizeof (Verdef);
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 		/*
2240Sstevel@tonic-gate 		 * Traverse this versions dependency list to determine what
2250Sstevel@tonic-gate 		 * additional version dependencies we must account for against
2260Sstevel@tonic-gate 		 * this descriptor.
2270Sstevel@tonic-gate 		 */
2280Sstevel@tonic-gate 		cnt = 1;
2299131SRod.Evans@Sun.COM 		for (APLIST_TRAVERSE(vdp->vd_deps, idx2, _vdp)) {
2300Sstevel@tonic-gate #if	defined(__lint)
2310Sstevel@tonic-gate 			/* get lint to think `_vdp' is used... */
2329131SRod.Evans@Sun.COM 			vdp = _vdp;
2330Sstevel@tonic-gate #endif
2340Sstevel@tonic-gate 			cnt++;
2350Sstevel@tonic-gate 		}
2360Sstevel@tonic-gate 		ofl->ofl_verdefsz += (cnt * sizeof (Verdaux));
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 		/*
2390Sstevel@tonic-gate 		 * Except for the base version descriptor, generate an absolute
2400Sstevel@tonic-gate 		 * symbol to reflect this version.
2410Sstevel@tonic-gate 		 */
2420Sstevel@tonic-gate 		if (vdp->vd_flags & VER_FLG_BASE)
2430Sstevel@tonic-gate 			continue;
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 		if (vdp->vd_flags & VER_FLG_WEAK)
2460Sstevel@tonic-gate 			bind = STB_WEAK;
2470Sstevel@tonic-gate 		else
2480Sstevel@tonic-gate 			bind = STB_GLOBAL;
2490Sstevel@tonic-gate 
2501618Srie 		if (sdp = ld_sym_find(name, vdp->vd_hash, &where, ofl)) {
2510Sstevel@tonic-gate 			/*
2520Sstevel@tonic-gate 			 * If the symbol already exists and is undefined or was
2530Sstevel@tonic-gate 			 * defined in a shared library, convert it to an
2540Sstevel@tonic-gate 			 * absolute.
2550Sstevel@tonic-gate 			 */
2561682Srie 			if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
2570Sstevel@tonic-gate 			    (sdp->sd_ref != REF_REL_NEED)) {
2580Sstevel@tonic-gate 				sdp->sd_shndx = sdp->sd_sym->st_shndx = SHN_ABS;
2590Sstevel@tonic-gate 				sdp->sd_sym->st_info =
2605220Srie 				    ELF_ST_INFO(bind, STT_OBJECT);
2610Sstevel@tonic-gate 				sdp->sd_ref = REF_REL_NEED;
26210792SRod.Evans@Sun.COM 				sdp->sd_flags |= (FLG_SY_SPECSEC |
26310792SRod.Evans@Sun.COM 				    FLG_SY_DEFAULT | FLG_SY_EXPDEF);
2640Sstevel@tonic-gate 				sdp->sd_aux->sa_overndx = vdp->vd_ndx;
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 				/*
2670Sstevel@tonic-gate 				 * If the reference originated from a mapfile
2680Sstevel@tonic-gate 				 * insure we mark the symbol as used.
2690Sstevel@tonic-gate 				 */
2700Sstevel@tonic-gate 				if (sdp->sd_flags & FLG_SY_MAPREF)
2710Sstevel@tonic-gate 					sdp->sd_flags |= FLG_SY_MAPUSED;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 			} else if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
2741682Srie 			    (sdp->sd_sym->st_shndx != SHN_ABS) &&
2750Sstevel@tonic-gate 			    (sdp->sd_ref == REF_REL_NEED)) {
276*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_WARNING,
2771618Srie 				    MSG_INTL(MSG_VER_DEFINED), name,
2781618Srie 				    sdp->sd_file->ifl_name);
2790Sstevel@tonic-gate 			}
2800Sstevel@tonic-gate 		} else {
2810Sstevel@tonic-gate 			/*
2820Sstevel@tonic-gate 			 * If the symbol does not exist create it.
2830Sstevel@tonic-gate 			 */
2849131SRod.Evans@Sun.COM 			if ((sym = libld_calloc(sizeof (Sym), 1)) == NULL)
2850Sstevel@tonic-gate 				return (S_ERROR);
2869131SRod.Evans@Sun.COM 
2870Sstevel@tonic-gate 			sym->st_shndx = SHN_ABS;
2880Sstevel@tonic-gate 			sym->st_info = ELF_ST_INFO(bind, STT_OBJECT);
2891618Srie 			DBG_CALL(Dbg_ver_symbol(ofl->ofl_lml, name));
2909131SRod.Evans@Sun.COM 
2911618Srie 			if ((sdp = ld_sym_enter(name, sym, vdp->vd_hash,
29210792SRod.Evans@Sun.COM 			    vdp->vd_file, ofl, 0, SHN_ABS,
29310792SRod.Evans@Sun.COM 			    (FLG_SY_SPECSEC | FLG_SY_DEFAULT | FLG_SY_EXPDEF),
2945220Srie 			    &where)) == (Sym_desc *)S_ERROR)
2950Sstevel@tonic-gate 				return (S_ERROR);
2969131SRod.Evans@Sun.COM 
2970Sstevel@tonic-gate 			sdp->sd_ref = REF_REL_NEED;
2980Sstevel@tonic-gate 			sdp->sd_aux->sa_overndx = vdp->vd_ndx;
2990Sstevel@tonic-gate 		}
3000Sstevel@tonic-gate 	}
3010Sstevel@tonic-gate 	return (1);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate /*
3050Sstevel@tonic-gate  * Dereference dependencies as a part of normalizing (allows recursion).
3060Sstevel@tonic-gate  */
3071618Srie static void
vers_derefer(Ifl_desc * ifl,Ver_desc * vdp,int weak)3080Sstevel@tonic-gate vers_derefer(Ifl_desc *ifl, Ver_desc *vdp, int weak)
3090Sstevel@tonic-gate {
3109131SRod.Evans@Sun.COM 	Aliste		idx;
3110Sstevel@tonic-gate 	Ver_desc	*_vdp;
3120Sstevel@tonic-gate 	Ver_index	*vip = &ifl->ifl_verndx[vdp->vd_ndx];
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	/*
3157682SAli.Bahrami@Sun.COM 	 * Set the INFO bit on all dependencies that ld.so.1
3167682SAli.Bahrami@Sun.COM 	 * can skip verification for. These are the dependencies
3177682SAli.Bahrami@Sun.COM 	 * that are inherited by others -- verifying the inheriting
3187682SAli.Bahrami@Sun.COM 	 * version implicitily covers this one.
3197682SAli.Bahrami@Sun.COM 	 *
3207682SAli.Bahrami@Sun.COM 	 * If the head of the list was a weak then we only mark
3210Sstevel@tonic-gate 	 * weak dependencies, but if the head of the list was 'strong'
3227682SAli.Bahrami@Sun.COM 	 * we set INFO on all dependencies.
3230Sstevel@tonic-gate 	 */
3240Sstevel@tonic-gate 	if ((weak && (vdp->vd_flags & VER_FLG_WEAK)) || (!weak))
3257682SAli.Bahrami@Sun.COM 		vip->vi_flags |= VER_FLG_INFO;
3260Sstevel@tonic-gate 
3279131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp))
3280Sstevel@tonic-gate 		vers_derefer(ifl, _vdp, weak);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate /*
3320Sstevel@tonic-gate  * If we need to record the versions of any needed dependencies traverse the
3330Sstevel@tonic-gate  * shared object dependency list and calculate what version needed entries are
3340Sstevel@tonic-gate  * required.
3350Sstevel@tonic-gate  */
3360Sstevel@tonic-gate uintptr_t
ld_vers_check_need(Ofl_desc * ofl)3371618Srie ld_vers_check_need(Ofl_desc *ofl)
3380Sstevel@tonic-gate {
3399131SRod.Evans@Sun.COM 	Aliste		idx1;
3400Sstevel@tonic-gate 	Ifl_desc	*ifl;
3417682SAli.Bahrami@Sun.COM 	Half		needndx;
34211803SAli.Bahrami@Sun.COM 	Str_tbl		*strtbl;
34311803SAli.Bahrami@Sun.COM 
34411803SAli.Bahrami@Sun.COM 
34511803SAli.Bahrami@Sun.COM 	/*
34611803SAli.Bahrami@Sun.COM 	 * Determine which string table is appropriate.
34711803SAli.Bahrami@Sun.COM 	 */
34811803SAli.Bahrami@Sun.COM 	strtbl = (OFL_IS_STATIC_OBJ(ofl)) ? ofl->ofl_strtab :
34911803SAli.Bahrami@Sun.COM 	    ofl->ofl_dynstrtab;
3507682SAli.Bahrami@Sun.COM 
3517682SAli.Bahrami@Sun.COM 	/*
3527682SAli.Bahrami@Sun.COM 	 * Versym indexes for needed versions start with the next
3537682SAli.Bahrami@Sun.COM 	 * available version after the final definied version.
3547682SAli.Bahrami@Sun.COM 	 * However, it can never be less than 2. 0 is always for local
3557682SAli.Bahrami@Sun.COM 	 * scope, and 1 is always the first global definition.
3567682SAli.Bahrami@Sun.COM 	 */
3577682SAli.Bahrami@Sun.COM 	needndx = (ofl->ofl_vercnt > 0) ? (ofl->ofl_vercnt + 1) : 2;
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	/*
3600Sstevel@tonic-gate 	 * Traverse the shared object list looking for dependencies.
3610Sstevel@tonic-gate 	 */
3629131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(ofl->ofl_sos, idx1, ifl)) {
3639131SRod.Evans@Sun.COM 		Aliste		idx2;
3640Sstevel@tonic-gate 		Ver_index	*vip;
3650Sstevel@tonic-gate 		Ver_desc	*vdp;
3667682SAli.Bahrami@Sun.COM 		Byte		cnt, need = 0;
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 		if (!(ifl->ifl_flags & FLG_IF_NEEDED))
3690Sstevel@tonic-gate 			continue;
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 		if (ifl->ifl_vercnt <= VER_NDX_GLOBAL)
3720Sstevel@tonic-gate 			continue;
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 		/*
3750Sstevel@tonic-gate 		 * Scan the version index list and if any weak version
3760Sstevel@tonic-gate 		 * definition has been referenced by the user promote the
3770Sstevel@tonic-gate 		 * dependency to be non-weak.  Weak version dependencies do not
3780Sstevel@tonic-gate 		 * cause fatal errors from the runtime linker, non-weak
3790Sstevel@tonic-gate 		 * dependencies do.
3800Sstevel@tonic-gate 		 */
3817682SAli.Bahrami@Sun.COM 		for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) {
3820Sstevel@tonic-gate 			vip = &ifl->ifl_verndx[cnt];
3830Sstevel@tonic-gate 			vdp = vip->vi_desc;
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 			if ((vip->vi_flags & (FLG_VER_REFER | VER_FLG_WEAK)) ==
3860Sstevel@tonic-gate 			    (FLG_VER_REFER | VER_FLG_WEAK))
3870Sstevel@tonic-gate 				vdp->vd_flags &= ~VER_FLG_WEAK;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 			/*
3900Sstevel@tonic-gate 			 * Mark any weak reference as referred to so as to
3910Sstevel@tonic-gate 			 * simplify normalization and later version dependency
3920Sstevel@tonic-gate 			 * manipulation.
3930Sstevel@tonic-gate 			 */
3940Sstevel@tonic-gate 			if (vip->vi_flags & VER_FLG_WEAK)
3950Sstevel@tonic-gate 				vip->vi_flags |= FLG_VER_REFER;
3960Sstevel@tonic-gate 		}
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 		/*
3990Sstevel@tonic-gate 		 * Scan the version dependency list to normalize the referenced
4000Sstevel@tonic-gate 		 * dependencies.  Any needed version that is inherited by
4019131SRod.Evans@Sun.COM 		 * another like version is dereferenced as it is not necessary
4020Sstevel@tonic-gate 		 * to make this part of the version dependencies.
4030Sstevel@tonic-gate 		 */
4049131SRod.Evans@Sun.COM 		for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) {
4059131SRod.Evans@Sun.COM 			Aliste		idx3;
4060Sstevel@tonic-gate 			Ver_desc	*_vdp;
4070Sstevel@tonic-gate 			int		type;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 			vip = &ifl->ifl_verndx[vdp->vd_ndx];
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 			if (!(vip->vi_flags & FLG_VER_REFER))
4120Sstevel@tonic-gate 				continue;
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 			type = vdp->vd_flags & VER_FLG_WEAK;
4159131SRod.Evans@Sun.COM 			for (APLIST_TRAVERSE(vdp->vd_deps, idx3, _vdp))
4160Sstevel@tonic-gate 				vers_derefer(ifl, _vdp, type);
4170Sstevel@tonic-gate 		}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 		/*
4200Sstevel@tonic-gate 		 * Finally, determine how many of the version dependencies need
4210Sstevel@tonic-gate 		 * to be recorded.
4220Sstevel@tonic-gate 		 */
4237682SAli.Bahrami@Sun.COM 		for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) {
4240Sstevel@tonic-gate 			vip = &ifl->ifl_verndx[cnt];
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 			/*
4270Sstevel@tonic-gate 			 * If a version has been referenced then record it as a
4280Sstevel@tonic-gate 			 * version dependency.
4290Sstevel@tonic-gate 			 */
4300Sstevel@tonic-gate 			if (vip->vi_flags & FLG_VER_REFER) {
4317682SAli.Bahrami@Sun.COM 				/* Assign a VERSYM index for it */
4327682SAli.Bahrami@Sun.COM 				vip->vi_overndx = needndx++;
4337682SAli.Bahrami@Sun.COM 
4340Sstevel@tonic-gate 				ofl->ofl_verneedsz += sizeof (Vernaux);
43511803SAli.Bahrami@Sun.COM 				if (st_insert(strtbl, vip->vi_name) == -1)
4360Sstevel@tonic-gate 					return (S_ERROR);
4370Sstevel@tonic-gate 				need++;
4380Sstevel@tonic-gate 			}
4390Sstevel@tonic-gate 		}
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 		if (need) {
4420Sstevel@tonic-gate 			ifl->ifl_flags |= FLG_IF_VERNEED;
4430Sstevel@tonic-gate 			ofl->ofl_verneedsz += sizeof (Verneed);
44411803SAli.Bahrami@Sun.COM 			if (st_insert(strtbl, ifl->ifl_soname) == -1)
4450Sstevel@tonic-gate 				return (S_ERROR);
4460Sstevel@tonic-gate 		}
4470Sstevel@tonic-gate 	}
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	/*
4500Sstevel@tonic-gate 	 * If no version needed information is required unset the output file
4510Sstevel@tonic-gate 	 * flag.
4520Sstevel@tonic-gate 	 */
4530Sstevel@tonic-gate 	if (ofl->ofl_verneedsz == 0)
4540Sstevel@tonic-gate 		ofl->ofl_flags &= ~FLG_OF_VERNEED;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	return (1);
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate /*
4600Sstevel@tonic-gate  * Indicate dependency selection (allows recursion).
4610Sstevel@tonic-gate  */
4621618Srie static void
vers_select(Ofl_desc * ofl,Ifl_desc * ifl,Ver_desc * vdp,const char * ref)4631618Srie vers_select(Ofl_desc *ofl, Ifl_desc *ifl, Ver_desc *vdp, const char *ref)
4640Sstevel@tonic-gate {
4659131SRod.Evans@Sun.COM 	Aliste		idx;
4660Sstevel@tonic-gate 	Ver_desc	*_vdp;
4670Sstevel@tonic-gate 	Ver_index	*vip = &ifl->ifl_verndx[vdp->vd_ndx];
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	vip->vi_flags |= FLG_VER_AVAIL;
4701618Srie 	DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, ref));
4710Sstevel@tonic-gate 
4729131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp))
4731618Srie 		vers_select(ofl, ifl, _vdp, ref);
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate 
4761618Srie static Ver_index *
vers_index(Ofl_desc * ofl,Ifl_desc * ifl,int avail)4771618Srie vers_index(Ofl_desc *ofl, Ifl_desc *ifl, int avail)
4780Sstevel@tonic-gate {
4799131SRod.Evans@Sun.COM 	Aliste		idx1;
4800Sstevel@tonic-gate 	Ver_desc	*vdp;
4810Sstevel@tonic-gate 	Ver_index	*vip;
4820Sstevel@tonic-gate 	Sdf_desc	*sdf = ifl->ifl_sdfdesc;
4830Sstevel@tonic-gate 	Word		count = ifl->ifl_vercnt;
4840Sstevel@tonic-gate 	Sdv_desc	*sdv;
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	/*
4870Sstevel@tonic-gate 	 * Allocate an index array large enough to hold all of the files
4880Sstevel@tonic-gate 	 * version descriptors.
4890Sstevel@tonic-gate 	 */
4909131SRod.Evans@Sun.COM 	if ((vip = libld_calloc(sizeof (Ver_index), (count + 1))) == NULL)
4910Sstevel@tonic-gate 		return ((Ver_index *)S_ERROR);
4920Sstevel@tonic-gate 
4939131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx1, vdp)) {
4949131SRod.Evans@Sun.COM 		int	ndx = vdp->vd_ndx;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 		vip[ndx].vi_name = vdp->vd_name;
4970Sstevel@tonic-gate 		vip[ndx].vi_desc = vdp;
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 		/*
5000Sstevel@tonic-gate 		 * Any relocatable object versions, and the `base' version are
5010Sstevel@tonic-gate 		 * always available.
5020Sstevel@tonic-gate 		 */
5030Sstevel@tonic-gate 		if (avail || (vdp->vd_flags & VER_FLG_BASE))
5040Sstevel@tonic-gate 			vip[ndx].vi_flags |= FLG_VER_AVAIL;
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 		/*
5070Sstevel@tonic-gate 		 * If this is a weak version mark it as such.  Weak versions
5080Sstevel@tonic-gate 		 * are always dragged into any version dependencies created,
5090Sstevel@tonic-gate 		 * and if a weak version is referenced it will be promoted to
5100Sstevel@tonic-gate 		 * a non-weak version dependency.
5110Sstevel@tonic-gate 		 */
5120Sstevel@tonic-gate 		if (vdp->vd_flags & VER_FLG_WEAK)
5130Sstevel@tonic-gate 			vip[ndx].vi_flags |= VER_FLG_WEAK;
5140Sstevel@tonic-gate 		/*
5159878SAli.Bahrami@Sun.COM 		 * If this version is mentioned in a mapfile using ADDVERS
5169878SAli.Bahrami@Sun.COM 		 * syntax then check to see if it corresponds to an actual
5179878SAli.Bahrami@Sun.COM 		 * version in the file.
5180Sstevel@tonic-gate 		 */
5199878SAli.Bahrami@Sun.COM 		if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) {
5209131SRod.Evans@Sun.COM 			Aliste	idx2;
5219131SRod.Evans@Sun.COM 
5229131SRod.Evans@Sun.COM 			for (ALIST_TRAVERSE(sdf->sdf_verneed, idx2, sdv)) {
5239131SRod.Evans@Sun.COM 				if (strcmp(vip[ndx].vi_name, sdv->sdv_name))
5249131SRod.Evans@Sun.COM 					continue;
5259131SRod.Evans@Sun.COM 
5269131SRod.Evans@Sun.COM 				vip[ndx].vi_flags |= FLG_VER_REFER;
5279131SRod.Evans@Sun.COM 				sdv->sdv_flags |= FLG_SDV_MATCHED;
5289131SRod.Evans@Sun.COM 				break;
5290Sstevel@tonic-gate 			}
5300Sstevel@tonic-gate 		}
5310Sstevel@tonic-gate 	}
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	/*
5340Sstevel@tonic-gate 	 * if $ADDVER was specified for this object verify that
5350Sstevel@tonic-gate 	 * all of it's dependent upon versions were refered to.
5360Sstevel@tonic-gate 	 */
5370Sstevel@tonic-gate 	if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) {
5380Sstevel@tonic-gate 		int	fail = 0;
5399131SRod.Evans@Sun.COM 
5409131SRod.Evans@Sun.COM 		for (ALIST_TRAVERSE(sdf->sdf_verneed, idx1, sdv)) {
5419131SRod.Evans@Sun.COM 			if (sdv->sdv_flags & FLG_SDV_MATCHED)
5429131SRod.Evans@Sun.COM 				continue;
5439131SRod.Evans@Sun.COM 
5449131SRod.Evans@Sun.COM 			if (fail++ == 0) {
545*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_NONE,
5469131SRod.Evans@Sun.COM 				    MSG_INTL(MSG_VER_ADDVERS), sdf->sdf_rfile,
5479131SRod.Evans@Sun.COM 				    sdf->sdf_name);
5480Sstevel@tonic-gate 			}
549*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_VER_ADDVER),
550*13074SAli.Bahrami@Oracle.COM 			    sdv->sdv_name);
5510Sstevel@tonic-gate 		}
5520Sstevel@tonic-gate 		if (fail)
5530Sstevel@tonic-gate 			return ((Ver_index *)S_ERROR);
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	return (vip);
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate  * Process a version symbol index section.
5610Sstevel@tonic-gate  */
5620Sstevel@tonic-gate int
ld_vers_sym_process(Ofl_desc * ofl,Is_desc * isp,Ifl_desc * ifl)563*13074SAli.Bahrami@Oracle.COM ld_vers_sym_process(Ofl_desc *ofl, Is_desc *isp, Ifl_desc *ifl)
5640Sstevel@tonic-gate {
5650Sstevel@tonic-gate 	Shdr	*symshdr;
5660Sstevel@tonic-gate 	Shdr	*vershdr = isp->is_shdr;
5671618Srie 
5680Sstevel@tonic-gate 	/*
5691618Srie 	 * Verify that the versym is the same size as the linked symbol table.
5701618Srie 	 * If these two get out of sync the file is considered corrupted.
5710Sstevel@tonic-gate 	 */
5720Sstevel@tonic-gate 	symshdr = ifl->ifl_isdesc[vershdr->sh_link]->is_shdr;
5730Sstevel@tonic-gate 	if ((symshdr->sh_size / symshdr->sh_entsize) != (vershdr->sh_size /
5740Sstevel@tonic-gate 	    vershdr->sh_entsize)) {
5759878SAli.Bahrami@Sun.COM 		Is_desc	*sym_isp = ifl->ifl_isdesc[vershdr->sh_link];
5769878SAli.Bahrami@Sun.COM 
577*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ELF_VERSYM),
5789878SAli.Bahrami@Sun.COM 		    ifl->ifl_name, EC_WORD(isp->is_scnndx), isp->is_name,
5791618Srie 		    EC_WORD(vershdr->sh_size / vershdr->sh_entsize),
5809878SAli.Bahrami@Sun.COM 		    EC_WORD(sym_isp->is_scnndx), sym_isp->is_name,
5811618Srie 		    EC_WORD(symshdr->sh_size / symshdr->sh_entsize));
5820Sstevel@tonic-gate 		return (1);
5830Sstevel@tonic-gate 	}
5840Sstevel@tonic-gate 	ifl->ifl_versym = (Versym *)isp->is_indata->d_buf;
5850Sstevel@tonic-gate 	return (1);
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate /*
5890Sstevel@tonic-gate  * Process a version definition section from an input file.  A list of version
5900Sstevel@tonic-gate  * descriptors is created and associated with the input files descriptor.  If
5910Sstevel@tonic-gate  * this is a shared object these descriptors will be used to indicate the
5920Sstevel@tonic-gate  * availability of each version.  If this is a relocatable object then these
5930Sstevel@tonic-gate  * descriptors will be promoted (concatenated) to the output files image.
5940Sstevel@tonic-gate  */
5950Sstevel@tonic-gate uintptr_t
ld_vers_def_process(Is_desc * isp,Ifl_desc * ifl,Ofl_desc * ofl)5961618Srie ld_vers_def_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl)
5970Sstevel@tonic-gate {
5980Sstevel@tonic-gate 	const char	*str, *file = ifl->ifl_name;
5990Sstevel@tonic-gate 	Sdf_desc	*sdf = ifl->ifl_sdfdesc;
6000Sstevel@tonic-gate 	Sdv_desc	*sdv;
6010Sstevel@tonic-gate 	Word		num, _num;
6020Sstevel@tonic-gate 	Verdef		*vdf;
6030Sstevel@tonic-gate 	int		relobj;
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	/*
6060Sstevel@tonic-gate 	 * If there is no version section then simply indicate that all version
6070Sstevel@tonic-gate 	 * definitions asked for do not exist.
6080Sstevel@tonic-gate 	 */
6099131SRod.Evans@Sun.COM 	if (isp == NULL) {
6109131SRod.Evans@Sun.COM 		Aliste	idx;
6110Sstevel@tonic-gate 
6129131SRod.Evans@Sun.COM 		for (ALIST_TRAVERSE(sdf->sdf_vers, idx, sdv)) {
613*13074SAli.Bahrami@Oracle.COM 			ld_eprintf(ofl, ERR_FATAL,
6141618Srie 			    MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
6151618Srie 			    sdv->sdv_name, sdv->sdv_ref);
6160Sstevel@tonic-gate 		}
6170Sstevel@tonic-gate 		return (0);
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	vdf = (Verdef *)isp->is_indata->d_buf;
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	/*
6230Sstevel@tonic-gate 	 * Verify the version revision.  We only check the first version
6240Sstevel@tonic-gate 	 * structure as it is assumed all other version structures in this
6250Sstevel@tonic-gate 	 * data section will be of the same revision.
6260Sstevel@tonic-gate 	 */
6270Sstevel@tonic-gate 	if (vdf->vd_version > VER_DEF_CURRENT)
628*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_VER_HIGHER),
629*13074SAli.Bahrami@Oracle.COM 		    ifl->ifl_name, vdf->vd_version, VER_DEF_CURRENT);
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	num = isp->is_shdr->sh_info;
6330Sstevel@tonic-gate 	str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf;
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 	if (ifl->ifl_ehdr->e_type == ET_REL)
6360Sstevel@tonic-gate 		relobj = 1;
6370Sstevel@tonic-gate 	else
6380Sstevel@tonic-gate 		relobj = 0;
6390Sstevel@tonic-gate 
6401618Srie 	DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, file));
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	/*
6430Sstevel@tonic-gate 	 * Loop through the version information setting up a version descriptor
6440Sstevel@tonic-gate 	 * for each version definition.
6450Sstevel@tonic-gate 	 */
6460Sstevel@tonic-gate 	for (_num = 1; _num <= num; _num++,
6470Sstevel@tonic-gate 	    vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
6480Sstevel@tonic-gate 		const char	*name;
6499131SRod.Evans@Sun.COM 		Ver_desc	*ivdp, *ovdp = NULL;
6500Sstevel@tonic-gate 		Word		hash;
6510Sstevel@tonic-gate 		Half 		cnt = vdf->vd_cnt;
6520Sstevel@tonic-gate 		Half		ndx = vdf->vd_ndx;
6530Sstevel@tonic-gate 		Verdaux		*vdap = (Verdaux *)((uintptr_t)vdf +
6545220Srie 		    vdf->vd_aux);
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 		/*
6570Sstevel@tonic-gate 		 * Keep track of the largest index for use in creating a
6580Sstevel@tonic-gate 		 * version index array later, and create a version descriptor.
6590Sstevel@tonic-gate 		 */
6600Sstevel@tonic-gate 		if (ndx > ifl->ifl_vercnt)
6610Sstevel@tonic-gate 			ifl->ifl_vercnt = ndx;
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 		name = (char *)(str + vdap->vda_name);
6640Sstevel@tonic-gate 		/* LINTED */
6650Sstevel@tonic-gate 		hash = (Word)elf_hash(name);
6669131SRod.Evans@Sun.COM 		if (((ivdp = ld_vers_find(name, hash,
6679131SRod.Evans@Sun.COM 		    ifl->ifl_verdesc)) == NULL) &&
6689131SRod.Evans@Sun.COM 		    ((ivdp = ld_vers_desc(name, hash,
6699131SRod.Evans@Sun.COM 		    &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR))
6709131SRod.Evans@Sun.COM 			return (S_ERROR);
6719131SRod.Evans@Sun.COM 
6720Sstevel@tonic-gate 		ivdp->vd_ndx = ndx;
6730Sstevel@tonic-gate 		ivdp->vd_file = ifl;
6740Sstevel@tonic-gate 		ivdp->vd_flags = vdf->vd_flags;
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 		/*
6770Sstevel@tonic-gate 		 * If we're processing a relocatable object then this version
6780Sstevel@tonic-gate 		 * definition needs to be propagated to the output file.
6790Sstevel@tonic-gate 		 * Generate a new output file version and associated this input
6800Sstevel@tonic-gate 		 * version to it.  During symbol processing the version index of
6810Sstevel@tonic-gate 		 * the symbol will be promoted from the input file to the output
6820Sstevel@tonic-gate 		 * files version definition.
6830Sstevel@tonic-gate 		 */
6840Sstevel@tonic-gate 		if (relobj) {
6850Sstevel@tonic-gate 			if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
6860Sstevel@tonic-gate 				ofl->ofl_flags |= FLG_OF_PROCRED;
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 			if ((ivdp->vd_flags & VER_FLG_BASE) == 0) {
6890Sstevel@tonic-gate 				/*
6900Sstevel@tonic-gate 				 * If no version descriptors have yet been set
6910Sstevel@tonic-gate 				 * up, initialize a base version to represent
6920Sstevel@tonic-gate 				 * the output file itself.  This `base' version
6930Sstevel@tonic-gate 				 * catches any internally generated symbols
6940Sstevel@tonic-gate 				 * (_end, _etext, etc.) and
6950Sstevel@tonic-gate 				 * serves to initialize the output version
6960Sstevel@tonic-gate 				 * descriptor count.
6970Sstevel@tonic-gate 				 */
6980Sstevel@tonic-gate 				if (ofl->ofl_vercnt == 0) {
6991618Srie 					if (ld_vers_base(ofl) ==
7000Sstevel@tonic-gate 					    (Ver_desc *)S_ERROR)
7010Sstevel@tonic-gate 						return (S_ERROR);
7020Sstevel@tonic-gate 				}
7030Sstevel@tonic-gate 				ofl->ofl_flags |= FLG_OF_VERDEF;
7041618Srie 				if ((ovdp = ld_vers_find(name, hash,
7059131SRod.Evans@Sun.COM 				    ofl->ofl_verdesc)) == NULL) {
7061618Srie 					if ((ovdp = ld_vers_desc(name, hash,
7070Sstevel@tonic-gate 					    &ofl->ofl_verdesc)) ==
7080Sstevel@tonic-gate 					    (Ver_desc *)S_ERROR)
7090Sstevel@tonic-gate 						return (S_ERROR);
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 					/* LINTED */
7120Sstevel@tonic-gate 					ovdp->vd_ndx = (Half)++ofl->ofl_vercnt;
7130Sstevel@tonic-gate 					ovdp->vd_file = ifl;
7140Sstevel@tonic-gate 					ovdp->vd_flags = vdf->vd_flags;
7150Sstevel@tonic-gate 				}
7160Sstevel@tonic-gate 			}
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 			/*
7190Sstevel@tonic-gate 			 * Maintain the association between the input version
7200Sstevel@tonic-gate 			 * descriptor and the output version descriptor so that
7210Sstevel@tonic-gate 			 * an associated symbols will be assigned to the
7220Sstevel@tonic-gate 			 * correct version.
7230Sstevel@tonic-gate 			 */
7240Sstevel@tonic-gate 			ivdp->vd_ref = ovdp;
7250Sstevel@tonic-gate 		}
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 		/*
7280Sstevel@tonic-gate 		 * Process any dependencies this version may have.
7290Sstevel@tonic-gate 		 */
7300Sstevel@tonic-gate 		vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
7310Sstevel@tonic-gate 		for (cnt--; cnt; cnt--,
7320Sstevel@tonic-gate 		    vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next)) {
7330Sstevel@tonic-gate 			Ver_desc	*_ivdp;
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 			name = (char *)(str + vdap->vda_name);
7360Sstevel@tonic-gate 			/* LINTED */
7370Sstevel@tonic-gate 			hash = (Word)elf_hash(name);
7380Sstevel@tonic-gate 
7399131SRod.Evans@Sun.COM 			if (((_ivdp = ld_vers_find(name, hash,
7409131SRod.Evans@Sun.COM 			    ifl->ifl_verdesc)) == NULL) &&
7419131SRod.Evans@Sun.COM 			    ((_ivdp = ld_vers_desc(name, hash,
7429131SRod.Evans@Sun.COM 			    &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR))
7439131SRod.Evans@Sun.COM 				return (S_ERROR);
7449131SRod.Evans@Sun.COM 
7459131SRod.Evans@Sun.COM 			if (aplist_append(&ivdp->vd_deps, _ivdp,
7469131SRod.Evans@Sun.COM 			    AL_CNT_VERDESCS) == NULL)
7470Sstevel@tonic-gate 				return (S_ERROR);
7480Sstevel@tonic-gate 		}
7491618Srie 		DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, ivdp));
7500Sstevel@tonic-gate 	}
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	/*
7530Sstevel@tonic-gate 	 * Now that we know the total number of version definitions for this
7540Sstevel@tonic-gate 	 * file, build an index array for fast access when processing symbols.
7550Sstevel@tonic-gate 	 */
7561618Srie 	if ((ifl->ifl_verndx =
7571618Srie 	    vers_index(ofl, ifl, relobj)) == (Ver_index *)S_ERROR)
7580Sstevel@tonic-gate 		return (S_ERROR);
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	if (relobj)
7610Sstevel@tonic-gate 		return (1);
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	/*
7640Sstevel@tonic-gate 	 * If this object has version control definitions against it then these
7650Sstevel@tonic-gate 	 * must be processed so as to select those version definitions to which
7660Sstevel@tonic-gate 	 * symbol bindings can occur.  Otherwise simply mark all versions as
7670Sstevel@tonic-gate 	 * available.
7680Sstevel@tonic-gate 	 */
7691618Srie 	DBG_CALL(Dbg_ver_avail_title(ofl->ofl_lml, file));
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	if (sdf && (sdf->sdf_flags & FLG_SDF_SELECT)) {
7729131SRod.Evans@Sun.COM 		Aliste	idx1;
7730Sstevel@tonic-gate 
7749131SRod.Evans@Sun.COM 		for (ALIST_TRAVERSE(sdf->sdf_vers, idx1, sdv)) {
7759131SRod.Evans@Sun.COM 			Aliste		idx2;
7760Sstevel@tonic-gate 			Ver_desc	*vdp;
7770Sstevel@tonic-gate 			int		found = 0;
7780Sstevel@tonic-gate 
7799131SRod.Evans@Sun.COM 			for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) {
7800Sstevel@tonic-gate 				if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) {
7810Sstevel@tonic-gate 					found++;
7820Sstevel@tonic-gate 					break;
7830Sstevel@tonic-gate 				}
7840Sstevel@tonic-gate 			}
7850Sstevel@tonic-gate 			if (found)
7861618Srie 				vers_select(ofl, ifl, vdp, sdv->sdv_ref);
787*13074SAli.Bahrami@Oracle.COM 			else
788*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_FATAL,
7891618Srie 				    MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
7901618Srie 				    sdv->sdv_name, sdv->sdv_ref);
7910Sstevel@tonic-gate 		}
7920Sstevel@tonic-gate 	} else {
7930Sstevel@tonic-gate 		Ver_index	*vip;
7940Sstevel@tonic-gate 		int		cnt;
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 		for (cnt = VER_NDX_GLOBAL; cnt <= ifl->ifl_vercnt; cnt++) {
7970Sstevel@tonic-gate 			vip = &ifl->ifl_verndx[cnt];
7980Sstevel@tonic-gate 			vip->vi_flags |= FLG_VER_AVAIL;
7991618Srie 			DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, 0));
8000Sstevel@tonic-gate 		}
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	/*
8040Sstevel@tonic-gate 	 * If this is an explict dependency indicate that this file is a
8050Sstevel@tonic-gate 	 * candidate for requiring version needed information to be recorded in
8060Sstevel@tonic-gate 	 * the image we're creating.
8070Sstevel@tonic-gate 	 */
8080Sstevel@tonic-gate 	if (ifl->ifl_flags & FLG_IF_NEEDED)
8090Sstevel@tonic-gate 		ofl->ofl_flags |= FLG_OF_VERNEED;
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	return (1);
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate  * Process a version needed section.
8160Sstevel@tonic-gate  */
8170Sstevel@tonic-gate uintptr_t
ld_vers_need_process(Is_desc * isp,Ifl_desc * ifl,Ofl_desc * ofl)8181618Srie ld_vers_need_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl)
8190Sstevel@tonic-gate {
8200Sstevel@tonic-gate 	const char	*str, *file = ifl->ifl_name;
8210Sstevel@tonic-gate 	Word		num, _num;
8220Sstevel@tonic-gate 	Verneed		*vnd;
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	vnd = (Verneed *)isp->is_indata->d_buf;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	/*
8270Sstevel@tonic-gate 	 * Verify the version revision.  We only check the first version
8280Sstevel@tonic-gate 	 * structure as it is assumed all other version structures in this
8290Sstevel@tonic-gate 	 * data section will be of the same revision.
8300Sstevel@tonic-gate 	 */
8311618Srie 	if (vnd->vn_version > VER_DEF_CURRENT) {
832*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_VER_HIGHER),
833*13074SAli.Bahrami@Oracle.COM 		    ifl->ifl_name, vnd->vn_version, VER_DEF_CURRENT);
8341618Srie 	}
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	num = isp->is_shdr->sh_info;
8370Sstevel@tonic-gate 	str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf;
8380Sstevel@tonic-gate 
8391618Srie 	DBG_CALL(Dbg_ver_need_title(ofl->ofl_lml, file));
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	/*
8420Sstevel@tonic-gate 	 * Loop through the version information setting up a version descriptor
8430Sstevel@tonic-gate 	 * for each version definition.
8440Sstevel@tonic-gate 	 */
8450Sstevel@tonic-gate 	for (_num = 1; _num <= num; _num++,
8460Sstevel@tonic-gate 	    vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
8470Sstevel@tonic-gate 		Sdf_desc	*sdf;
8480Sstevel@tonic-gate 		const char	*name;
8490Sstevel@tonic-gate 		Half		cnt = vnd->vn_cnt;
8500Sstevel@tonic-gate 		Vernaux		*vnap = (Vernaux *)((uintptr_t)vnd +
8515220Srie 		    vnd->vn_aux);
8520Sstevel@tonic-gate 		Half		_cnt;
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 		name = (char *)(str + vnd->vn_file);
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 		/*
8570Sstevel@tonic-gate 		 * Set up a shared object descriptor and add to it the necessary
8580Sstevel@tonic-gate 		 * needed versions.  This information may also have been added
8590Sstevel@tonic-gate 		 * by a mapfile (see map_dash()).
8600Sstevel@tonic-gate 		 */
8619131SRod.Evans@Sun.COM 		if ((sdf = sdf_find(name, ofl->ofl_soneed)) == NULL) {
8620Sstevel@tonic-gate 			if ((sdf = sdf_add(name, &ofl->ofl_soneed)) ==
8630Sstevel@tonic-gate 			    (Sdf_desc *)S_ERROR)
8640Sstevel@tonic-gate 				return (S_ERROR);
8650Sstevel@tonic-gate 			sdf->sdf_rfile = file;
8660Sstevel@tonic-gate 			sdf->sdf_flags |= FLG_SDF_VERIFY;
8670Sstevel@tonic-gate 		}
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate 		for (_cnt = 0; cnt; _cnt++, cnt--,
8700Sstevel@tonic-gate 		    vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next)) {
8719131SRod.Evans@Sun.COM 			Sdv_desc	sdv;
8729131SRod.Evans@Sun.COM 
8739131SRod.Evans@Sun.COM 			sdv.sdv_name = str + vnap->vna_name;
8749131SRod.Evans@Sun.COM 			sdv.sdv_ref = file;
8759131SRod.Evans@Sun.COM 			sdv.sdv_flags = 0;
8769131SRod.Evans@Sun.COM 
8779131SRod.Evans@Sun.COM 			if (alist_append(&sdf->sdf_vers, &sdv,
8789131SRod.Evans@Sun.COM 			    sizeof (Sdv_desc), AL_CNT_SDF_VERSIONS) == NULL)
8790Sstevel@tonic-gate 				return (S_ERROR);
8809131SRod.Evans@Sun.COM 
8811618Srie 			DBG_CALL(Dbg_ver_need_entry(ofl->ofl_lml, _cnt, name,
8829131SRod.Evans@Sun.COM 			    sdv.sdv_name));
8830Sstevel@tonic-gate 		}
8840Sstevel@tonic-gate 	}
8850Sstevel@tonic-gate 	return (1);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate /*
8890Sstevel@tonic-gate  * If a symbol is obtained from a versioned relocatable object then the symbols
8900Sstevel@tonic-gate  * version association must be promoted to the version definition as it will be
8910Sstevel@tonic-gate  * represented in the output file.
8920Sstevel@tonic-gate  */
8930Sstevel@tonic-gate void
ld_vers_promote(Sym_desc * sdp,Word ndx,Ifl_desc * ifl,Ofl_desc * ofl)8941618Srie ld_vers_promote(Sym_desc *sdp, Word ndx, Ifl_desc *ifl, Ofl_desc *ofl)
8950Sstevel@tonic-gate {
8960Sstevel@tonic-gate 	Half 	vndx;
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate 	/*
8990Sstevel@tonic-gate 	 * A version symbol index of 0 implies the symbol is local.  A value of
9000Sstevel@tonic-gate 	 * VER_NDX_GLOBAL implies the symbol is global but has not been
9010Sstevel@tonic-gate 	 * assigned to a specfic version definition.
9020Sstevel@tonic-gate 	 */
9030Sstevel@tonic-gate 	vndx = ifl->ifl_versym[ndx];
9040Sstevel@tonic-gate 	if (vndx == 0) {
90510792SRod.Evans@Sun.COM 		sdp->sd_flags |= (FLG_SY_REDUCED | FLG_SY_HIDDEN);
9060Sstevel@tonic-gate 		return;
9070Sstevel@tonic-gate 	}
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 	if (vndx == VER_NDX_ELIMINATE) {
91010792SRod.Evans@Sun.COM 		sdp->sd_flags |= (FLG_SY_REDUCED | FLG_SY_HIDDEN | FLG_SY_ELIM);
9110Sstevel@tonic-gate 		return;
9120Sstevel@tonic-gate 	}
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	if (vndx == VER_NDX_GLOBAL) {
91511827SRod.Evans@Sun.COM 		if (!SYM_IS_HIDDEN(sdp))
91610792SRod.Evans@Sun.COM 			sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF);
9175220Srie 		if (sdp->sd_aux->sa_overndx <= VER_NDX_GLOBAL)
9180Sstevel@tonic-gate 			sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL;
9190Sstevel@tonic-gate 		return;
9200Sstevel@tonic-gate 	}
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	/*
9230Sstevel@tonic-gate 	 * Any other version index requires association to the appropriate
9240Sstevel@tonic-gate 	 * version definition.
9250Sstevel@tonic-gate 	 */
9260Sstevel@tonic-gate 	if ((ifl->ifl_verndx == 0) || (vndx > ifl->ifl_vercnt)) {
927*13074SAli.Bahrami@Oracle.COM 		ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_VER_INVALNDX),
9281618Srie 		    sdp->sd_name, ifl->ifl_name, vndx);
9290Sstevel@tonic-gate 		return;
9300Sstevel@tonic-gate 	}
9310Sstevel@tonic-gate 
93211827SRod.Evans@Sun.COM 	if (!SYM_IS_HIDDEN(sdp))
93310792SRod.Evans@Sun.COM 		sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	/*
9360Sstevel@tonic-gate 	 * Promote the symbols version index to the appropriate output version
9370Sstevel@tonic-gate 	 * definition.
9380Sstevel@tonic-gate 	 */
9390Sstevel@tonic-gate 	if (!(sdp->sd_flags & FLG_SY_VERSPROM)) {
9400Sstevel@tonic-gate 		Ver_index	*vip;
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 		vip = &ifl->ifl_verndx[vndx];
9430Sstevel@tonic-gate 		sdp->sd_aux->sa_overndx = vip->vi_desc->vd_ref->vd_ndx;
9440Sstevel@tonic-gate 		sdp->sd_flags |= FLG_SY_VERSPROM;
9450Sstevel@tonic-gate 	}
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate /*
9490Sstevel@tonic-gate  * If any versioning is called for make sure an initial version descriptor is
9500Sstevel@tonic-gate  * assigned to represent the file itself.  Known as the base version.
9510Sstevel@tonic-gate  */
9520Sstevel@tonic-gate Ver_desc *
ld_vers_base(Ofl_desc * ofl)9531618Srie ld_vers_base(Ofl_desc *ofl)
9540Sstevel@tonic-gate {
9550Sstevel@tonic-gate 	Ver_desc	*vdp;
9560Sstevel@tonic-gate 	const char	*name;
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 	/*
9590Sstevel@tonic-gate 	 * Determine the filename to associate to the version descriptor.  This
9600Sstevel@tonic-gate 	 * is either the SONAME (if one has been supplied) or the basename of
9610Sstevel@tonic-gate 	 * the output file.
9620Sstevel@tonic-gate 	 */
9639131SRod.Evans@Sun.COM 	if ((name = ofl->ofl_soname) == NULL) {
9640Sstevel@tonic-gate 		const char	*str = ofl->ofl_name;
9650Sstevel@tonic-gate 
9660Sstevel@tonic-gate 		while (*str != '\0') {
9670Sstevel@tonic-gate 			if (*str++ == '/')
9680Sstevel@tonic-gate 				name = str;
9690Sstevel@tonic-gate 		}
9709131SRod.Evans@Sun.COM 		if (name == NULL)
9710Sstevel@tonic-gate 			name = ofl->ofl_name;
9720Sstevel@tonic-gate 	}
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 	/*
9750Sstevel@tonic-gate 	 * Generate the version descriptor.
9760Sstevel@tonic-gate 	 */
9770Sstevel@tonic-gate 	/* LINTED */
9781618Srie 	if ((vdp = ld_vers_desc(name, (Word)elf_hash(name),
9791618Srie 	    &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
9800Sstevel@tonic-gate 		return ((Ver_desc *)S_ERROR);
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 	/*
9830Sstevel@tonic-gate 	 * Assign the base index to this version and initialize the output file
9840Sstevel@tonic-gate 	 * descriptor with the number of version descriptors presently in use.
9850Sstevel@tonic-gate 	 */
9860Sstevel@tonic-gate 	vdp->vd_ndx = ofl->ofl_vercnt = VER_NDX_GLOBAL;
9870Sstevel@tonic-gate 	vdp->vd_flags |= VER_FLG_BASE;
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 	return (vdp);
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate 
9920Sstevel@tonic-gate /*
9930Sstevel@tonic-gate  * Now that all input shared objects have been processed, verify that all
9940Sstevel@tonic-gate  * version requirements have been met.  Any version control requirements will
9950Sstevel@tonic-gate  * have been specified by the user (and placed on the ofl_oscntl list) and are
9960Sstevel@tonic-gate  * verified at the time the object was processed (see ver_def_process()).
9970Sstevel@tonic-gate  * Here we process all version requirements established from shared objects
9980Sstevel@tonic-gate  * themselves (ie,. NEEDED dependencies).
9990Sstevel@tonic-gate  */
10000Sstevel@tonic-gate int
ld_vers_verify(Ofl_desc * ofl)10011618Srie ld_vers_verify(Ofl_desc *ofl)
10020Sstevel@tonic-gate {
10039131SRod.Evans@Sun.COM 	Aliste		idx1;
10040Sstevel@tonic-gate 	Sdf_desc	*sdf;
10050Sstevel@tonic-gate 	char		*nv;
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 	/*
10080Sstevel@tonic-gate 	 * As with the runtime environment, disable all version verification if
10090Sstevel@tonic-gate 	 * requested.
10100Sstevel@tonic-gate 	 */
10110Sstevel@tonic-gate #if	defined(_ELF64)
10120Sstevel@tonic-gate 	if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_64))) == NULL)
10130Sstevel@tonic-gate #else
10140Sstevel@tonic-gate 	if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_32))) == NULL)
10150Sstevel@tonic-gate #endif
10165220Srie 		nv = getenv(MSG_ORIG(MSG_LD_NOVERSION));
10170Sstevel@tonic-gate 
101812029SRod.Evans@Sun.COM 	if (nv && nv[0])
10190Sstevel@tonic-gate 		return (1);
10200Sstevel@tonic-gate 
10219131SRod.Evans@Sun.COM 	for (APLIST_TRAVERSE(ofl->ofl_soneed, idx1, sdf)) {
10229131SRod.Evans@Sun.COM 		Aliste		idx2;
10230Sstevel@tonic-gate 		Sdv_desc	*sdv;
10240Sstevel@tonic-gate 		Ifl_desc	*ifl = sdf->sdf_file;
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate 		if (!(sdf->sdf_flags & FLG_SDF_VERIFY))
10270Sstevel@tonic-gate 			continue;
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 		/*
10300Sstevel@tonic-gate 		 * If this file contains no version definitions then ignore
10310Sstevel@tonic-gate 		 * any versioning verification.  This is the same model as
10320Sstevel@tonic-gate 		 * carried out by ld.so.1 and is intended to allow backward
10330Sstevel@tonic-gate 		 * compatibility should a shared object with a version
10349131SRod.Evans@Sun.COM 		 * requirement be returned to an older system on which a
10350Sstevel@tonic-gate 		 * non-versioned shared object exists.
10360Sstevel@tonic-gate 		 */
10379131SRod.Evans@Sun.COM 		if ((ifl == NULL) || (ifl->ifl_verdesc == NULL))
10380Sstevel@tonic-gate 			continue;
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 		/*
10410Sstevel@tonic-gate 		 * If individual versions were specified for this file make
10420Sstevel@tonic-gate 		 * sure that they actually exist in the appropriate file, and
10430Sstevel@tonic-gate 		 * that they are available for binding.
10440Sstevel@tonic-gate 		 */
10459131SRod.Evans@Sun.COM 		for (ALIST_TRAVERSE(sdf->sdf_vers, idx2, sdv)) {
10469131SRod.Evans@Sun.COM 			Aliste		idx3;
10470Sstevel@tonic-gate 			Ver_desc	*vdp;
10480Sstevel@tonic-gate 			int		found = 0;
10490Sstevel@tonic-gate 
10509131SRod.Evans@Sun.COM 			for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx3, vdp)) {
10510Sstevel@tonic-gate 				if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) {
10520Sstevel@tonic-gate 					found++;
10530Sstevel@tonic-gate 					break;
10540Sstevel@tonic-gate 				}
10550Sstevel@tonic-gate 			}
10560Sstevel@tonic-gate 			if (found) {
10570Sstevel@tonic-gate 				Ver_index	*vip;
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate 				vip = &ifl->ifl_verndx[vdp->vd_ndx];
10600Sstevel@tonic-gate 				if (!(vip->vi_flags & FLG_VER_AVAIL)) {
1061*13074SAli.Bahrami@Oracle.COM 					ld_eprintf(ofl, ERR_FATAL,
10620Sstevel@tonic-gate 					    MSG_INTL(MSG_VER_UNAVAIL),
10630Sstevel@tonic-gate 					    ifl->ifl_name, sdv->sdv_name,
10640Sstevel@tonic-gate 					    sdv->sdv_ref);
10650Sstevel@tonic-gate 				}
10660Sstevel@tonic-gate 			} else {
1067*13074SAli.Bahrami@Oracle.COM 				ld_eprintf(ofl, ERR_FATAL,
10681618Srie 				    MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
10691618Srie 				    sdv->sdv_name, sdv->sdv_ref);
10700Sstevel@tonic-gate 			}
10710Sstevel@tonic-gate 		}
10720Sstevel@tonic-gate 	}
10730Sstevel@tonic-gate 	return (1);
10740Sstevel@tonic-gate }
1075