17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55aefb655Srie * Common Development and Distribution License (the "License").
65aefb655Srie * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
215aefb655Srie
227c478bd9Sstevel@tonic-gate /*
231007fd6fSAli Bahrami * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <string.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
285aefb655Srie #include <debug.h>
297c478bd9Sstevel@tonic-gate #include "msg.h"
307c478bd9Sstevel@tonic-gate #include "_libld.h"
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate * Locate a version descriptor.
347c478bd9Sstevel@tonic-gate */
357c478bd9Sstevel@tonic-gate Ver_desc *
ld_vers_find(const char * name,Word hash,APlist * alp)3657ef7aa9SRod Evans ld_vers_find(const char *name, Word hash, APlist *alp)
377c478bd9Sstevel@tonic-gate {
3857ef7aa9SRod Evans Aliste idx;
397c478bd9Sstevel@tonic-gate Ver_desc *vdp;
407c478bd9Sstevel@tonic-gate
4157ef7aa9SRod Evans for (APLIST_TRAVERSE(alp, idx, vdp)) {
427c478bd9Sstevel@tonic-gate if (vdp->vd_hash != hash)
437c478bd9Sstevel@tonic-gate continue;
447c478bd9Sstevel@tonic-gate if (strcmp(vdp->vd_name, name) == 0)
457c478bd9Sstevel@tonic-gate return (vdp);
467c478bd9Sstevel@tonic-gate }
4757ef7aa9SRod Evans return (NULL);
487c478bd9Sstevel@tonic-gate }
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate * Add a new version descriptor to a version descriptor list. Note, users of
527c478bd9Sstevel@tonic-gate * this are responsible for determining if the version descriptor already
537c478bd9Sstevel@tonic-gate * exists (this can reduce the need to allocate storage for descriptor names
547c478bd9Sstevel@tonic-gate * until it is determined a descriptor need be created (see map_symbol())).
557c478bd9Sstevel@tonic-gate */
567c478bd9Sstevel@tonic-gate Ver_desc *
ld_vers_desc(const char * name,Word hash,APlist ** alpp)5757ef7aa9SRod Evans ld_vers_desc(const char *name, Word hash, APlist **alpp)
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate Ver_desc *vdp;
607c478bd9Sstevel@tonic-gate
61*fb12490aSRichard Lowe if ((vdp = libld_calloc(1, sizeof (Ver_desc))) == NULL)
627c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR);
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate vdp->vd_name = name;
657c478bd9Sstevel@tonic-gate vdp->vd_hash = hash;
667c478bd9Sstevel@tonic-gate
6757ef7aa9SRod Evans if (aplist_append(alpp, vdp, AL_CNT_VERDESCS) == NULL)
687c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR);
6957ef7aa9SRod Evans
7057ef7aa9SRod Evans return (vdp);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate * Now that all explict files have been processed validate any version
757c478bd9Sstevel@tonic-gate * definitions. Insure that any version references are available (a version
767c478bd9Sstevel@tonic-gate * has been defined when it's been assigned an index). Also calculate the
777c478bd9Sstevel@tonic-gate * number of .version section entries that will be required to hold this
787c478bd9Sstevel@tonic-gate * information.
797c478bd9Sstevel@tonic-gate */
807c478bd9Sstevel@tonic-gate #define _NUM_OF_VERS_ 40 /* twice as big as the depth for libc version */
817c478bd9Sstevel@tonic-gate typedef struct {
827c478bd9Sstevel@tonic-gate Ver_desc **ver_stk;
83*fb12490aSRichard Lowe int ver_sp;
84*fb12490aSRichard Lowe int ver_lmt;
857c478bd9Sstevel@tonic-gate } Ver_Stack;
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate static uintptr_t
vers_visit_children(Ofl_desc * ofl,Ver_desc * vp,int flag)885aefb655Srie vers_visit_children(Ofl_desc *ofl, Ver_desc *vp, int flag)
897c478bd9Sstevel@tonic-gate {
9057ef7aa9SRod Evans Aliste idx;
917c478bd9Sstevel@tonic-gate Ver_desc *vdp;
927c478bd9Sstevel@tonic-gate static int err = 0;
937c478bd9Sstevel@tonic-gate static Ver_Stack ver_stk = {0, 0, 0};
947c478bd9Sstevel@tonic-gate int tmp_sp;
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate * If there was any fatal error,
987c478bd9Sstevel@tonic-gate * just return.
997c478bd9Sstevel@tonic-gate */
1007c478bd9Sstevel@tonic-gate if (err == S_ERROR)
1017c478bd9Sstevel@tonic-gate return (err);
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate * if this is called from, ver_check_defs(), initialize sp.
1057c478bd9Sstevel@tonic-gate */
1067c478bd9Sstevel@tonic-gate if (flag == 0)
1077c478bd9Sstevel@tonic-gate ver_stk.ver_sp = 0;
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate * Check if passed version pointer vp is already in the stack.
1117c478bd9Sstevel@tonic-gate */
1127c478bd9Sstevel@tonic-gate for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) {
1137c478bd9Sstevel@tonic-gate Ver_desc *v;
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate v = ver_stk.ver_stk[tmp_sp];
1167c478bd9Sstevel@tonic-gate if (v == vp) {
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate * cyclic dependency.
1197c478bd9Sstevel@tonic-gate */
1207c478bd9Sstevel@tonic-gate if (err == 0) {
1211007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
1225aefb655Srie MSG_INTL(MSG_VER_CYCLIC));
1237c478bd9Sstevel@tonic-gate err = 1;
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) {
1267c478bd9Sstevel@tonic-gate v = ver_stk.ver_stk[tmp_sp];
1277c478bd9Sstevel@tonic-gate if ((v->vd_flags & FLG_VER_CYCLIC) == 0) {
1287c478bd9Sstevel@tonic-gate v->vd_flags |= FLG_VER_CYCLIC;
1291007fd6fSAli Bahrami ld_eprintf(ofl, ERR_NONE,
1305aefb655Srie MSG_INTL(MSG_VER_ADDVER),
1315aefb655Srie v->vd_name);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate if ((vp->vd_flags & FLG_VER_CYCLIC) == 0) {
1357c478bd9Sstevel@tonic-gate vp->vd_flags |= FLG_VER_CYCLIC;
1361007fd6fSAli Bahrami ld_eprintf(ofl, ERR_NONE,
1375aefb655Srie MSG_INTL(MSG_VER_ADDVER), vp->vd_name);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate return (err);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate * Push version on the stack.
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate if (ver_stk.ver_sp >= ver_stk.ver_lmt) {
1477c478bd9Sstevel@tonic-gate ver_stk.ver_lmt += _NUM_OF_VERS_;
1487c478bd9Sstevel@tonic-gate if ((ver_stk.ver_stk = (Ver_desc **)
149*fb12490aSRichard Lowe libld_realloc(ver_stk.ver_stk,
1507c478bd9Sstevel@tonic-gate ver_stk.ver_lmt * sizeof (Ver_desc *))) == NULL)
1517c478bd9Sstevel@tonic-gate return (S_ERROR);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate ver_stk.ver_stk[(ver_stk.ver_sp)++] = vp;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate * Now visit children.
1577c478bd9Sstevel@tonic-gate */
15857ef7aa9SRod Evans for (APLIST_TRAVERSE(vp->vd_deps, idx, vdp))
1595aefb655Srie if (vers_visit_children(ofl, vdp, 1) == S_ERROR)
1607c478bd9Sstevel@tonic-gate return (S_ERROR);
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate /*
1637c478bd9Sstevel@tonic-gate * Pop version from the stack.
1647c478bd9Sstevel@tonic-gate */
1657c478bd9Sstevel@tonic-gate (ver_stk.ver_sp)--;
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate return (err);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate uintptr_t
ld_vers_check_defs(Ofl_desc * ofl)1715aefb655Srie ld_vers_check_defs(Ofl_desc *ofl)
1727c478bd9Sstevel@tonic-gate {
17357ef7aa9SRod Evans Aliste idx1;
1747c478bd9Sstevel@tonic-gate Ver_desc *vdp;
175*fb12490aSRichard Lowe uintptr_t is_cyclic = 0;
1767c478bd9Sstevel@tonic-gate
1775aefb655Srie DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, ofl->ofl_name));
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * First check if there are any cyclic dependency
1817c478bd9Sstevel@tonic-gate */
18257ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp))
1835aefb655Srie if ((is_cyclic = vers_visit_children(ofl, vdp, 0)) == S_ERROR)
1847c478bd9Sstevel@tonic-gate return (S_ERROR);
185635216b6SRod Evans
1867c478bd9Sstevel@tonic-gate if (is_cyclic)
1877c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL;
1887c478bd9Sstevel@tonic-gate
18957ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) {
1907c478bd9Sstevel@tonic-gate Byte cnt;
1917c478bd9Sstevel@tonic-gate Sym *sym;
1927c478bd9Sstevel@tonic-gate Sym_desc *sdp;
1937c478bd9Sstevel@tonic-gate const char *name = vdp->vd_name;
194635216b6SRod Evans uchar_t bind;
19596b6509cSToomas Soome Ver_desc *_vdp __unused;
1967c478bd9Sstevel@tonic-gate avl_index_t where;
19757ef7aa9SRod Evans Aliste idx2;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate if (vdp->vd_ndx == 0) {
2001007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
2015aefb655Srie MSG_INTL(MSG_VER_UNDEF), name, vdp->vd_ref->vd_name,
2027c478bd9Sstevel@tonic-gate vdp->vd_ref->vd_file->ifl_name);
2037c478bd9Sstevel@tonic-gate continue;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate
2065aefb655Srie DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, vdp));
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate * If a version definition contains no symbols this is possibly
2107c478bd9Sstevel@tonic-gate * a mapfile error.
2117c478bd9Sstevel@tonic-gate */
2127c478bd9Sstevel@tonic-gate if ((vdp->vd_flags &
2137c478bd9Sstevel@tonic-gate (VER_FLG_BASE | VER_FLG_WEAK | FLG_VER_REFER)) == 0)
2145aefb655Srie DBG_CALL(Dbg_ver_nointerface(ofl->ofl_lml,
2155aefb655Srie vdp->vd_name));
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate /*
2187c478bd9Sstevel@tonic-gate * Update the version entry count to account for this new
2197c478bd9Sstevel@tonic-gate * version descriptor (the count is the size in bytes).
2207c478bd9Sstevel@tonic-gate */
2217c478bd9Sstevel@tonic-gate ofl->ofl_verdefsz += sizeof (Verdef);
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate * Traverse this versions dependency list to determine what
2257c478bd9Sstevel@tonic-gate * additional version dependencies we must account for against
2267c478bd9Sstevel@tonic-gate * this descriptor.
2277c478bd9Sstevel@tonic-gate */
2287c478bd9Sstevel@tonic-gate cnt = 1;
22957ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx2, _vdp)) {
2307c478bd9Sstevel@tonic-gate #if defined(__lint)
2317c478bd9Sstevel@tonic-gate /* get lint to think `_vdp' is used... */
23257ef7aa9SRod Evans vdp = _vdp;
2337c478bd9Sstevel@tonic-gate #endif
2347c478bd9Sstevel@tonic-gate cnt++;
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate ofl->ofl_verdefsz += (cnt * sizeof (Verdaux));
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * Except for the base version descriptor, generate an absolute
2407c478bd9Sstevel@tonic-gate * symbol to reflect this version.
2417c478bd9Sstevel@tonic-gate */
2427c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_BASE)
2437c478bd9Sstevel@tonic-gate continue;
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_WEAK)
2467c478bd9Sstevel@tonic-gate bind = STB_WEAK;
2477c478bd9Sstevel@tonic-gate else
2487c478bd9Sstevel@tonic-gate bind = STB_GLOBAL;
2497c478bd9Sstevel@tonic-gate
2505aefb655Srie if (sdp = ld_sym_find(name, vdp->vd_hash, &where, ofl)) {
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate * If the symbol already exists and is undefined or was
2537c478bd9Sstevel@tonic-gate * defined in a shared library, convert it to an
2547c478bd9Sstevel@tonic-gate * absolute.
2557c478bd9Sstevel@tonic-gate */
2560bc07c75Srie if ((sdp->sd_sym->st_shndx == SHN_UNDEF) ||
2577c478bd9Sstevel@tonic-gate (sdp->sd_ref != REF_REL_NEED)) {
2587c478bd9Sstevel@tonic-gate sdp->sd_shndx = sdp->sd_sym->st_shndx = SHN_ABS;
2597c478bd9Sstevel@tonic-gate sdp->sd_sym->st_info =
26060758829Srie ELF_ST_INFO(bind, STT_OBJECT);
2617c478bd9Sstevel@tonic-gate sdp->sd_ref = REF_REL_NEED;
262635216b6SRod Evans sdp->sd_flags |= (FLG_SY_SPECSEC |
263635216b6SRod Evans FLG_SY_DEFAULT | FLG_SY_EXPDEF);
2647c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vdp->vd_ndx;
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * If the reference originated from a mapfile
2687c478bd9Sstevel@tonic-gate * insure we mark the symbol as used.
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_MAPREF)
2717c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_MAPUSED;
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate } else if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
2740bc07c75Srie (sdp->sd_sym->st_shndx != SHN_ABS) &&
2757c478bd9Sstevel@tonic-gate (sdp->sd_ref == REF_REL_NEED)) {
2761007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING,
2775aefb655Srie MSG_INTL(MSG_VER_DEFINED), name,
2785aefb655Srie sdp->sd_file->ifl_name);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate } else {
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate * If the symbol does not exist create it.
2837c478bd9Sstevel@tonic-gate */
284*fb12490aSRichard Lowe if ((sym = libld_calloc(1, sizeof (Sym))) == NULL)
2857c478bd9Sstevel@tonic-gate return (S_ERROR);
28657ef7aa9SRod Evans
2877c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_ABS;
2887c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, STT_OBJECT);
2895aefb655Srie DBG_CALL(Dbg_ver_symbol(ofl->ofl_lml, name));
29057ef7aa9SRod Evans
2915aefb655Srie if ((sdp = ld_sym_enter(name, sym, vdp->vd_hash,
292635216b6SRod Evans vdp->vd_file, ofl, 0, SHN_ABS,
293635216b6SRod Evans (FLG_SY_SPECSEC | FLG_SY_DEFAULT | FLG_SY_EXPDEF),
29460758829Srie &where)) == (Sym_desc *)S_ERROR)
2957c478bd9Sstevel@tonic-gate return (S_ERROR);
29657ef7aa9SRod Evans
2977c478bd9Sstevel@tonic-gate sdp->sd_ref = REF_REL_NEED;
2987c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vdp->vd_ndx;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate return (1);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate * Dereference dependencies as a part of normalizing (allows recursion).
3067c478bd9Sstevel@tonic-gate */
3075aefb655Srie static void
vers_derefer(Ifl_desc * ifl,Ver_desc * vdp,int weak)3087c478bd9Sstevel@tonic-gate vers_derefer(Ifl_desc *ifl, Ver_desc *vdp, int weak)
3097c478bd9Sstevel@tonic-gate {
31057ef7aa9SRod Evans Aliste idx;
3117c478bd9Sstevel@tonic-gate Ver_desc *_vdp;
3127c478bd9Sstevel@tonic-gate Ver_index *vip = &ifl->ifl_verndx[vdp->vd_ndx];
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate /*
315090a8d9eSAli Bahrami * Set the INFO bit on all dependencies that ld.so.1
316090a8d9eSAli Bahrami * can skip verification for. These are the dependencies
317090a8d9eSAli Bahrami * that are inherited by others -- verifying the inheriting
318090a8d9eSAli Bahrami * version implicitily covers this one.
319090a8d9eSAli Bahrami *
320090a8d9eSAli Bahrami * If the head of the list was a weak then we only mark
3217c478bd9Sstevel@tonic-gate * weak dependencies, but if the head of the list was 'strong'
322090a8d9eSAli Bahrami * we set INFO on all dependencies.
3237c478bd9Sstevel@tonic-gate */
3247c478bd9Sstevel@tonic-gate if ((weak && (vdp->vd_flags & VER_FLG_WEAK)) || (!weak))
325090a8d9eSAli Bahrami vip->vi_flags |= VER_FLG_INFO;
3267c478bd9Sstevel@tonic-gate
32757ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp))
3287c478bd9Sstevel@tonic-gate vers_derefer(ifl, _vdp, weak);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate * If we need to record the versions of any needed dependencies traverse the
3337c478bd9Sstevel@tonic-gate * shared object dependency list and calculate what version needed entries are
3347c478bd9Sstevel@tonic-gate * required.
3357c478bd9Sstevel@tonic-gate */
3367c478bd9Sstevel@tonic-gate uintptr_t
ld_vers_check_need(Ofl_desc * ofl)3375aefb655Srie ld_vers_check_need(Ofl_desc *ofl)
3387c478bd9Sstevel@tonic-gate {
33957ef7aa9SRod Evans Aliste idx1;
3407c478bd9Sstevel@tonic-gate Ifl_desc *ifl;
341090a8d9eSAli Bahrami Half needndx;
34243ed631fSAli Bahrami Str_tbl *strtbl;
34343ed631fSAli Bahrami
34443ed631fSAli Bahrami
34543ed631fSAli Bahrami /*
34643ed631fSAli Bahrami * Determine which string table is appropriate.
34743ed631fSAli Bahrami */
34843ed631fSAli Bahrami strtbl = (OFL_IS_STATIC_OBJ(ofl)) ? ofl->ofl_strtab :
34943ed631fSAli Bahrami ofl->ofl_dynstrtab;
350090a8d9eSAli Bahrami
351090a8d9eSAli Bahrami /*
352090a8d9eSAli Bahrami * Versym indexes for needed versions start with the next
353090a8d9eSAli Bahrami * available version after the final definied version.
354090a8d9eSAli Bahrami * However, it can never be less than 2. 0 is always for local
355090a8d9eSAli Bahrami * scope, and 1 is always the first global definition.
356090a8d9eSAli Bahrami */
357090a8d9eSAli Bahrami needndx = (ofl->ofl_vercnt > 0) ? (ofl->ofl_vercnt + 1) : 2;
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate * Traverse the shared object list looking for dependencies.
3617c478bd9Sstevel@tonic-gate */
36257ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_sos, idx1, ifl)) {
36357ef7aa9SRod Evans Aliste idx2;
3647c478bd9Sstevel@tonic-gate Ver_index *vip;
3657c478bd9Sstevel@tonic-gate Ver_desc *vdp;
366090a8d9eSAli Bahrami Byte cnt, need = 0;
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate if (!(ifl->ifl_flags & FLG_IF_NEEDED))
3697c478bd9Sstevel@tonic-gate continue;
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate if (ifl->ifl_vercnt <= VER_NDX_GLOBAL)
3727c478bd9Sstevel@tonic-gate continue;
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate * Scan the version index list and if any weak version
3767c478bd9Sstevel@tonic-gate * definition has been referenced by the user promote the
3777c478bd9Sstevel@tonic-gate * dependency to be non-weak. Weak version dependencies do not
3787c478bd9Sstevel@tonic-gate * cause fatal errors from the runtime linker, non-weak
3797c478bd9Sstevel@tonic-gate * dependencies do.
3807c478bd9Sstevel@tonic-gate */
381090a8d9eSAli Bahrami for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) {
3827c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt];
3837c478bd9Sstevel@tonic-gate vdp = vip->vi_desc;
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate if ((vip->vi_flags & (FLG_VER_REFER | VER_FLG_WEAK)) ==
3867c478bd9Sstevel@tonic-gate (FLG_VER_REFER | VER_FLG_WEAK))
3877c478bd9Sstevel@tonic-gate vdp->vd_flags &= ~VER_FLG_WEAK;
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate * Mark any weak reference as referred to so as to
3917c478bd9Sstevel@tonic-gate * simplify normalization and later version dependency
3927c478bd9Sstevel@tonic-gate * manipulation.
3937c478bd9Sstevel@tonic-gate */
3947c478bd9Sstevel@tonic-gate if (vip->vi_flags & VER_FLG_WEAK)
3957c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_REFER;
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate /*
3997c478bd9Sstevel@tonic-gate * Scan the version dependency list to normalize the referenced
4007c478bd9Sstevel@tonic-gate * dependencies. Any needed version that is inherited by
40157ef7aa9SRod Evans * another like version is dereferenced as it is not necessary
4027c478bd9Sstevel@tonic-gate * to make this part of the version dependencies.
4037c478bd9Sstevel@tonic-gate */
40457ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) {
40557ef7aa9SRod Evans Aliste idx3;
4067c478bd9Sstevel@tonic-gate Ver_desc *_vdp;
4077c478bd9Sstevel@tonic-gate int type;
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vdp->vd_ndx];
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate if (!(vip->vi_flags & FLG_VER_REFER))
4127c478bd9Sstevel@tonic-gate continue;
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate type = vdp->vd_flags & VER_FLG_WEAK;
41557ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx3, _vdp))
4167c478bd9Sstevel@tonic-gate vers_derefer(ifl, _vdp, type);
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate /*
4207c478bd9Sstevel@tonic-gate * Finally, determine how many of the version dependencies need
4217c478bd9Sstevel@tonic-gate * to be recorded.
4227c478bd9Sstevel@tonic-gate */
423090a8d9eSAli Bahrami for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) {
4247c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt];
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate * If a version has been referenced then record it as a
4287c478bd9Sstevel@tonic-gate * version dependency.
4297c478bd9Sstevel@tonic-gate */
4307c478bd9Sstevel@tonic-gate if (vip->vi_flags & FLG_VER_REFER) {
431090a8d9eSAli Bahrami /* Assign a VERSYM index for it */
432090a8d9eSAli Bahrami vip->vi_overndx = needndx++;
433090a8d9eSAli Bahrami
4347c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Vernaux);
43543ed631fSAli Bahrami if (st_insert(strtbl, vip->vi_name) == -1)
4367c478bd9Sstevel@tonic-gate return (S_ERROR);
4377c478bd9Sstevel@tonic-gate need++;
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate if (need) {
4427c478bd9Sstevel@tonic-gate ifl->ifl_flags |= FLG_IF_VERNEED;
4437c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Verneed);
44443ed631fSAli Bahrami if (st_insert(strtbl, ifl->ifl_soname) == -1)
4457c478bd9Sstevel@tonic-gate return (S_ERROR);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate /*
4507c478bd9Sstevel@tonic-gate * If no version needed information is required unset the output file
4517c478bd9Sstevel@tonic-gate * flag.
4527c478bd9Sstevel@tonic-gate */
4537c478bd9Sstevel@tonic-gate if (ofl->ofl_verneedsz == 0)
4547c478bd9Sstevel@tonic-gate ofl->ofl_flags &= ~FLG_OF_VERNEED;
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate return (1);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate /*
4607c478bd9Sstevel@tonic-gate * Indicate dependency selection (allows recursion).
4617c478bd9Sstevel@tonic-gate */
4625aefb655Srie static void
vers_select(Ofl_desc * ofl,Ifl_desc * ifl,Ver_desc * vdp,const char * ref)4635aefb655Srie vers_select(Ofl_desc *ofl, Ifl_desc *ifl, Ver_desc *vdp, const char *ref)
4647c478bd9Sstevel@tonic-gate {
46557ef7aa9SRod Evans Aliste idx;
4667c478bd9Sstevel@tonic-gate Ver_desc *_vdp;
4677c478bd9Sstevel@tonic-gate Ver_index *vip = &ifl->ifl_verndx[vdp->vd_ndx];
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_AVAIL;
4705aefb655Srie DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, ref));
4717c478bd9Sstevel@tonic-gate
47257ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp))
4735aefb655Srie vers_select(ofl, ifl, _vdp, ref);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate
4765aefb655Srie static Ver_index *
vers_index(Ofl_desc * ofl,Ifl_desc * ifl,int avail)4775aefb655Srie vers_index(Ofl_desc *ofl, Ifl_desc *ifl, int avail)
4787c478bd9Sstevel@tonic-gate {
47957ef7aa9SRod Evans Aliste idx1;
4807c478bd9Sstevel@tonic-gate Ver_desc *vdp;
4817c478bd9Sstevel@tonic-gate Ver_index *vip;
4827c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc;
4837c478bd9Sstevel@tonic-gate Word count = ifl->ifl_vercnt;
4847c478bd9Sstevel@tonic-gate Sdv_desc *sdv;
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate /*
4877c478bd9Sstevel@tonic-gate * Allocate an index array large enough to hold all of the files
4887c478bd9Sstevel@tonic-gate * version descriptors.
4897c478bd9Sstevel@tonic-gate */
490*fb12490aSRichard Lowe if ((vip = libld_calloc((count + 1), sizeof (Ver_index))) == NULL)
4917c478bd9Sstevel@tonic-gate return ((Ver_index *)S_ERROR);
4927c478bd9Sstevel@tonic-gate
49357ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx1, vdp)) {
49457ef7aa9SRod Evans int ndx = vdp->vd_ndx;
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate vip[ndx].vi_name = vdp->vd_name;
4977c478bd9Sstevel@tonic-gate vip[ndx].vi_desc = vdp;
4987c478bd9Sstevel@tonic-gate
4997c478bd9Sstevel@tonic-gate /*
5007c478bd9Sstevel@tonic-gate * Any relocatable object versions, and the `base' version are
5017c478bd9Sstevel@tonic-gate * always available.
5027c478bd9Sstevel@tonic-gate */
5037c478bd9Sstevel@tonic-gate if (avail || (vdp->vd_flags & VER_FLG_BASE))
5047c478bd9Sstevel@tonic-gate vip[ndx].vi_flags |= FLG_VER_AVAIL;
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate /*
5077c478bd9Sstevel@tonic-gate * If this is a weak version mark it as such. Weak versions
5087c478bd9Sstevel@tonic-gate * are always dragged into any version dependencies created,
5097c478bd9Sstevel@tonic-gate * and if a weak version is referenced it will be promoted to
5107c478bd9Sstevel@tonic-gate * a non-weak version dependency.
5117c478bd9Sstevel@tonic-gate */
5127c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_WEAK)
5137c478bd9Sstevel@tonic-gate vip[ndx].vi_flags |= VER_FLG_WEAK;
5147c478bd9Sstevel@tonic-gate /*
5154a8d0ea7SAli Bahrami * If this version is mentioned in a mapfile using ADDVERS
5164a8d0ea7SAli Bahrami * syntax then check to see if it corresponds to an actual
5174a8d0ea7SAli Bahrami * version in the file.
5187c478bd9Sstevel@tonic-gate */
5194a8d0ea7SAli Bahrami if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) {
52057ef7aa9SRod Evans Aliste idx2;
52157ef7aa9SRod Evans
52257ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_verneed, idx2, sdv)) {
52357ef7aa9SRod Evans if (strcmp(vip[ndx].vi_name, sdv->sdv_name))
52457ef7aa9SRod Evans continue;
52557ef7aa9SRod Evans
52657ef7aa9SRod Evans vip[ndx].vi_flags |= FLG_VER_REFER;
52757ef7aa9SRod Evans sdv->sdv_flags |= FLG_SDV_MATCHED;
52857ef7aa9SRod Evans break;
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate * if $ADDVER was specified for this object verify that
5357c478bd9Sstevel@tonic-gate * all of it's dependent upon versions were refered to.
5367c478bd9Sstevel@tonic-gate */
5377c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) {
5387c478bd9Sstevel@tonic-gate int fail = 0;
53957ef7aa9SRod Evans
54057ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_verneed, idx1, sdv)) {
54157ef7aa9SRod Evans if (sdv->sdv_flags & FLG_SDV_MATCHED)
54257ef7aa9SRod Evans continue;
54357ef7aa9SRod Evans
54457ef7aa9SRod Evans if (fail++ == 0) {
5451007fd6fSAli Bahrami ld_eprintf(ofl, ERR_NONE,
54657ef7aa9SRod Evans MSG_INTL(MSG_VER_ADDVERS), sdf->sdf_rfile,
54757ef7aa9SRod Evans sdf->sdf_name);
5487c478bd9Sstevel@tonic-gate }
5491007fd6fSAli Bahrami ld_eprintf(ofl, ERR_NONE, MSG_INTL(MSG_VER_ADDVER),
5501007fd6fSAli Bahrami sdv->sdv_name);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate if (fail)
5537c478bd9Sstevel@tonic-gate return ((Ver_index *)S_ERROR);
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate
5567c478bd9Sstevel@tonic-gate return (vip);
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate * Process a version symbol index section.
5617c478bd9Sstevel@tonic-gate */
5627c478bd9Sstevel@tonic-gate int
ld_vers_sym_process(Ofl_desc * ofl,Is_desc * isp,Ifl_desc * ifl)5631007fd6fSAli Bahrami ld_vers_sym_process(Ofl_desc *ofl, Is_desc *isp, Ifl_desc *ifl)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate Shdr *symshdr;
5667c478bd9Sstevel@tonic-gate Shdr *vershdr = isp->is_shdr;
5675aefb655Srie
5687c478bd9Sstevel@tonic-gate /*
5695aefb655Srie * Verify that the versym is the same size as the linked symbol table.
5705aefb655Srie * If these two get out of sync the file is considered corrupted.
5717c478bd9Sstevel@tonic-gate */
5727c478bd9Sstevel@tonic-gate symshdr = ifl->ifl_isdesc[vershdr->sh_link]->is_shdr;
5737c478bd9Sstevel@tonic-gate if ((symshdr->sh_size / symshdr->sh_entsize) != (vershdr->sh_size /
5747c478bd9Sstevel@tonic-gate vershdr->sh_entsize)) {
5754a8d0ea7SAli Bahrami Is_desc *sym_isp = ifl->ifl_isdesc[vershdr->sh_link];
5764a8d0ea7SAli Bahrami
5771007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_ELF_VERSYM),
5784a8d0ea7SAli Bahrami ifl->ifl_name, EC_WORD(isp->is_scnndx), isp->is_name,
5795aefb655Srie EC_WORD(vershdr->sh_size / vershdr->sh_entsize),
5804a8d0ea7SAli Bahrami EC_WORD(sym_isp->is_scnndx), sym_isp->is_name,
5815aefb655Srie EC_WORD(symshdr->sh_size / symshdr->sh_entsize));
5827c478bd9Sstevel@tonic-gate return (1);
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate ifl->ifl_versym = (Versym *)isp->is_indata->d_buf;
5857c478bd9Sstevel@tonic-gate return (1);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate /*
5897c478bd9Sstevel@tonic-gate * Process a version definition section from an input file. A list of version
5907c478bd9Sstevel@tonic-gate * descriptors is created and associated with the input files descriptor. If
5917c478bd9Sstevel@tonic-gate * this is a shared object these descriptors will be used to indicate the
5927c478bd9Sstevel@tonic-gate * availability of each version. If this is a relocatable object then these
5937c478bd9Sstevel@tonic-gate * descriptors will be promoted (concatenated) to the output files image.
5947c478bd9Sstevel@tonic-gate */
5957c478bd9Sstevel@tonic-gate uintptr_t
ld_vers_def_process(Is_desc * isp,Ifl_desc * ifl,Ofl_desc * ofl)5965aefb655Srie ld_vers_def_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate const char *str, *file = ifl->ifl_name;
5997c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc;
6007c478bd9Sstevel@tonic-gate Sdv_desc *sdv;
6017c478bd9Sstevel@tonic-gate Word num, _num;
6027c478bd9Sstevel@tonic-gate Verdef *vdf;
6037c478bd9Sstevel@tonic-gate int relobj;
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate /*
6067c478bd9Sstevel@tonic-gate * If there is no version section then simply indicate that all version
6077c478bd9Sstevel@tonic-gate * definitions asked for do not exist.
6087c478bd9Sstevel@tonic-gate */
60957ef7aa9SRod Evans if (isp == NULL) {
61057ef7aa9SRod Evans Aliste idx;
6117c478bd9Sstevel@tonic-gate
61257ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_vers, idx, sdv)) {
6131007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
6145aefb655Srie MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
6155aefb655Srie sdv->sdv_name, sdv->sdv_ref);
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate return (0);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate vdf = (Verdef *)isp->is_indata->d_buf;
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate /*
6237c478bd9Sstevel@tonic-gate * Verify the version revision. We only check the first version
6247c478bd9Sstevel@tonic-gate * structure as it is assumed all other version structures in this
6257c478bd9Sstevel@tonic-gate * data section will be of the same revision.
6267c478bd9Sstevel@tonic-gate */
6277c478bd9Sstevel@tonic-gate if (vdf->vd_version > VER_DEF_CURRENT)
6281007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_VER_HIGHER),
6291007fd6fSAli Bahrami ifl->ifl_name, vdf->vd_version, VER_DEF_CURRENT);
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate num = isp->is_shdr->sh_info;
6337c478bd9Sstevel@tonic-gate str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf;
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate if (ifl->ifl_ehdr->e_type == ET_REL)
6367c478bd9Sstevel@tonic-gate relobj = 1;
6377c478bd9Sstevel@tonic-gate else
6387c478bd9Sstevel@tonic-gate relobj = 0;
6397c478bd9Sstevel@tonic-gate
6405aefb655Srie DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, file));
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate * Loop through the version information setting up a version descriptor
6447c478bd9Sstevel@tonic-gate * for each version definition.
6457c478bd9Sstevel@tonic-gate */
6467c478bd9Sstevel@tonic-gate for (_num = 1; _num <= num; _num++,
6477c478bd9Sstevel@tonic-gate vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) {
6487c478bd9Sstevel@tonic-gate const char *name;
64957ef7aa9SRod Evans Ver_desc *ivdp, *ovdp = NULL;
6507c478bd9Sstevel@tonic-gate Word hash;
651*fb12490aSRichard Lowe Half cnt = vdf->vd_cnt;
6527c478bd9Sstevel@tonic-gate Half ndx = vdf->vd_ndx;
6537c478bd9Sstevel@tonic-gate Verdaux *vdap = (Verdaux *)((uintptr_t)vdf +
65460758829Srie vdf->vd_aux);
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate /*
6577c478bd9Sstevel@tonic-gate * Keep track of the largest index for use in creating a
6587c478bd9Sstevel@tonic-gate * version index array later, and create a version descriptor.
6597c478bd9Sstevel@tonic-gate */
6607c478bd9Sstevel@tonic-gate if (ndx > ifl->ifl_vercnt)
6617c478bd9Sstevel@tonic-gate ifl->ifl_vercnt = ndx;
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate name = (char *)(str + vdap->vda_name);
6647c478bd9Sstevel@tonic-gate /* LINTED */
6657c478bd9Sstevel@tonic-gate hash = (Word)elf_hash(name);
66657ef7aa9SRod Evans if (((ivdp = ld_vers_find(name, hash,
66757ef7aa9SRod Evans ifl->ifl_verdesc)) == NULL) &&
66857ef7aa9SRod Evans ((ivdp = ld_vers_desc(name, hash,
66957ef7aa9SRod Evans &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR))
67057ef7aa9SRod Evans return (S_ERROR);
67157ef7aa9SRod Evans
6727c478bd9Sstevel@tonic-gate ivdp->vd_ndx = ndx;
6737c478bd9Sstevel@tonic-gate ivdp->vd_file = ifl;
6747c478bd9Sstevel@tonic-gate ivdp->vd_flags = vdf->vd_flags;
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate * If we're processing a relocatable object then this version
6787c478bd9Sstevel@tonic-gate * definition needs to be propagated to the output file.
6797c478bd9Sstevel@tonic-gate * Generate a new output file version and associated this input
6807c478bd9Sstevel@tonic-gate * version to it. During symbol processing the version index of
6817c478bd9Sstevel@tonic-gate * the symbol will be promoted from the input file to the output
6827c478bd9Sstevel@tonic-gate * files version definition.
6837c478bd9Sstevel@tonic-gate */
6847c478bd9Sstevel@tonic-gate if (relobj) {
6857c478bd9Sstevel@tonic-gate if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
6867c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_PROCRED;
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate if ((ivdp->vd_flags & VER_FLG_BASE) == 0) {
6897c478bd9Sstevel@tonic-gate /*
6907c478bd9Sstevel@tonic-gate * If no version descriptors have yet been set
6917c478bd9Sstevel@tonic-gate * up, initialize a base version to represent
6927c478bd9Sstevel@tonic-gate * the output file itself. This `base' version
6937c478bd9Sstevel@tonic-gate * catches any internally generated symbols
6947c478bd9Sstevel@tonic-gate * (_end, _etext, etc.) and
6957c478bd9Sstevel@tonic-gate * serves to initialize the output version
6967c478bd9Sstevel@tonic-gate * descriptor count.
6977c478bd9Sstevel@tonic-gate */
6987c478bd9Sstevel@tonic-gate if (ofl->ofl_vercnt == 0) {
6995aefb655Srie if (ld_vers_base(ofl) ==
7007c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR)
7017c478bd9Sstevel@tonic-gate return (S_ERROR);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_VERDEF;
7045aefb655Srie if ((ovdp = ld_vers_find(name, hash,
70557ef7aa9SRod Evans ofl->ofl_verdesc)) == NULL) {
7065aefb655Srie if ((ovdp = ld_vers_desc(name, hash,
7077c478bd9Sstevel@tonic-gate &ofl->ofl_verdesc)) ==
7087c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR)
7097c478bd9Sstevel@tonic-gate return (S_ERROR);
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate /* LINTED */
7127c478bd9Sstevel@tonic-gate ovdp->vd_ndx = (Half)++ofl->ofl_vercnt;
7137c478bd9Sstevel@tonic-gate ovdp->vd_file = ifl;
7147c478bd9Sstevel@tonic-gate ovdp->vd_flags = vdf->vd_flags;
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gate /*
7197c478bd9Sstevel@tonic-gate * Maintain the association between the input version
7207c478bd9Sstevel@tonic-gate * descriptor and the output version descriptor so that
7217c478bd9Sstevel@tonic-gate * an associated symbols will be assigned to the
7227c478bd9Sstevel@tonic-gate * correct version.
7237c478bd9Sstevel@tonic-gate */
7247c478bd9Sstevel@tonic-gate ivdp->vd_ref = ovdp;
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate /*
7287c478bd9Sstevel@tonic-gate * Process any dependencies this version may have.
7297c478bd9Sstevel@tonic-gate */
7307c478bd9Sstevel@tonic-gate vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next);
7317c478bd9Sstevel@tonic-gate for (cnt--; cnt; cnt--,
7327c478bd9Sstevel@tonic-gate vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next)) {
7337c478bd9Sstevel@tonic-gate Ver_desc *_ivdp;
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate name = (char *)(str + vdap->vda_name);
7367c478bd9Sstevel@tonic-gate /* LINTED */
7377c478bd9Sstevel@tonic-gate hash = (Word)elf_hash(name);
7387c478bd9Sstevel@tonic-gate
73957ef7aa9SRod Evans if (((_ivdp = ld_vers_find(name, hash,
74057ef7aa9SRod Evans ifl->ifl_verdesc)) == NULL) &&
74157ef7aa9SRod Evans ((_ivdp = ld_vers_desc(name, hash,
74257ef7aa9SRod Evans &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR))
74357ef7aa9SRod Evans return (S_ERROR);
74457ef7aa9SRod Evans
74557ef7aa9SRod Evans if (aplist_append(&ivdp->vd_deps, _ivdp,
74657ef7aa9SRod Evans AL_CNT_VERDESCS) == NULL)
7477c478bd9Sstevel@tonic-gate return (S_ERROR);
7487c478bd9Sstevel@tonic-gate }
7495aefb655Srie DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, ivdp));
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate /*
7537c478bd9Sstevel@tonic-gate * Now that we know the total number of version definitions for this
7547c478bd9Sstevel@tonic-gate * file, build an index array for fast access when processing symbols.
7557c478bd9Sstevel@tonic-gate */
7565aefb655Srie if ((ifl->ifl_verndx =
7575aefb655Srie vers_index(ofl, ifl, relobj)) == (Ver_index *)S_ERROR)
7587c478bd9Sstevel@tonic-gate return (S_ERROR);
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate if (relobj)
7617c478bd9Sstevel@tonic-gate return (1);
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate /*
7647c478bd9Sstevel@tonic-gate * If this object has version control definitions against it then these
7657c478bd9Sstevel@tonic-gate * must be processed so as to select those version definitions to which
7667c478bd9Sstevel@tonic-gate * symbol bindings can occur. Otherwise simply mark all versions as
7677c478bd9Sstevel@tonic-gate * available.
7687c478bd9Sstevel@tonic-gate */
7695aefb655Srie DBG_CALL(Dbg_ver_avail_title(ofl->ofl_lml, file));
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_SELECT)) {
77257ef7aa9SRod Evans Aliste idx1;
7737c478bd9Sstevel@tonic-gate
77457ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_vers, idx1, sdv)) {
77557ef7aa9SRod Evans Aliste idx2;
7767c478bd9Sstevel@tonic-gate Ver_desc *vdp;
7777c478bd9Sstevel@tonic-gate int found = 0;
7787c478bd9Sstevel@tonic-gate
77957ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) {
7807c478bd9Sstevel@tonic-gate if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) {
7817c478bd9Sstevel@tonic-gate found++;
7827c478bd9Sstevel@tonic-gate break;
7837c478bd9Sstevel@tonic-gate }
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate if (found)
7865aefb655Srie vers_select(ofl, ifl, vdp, sdv->sdv_ref);
7871007fd6fSAli Bahrami else
7881007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
7895aefb655Srie MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
7905aefb655Srie sdv->sdv_name, sdv->sdv_ref);
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate } else {
7937c478bd9Sstevel@tonic-gate Ver_index *vip;
7947c478bd9Sstevel@tonic-gate int cnt;
7957c478bd9Sstevel@tonic-gate
7967c478bd9Sstevel@tonic-gate for (cnt = VER_NDX_GLOBAL; cnt <= ifl->ifl_vercnt; cnt++) {
7977c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt];
7987c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_AVAIL;
7995aefb655Srie DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, 0));
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate /*
8047c478bd9Sstevel@tonic-gate * If this is an explict dependency indicate that this file is a
8057c478bd9Sstevel@tonic-gate * candidate for requiring version needed information to be recorded in
8067c478bd9Sstevel@tonic-gate * the image we're creating.
8077c478bd9Sstevel@tonic-gate */
8087c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_NEEDED)
8097c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_VERNEED;
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate return (1);
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate /*
8157c478bd9Sstevel@tonic-gate * Process a version needed section.
8167c478bd9Sstevel@tonic-gate */
8177c478bd9Sstevel@tonic-gate uintptr_t
ld_vers_need_process(Is_desc * isp,Ifl_desc * ifl,Ofl_desc * ofl)8185aefb655Srie ld_vers_need_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl)
8197c478bd9Sstevel@tonic-gate {
8207c478bd9Sstevel@tonic-gate const char *str, *file = ifl->ifl_name;
8217c478bd9Sstevel@tonic-gate Word num, _num;
8227c478bd9Sstevel@tonic-gate Verneed *vnd;
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate vnd = (Verneed *)isp->is_indata->d_buf;
8257c478bd9Sstevel@tonic-gate
8267c478bd9Sstevel@tonic-gate /*
8277c478bd9Sstevel@tonic-gate * Verify the version revision. We only check the first version
8287c478bd9Sstevel@tonic-gate * structure as it is assumed all other version structures in this
8297c478bd9Sstevel@tonic-gate * data section will be of the same revision.
8307c478bd9Sstevel@tonic-gate */
8315aefb655Srie if (vnd->vn_version > VER_DEF_CURRENT) {
8321007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_VER_HIGHER),
8331007fd6fSAli Bahrami ifl->ifl_name, vnd->vn_version, VER_DEF_CURRENT);
8345aefb655Srie }
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate num = isp->is_shdr->sh_info;
8377c478bd9Sstevel@tonic-gate str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf;
8387c478bd9Sstevel@tonic-gate
8395aefb655Srie DBG_CALL(Dbg_ver_need_title(ofl->ofl_lml, file));
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate /*
8427c478bd9Sstevel@tonic-gate * Loop through the version information setting up a version descriptor
8437c478bd9Sstevel@tonic-gate * for each version definition.
8447c478bd9Sstevel@tonic-gate */
8457c478bd9Sstevel@tonic-gate for (_num = 1; _num <= num; _num++,
8467c478bd9Sstevel@tonic-gate vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) {
8477c478bd9Sstevel@tonic-gate Sdf_desc *sdf;
8487c478bd9Sstevel@tonic-gate const char *name;
8497c478bd9Sstevel@tonic-gate Half cnt = vnd->vn_cnt;
8507c478bd9Sstevel@tonic-gate Vernaux *vnap = (Vernaux *)((uintptr_t)vnd +
85160758829Srie vnd->vn_aux);
8527c478bd9Sstevel@tonic-gate Half _cnt;
8537c478bd9Sstevel@tonic-gate
8547c478bd9Sstevel@tonic-gate name = (char *)(str + vnd->vn_file);
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate /*
8577c478bd9Sstevel@tonic-gate * Set up a shared object descriptor and add to it the necessary
8587c478bd9Sstevel@tonic-gate * needed versions. This information may also have been added
8597c478bd9Sstevel@tonic-gate * by a mapfile (see map_dash()).
8607c478bd9Sstevel@tonic-gate */
86157ef7aa9SRod Evans if ((sdf = sdf_find(name, ofl->ofl_soneed)) == NULL) {
8627c478bd9Sstevel@tonic-gate if ((sdf = sdf_add(name, &ofl->ofl_soneed)) ==
8637c478bd9Sstevel@tonic-gate (Sdf_desc *)S_ERROR)
8647c478bd9Sstevel@tonic-gate return (S_ERROR);
8657c478bd9Sstevel@tonic-gate sdf->sdf_rfile = file;
8667c478bd9Sstevel@tonic-gate sdf->sdf_flags |= FLG_SDF_VERIFY;
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate for (_cnt = 0; cnt; _cnt++, cnt--,
8707c478bd9Sstevel@tonic-gate vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next)) {
87157ef7aa9SRod Evans Sdv_desc sdv;
87257ef7aa9SRod Evans
87357ef7aa9SRod Evans sdv.sdv_name = str + vnap->vna_name;
87457ef7aa9SRod Evans sdv.sdv_ref = file;
87557ef7aa9SRod Evans sdv.sdv_flags = 0;
87657ef7aa9SRod Evans
87757ef7aa9SRod Evans if (alist_append(&sdf->sdf_vers, &sdv,
87857ef7aa9SRod Evans sizeof (Sdv_desc), AL_CNT_SDF_VERSIONS) == NULL)
8797c478bd9Sstevel@tonic-gate return (S_ERROR);
88057ef7aa9SRod Evans
8815aefb655Srie DBG_CALL(Dbg_ver_need_entry(ofl->ofl_lml, _cnt, name,
88257ef7aa9SRod Evans sdv.sdv_name));
8837c478bd9Sstevel@tonic-gate }
8847c478bd9Sstevel@tonic-gate }
8857c478bd9Sstevel@tonic-gate return (1);
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate /*
8897c478bd9Sstevel@tonic-gate * If a symbol is obtained from a versioned relocatable object then the symbols
8907c478bd9Sstevel@tonic-gate * version association must be promoted to the version definition as it will be
8917c478bd9Sstevel@tonic-gate * represented in the output file.
8927c478bd9Sstevel@tonic-gate */
8937c478bd9Sstevel@tonic-gate void
ld_vers_promote(Sym_desc * sdp,Word ndx,Ifl_desc * ifl,Ofl_desc * ofl)8945aefb655Srie ld_vers_promote(Sym_desc *sdp, Word ndx, Ifl_desc *ifl, Ofl_desc *ofl)
8957c478bd9Sstevel@tonic-gate {
896*fb12490aSRichard Lowe Half vndx;
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate /*
8997c478bd9Sstevel@tonic-gate * A version symbol index of 0 implies the symbol is local. A value of
9007c478bd9Sstevel@tonic-gate * VER_NDX_GLOBAL implies the symbol is global but has not been
9017c478bd9Sstevel@tonic-gate * assigned to a specfic version definition.
9027c478bd9Sstevel@tonic-gate */
9037c478bd9Sstevel@tonic-gate vndx = ifl->ifl_versym[ndx];
9047c478bd9Sstevel@tonic-gate if (vndx == 0) {
905635216b6SRod Evans sdp->sd_flags |= (FLG_SY_REDUCED | FLG_SY_HIDDEN);
9067c478bd9Sstevel@tonic-gate return;
9077c478bd9Sstevel@tonic-gate }
9087c478bd9Sstevel@tonic-gate
9097c478bd9Sstevel@tonic-gate if (vndx == VER_NDX_ELIMINATE) {
910635216b6SRod Evans sdp->sd_flags |= (FLG_SY_REDUCED | FLG_SY_HIDDEN | FLG_SY_ELIM);
9117c478bd9Sstevel@tonic-gate return;
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate if (vndx == VER_NDX_GLOBAL) {
91508278a5eSRod Evans if (!SYM_IS_HIDDEN(sdp))
916635216b6SRod Evans sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF);
91760758829Srie if (sdp->sd_aux->sa_overndx <= VER_NDX_GLOBAL)
9187c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL;
9197c478bd9Sstevel@tonic-gate return;
9207c478bd9Sstevel@tonic-gate }
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate /*
9237c478bd9Sstevel@tonic-gate * Any other version index requires association to the appropriate
9247c478bd9Sstevel@tonic-gate * version definition.
9257c478bd9Sstevel@tonic-gate */
9267c478bd9Sstevel@tonic-gate if ((ifl->ifl_verndx == 0) || (vndx > ifl->ifl_vercnt)) {
9271007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_VER_INVALNDX),
9285aefb655Srie sdp->sd_name, ifl->ifl_name, vndx);
9297c478bd9Sstevel@tonic-gate return;
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate
93208278a5eSRod Evans if (!SYM_IS_HIDDEN(sdp))
933635216b6SRod Evans sdp->sd_flags |= (FLG_SY_DEFAULT | FLG_SY_EXPDEF);
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate /*
9367c478bd9Sstevel@tonic-gate * Promote the symbols version index to the appropriate output version
9377c478bd9Sstevel@tonic-gate * definition.
9387c478bd9Sstevel@tonic-gate */
9397c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags & FLG_SY_VERSPROM)) {
9407c478bd9Sstevel@tonic-gate Ver_index *vip;
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vndx];
9437c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vip->vi_desc->vd_ref->vd_ndx;
9447c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_VERSPROM;
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate /*
9497c478bd9Sstevel@tonic-gate * If any versioning is called for make sure an initial version descriptor is
9507c478bd9Sstevel@tonic-gate * assigned to represent the file itself. Known as the base version.
9517c478bd9Sstevel@tonic-gate */
9527c478bd9Sstevel@tonic-gate Ver_desc *
ld_vers_base(Ofl_desc * ofl)9535aefb655Srie ld_vers_base(Ofl_desc *ofl)
9547c478bd9Sstevel@tonic-gate {
9557c478bd9Sstevel@tonic-gate Ver_desc *vdp;
9567c478bd9Sstevel@tonic-gate const char *name;
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate /*
9597c478bd9Sstevel@tonic-gate * Determine the filename to associate to the version descriptor. This
9607c478bd9Sstevel@tonic-gate * is either the SONAME (if one has been supplied) or the basename of
9617c478bd9Sstevel@tonic-gate * the output file.
9627c478bd9Sstevel@tonic-gate */
96357ef7aa9SRod Evans if ((name = ofl->ofl_soname) == NULL) {
9647c478bd9Sstevel@tonic-gate const char *str = ofl->ofl_name;
9657c478bd9Sstevel@tonic-gate
9667c478bd9Sstevel@tonic-gate while (*str != '\0') {
9677c478bd9Sstevel@tonic-gate if (*str++ == '/')
9687c478bd9Sstevel@tonic-gate name = str;
9697c478bd9Sstevel@tonic-gate }
97057ef7aa9SRod Evans if (name == NULL)
9717c478bd9Sstevel@tonic-gate name = ofl->ofl_name;
9727c478bd9Sstevel@tonic-gate }
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate /*
9757c478bd9Sstevel@tonic-gate * Generate the version descriptor.
9767c478bd9Sstevel@tonic-gate */
9777c478bd9Sstevel@tonic-gate /* LINTED */
9785aefb655Srie if ((vdp = ld_vers_desc(name, (Word)elf_hash(name),
9795aefb655Srie &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR)
9807c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR);
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate /*
9837c478bd9Sstevel@tonic-gate * Assign the base index to this version and initialize the output file
9847c478bd9Sstevel@tonic-gate * descriptor with the number of version descriptors presently in use.
9857c478bd9Sstevel@tonic-gate */
9867c478bd9Sstevel@tonic-gate vdp->vd_ndx = ofl->ofl_vercnt = VER_NDX_GLOBAL;
9877c478bd9Sstevel@tonic-gate vdp->vd_flags |= VER_FLG_BASE;
9887c478bd9Sstevel@tonic-gate
9897c478bd9Sstevel@tonic-gate return (vdp);
9907c478bd9Sstevel@tonic-gate }
9917c478bd9Sstevel@tonic-gate
9927c478bd9Sstevel@tonic-gate /*
9937c478bd9Sstevel@tonic-gate * Now that all input shared objects have been processed, verify that all
9947c478bd9Sstevel@tonic-gate * version requirements have been met. Any version control requirements will
9957c478bd9Sstevel@tonic-gate * have been specified by the user (and placed on the ofl_oscntl list) and are
9967c478bd9Sstevel@tonic-gate * verified at the time the object was processed (see ver_def_process()).
9977c478bd9Sstevel@tonic-gate * Here we process all version requirements established from shared objects
9987c478bd9Sstevel@tonic-gate * themselves (ie,. NEEDED dependencies).
9997c478bd9Sstevel@tonic-gate */
10007c478bd9Sstevel@tonic-gate int
ld_vers_verify(Ofl_desc * ofl)10015aefb655Srie ld_vers_verify(Ofl_desc *ofl)
10027c478bd9Sstevel@tonic-gate {
100357ef7aa9SRod Evans Aliste idx1;
10047c478bd9Sstevel@tonic-gate Sdf_desc *sdf;
10057c478bd9Sstevel@tonic-gate char *nv;
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate /*
10087c478bd9Sstevel@tonic-gate * As with the runtime environment, disable all version verification if
10097c478bd9Sstevel@tonic-gate * requested.
10107c478bd9Sstevel@tonic-gate */
10117c478bd9Sstevel@tonic-gate #if defined(_ELF64)
10127c478bd9Sstevel@tonic-gate if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_64))) == NULL)
10137c478bd9Sstevel@tonic-gate #else
10147c478bd9Sstevel@tonic-gate if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_32))) == NULL)
10157c478bd9Sstevel@tonic-gate #endif
101660758829Srie nv = getenv(MSG_ORIG(MSG_LD_NOVERSION));
10177c478bd9Sstevel@tonic-gate
101898c080d5SRod Evans if (nv && nv[0])
10197c478bd9Sstevel@tonic-gate return (1);
10207c478bd9Sstevel@tonic-gate
102157ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_soneed, idx1, sdf)) {
102257ef7aa9SRod Evans Aliste idx2;
10237c478bd9Sstevel@tonic-gate Sdv_desc *sdv;
10247c478bd9Sstevel@tonic-gate Ifl_desc *ifl = sdf->sdf_file;
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate if (!(sdf->sdf_flags & FLG_SDF_VERIFY))
10277c478bd9Sstevel@tonic-gate continue;
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate /*
10307c478bd9Sstevel@tonic-gate * If this file contains no version definitions then ignore
10317c478bd9Sstevel@tonic-gate * any versioning verification. This is the same model as
10327c478bd9Sstevel@tonic-gate * carried out by ld.so.1 and is intended to allow backward
10337c478bd9Sstevel@tonic-gate * compatibility should a shared object with a version
103457ef7aa9SRod Evans * requirement be returned to an older system on which a
10357c478bd9Sstevel@tonic-gate * non-versioned shared object exists.
10367c478bd9Sstevel@tonic-gate */
103757ef7aa9SRod Evans if ((ifl == NULL) || (ifl->ifl_verdesc == NULL))
10387c478bd9Sstevel@tonic-gate continue;
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate /*
10417c478bd9Sstevel@tonic-gate * If individual versions were specified for this file make
10427c478bd9Sstevel@tonic-gate * sure that they actually exist in the appropriate file, and
10437c478bd9Sstevel@tonic-gate * that they are available for binding.
10447c478bd9Sstevel@tonic-gate */
104557ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_vers, idx2, sdv)) {
104657ef7aa9SRod Evans Aliste idx3;
10477c478bd9Sstevel@tonic-gate Ver_desc *vdp;
10487c478bd9Sstevel@tonic-gate int found = 0;
10497c478bd9Sstevel@tonic-gate
105057ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx3, vdp)) {
10517c478bd9Sstevel@tonic-gate if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) {
10527c478bd9Sstevel@tonic-gate found++;
10537c478bd9Sstevel@tonic-gate break;
10547c478bd9Sstevel@tonic-gate }
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate if (found) {
10577c478bd9Sstevel@tonic-gate Ver_index *vip;
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vdp->vd_ndx];
10607c478bd9Sstevel@tonic-gate if (!(vip->vi_flags & FLG_VER_AVAIL)) {
10611007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
10627c478bd9Sstevel@tonic-gate MSG_INTL(MSG_VER_UNAVAIL),
10637c478bd9Sstevel@tonic-gate ifl->ifl_name, sdv->sdv_name,
10647c478bd9Sstevel@tonic-gate sdv->sdv_ref);
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate } else {
10671007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL,
10685aefb655Srie MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name,
10695aefb655Srie sdv->sdv_name, sdv->sdv_ref);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate }
10727c478bd9Sstevel@tonic-gate }
10737c478bd9Sstevel@tonic-gate return (1);
10747c478bd9Sstevel@tonic-gate }
1075