1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <string.h> 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include "debug.h" 31*7c478bd9Sstevel@tonic-gate #include "msg.h" 32*7c478bd9Sstevel@tonic-gate #include "_libld.h" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * Locate a version descriptor. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate Ver_desc * 39*7c478bd9Sstevel@tonic-gate vers_find(const char *name, Word hash, List *lst) 40*7c478bd9Sstevel@tonic-gate { 41*7c478bd9Sstevel@tonic-gate Listnode *lnp; 42*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(lst, lnp, vdp)) { 45*7c478bd9Sstevel@tonic-gate if (vdp->vd_hash != hash) 46*7c478bd9Sstevel@tonic-gate continue; 47*7c478bd9Sstevel@tonic-gate if (strcmp(vdp->vd_name, name) == 0) 48*7c478bd9Sstevel@tonic-gate return (vdp); 49*7c478bd9Sstevel@tonic-gate } 50*7c478bd9Sstevel@tonic-gate return (0); 51*7c478bd9Sstevel@tonic-gate } 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /* 54*7c478bd9Sstevel@tonic-gate * Add a new version descriptor to a version descriptor list. Note, users of 55*7c478bd9Sstevel@tonic-gate * this are responsible for determining if the version descriptor already 56*7c478bd9Sstevel@tonic-gate * exists (this can reduce the need to allocate storage for descriptor names 57*7c478bd9Sstevel@tonic-gate * until it is determined a descriptor need be created (see map_symbol())). 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate Ver_desc * 60*7c478bd9Sstevel@tonic-gate vers_desc(const char *name, Word hash, List *lst) 61*7c478bd9Sstevel@tonic-gate { 62*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate if ((vdp = libld_calloc(sizeof (Ver_desc), 1)) == 0) 65*7c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR); 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate vdp->vd_name = name; 68*7c478bd9Sstevel@tonic-gate vdp->vd_hash = hash; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate if (list_appendc(lst, vdp) == 0) 71*7c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR); 72*7c478bd9Sstevel@tonic-gate else 73*7c478bd9Sstevel@tonic-gate return (vdp); 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * Now that all explict files have been processed validate any version 78*7c478bd9Sstevel@tonic-gate * definitions. Insure that any version references are available (a version 79*7c478bd9Sstevel@tonic-gate * has been defined when it's been assigned an index). Also calculate the 80*7c478bd9Sstevel@tonic-gate * number of .version section entries that will be required to hold this 81*7c478bd9Sstevel@tonic-gate * information. 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate #define _NUM_OF_VERS_ 40 /* twice as big as the depth for libc version */ 84*7c478bd9Sstevel@tonic-gate typedef struct { 85*7c478bd9Sstevel@tonic-gate Ver_desc **ver_stk; 86*7c478bd9Sstevel@tonic-gate int ver_sp; 87*7c478bd9Sstevel@tonic-gate int ver_lmt; 88*7c478bd9Sstevel@tonic-gate } Ver_Stack; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static uintptr_t 91*7c478bd9Sstevel@tonic-gate vers_visit_children(Ver_desc *vp, int flag) 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate Listnode *lnp1; 94*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 95*7c478bd9Sstevel@tonic-gate static int err = 0; 96*7c478bd9Sstevel@tonic-gate static Ver_Stack ver_stk = {0, 0, 0}; 97*7c478bd9Sstevel@tonic-gate int tmp_sp; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * If there was any fatal error, 101*7c478bd9Sstevel@tonic-gate * just return. 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate if (err == S_ERROR) 104*7c478bd9Sstevel@tonic-gate return (err); 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * if this is called from, ver_check_defs(), initialize sp. 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate if (flag == 0) 110*7c478bd9Sstevel@tonic-gate ver_stk.ver_sp = 0; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * Check if passed version pointer vp is already in the stack. 114*7c478bd9Sstevel@tonic-gate */ 115*7c478bd9Sstevel@tonic-gate for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) { 116*7c478bd9Sstevel@tonic-gate Ver_desc *v; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate v = ver_stk.ver_stk[tmp_sp]; 119*7c478bd9Sstevel@tonic-gate if (v == vp) { 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * cyclic dependency. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate if (err == 0) { 124*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_VER_CYCLIC)); 125*7c478bd9Sstevel@tonic-gate err = 1; 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) { 128*7c478bd9Sstevel@tonic-gate v = ver_stk.ver_stk[tmp_sp]; 129*7c478bd9Sstevel@tonic-gate if ((v->vd_flags & FLG_VER_CYCLIC) == 0) { 130*7c478bd9Sstevel@tonic-gate v->vd_flags |= FLG_VER_CYCLIC; 131*7c478bd9Sstevel@tonic-gate eprintf(ERR_NONE, 132*7c478bd9Sstevel@tonic-gate MSG_INTL(MSG_VER_ADDVER), 133*7c478bd9Sstevel@tonic-gate v->vd_name); 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate if ((vp->vd_flags & FLG_VER_CYCLIC) == 0) { 137*7c478bd9Sstevel@tonic-gate vp->vd_flags |= FLG_VER_CYCLIC; 138*7c478bd9Sstevel@tonic-gate eprintf(ERR_NONE, 139*7c478bd9Sstevel@tonic-gate MSG_INTL(MSG_VER_ADDVER), 140*7c478bd9Sstevel@tonic-gate vp->vd_name); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate return (err); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* 147*7c478bd9Sstevel@tonic-gate * Push version on the stack. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate if (ver_stk.ver_sp >= ver_stk.ver_lmt) { 150*7c478bd9Sstevel@tonic-gate ver_stk.ver_lmt += _NUM_OF_VERS_; 151*7c478bd9Sstevel@tonic-gate if ((ver_stk.ver_stk = (Ver_desc **) 152*7c478bd9Sstevel@tonic-gate libld_realloc((void *)ver_stk.ver_stk, 153*7c478bd9Sstevel@tonic-gate ver_stk.ver_lmt * sizeof (Ver_desc *))) == NULL) 154*7c478bd9Sstevel@tonic-gate return (S_ERROR); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate ver_stk.ver_stk[(ver_stk.ver_sp)++] = vp; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate /* 159*7c478bd9Sstevel@tonic-gate * Now visit children. 160*7c478bd9Sstevel@tonic-gate */ 161*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&vp->vd_deps, lnp1, vdp)) 162*7c478bd9Sstevel@tonic-gate if (vers_visit_children(vdp, 1) == S_ERROR) 163*7c478bd9Sstevel@tonic-gate return (S_ERROR); 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * Pop version from the stack. 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate (ver_stk.ver_sp)--; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate return (err); 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate uintptr_t 174*7c478bd9Sstevel@tonic-gate vers_check_defs(Ofl_desc *ofl) 175*7c478bd9Sstevel@tonic-gate { 176*7c478bd9Sstevel@tonic-gate Listnode *lnp1, *lnp2; 177*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 178*7c478bd9Sstevel@tonic-gate uintptr_t is_cyclic = 0; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_def_title(ofl->ofl_name)); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * First check if there are any cyclic dependency 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ofl->ofl_verdesc, lnp1, vdp)) 187*7c478bd9Sstevel@tonic-gate if ((is_cyclic = vers_visit_children(vdp, 0)) == S_ERROR) 188*7c478bd9Sstevel@tonic-gate return (S_ERROR); 189*7c478bd9Sstevel@tonic-gate if (is_cyclic) 190*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ofl->ofl_verdesc, lnp1, vdp)) { 193*7c478bd9Sstevel@tonic-gate Byte cnt; 194*7c478bd9Sstevel@tonic-gate Sym *sym; 195*7c478bd9Sstevel@tonic-gate Sym_desc *sdp; 196*7c478bd9Sstevel@tonic-gate const char *name = vdp->vd_name; 197*7c478bd9Sstevel@tonic-gate unsigned char bind; 198*7c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 199*7c478bd9Sstevel@tonic-gate avl_index_t where; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (vdp->vd_ndx == 0) { 202*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_VER_UNDEF), name, 203*7c478bd9Sstevel@tonic-gate vdp->vd_ref->vd_name, 204*7c478bd9Sstevel@tonic-gate vdp->vd_ref->vd_file->ifl_name); 205*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 206*7c478bd9Sstevel@tonic-gate continue; 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_desc_entry(vdp)); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * If a version definition contains no symbols this is possibly 213*7c478bd9Sstevel@tonic-gate * a mapfile error. 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate if ((vdp->vd_flags & 216*7c478bd9Sstevel@tonic-gate (VER_FLG_BASE | VER_FLG_WEAK | FLG_VER_REFER)) == 0) 217*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_nointerface(vdp->vd_name)); 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate /* 220*7c478bd9Sstevel@tonic-gate * Update the version entry count to account for this new 221*7c478bd9Sstevel@tonic-gate * version descriptor (the count is the size in bytes). 222*7c478bd9Sstevel@tonic-gate */ 223*7c478bd9Sstevel@tonic-gate ofl->ofl_verdefsz += sizeof (Verdef); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * Traverse this versions dependency list to determine what 227*7c478bd9Sstevel@tonic-gate * additional version dependencies we must account for against 228*7c478bd9Sstevel@tonic-gate * this descriptor. 229*7c478bd9Sstevel@tonic-gate */ 230*7c478bd9Sstevel@tonic-gate cnt = 1; 231*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&vdp->vd_deps, lnp2, _vdp)) { 232*7c478bd9Sstevel@tonic-gate #if defined(__lint) 233*7c478bd9Sstevel@tonic-gate /* get lint to think `_vdp' is used... */ 234*7c478bd9Sstevel@tonic-gate lnp2 = (Listnode *)_vdp; 235*7c478bd9Sstevel@tonic-gate #endif 236*7c478bd9Sstevel@tonic-gate cnt++; 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate ofl->ofl_verdefsz += (cnt * sizeof (Verdaux)); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* 241*7c478bd9Sstevel@tonic-gate * Except for the base version descriptor, generate an absolute 242*7c478bd9Sstevel@tonic-gate * symbol to reflect this version. 243*7c478bd9Sstevel@tonic-gate */ 244*7c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_BASE) 245*7c478bd9Sstevel@tonic-gate continue; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_WEAK) 248*7c478bd9Sstevel@tonic-gate bind = STB_WEAK; 249*7c478bd9Sstevel@tonic-gate else 250*7c478bd9Sstevel@tonic-gate bind = STB_GLOBAL; 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate if (sdp = sym_find(name, vdp->vd_hash, &where, ofl)) { 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * If the symbol already exists and is undefined or was 255*7c478bd9Sstevel@tonic-gate * defined in a shared library, convert it to an 256*7c478bd9Sstevel@tonic-gate * absolute. 257*7c478bd9Sstevel@tonic-gate */ 258*7c478bd9Sstevel@tonic-gate if ((sdp->sd_shndx == SHN_UNDEF) || 259*7c478bd9Sstevel@tonic-gate (sdp->sd_ref != REF_REL_NEED)) { 260*7c478bd9Sstevel@tonic-gate sdp->sd_shndx = sdp->sd_sym->st_shndx = SHN_ABS; 261*7c478bd9Sstevel@tonic-gate sdp->sd_sym->st_info = 262*7c478bd9Sstevel@tonic-gate ELF_ST_INFO(bind, STT_OBJECT); 263*7c478bd9Sstevel@tonic-gate sdp->sd_ref = REF_REL_NEED; 264*7c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 265*7c478bd9Sstevel@tonic-gate sdp->sd_flags1 |= FLG_SY1_GLOB; 266*7c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vdp->vd_ndx; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * If the reference originated from a mapfile 270*7c478bd9Sstevel@tonic-gate * insure we mark the symbol as used. 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_MAPREF) 273*7c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_MAPUSED; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate } else if ((sdp->sd_flags & FLG_SY_SPECSEC) && 276*7c478bd9Sstevel@tonic-gate (sdp->sd_shndx != SHN_ABS) && 277*7c478bd9Sstevel@tonic-gate (sdp->sd_ref == REF_REL_NEED)) { 278*7c478bd9Sstevel@tonic-gate eprintf(ERR_WARNING, MSG_INTL(MSG_VER_DEFINED), 279*7c478bd9Sstevel@tonic-gate name, sdp->sd_file->ifl_name); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate } else { 282*7c478bd9Sstevel@tonic-gate /* 283*7c478bd9Sstevel@tonic-gate * If the symbol does not exist create it. 284*7c478bd9Sstevel@tonic-gate */ 285*7c478bd9Sstevel@tonic-gate if ((sym = libld_calloc(sizeof (Sym), 1)) == 0) 286*7c478bd9Sstevel@tonic-gate return (S_ERROR); 287*7c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_ABS; 288*7c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, STT_OBJECT); 289*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_symbol(name)); 290*7c478bd9Sstevel@tonic-gate if ((sdp = sym_enter(name, sym, vdp->vd_hash, 291*7c478bd9Sstevel@tonic-gate vdp->vd_file, ofl, 0, SHN_ABS, FLG_SY_SPECSEC, 292*7c478bd9Sstevel@tonic-gate FLG_SY1_GLOB, &where)) == (Sym_desc *)S_ERROR) 293*7c478bd9Sstevel@tonic-gate return (S_ERROR); 294*7c478bd9Sstevel@tonic-gate sdp->sd_ref = REF_REL_NEED; 295*7c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vdp->vd_ndx; 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate return (1); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate /* 302*7c478bd9Sstevel@tonic-gate * Dereference dependencies as a part of normalizing (allows recursion). 303*7c478bd9Sstevel@tonic-gate */ 304*7c478bd9Sstevel@tonic-gate void 305*7c478bd9Sstevel@tonic-gate vers_derefer(Ifl_desc *ifl, Ver_desc *vdp, int weak) 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate Listnode *lnp; 308*7c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 309*7c478bd9Sstevel@tonic-gate Ver_index *vip = &ifl->ifl_verndx[vdp->vd_ndx]; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate /* 312*7c478bd9Sstevel@tonic-gate * If the head of the list was a weak then we only clear out 313*7c478bd9Sstevel@tonic-gate * weak dependencies, but if the head of the list was 'strong' 314*7c478bd9Sstevel@tonic-gate * we clear the REFER bit on all dependencies. 315*7c478bd9Sstevel@tonic-gate */ 316*7c478bd9Sstevel@tonic-gate if ((weak && (vdp->vd_flags & VER_FLG_WEAK)) || (!weak)) 317*7c478bd9Sstevel@tonic-gate vip->vi_flags &= ~FLG_VER_REFER; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&vdp->vd_deps, lnp, _vdp)) 320*7c478bd9Sstevel@tonic-gate vers_derefer(ifl, _vdp, weak); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * If we need to record the versions of any needed dependencies traverse the 325*7c478bd9Sstevel@tonic-gate * shared object dependency list and calculate what version needed entries are 326*7c478bd9Sstevel@tonic-gate * required. 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate uintptr_t 329*7c478bd9Sstevel@tonic-gate vers_check_need(Ofl_desc *ofl) 330*7c478bd9Sstevel@tonic-gate { 331*7c478bd9Sstevel@tonic-gate Listnode *lnp1; 332*7c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * Traverse the shared object list looking for dependencies. 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ofl->ofl_sos, lnp1, ifl)) { 338*7c478bd9Sstevel@tonic-gate Listnode *lnp2; 339*7c478bd9Sstevel@tonic-gate Ver_index *vip; 340*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 341*7c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc; 342*7c478bd9Sstevel@tonic-gate Byte cnt, need; 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate if (!(ifl->ifl_flags & FLG_IF_NEEDED)) 345*7c478bd9Sstevel@tonic-gate continue; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate if (ifl->ifl_vercnt <= VER_NDX_GLOBAL) 348*7c478bd9Sstevel@tonic-gate continue; 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate /* 351*7c478bd9Sstevel@tonic-gate * If version needed definitions were specified in 352*7c478bd9Sstevel@tonic-gate * a mapfile ($SPECVERS=) then record those definitions 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_SPECVER)) { 355*7c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 356*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&sdf->sdf_verneed, lnp2, 357*7c478bd9Sstevel@tonic-gate sdv)) { 358*7c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Vernaux); 359*7c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, 360*7c478bd9Sstevel@tonic-gate sdv->sdv_name) == -1) 361*7c478bd9Sstevel@tonic-gate return (S_ERROR); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate ifl->ifl_flags |= FLG_IF_VERNEED; 364*7c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Verneed); 365*7c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, 366*7c478bd9Sstevel@tonic-gate ifl->ifl_soname) == -1) 367*7c478bd9Sstevel@tonic-gate return (S_ERROR); 368*7c478bd9Sstevel@tonic-gate continue; 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * Scan the version index list and if any weak version 373*7c478bd9Sstevel@tonic-gate * definition has been referenced by the user promote the 374*7c478bd9Sstevel@tonic-gate * dependency to be non-weak. Weak version dependencies do not 375*7c478bd9Sstevel@tonic-gate * cause fatal errors from the runtime linker, non-weak 376*7c478bd9Sstevel@tonic-gate * dependencies do. 377*7c478bd9Sstevel@tonic-gate */ 378*7c478bd9Sstevel@tonic-gate for (need = 0, cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) { 379*7c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt]; 380*7c478bd9Sstevel@tonic-gate vdp = vip->vi_desc; 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate if ((vip->vi_flags & (FLG_VER_REFER | VER_FLG_WEAK)) == 383*7c478bd9Sstevel@tonic-gate (FLG_VER_REFER | VER_FLG_WEAK)) 384*7c478bd9Sstevel@tonic-gate vdp->vd_flags &= ~VER_FLG_WEAK; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* 387*7c478bd9Sstevel@tonic-gate * Mark any weak reference as referred to so as to 388*7c478bd9Sstevel@tonic-gate * simplify normalization and later version dependency 389*7c478bd9Sstevel@tonic-gate * manipulation. 390*7c478bd9Sstevel@tonic-gate */ 391*7c478bd9Sstevel@tonic-gate if (vip->vi_flags & VER_FLG_WEAK) 392*7c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_REFER; 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate /* 396*7c478bd9Sstevel@tonic-gate * Scan the version dependency list to normalize the referenced 397*7c478bd9Sstevel@tonic-gate * dependencies. Any needed version that is inherited by 398*7c478bd9Sstevel@tonic-gate * another like version is derefereced as it is not necessary 399*7c478bd9Sstevel@tonic-gate * to make this part of the version dependencies. 400*7c478bd9Sstevel@tonic-gate */ 401*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ifl->ifl_verdesc, lnp2, vdp)) { 402*7c478bd9Sstevel@tonic-gate Listnode *lnp3; 403*7c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 404*7c478bd9Sstevel@tonic-gate int type; 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vdp->vd_ndx]; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate if (!(vip->vi_flags & FLG_VER_REFER)) 409*7c478bd9Sstevel@tonic-gate continue; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate type = vdp->vd_flags & VER_FLG_WEAK; 412*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&vdp->vd_deps, lnp3, _vdp)) 413*7c478bd9Sstevel@tonic-gate vers_derefer(ifl, _vdp, type); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate /* 417*7c478bd9Sstevel@tonic-gate * Finally, determine how many of the version dependencies need 418*7c478bd9Sstevel@tonic-gate * to be recorded. 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate for (need = 0, cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) { 421*7c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt]; 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * If a version has been referenced then record it as a 425*7c478bd9Sstevel@tonic-gate * version dependency. 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate if (vip->vi_flags & FLG_VER_REFER) { 428*7c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Vernaux); 429*7c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, 430*7c478bd9Sstevel@tonic-gate vip->vi_name) == -1) 431*7c478bd9Sstevel@tonic-gate return (S_ERROR); 432*7c478bd9Sstevel@tonic-gate need++; 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate if (need) { 437*7c478bd9Sstevel@tonic-gate ifl->ifl_flags |= FLG_IF_VERNEED; 438*7c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Verneed); 439*7c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, 440*7c478bd9Sstevel@tonic-gate ifl->ifl_soname) == -1) 441*7c478bd9Sstevel@tonic-gate return (S_ERROR); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate /* 446*7c478bd9Sstevel@tonic-gate * If no version needed information is required unset the output file 447*7c478bd9Sstevel@tonic-gate * flag. 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate if (ofl->ofl_verneedsz == 0) 450*7c478bd9Sstevel@tonic-gate ofl->ofl_flags &= ~FLG_OF_VERNEED; 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate return (1); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate /* 456*7c478bd9Sstevel@tonic-gate * Indicate dependency selection (allows recursion). 457*7c478bd9Sstevel@tonic-gate */ 458*7c478bd9Sstevel@tonic-gate void 459*7c478bd9Sstevel@tonic-gate vers_select(Ifl_desc *ifl, Ver_desc *vdp, const char *ref) 460*7c478bd9Sstevel@tonic-gate { 461*7c478bd9Sstevel@tonic-gate Listnode *lnp; 462*7c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 463*7c478bd9Sstevel@tonic-gate Ver_index *vip = &ifl->ifl_verndx[vdp->vd_ndx]; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_AVAIL; 466*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_avail_entry(vip, ref)); 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&vdp->vd_deps, lnp, _vdp)) 469*7c478bd9Sstevel@tonic-gate vers_select(ifl, _vdp, ref); 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate Ver_index * 473*7c478bd9Sstevel@tonic-gate vers_index(Ifl_desc *ifl, int avail) 474*7c478bd9Sstevel@tonic-gate { 475*7c478bd9Sstevel@tonic-gate Listnode *lnp; 476*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 477*7c478bd9Sstevel@tonic-gate Ver_index *vip; 478*7c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc; 479*7c478bd9Sstevel@tonic-gate Word count = ifl->ifl_vercnt; 480*7c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate /* 483*7c478bd9Sstevel@tonic-gate * Allocate an index array large enough to hold all of the files 484*7c478bd9Sstevel@tonic-gate * version descriptors. 485*7c478bd9Sstevel@tonic-gate */ 486*7c478bd9Sstevel@tonic-gate if ((vip = libld_calloc(sizeof (Ver_index), 487*7c478bd9Sstevel@tonic-gate (count + 1))) == 0) 488*7c478bd9Sstevel@tonic-gate return ((Ver_index *)S_ERROR); 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ifl->ifl_verdesc, lnp, vdp)) { 491*7c478bd9Sstevel@tonic-gate int ndx = vdp->vd_ndx; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate vip[ndx].vi_name = vdp->vd_name; 494*7c478bd9Sstevel@tonic-gate vip[ndx].vi_desc = vdp; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate /* 497*7c478bd9Sstevel@tonic-gate * Any relocatable object versions, and the `base' version are 498*7c478bd9Sstevel@tonic-gate * always available. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate if (avail || (vdp->vd_flags & VER_FLG_BASE)) 501*7c478bd9Sstevel@tonic-gate vip[ndx].vi_flags |= FLG_VER_AVAIL; 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate /* 504*7c478bd9Sstevel@tonic-gate * If this is a weak version mark it as such. Weak versions 505*7c478bd9Sstevel@tonic-gate * are always dragged into any version dependencies created, 506*7c478bd9Sstevel@tonic-gate * and if a weak version is referenced it will be promoted to 507*7c478bd9Sstevel@tonic-gate * a non-weak version dependency. 508*7c478bd9Sstevel@tonic-gate */ 509*7c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_WEAK) 510*7c478bd9Sstevel@tonic-gate vip[ndx].vi_flags |= VER_FLG_WEAK; 511*7c478bd9Sstevel@tonic-gate /* 512*7c478bd9Sstevel@tonic-gate * If this version is mentioned in a mapfile 513*7c478bd9Sstevel@tonic-gate * $ADDVERS syntax then add a FLG_IF_NEEDED flag now 514*7c478bd9Sstevel@tonic-gate */ 515*7c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) { 516*7c478bd9Sstevel@tonic-gate Listnode * lnp2; 517*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&sdf->sdf_verneed, lnp2, sdv)) { 518*7c478bd9Sstevel@tonic-gate if (strcmp(vip[ndx].vi_name, 519*7c478bd9Sstevel@tonic-gate sdv->sdv_name) == 0) { 520*7c478bd9Sstevel@tonic-gate vip[ndx].vi_flags |= FLG_VER_REFER; 521*7c478bd9Sstevel@tonic-gate sdv->sdv_flags |= FLG_SDV_MATCHED; 522*7c478bd9Sstevel@tonic-gate break; 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * if $ADDVER was specified for this object verify that 530*7c478bd9Sstevel@tonic-gate * all of it's dependent upon versions were refered to. 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) { 533*7c478bd9Sstevel@tonic-gate int fail = 0; 534*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&sdf->sdf_verneed, lnp, sdv)) { 535*7c478bd9Sstevel@tonic-gate if (!(sdv->sdv_flags & FLG_SDV_MATCHED)) { 536*7c478bd9Sstevel@tonic-gate if (fail == 0) { 537*7c478bd9Sstevel@tonic-gate fail++; 538*7c478bd9Sstevel@tonic-gate eprintf(ERR_NONE, 539*7c478bd9Sstevel@tonic-gate MSG_INTL(MSG_VER_ADDVERS), 540*7c478bd9Sstevel@tonic-gate sdf->sdf_rfile, sdf->sdf_name); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate eprintf(ERR_NONE, MSG_INTL(MSG_VER_ADDVER), 543*7c478bd9Sstevel@tonic-gate sdv->sdv_name); 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate if (fail) 547*7c478bd9Sstevel@tonic-gate return ((Ver_index *)S_ERROR); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate return (vip); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * Process a version symbol index section. 555*7c478bd9Sstevel@tonic-gate */ 556*7c478bd9Sstevel@tonic-gate int 557*7c478bd9Sstevel@tonic-gate vers_sym_process(Is_desc *isp, Ifl_desc *ifl) 558*7c478bd9Sstevel@tonic-gate { 559*7c478bd9Sstevel@tonic-gate Shdr *symshdr; 560*7c478bd9Sstevel@tonic-gate Shdr *vershdr = isp->is_shdr; 561*7c478bd9Sstevel@tonic-gate /* 562*7c478bd9Sstevel@tonic-gate * Verify that the versym is the same size as the 563*7c478bd9Sstevel@tonic-gate * linked symbol table. If these two get out of sync 564*7c478bd9Sstevel@tonic-gate * the file is considered corrupted. 565*7c478bd9Sstevel@tonic-gate */ 566*7c478bd9Sstevel@tonic-gate symshdr = ifl->ifl_isdesc[vershdr->sh_link]->is_shdr; 567*7c478bd9Sstevel@tonic-gate if ((symshdr->sh_size / symshdr->sh_entsize) != (vershdr->sh_size / 568*7c478bd9Sstevel@tonic-gate vershdr->sh_entsize)) { 569*7c478bd9Sstevel@tonic-gate eprintf(ERR_WARNING, MSG_INTL(MSG_ELF_VERSYM), ifl->ifl_name, 570*7c478bd9Sstevel@tonic-gate isp->is_name, 571*7c478bd9Sstevel@tonic-gate EC_WORD(vershdr->sh_size / vershdr->sh_entsize), 572*7c478bd9Sstevel@tonic-gate ifl->ifl_isdesc[vershdr->sh_link]->is_name, 573*7c478bd9Sstevel@tonic-gate EC_WORD(symshdr->sh_size / symshdr->sh_entsize)); 574*7c478bd9Sstevel@tonic-gate return (1); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate ifl->ifl_versym = (Versym *)isp->is_indata->d_buf; 577*7c478bd9Sstevel@tonic-gate return (1); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate /* 581*7c478bd9Sstevel@tonic-gate * Process a version definition section from an input file. A list of version 582*7c478bd9Sstevel@tonic-gate * descriptors is created and associated with the input files descriptor. If 583*7c478bd9Sstevel@tonic-gate * this is a shared object these descriptors will be used to indicate the 584*7c478bd9Sstevel@tonic-gate * availability of each version. If this is a relocatable object then these 585*7c478bd9Sstevel@tonic-gate * descriptors will be promoted (concatenated) to the output files image. 586*7c478bd9Sstevel@tonic-gate */ 587*7c478bd9Sstevel@tonic-gate uintptr_t 588*7c478bd9Sstevel@tonic-gate vers_def_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl) 589*7c478bd9Sstevel@tonic-gate { 590*7c478bd9Sstevel@tonic-gate const char *str, *file = ifl->ifl_name; 591*7c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc; 592*7c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 593*7c478bd9Sstevel@tonic-gate Word num, _num; 594*7c478bd9Sstevel@tonic-gate Verdef *vdf; 595*7c478bd9Sstevel@tonic-gate int relobj; 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate /* 598*7c478bd9Sstevel@tonic-gate * If there is no version section then simply indicate that all version 599*7c478bd9Sstevel@tonic-gate * definitions asked for do not exist. 600*7c478bd9Sstevel@tonic-gate */ 601*7c478bd9Sstevel@tonic-gate if (isp == 0) { 602*7c478bd9Sstevel@tonic-gate Listnode *lnp; 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&sdf->sdf_vers, lnp, sdv)) { 605*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_VER_NOEXIST), 606*7c478bd9Sstevel@tonic-gate ifl->ifl_name, sdv->sdv_name, sdv->sdv_ref); 607*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate return (0); 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate vdf = (Verdef *)isp->is_indata->d_buf; 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate /* 615*7c478bd9Sstevel@tonic-gate * Verify the version revision. We only check the first version 616*7c478bd9Sstevel@tonic-gate * structure as it is assumed all other version structures in this 617*7c478bd9Sstevel@tonic-gate * data section will be of the same revision. 618*7c478bd9Sstevel@tonic-gate */ 619*7c478bd9Sstevel@tonic-gate if (vdf->vd_version > VER_DEF_CURRENT) 620*7c478bd9Sstevel@tonic-gate (void) eprintf(ERR_WARNING, MSG_INTL(MSG_VER_HIGHER), 621*7c478bd9Sstevel@tonic-gate ifl->ifl_name, vdf->vd_version, VER_DEF_CURRENT); 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate num = isp->is_shdr->sh_info; 625*7c478bd9Sstevel@tonic-gate str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf; 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate if (ifl->ifl_ehdr->e_type == ET_REL) 628*7c478bd9Sstevel@tonic-gate relobj = 1; 629*7c478bd9Sstevel@tonic-gate else 630*7c478bd9Sstevel@tonic-gate relobj = 0; 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_def_title(file)); 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate /* 635*7c478bd9Sstevel@tonic-gate * Loop through the version information setting up a version descriptor 636*7c478bd9Sstevel@tonic-gate * for each version definition. 637*7c478bd9Sstevel@tonic-gate */ 638*7c478bd9Sstevel@tonic-gate for (_num = 1; _num <= num; _num++, 639*7c478bd9Sstevel@tonic-gate vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 640*7c478bd9Sstevel@tonic-gate const char *name; 641*7c478bd9Sstevel@tonic-gate Ver_desc *ivdp, *ovdp = 0; 642*7c478bd9Sstevel@tonic-gate Word hash; 643*7c478bd9Sstevel@tonic-gate Half cnt = vdf->vd_cnt; 644*7c478bd9Sstevel@tonic-gate Half ndx = vdf->vd_ndx; 645*7c478bd9Sstevel@tonic-gate Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + 646*7c478bd9Sstevel@tonic-gate vdf->vd_aux); 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate /* 649*7c478bd9Sstevel@tonic-gate * Keep track of the largest index for use in creating a 650*7c478bd9Sstevel@tonic-gate * version index array later, and create a version descriptor. 651*7c478bd9Sstevel@tonic-gate */ 652*7c478bd9Sstevel@tonic-gate if (ndx > ifl->ifl_vercnt) 653*7c478bd9Sstevel@tonic-gate ifl->ifl_vercnt = ndx; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate name = (char *)(str + vdap->vda_name); 656*7c478bd9Sstevel@tonic-gate /* LINTED */ 657*7c478bd9Sstevel@tonic-gate hash = (Word)elf_hash(name); 658*7c478bd9Sstevel@tonic-gate if ((ivdp = vers_find(name, hash, &ifl->ifl_verdesc)) == 0) { 659*7c478bd9Sstevel@tonic-gate if ((ivdp = vers_desc(name, hash, 660*7c478bd9Sstevel@tonic-gate &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR) 661*7c478bd9Sstevel@tonic-gate return (S_ERROR); 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate ivdp->vd_ndx = ndx; 664*7c478bd9Sstevel@tonic-gate ivdp->vd_file = ifl; 665*7c478bd9Sstevel@tonic-gate ivdp->vd_flags = vdf->vd_flags; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate /* 668*7c478bd9Sstevel@tonic-gate * If we're processing a relocatable object then this version 669*7c478bd9Sstevel@tonic-gate * definition needs to be propagated to the output file. 670*7c478bd9Sstevel@tonic-gate * Generate a new output file version and associated this input 671*7c478bd9Sstevel@tonic-gate * version to it. During symbol processing the version index of 672*7c478bd9Sstevel@tonic-gate * the symbol will be promoted from the input file to the output 673*7c478bd9Sstevel@tonic-gate * files version definition. 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate if (relobj) { 676*7c478bd9Sstevel@tonic-gate if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) 677*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_PROCRED; 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate if ((ivdp->vd_flags & VER_FLG_BASE) == 0) { 680*7c478bd9Sstevel@tonic-gate /* 681*7c478bd9Sstevel@tonic-gate * If no version descriptors have yet been set 682*7c478bd9Sstevel@tonic-gate * up, initialize a base version to represent 683*7c478bd9Sstevel@tonic-gate * the output file itself. This `base' version 684*7c478bd9Sstevel@tonic-gate * catches any internally generated symbols 685*7c478bd9Sstevel@tonic-gate * (_end, _etext, etc.) and 686*7c478bd9Sstevel@tonic-gate * serves to initialize the output version 687*7c478bd9Sstevel@tonic-gate * descriptor count. 688*7c478bd9Sstevel@tonic-gate */ 689*7c478bd9Sstevel@tonic-gate if (ofl->ofl_vercnt == 0) { 690*7c478bd9Sstevel@tonic-gate if (vers_base(ofl) == 691*7c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR) 692*7c478bd9Sstevel@tonic-gate return (S_ERROR); 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_VERDEF; 695*7c478bd9Sstevel@tonic-gate if ((ovdp = vers_find(name, hash, 696*7c478bd9Sstevel@tonic-gate &ofl->ofl_verdesc)) == 0) { 697*7c478bd9Sstevel@tonic-gate if ((ovdp = vers_desc(name, hash, 698*7c478bd9Sstevel@tonic-gate &ofl->ofl_verdesc)) == 699*7c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR) 700*7c478bd9Sstevel@tonic-gate return (S_ERROR); 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate /* LINTED */ 703*7c478bd9Sstevel@tonic-gate ovdp->vd_ndx = (Half)++ofl->ofl_vercnt; 704*7c478bd9Sstevel@tonic-gate ovdp->vd_file = ifl; 705*7c478bd9Sstevel@tonic-gate ovdp->vd_flags = vdf->vd_flags; 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate /* 710*7c478bd9Sstevel@tonic-gate * Maintain the association between the input version 711*7c478bd9Sstevel@tonic-gate * descriptor and the output version descriptor so that 712*7c478bd9Sstevel@tonic-gate * an associated symbols will be assigned to the 713*7c478bd9Sstevel@tonic-gate * correct version. 714*7c478bd9Sstevel@tonic-gate */ 715*7c478bd9Sstevel@tonic-gate ivdp->vd_ref = ovdp; 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* 719*7c478bd9Sstevel@tonic-gate * Process any dependencies this version may have. 720*7c478bd9Sstevel@tonic-gate */ 721*7c478bd9Sstevel@tonic-gate vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 722*7c478bd9Sstevel@tonic-gate for (cnt--; cnt; cnt--, 723*7c478bd9Sstevel@tonic-gate vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next)) { 724*7c478bd9Sstevel@tonic-gate Ver_desc *_ivdp; 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate name = (char *)(str + vdap->vda_name); 727*7c478bd9Sstevel@tonic-gate /* LINTED */ 728*7c478bd9Sstevel@tonic-gate hash = (Word)elf_hash(name); 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate if ((_ivdp = vers_find(name, hash, 731*7c478bd9Sstevel@tonic-gate &ifl->ifl_verdesc)) == 0) { 732*7c478bd9Sstevel@tonic-gate if ((_ivdp = vers_desc(name, hash, 733*7c478bd9Sstevel@tonic-gate &ifl->ifl_verdesc)) == 734*7c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR) 735*7c478bd9Sstevel@tonic-gate return (S_ERROR); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate if (list_appendc(&ivdp->vd_deps, _ivdp) == 0) 738*7c478bd9Sstevel@tonic-gate return (S_ERROR); 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_desc_entry(ivdp)); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate /* 744*7c478bd9Sstevel@tonic-gate * Now that we know the total number of version definitions for this 745*7c478bd9Sstevel@tonic-gate * file, build an index array for fast access when processing symbols. 746*7c478bd9Sstevel@tonic-gate */ 747*7c478bd9Sstevel@tonic-gate if ((ifl->ifl_verndx = vers_index(ifl, relobj)) == (Ver_index *)S_ERROR) 748*7c478bd9Sstevel@tonic-gate return (S_ERROR); 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate if (relobj) 751*7c478bd9Sstevel@tonic-gate return (1); 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * If this object has version control definitions against it then these 755*7c478bd9Sstevel@tonic-gate * must be processed so as to select those version definitions to which 756*7c478bd9Sstevel@tonic-gate * symbol bindings can occur. Otherwise simply mark all versions as 757*7c478bd9Sstevel@tonic-gate * available. 758*7c478bd9Sstevel@tonic-gate */ 759*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_avail_title(file)); 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_SELECT)) { 762*7c478bd9Sstevel@tonic-gate Listnode *lnp1; 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&sdf->sdf_vers, lnp1, sdv)) { 765*7c478bd9Sstevel@tonic-gate Listnode *lnp2; 766*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 767*7c478bd9Sstevel@tonic-gate int found = 0; 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ifl->ifl_verdesc, lnp2, vdp)) { 770*7c478bd9Sstevel@tonic-gate if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) { 771*7c478bd9Sstevel@tonic-gate found++; 772*7c478bd9Sstevel@tonic-gate break; 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate if (found) 776*7c478bd9Sstevel@tonic-gate vers_select(ifl, vdp, sdv->sdv_ref); 777*7c478bd9Sstevel@tonic-gate else { 778*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_VER_NOEXIST), 779*7c478bd9Sstevel@tonic-gate ifl->ifl_name, sdv->sdv_name, sdv->sdv_ref); 780*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate } else { 784*7c478bd9Sstevel@tonic-gate Ver_index *vip; 785*7c478bd9Sstevel@tonic-gate int cnt; 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate for (cnt = VER_NDX_GLOBAL; cnt <= ifl->ifl_vercnt; cnt++) { 788*7c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt]; 789*7c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_AVAIL; 790*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_avail_entry(vip, 0)); 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate /* 795*7c478bd9Sstevel@tonic-gate * If this is an explict dependency indicate that this file is a 796*7c478bd9Sstevel@tonic-gate * candidate for requiring version needed information to be recorded in 797*7c478bd9Sstevel@tonic-gate * the image we're creating. 798*7c478bd9Sstevel@tonic-gate */ 799*7c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_NEEDED) 800*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_VERNEED; 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate return (1); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate /* 806*7c478bd9Sstevel@tonic-gate * Process a version needed section. 807*7c478bd9Sstevel@tonic-gate */ 808*7c478bd9Sstevel@tonic-gate uintptr_t 809*7c478bd9Sstevel@tonic-gate vers_need_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl) 810*7c478bd9Sstevel@tonic-gate { 811*7c478bd9Sstevel@tonic-gate const char *str, *file = ifl->ifl_name; 812*7c478bd9Sstevel@tonic-gate Word num, _num; 813*7c478bd9Sstevel@tonic-gate Verneed *vnd; 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate vnd = (Verneed *)isp->is_indata->d_buf; 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate /* 818*7c478bd9Sstevel@tonic-gate * Verify the version revision. We only check the first version 819*7c478bd9Sstevel@tonic-gate * structure as it is assumed all other version structures in this 820*7c478bd9Sstevel@tonic-gate * data section will be of the same revision. 821*7c478bd9Sstevel@tonic-gate */ 822*7c478bd9Sstevel@tonic-gate if (vnd->vn_version > VER_DEF_CURRENT) 823*7c478bd9Sstevel@tonic-gate (void) eprintf(ERR_WARNING, MSG_INTL(MSG_VER_HIGHER), 824*7c478bd9Sstevel@tonic-gate ifl->ifl_name, vnd->vn_version, VER_DEF_CURRENT); 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate num = isp->is_shdr->sh_info; 828*7c478bd9Sstevel@tonic-gate str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf; 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_need_title(file)); 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate /* 833*7c478bd9Sstevel@tonic-gate * Loop through the version information setting up a version descriptor 834*7c478bd9Sstevel@tonic-gate * for each version definition. 835*7c478bd9Sstevel@tonic-gate */ 836*7c478bd9Sstevel@tonic-gate for (_num = 1; _num <= num; _num++, 837*7c478bd9Sstevel@tonic-gate vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 838*7c478bd9Sstevel@tonic-gate Sdf_desc *sdf; 839*7c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 840*7c478bd9Sstevel@tonic-gate const char *name; 841*7c478bd9Sstevel@tonic-gate Half cnt = vnd->vn_cnt; 842*7c478bd9Sstevel@tonic-gate Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + 843*7c478bd9Sstevel@tonic-gate vnd->vn_aux); 844*7c478bd9Sstevel@tonic-gate Half _cnt; 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate name = (char *)(str + vnd->vn_file); 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate /* 849*7c478bd9Sstevel@tonic-gate * Set up a shared object descriptor and add to it the necessary 850*7c478bd9Sstevel@tonic-gate * needed versions. This information may also have been added 851*7c478bd9Sstevel@tonic-gate * by a mapfile (see map_dash()). 852*7c478bd9Sstevel@tonic-gate */ 853*7c478bd9Sstevel@tonic-gate if ((sdf = sdf_find(name, &ofl->ofl_soneed)) == 0) { 854*7c478bd9Sstevel@tonic-gate if ((sdf = sdf_add(name, &ofl->ofl_soneed)) == 855*7c478bd9Sstevel@tonic-gate (Sdf_desc *)S_ERROR) 856*7c478bd9Sstevel@tonic-gate return (S_ERROR); 857*7c478bd9Sstevel@tonic-gate sdf->sdf_rfile = file; 858*7c478bd9Sstevel@tonic-gate sdf->sdf_flags |= FLG_SDF_VERIFY; 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate for (_cnt = 0; cnt; _cnt++, cnt--, 862*7c478bd9Sstevel@tonic-gate vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next)) { 863*7c478bd9Sstevel@tonic-gate if (!(sdv = 864*7c478bd9Sstevel@tonic-gate libld_calloc(sizeof (Sdv_desc), 1))) 865*7c478bd9Sstevel@tonic-gate return (S_ERROR); 866*7c478bd9Sstevel@tonic-gate sdv->sdv_name = str + vnap->vna_name; 867*7c478bd9Sstevel@tonic-gate sdv->sdv_ref = file; 868*7c478bd9Sstevel@tonic-gate if (list_appendc(&sdf->sdf_vers, sdv) == 0) 869*7c478bd9Sstevel@tonic-gate return (S_ERROR); 870*7c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_ver_need_entry(_cnt, name, sdv->sdv_name)); 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate } 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate return (1); 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate 877*7c478bd9Sstevel@tonic-gate /* 878*7c478bd9Sstevel@tonic-gate * If a symbol is obtained from a versioned relocatable object then the symbols 879*7c478bd9Sstevel@tonic-gate * version association must be promoted to the version definition as it will be 880*7c478bd9Sstevel@tonic-gate * represented in the output file. 881*7c478bd9Sstevel@tonic-gate */ 882*7c478bd9Sstevel@tonic-gate void 883*7c478bd9Sstevel@tonic-gate vers_promote(Sym_desc *sdp, Word ndx, Ifl_desc *ifl, Ofl_desc *ofl) 884*7c478bd9Sstevel@tonic-gate { 885*7c478bd9Sstevel@tonic-gate Half vndx; 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate /* 888*7c478bd9Sstevel@tonic-gate * A version symbol index of 0 implies the symbol is local. A value of 889*7c478bd9Sstevel@tonic-gate * VER_NDX_GLOBAL implies the symbol is global but has not been 890*7c478bd9Sstevel@tonic-gate * assigned to a specfic version definition. 891*7c478bd9Sstevel@tonic-gate */ 892*7c478bd9Sstevel@tonic-gate vndx = ifl->ifl_versym[ndx]; 893*7c478bd9Sstevel@tonic-gate if (vndx == 0) { 894*7c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_REDUCED; 895*7c478bd9Sstevel@tonic-gate sdp->sd_flags1 |= FLG_SY1_LOCL; 896*7c478bd9Sstevel@tonic-gate return; 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate if (vndx == VER_NDX_ELIMINATE) { 900*7c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_REDUCED; 901*7c478bd9Sstevel@tonic-gate sdp->sd_flags1 |= (FLG_SY1_LOCL | FLG_SY1_ELIM); 902*7c478bd9Sstevel@tonic-gate return; 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate if (vndx == VER_NDX_GLOBAL) { 906*7c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags1 & FLG_SY1_LOCL)) { 907*7c478bd9Sstevel@tonic-gate sdp->sd_flags1 |= FLG_SY1_GLOB; 908*7c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL; 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate return; 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate /* 914*7c478bd9Sstevel@tonic-gate * Any other version index requires association to the appropriate 915*7c478bd9Sstevel@tonic-gate * version definition. 916*7c478bd9Sstevel@tonic-gate */ 917*7c478bd9Sstevel@tonic-gate if ((ifl->ifl_verndx == 0) || (vndx > ifl->ifl_vercnt)) { 918*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_VER_INVALNDX), sdp->sd_name, 919*7c478bd9Sstevel@tonic-gate ifl->ifl_name, vndx); 920*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 921*7c478bd9Sstevel@tonic-gate return; 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags1 & FLG_SY1_LOCL)) 925*7c478bd9Sstevel@tonic-gate sdp->sd_flags1 |= FLG_SY1_GLOB; 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate /* 928*7c478bd9Sstevel@tonic-gate * Promote the symbols version index to the appropriate output version 929*7c478bd9Sstevel@tonic-gate * definition. 930*7c478bd9Sstevel@tonic-gate */ 931*7c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags & FLG_SY_VERSPROM)) { 932*7c478bd9Sstevel@tonic-gate Ver_index *vip; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vndx]; 935*7c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vip->vi_desc->vd_ref->vd_ndx; 936*7c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_VERSPROM; 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate } 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate /* 941*7c478bd9Sstevel@tonic-gate * If any versioning is called for make sure an initial version descriptor is 942*7c478bd9Sstevel@tonic-gate * assigned to represent the file itself. Known as the base version. 943*7c478bd9Sstevel@tonic-gate */ 944*7c478bd9Sstevel@tonic-gate Ver_desc * 945*7c478bd9Sstevel@tonic-gate vers_base(Ofl_desc *ofl) 946*7c478bd9Sstevel@tonic-gate { 947*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 948*7c478bd9Sstevel@tonic-gate const char *name; 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate /* 951*7c478bd9Sstevel@tonic-gate * Determine the filename to associate to the version descriptor. This 952*7c478bd9Sstevel@tonic-gate * is either the SONAME (if one has been supplied) or the basename of 953*7c478bd9Sstevel@tonic-gate * the output file. 954*7c478bd9Sstevel@tonic-gate */ 955*7c478bd9Sstevel@tonic-gate if ((name = ofl->ofl_soname) == 0) { 956*7c478bd9Sstevel@tonic-gate const char *str = ofl->ofl_name; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate while (*str != '\0') { 959*7c478bd9Sstevel@tonic-gate if (*str++ == '/') 960*7c478bd9Sstevel@tonic-gate name = str; 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate if (name == 0) 963*7c478bd9Sstevel@tonic-gate name = ofl->ofl_name; 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate /* 967*7c478bd9Sstevel@tonic-gate * Generate the version descriptor. 968*7c478bd9Sstevel@tonic-gate */ 969*7c478bd9Sstevel@tonic-gate /* LINTED */ 970*7c478bd9Sstevel@tonic-gate if ((vdp = vers_desc(name, (Word)elf_hash(name), &ofl->ofl_verdesc)) == 971*7c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR) 972*7c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR); 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate /* 975*7c478bd9Sstevel@tonic-gate * Assign the base index to this version and initialize the output file 976*7c478bd9Sstevel@tonic-gate * descriptor with the number of version descriptors presently in use. 977*7c478bd9Sstevel@tonic-gate */ 978*7c478bd9Sstevel@tonic-gate vdp->vd_ndx = ofl->ofl_vercnt = VER_NDX_GLOBAL; 979*7c478bd9Sstevel@tonic-gate vdp->vd_flags |= VER_FLG_BASE; 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate return (vdp); 982*7c478bd9Sstevel@tonic-gate } 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate /* 985*7c478bd9Sstevel@tonic-gate * Now that all input shared objects have been processed, verify that all 986*7c478bd9Sstevel@tonic-gate * version requirements have been met. Any version control requirements will 987*7c478bd9Sstevel@tonic-gate * have been specified by the user (and placed on the ofl_oscntl list) and are 988*7c478bd9Sstevel@tonic-gate * verified at the time the object was processed (see ver_def_process()). 989*7c478bd9Sstevel@tonic-gate * Here we process all version requirements established from shared objects 990*7c478bd9Sstevel@tonic-gate * themselves (ie,. NEEDED dependencies). 991*7c478bd9Sstevel@tonic-gate */ 992*7c478bd9Sstevel@tonic-gate int 993*7c478bd9Sstevel@tonic-gate vers_verify(Ofl_desc *ofl) 994*7c478bd9Sstevel@tonic-gate { 995*7c478bd9Sstevel@tonic-gate Listnode *lnp1; 996*7c478bd9Sstevel@tonic-gate Sdf_desc *sdf; 997*7c478bd9Sstevel@tonic-gate char *nv; 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* 1000*7c478bd9Sstevel@tonic-gate * As with the runtime environment, disable all version verification if 1001*7c478bd9Sstevel@tonic-gate * requested. 1002*7c478bd9Sstevel@tonic-gate */ 1003*7c478bd9Sstevel@tonic-gate #if defined(_ELF64) 1004*7c478bd9Sstevel@tonic-gate if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_64))) == NULL) 1005*7c478bd9Sstevel@tonic-gate #else 1006*7c478bd9Sstevel@tonic-gate if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_32))) == NULL) 1007*7c478bd9Sstevel@tonic-gate #endif 1008*7c478bd9Sstevel@tonic-gate nv = getenv(MSG_ORIG(MSG_LD_NOVERSION)); 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate if (nv && (*nv != '\0')) 1011*7c478bd9Sstevel@tonic-gate return (1); 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ofl->ofl_soneed, lnp1, sdf)) { 1014*7c478bd9Sstevel@tonic-gate Listnode *lnp2; 1015*7c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 1016*7c478bd9Sstevel@tonic-gate Ifl_desc *ifl = sdf->sdf_file; 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate if (!(sdf->sdf_flags & FLG_SDF_VERIFY)) 1019*7c478bd9Sstevel@tonic-gate continue; 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate /* 1022*7c478bd9Sstevel@tonic-gate * If this file contains no version definitions then ignore 1023*7c478bd9Sstevel@tonic-gate * any versioning verification. This is the same model as 1024*7c478bd9Sstevel@tonic-gate * carried out by ld.so.1 and is intended to allow backward 1025*7c478bd9Sstevel@tonic-gate * compatibility should a shared object with a version 1026*7c478bd9Sstevel@tonic-gate * requirment be returned to an older system on which a 1027*7c478bd9Sstevel@tonic-gate * non-versioned shared object exists. 1028*7c478bd9Sstevel@tonic-gate */ 1029*7c478bd9Sstevel@tonic-gate if ((ifl == 0) || (ifl->ifl_verdesc.head == 0)) 1030*7c478bd9Sstevel@tonic-gate continue; 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate /* 1033*7c478bd9Sstevel@tonic-gate * If individual versions were specified for this file make 1034*7c478bd9Sstevel@tonic-gate * sure that they actually exist in the appropriate file, and 1035*7c478bd9Sstevel@tonic-gate * that they are available for binding. 1036*7c478bd9Sstevel@tonic-gate */ 1037*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&sdf->sdf_vers, lnp2, sdv)) { 1038*7c478bd9Sstevel@tonic-gate Listnode *lnp3; 1039*7c478bd9Sstevel@tonic-gate Ver_desc *vdp; 1040*7c478bd9Sstevel@tonic-gate int found = 0; 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ifl->ifl_verdesc, lnp3, vdp)) { 1043*7c478bd9Sstevel@tonic-gate if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) { 1044*7c478bd9Sstevel@tonic-gate found++; 1045*7c478bd9Sstevel@tonic-gate break; 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate if (found) { 1049*7c478bd9Sstevel@tonic-gate Ver_index *vip; 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vdp->vd_ndx]; 1052*7c478bd9Sstevel@tonic-gate if (!(vip->vi_flags & FLG_VER_AVAIL)) { 1053*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, 1054*7c478bd9Sstevel@tonic-gate MSG_INTL(MSG_VER_UNAVAIL), 1055*7c478bd9Sstevel@tonic-gate ifl->ifl_name, sdv->sdv_name, 1056*7c478bd9Sstevel@tonic-gate sdv->sdv_ref); 1057*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate } else { 1060*7c478bd9Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_VER_NOEXIST), 1061*7c478bd9Sstevel@tonic-gate ifl->ifl_name, sdv->sdv_name, sdv->sdv_ref); 1062*7c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate } 1066*7c478bd9Sstevel@tonic-gate return (1); 1067*7c478bd9Sstevel@tonic-gate } 1068