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 /* 231da7e599SAli Bahrami * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <string.h> 287c478bd9Sstevel@tonic-gate #include <stdio.h> 295aefb655Srie #include <debug.h> 307c478bd9Sstevel@tonic-gate #include "msg.h" 317c478bd9Sstevel@tonic-gate #include "_libld.h" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * Locate a version descriptor. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate Ver_desc * 37*57ef7aa9SRod Evans ld_vers_find(const char *name, Word hash, APlist *alp) 387c478bd9Sstevel@tonic-gate { 39*57ef7aa9SRod Evans Aliste idx; 407c478bd9Sstevel@tonic-gate Ver_desc *vdp; 417c478bd9Sstevel@tonic-gate 42*57ef7aa9SRod Evans for (APLIST_TRAVERSE(alp, idx, vdp)) { 437c478bd9Sstevel@tonic-gate if (vdp->vd_hash != hash) 447c478bd9Sstevel@tonic-gate continue; 457c478bd9Sstevel@tonic-gate if (strcmp(vdp->vd_name, name) == 0) 467c478bd9Sstevel@tonic-gate return (vdp); 477c478bd9Sstevel@tonic-gate } 48*57ef7aa9SRod Evans return (NULL); 497c478bd9Sstevel@tonic-gate } 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * Add a new version descriptor to a version descriptor list. Note, users of 537c478bd9Sstevel@tonic-gate * this are responsible for determining if the version descriptor already 547c478bd9Sstevel@tonic-gate * exists (this can reduce the need to allocate storage for descriptor names 557c478bd9Sstevel@tonic-gate * until it is determined a descriptor need be created (see map_symbol())). 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate Ver_desc * 58*57ef7aa9SRod Evans ld_vers_desc(const char *name, Word hash, APlist **alpp) 597c478bd9Sstevel@tonic-gate { 607c478bd9Sstevel@tonic-gate Ver_desc *vdp; 617c478bd9Sstevel@tonic-gate 62*57ef7aa9SRod Evans if ((vdp = libld_calloc(sizeof (Ver_desc), 1)) == NULL) 637c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate vdp->vd_name = name; 667c478bd9Sstevel@tonic-gate vdp->vd_hash = hash; 677c478bd9Sstevel@tonic-gate 68*57ef7aa9SRod Evans if (aplist_append(alpp, vdp, AL_CNT_VERDESCS) == NULL) 697c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR); 70*57ef7aa9SRod Evans 71*57ef7aa9SRod Evans return (vdp); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * Now that all explict files have been processed validate any version 767c478bd9Sstevel@tonic-gate * definitions. Insure that any version references are available (a version 777c478bd9Sstevel@tonic-gate * has been defined when it's been assigned an index). Also calculate the 787c478bd9Sstevel@tonic-gate * number of .version section entries that will be required to hold this 797c478bd9Sstevel@tonic-gate * information. 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate #define _NUM_OF_VERS_ 40 /* twice as big as the depth for libc version */ 827c478bd9Sstevel@tonic-gate typedef struct { 837c478bd9Sstevel@tonic-gate Ver_desc **ver_stk; 847c478bd9Sstevel@tonic-gate int ver_sp; 857c478bd9Sstevel@tonic-gate int ver_lmt; 867c478bd9Sstevel@tonic-gate } Ver_Stack; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static uintptr_t 895aefb655Srie vers_visit_children(Ofl_desc *ofl, Ver_desc *vp, int flag) 907c478bd9Sstevel@tonic-gate { 91*57ef7aa9SRod Evans Aliste idx; 927c478bd9Sstevel@tonic-gate Ver_desc *vdp; 937c478bd9Sstevel@tonic-gate static int err = 0; 947c478bd9Sstevel@tonic-gate static Ver_Stack ver_stk = {0, 0, 0}; 957c478bd9Sstevel@tonic-gate int tmp_sp; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * If there was any fatal error, 997c478bd9Sstevel@tonic-gate * just return. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate if (err == S_ERROR) 1027c478bd9Sstevel@tonic-gate return (err); 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * if this is called from, ver_check_defs(), initialize sp. 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate if (flag == 0) 1087c478bd9Sstevel@tonic-gate ver_stk.ver_sp = 0; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* 1117c478bd9Sstevel@tonic-gate * Check if passed version pointer vp is already in the stack. 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) { 1147c478bd9Sstevel@tonic-gate Ver_desc *v; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate v = ver_stk.ver_stk[tmp_sp]; 1177c478bd9Sstevel@tonic-gate if (v == vp) { 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * cyclic dependency. 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate if (err == 0) { 1225aefb655Srie eprintf(ofl->ofl_lml, ERR_FATAL, 1235aefb655Srie MSG_INTL(MSG_VER_CYCLIC)); 1247c478bd9Sstevel@tonic-gate err = 1; 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate for (tmp_sp = 0; tmp_sp < ver_stk.ver_sp; tmp_sp++) { 1277c478bd9Sstevel@tonic-gate v = ver_stk.ver_stk[tmp_sp]; 1287c478bd9Sstevel@tonic-gate if ((v->vd_flags & FLG_VER_CYCLIC) == 0) { 1297c478bd9Sstevel@tonic-gate v->vd_flags |= FLG_VER_CYCLIC; 1305aefb655Srie eprintf(ofl->ofl_lml, ERR_NONE, 1315aefb655Srie MSG_INTL(MSG_VER_ADDVER), 1325aefb655Srie v->vd_name); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate if ((vp->vd_flags & FLG_VER_CYCLIC) == 0) { 1367c478bd9Sstevel@tonic-gate vp->vd_flags |= FLG_VER_CYCLIC; 1375aefb655Srie eprintf(ofl->ofl_lml, ERR_NONE, 1385aefb655Srie MSG_INTL(MSG_VER_ADDVER), vp->vd_name); 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate return (err); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Push version on the stack. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate if (ver_stk.ver_sp >= ver_stk.ver_lmt) { 1487c478bd9Sstevel@tonic-gate ver_stk.ver_lmt += _NUM_OF_VERS_; 1497c478bd9Sstevel@tonic-gate if ((ver_stk.ver_stk = (Ver_desc **) 1507c478bd9Sstevel@tonic-gate libld_realloc((void *)ver_stk.ver_stk, 1517c478bd9Sstevel@tonic-gate ver_stk.ver_lmt * sizeof (Ver_desc *))) == NULL) 1527c478bd9Sstevel@tonic-gate return (S_ERROR); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate ver_stk.ver_stk[(ver_stk.ver_sp)++] = vp; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * Now visit children. 1587c478bd9Sstevel@tonic-gate */ 159*57ef7aa9SRod Evans for (APLIST_TRAVERSE(vp->vd_deps, idx, vdp)) 1605aefb655Srie if (vers_visit_children(ofl, vdp, 1) == S_ERROR) 1617c478bd9Sstevel@tonic-gate return (S_ERROR); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate /* 1647c478bd9Sstevel@tonic-gate * Pop version from the stack. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate (ver_stk.ver_sp)--; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate return (err); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate uintptr_t 1725aefb655Srie ld_vers_check_defs(Ofl_desc *ofl) 1737c478bd9Sstevel@tonic-gate { 174*57ef7aa9SRod Evans Aliste idx1; 1757c478bd9Sstevel@tonic-gate Ver_desc *vdp; 1767c478bd9Sstevel@tonic-gate uintptr_t is_cyclic = 0; 1777c478bd9Sstevel@tonic-gate 1785aefb655Srie DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, ofl->ofl_name)); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * First check if there are any cyclic dependency 1827c478bd9Sstevel@tonic-gate */ 183*57ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_verdesc, idx1, vdp)) 1845aefb655Srie if ((is_cyclic = vers_visit_children(ofl, vdp, 0)) == S_ERROR) 1857c478bd9Sstevel@tonic-gate return (S_ERROR); 1867c478bd9Sstevel@tonic-gate if (is_cyclic) 1877c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 1887c478bd9Sstevel@tonic-gate 189*57ef7aa9SRod 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; 1947c478bd9Sstevel@tonic-gate unsigned char bind; 1957c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 1967c478bd9Sstevel@tonic-gate avl_index_t where; 197*57ef7aa9SRod Evans Aliste idx2; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if (vdp->vd_ndx == 0) { 2005aefb655Srie eprintf(ofl->ofl_lml, 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 ofl->ofl_flags |= FLG_OF_FATAL; 2047c478bd9Sstevel@tonic-gate continue; 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2075aefb655Srie DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, vdp)); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * If a version definition contains no symbols this is possibly 2117c478bd9Sstevel@tonic-gate * a mapfile error. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate if ((vdp->vd_flags & 2147c478bd9Sstevel@tonic-gate (VER_FLG_BASE | VER_FLG_WEAK | FLG_VER_REFER)) == 0) 2155aefb655Srie DBG_CALL(Dbg_ver_nointerface(ofl->ofl_lml, 2165aefb655Srie vdp->vd_name)); 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * Update the version entry count to account for this new 2207c478bd9Sstevel@tonic-gate * version descriptor (the count is the size in bytes). 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate ofl->ofl_verdefsz += sizeof (Verdef); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Traverse this versions dependency list to determine what 2267c478bd9Sstevel@tonic-gate * additional version dependencies we must account for against 2277c478bd9Sstevel@tonic-gate * this descriptor. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate cnt = 1; 230*57ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx2, _vdp)) { 2317c478bd9Sstevel@tonic-gate #if defined(__lint) 2327c478bd9Sstevel@tonic-gate /* get lint to think `_vdp' is used... */ 233*57ef7aa9SRod Evans vdp = _vdp; 2347c478bd9Sstevel@tonic-gate #endif 2357c478bd9Sstevel@tonic-gate cnt++; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate ofl->ofl_verdefsz += (cnt * sizeof (Verdaux)); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * Except for the base version descriptor, generate an absolute 2417c478bd9Sstevel@tonic-gate * symbol to reflect this version. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_BASE) 2447c478bd9Sstevel@tonic-gate continue; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_WEAK) 2477c478bd9Sstevel@tonic-gate bind = STB_WEAK; 2487c478bd9Sstevel@tonic-gate else 2497c478bd9Sstevel@tonic-gate bind = STB_GLOBAL; 2507c478bd9Sstevel@tonic-gate 2515aefb655Srie if (sdp = ld_sym_find(name, vdp->vd_hash, &where, ofl)) { 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * If the symbol already exists and is undefined or was 2547c478bd9Sstevel@tonic-gate * defined in a shared library, convert it to an 2557c478bd9Sstevel@tonic-gate * absolute. 2567c478bd9Sstevel@tonic-gate */ 2570bc07c75Srie if ((sdp->sd_sym->st_shndx == SHN_UNDEF) || 2587c478bd9Sstevel@tonic-gate (sdp->sd_ref != REF_REL_NEED)) { 2597c478bd9Sstevel@tonic-gate sdp->sd_shndx = sdp->sd_sym->st_shndx = SHN_ABS; 2607c478bd9Sstevel@tonic-gate sdp->sd_sym->st_info = 26160758829Srie ELF_ST_INFO(bind, STT_OBJECT); 2627c478bd9Sstevel@tonic-gate sdp->sd_ref = REF_REL_NEED; 2637c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_SPECSEC; 26460758829Srie sdp->sd_flags1 |= 26560758829Srie (FLG_SY1_DEFAULT | FLG_SY1_EXPDEF); 2667c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vdp->vd_ndx; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate /* 2697c478bd9Sstevel@tonic-gate * If the reference originated from a mapfile 2707c478bd9Sstevel@tonic-gate * insure we mark the symbol as used. 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate if (sdp->sd_flags & FLG_SY_MAPREF) 2737c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_MAPUSED; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate } else if ((sdp->sd_flags & FLG_SY_SPECSEC) && 2760bc07c75Srie (sdp->sd_sym->st_shndx != SHN_ABS) && 2777c478bd9Sstevel@tonic-gate (sdp->sd_ref == REF_REL_NEED)) { 2785aefb655Srie eprintf(ofl->ofl_lml, ERR_WARNING, 2795aefb655Srie MSG_INTL(MSG_VER_DEFINED), name, 2805aefb655Srie sdp->sd_file->ifl_name); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate } else { 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * If the symbol does not exist create it. 2857c478bd9Sstevel@tonic-gate */ 286*57ef7aa9SRod Evans if ((sym = libld_calloc(sizeof (Sym), 1)) == NULL) 2877c478bd9Sstevel@tonic-gate return (S_ERROR); 288*57ef7aa9SRod Evans 2897c478bd9Sstevel@tonic-gate sym->st_shndx = SHN_ABS; 2907c478bd9Sstevel@tonic-gate sym->st_info = ELF_ST_INFO(bind, STT_OBJECT); 2915aefb655Srie DBG_CALL(Dbg_ver_symbol(ofl->ofl_lml, name)); 292*57ef7aa9SRod Evans 2935aefb655Srie if ((sdp = ld_sym_enter(name, sym, vdp->vd_hash, 2947c478bd9Sstevel@tonic-gate vdp->vd_file, ofl, 0, SHN_ABS, FLG_SY_SPECSEC, 29560758829Srie (FLG_SY1_DEFAULT | FLG_SY1_EXPDEF), 29660758829Srie &where)) == (Sym_desc *)S_ERROR) 2977c478bd9Sstevel@tonic-gate return (S_ERROR); 298*57ef7aa9SRod Evans 2997c478bd9Sstevel@tonic-gate sdp->sd_ref = REF_REL_NEED; 3007c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vdp->vd_ndx; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate return (1); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * Dereference dependencies as a part of normalizing (allows recursion). 3087c478bd9Sstevel@tonic-gate */ 3095aefb655Srie static void 3107c478bd9Sstevel@tonic-gate vers_derefer(Ifl_desc *ifl, Ver_desc *vdp, int weak) 3117c478bd9Sstevel@tonic-gate { 312*57ef7aa9SRod Evans Aliste idx; 3137c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 3147c478bd9Sstevel@tonic-gate Ver_index *vip = &ifl->ifl_verndx[vdp->vd_ndx]; 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 317090a8d9eSAli Bahrami * Set the INFO bit on all dependencies that ld.so.1 318090a8d9eSAli Bahrami * can skip verification for. These are the dependencies 319090a8d9eSAli Bahrami * that are inherited by others -- verifying the inheriting 320090a8d9eSAli Bahrami * version implicitily covers this one. 321090a8d9eSAli Bahrami * 322090a8d9eSAli Bahrami * If the head of the list was a weak then we only mark 3237c478bd9Sstevel@tonic-gate * weak dependencies, but if the head of the list was 'strong' 324090a8d9eSAli Bahrami * we set INFO on all dependencies. 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate if ((weak && (vdp->vd_flags & VER_FLG_WEAK)) || (!weak)) 327090a8d9eSAli Bahrami vip->vi_flags |= VER_FLG_INFO; 3287c478bd9Sstevel@tonic-gate 329*57ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp)) 3307c478bd9Sstevel@tonic-gate vers_derefer(ifl, _vdp, weak); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * If we need to record the versions of any needed dependencies traverse the 3357c478bd9Sstevel@tonic-gate * shared object dependency list and calculate what version needed entries are 3367c478bd9Sstevel@tonic-gate * required. 3377c478bd9Sstevel@tonic-gate */ 3387c478bd9Sstevel@tonic-gate uintptr_t 3395aefb655Srie ld_vers_check_need(Ofl_desc *ofl) 3407c478bd9Sstevel@tonic-gate { 341*57ef7aa9SRod Evans Aliste idx1; 3427c478bd9Sstevel@tonic-gate Ifl_desc *ifl; 343090a8d9eSAli Bahrami Half needndx; 344090a8d9eSAli Bahrami 345090a8d9eSAli Bahrami /* 346090a8d9eSAli Bahrami * Versym indexes for needed versions start with the next 347090a8d9eSAli Bahrami * available version after the final definied version. 348090a8d9eSAli Bahrami * However, it can never be less than 2. 0 is always for local 349090a8d9eSAli Bahrami * scope, and 1 is always the first global definition. 350090a8d9eSAli Bahrami */ 351090a8d9eSAli Bahrami needndx = (ofl->ofl_vercnt > 0) ? (ofl->ofl_vercnt + 1) : 2; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * Traverse the shared object list looking for dependencies. 3557c478bd9Sstevel@tonic-gate */ 356*57ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_sos, idx1, ifl)) { 357*57ef7aa9SRod Evans Aliste idx2; 3587c478bd9Sstevel@tonic-gate Ver_index *vip; 3597c478bd9Sstevel@tonic-gate Ver_desc *vdp; 3607c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc; 361090a8d9eSAli Bahrami Byte cnt, need = 0; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate if (!(ifl->ifl_flags & FLG_IF_NEEDED)) 3647c478bd9Sstevel@tonic-gate continue; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (ifl->ifl_vercnt <= VER_NDX_GLOBAL) 3677c478bd9Sstevel@tonic-gate continue; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate /* 3707c478bd9Sstevel@tonic-gate * If version needed definitions were specified in 371090a8d9eSAli Bahrami * a mapfile ($SPECVERS=) then record those definitions. 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_SPECVER)) { 3747c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 375*57ef7aa9SRod Evans Aliste idx3; 376090a8d9eSAli Bahrami 377*57ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_verneed, idx3, sdv)) { 378090a8d9eSAli Bahrami /* 379090a8d9eSAli Bahrami * If this $SPECVERS item corresponds to 380090a8d9eSAli Bahrami * a real version, then don't issue it 381090a8d9eSAli Bahrami * here, but use the real one instead. 382090a8d9eSAli Bahrami * This preserves the ability to reference it 383090a8d9eSAli Bahrami * from a symbol versym entry. 384090a8d9eSAli Bahrami */ 385090a8d9eSAli Bahrami if (sdv->sdv_flags & FLG_SDV_MATCHED) 386090a8d9eSAli Bahrami continue; 387090a8d9eSAli Bahrami 388090a8d9eSAli Bahrami /* Not found in known versions. Count it */ 3897c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Vernaux); 3907c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, 3917c478bd9Sstevel@tonic-gate sdv->sdv_name) == -1) 3927c478bd9Sstevel@tonic-gate return (S_ERROR); 393090a8d9eSAli Bahrami need++; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * Scan the version index list and if any weak version 3997c478bd9Sstevel@tonic-gate * definition has been referenced by the user promote the 4007c478bd9Sstevel@tonic-gate * dependency to be non-weak. Weak version dependencies do not 4017c478bd9Sstevel@tonic-gate * cause fatal errors from the runtime linker, non-weak 4027c478bd9Sstevel@tonic-gate * dependencies do. 4037c478bd9Sstevel@tonic-gate */ 404090a8d9eSAli Bahrami for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) { 4057c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt]; 4067c478bd9Sstevel@tonic-gate vdp = vip->vi_desc; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if ((vip->vi_flags & (FLG_VER_REFER | VER_FLG_WEAK)) == 4097c478bd9Sstevel@tonic-gate (FLG_VER_REFER | VER_FLG_WEAK)) 4107c478bd9Sstevel@tonic-gate vdp->vd_flags &= ~VER_FLG_WEAK; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * Mark any weak reference as referred to so as to 4147c478bd9Sstevel@tonic-gate * simplify normalization and later version dependency 4157c478bd9Sstevel@tonic-gate * manipulation. 4167c478bd9Sstevel@tonic-gate */ 4177c478bd9Sstevel@tonic-gate if (vip->vi_flags & VER_FLG_WEAK) 4187c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_REFER; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* 4227c478bd9Sstevel@tonic-gate * Scan the version dependency list to normalize the referenced 4237c478bd9Sstevel@tonic-gate * dependencies. Any needed version that is inherited by 424*57ef7aa9SRod Evans * another like version is dereferenced as it is not necessary 4257c478bd9Sstevel@tonic-gate * to make this part of the version dependencies. 4267c478bd9Sstevel@tonic-gate */ 427*57ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) { 428*57ef7aa9SRod Evans Aliste idx3; 4297c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 4307c478bd9Sstevel@tonic-gate int type; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vdp->vd_ndx]; 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate if (!(vip->vi_flags & FLG_VER_REFER)) 4357c478bd9Sstevel@tonic-gate continue; 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate type = vdp->vd_flags & VER_FLG_WEAK; 438*57ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx3, _vdp)) 4397c478bd9Sstevel@tonic-gate vers_derefer(ifl, _vdp, type); 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * Finally, determine how many of the version dependencies need 4447c478bd9Sstevel@tonic-gate * to be recorded. 4457c478bd9Sstevel@tonic-gate */ 446090a8d9eSAli Bahrami for (cnt = 0; cnt <= ifl->ifl_vercnt; cnt++) { 4477c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt]; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* 4507c478bd9Sstevel@tonic-gate * If a version has been referenced then record it as a 4517c478bd9Sstevel@tonic-gate * version dependency. 4527c478bd9Sstevel@tonic-gate */ 4537c478bd9Sstevel@tonic-gate if (vip->vi_flags & FLG_VER_REFER) { 454090a8d9eSAli Bahrami /* Assign a VERSYM index for it */ 455090a8d9eSAli Bahrami vip->vi_overndx = needndx++; 456090a8d9eSAli Bahrami 4577c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Vernaux); 4587c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, 4597c478bd9Sstevel@tonic-gate vip->vi_name) == -1) 4607c478bd9Sstevel@tonic-gate return (S_ERROR); 4617c478bd9Sstevel@tonic-gate need++; 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate if (need) { 4661da7e599SAli Bahrami const char *soname; 4671da7e599SAli Bahrami 4687c478bd9Sstevel@tonic-gate ifl->ifl_flags |= FLG_IF_VERNEED; 4697c478bd9Sstevel@tonic-gate ofl->ofl_verneedsz += sizeof (Verneed); 4701da7e599SAli Bahrami soname = ((sdf != NULL) && 4711da7e599SAli Bahrami (sdf->sdf_flags & FLG_SDF_SONAME)) ? 4721da7e599SAli Bahrami sdf->sdf_soname : ifl->ifl_soname; 4731da7e599SAli Bahrami if (st_insert(ofl->ofl_dynstrtab, soname) == -1) 4747c478bd9Sstevel@tonic-gate return (S_ERROR); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* 4797c478bd9Sstevel@tonic-gate * If no version needed information is required unset the output file 4807c478bd9Sstevel@tonic-gate * flag. 4817c478bd9Sstevel@tonic-gate */ 4827c478bd9Sstevel@tonic-gate if (ofl->ofl_verneedsz == 0) 4837c478bd9Sstevel@tonic-gate ofl->ofl_flags &= ~FLG_OF_VERNEED; 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate return (1); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * Indicate dependency selection (allows recursion). 4907c478bd9Sstevel@tonic-gate */ 4915aefb655Srie static void 4925aefb655Srie vers_select(Ofl_desc *ofl, Ifl_desc *ifl, Ver_desc *vdp, const char *ref) 4937c478bd9Sstevel@tonic-gate { 494*57ef7aa9SRod Evans Aliste idx; 4957c478bd9Sstevel@tonic-gate Ver_desc *_vdp; 4967c478bd9Sstevel@tonic-gate Ver_index *vip = &ifl->ifl_verndx[vdp->vd_ndx]; 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_AVAIL; 4995aefb655Srie DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, ref)); 5007c478bd9Sstevel@tonic-gate 501*57ef7aa9SRod Evans for (APLIST_TRAVERSE(vdp->vd_deps, idx, _vdp)) 5025aefb655Srie vers_select(ofl, ifl, _vdp, ref); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5055aefb655Srie static Ver_index * 5065aefb655Srie vers_index(Ofl_desc *ofl, Ifl_desc *ifl, int avail) 5077c478bd9Sstevel@tonic-gate { 508*57ef7aa9SRod Evans Aliste idx1; 5097c478bd9Sstevel@tonic-gate Ver_desc *vdp; 5107c478bd9Sstevel@tonic-gate Ver_index *vip; 5117c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc; 5127c478bd9Sstevel@tonic-gate Word count = ifl->ifl_vercnt; 5137c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * Allocate an index array large enough to hold all of the files 5177c478bd9Sstevel@tonic-gate * version descriptors. 5187c478bd9Sstevel@tonic-gate */ 519*57ef7aa9SRod Evans if ((vip = libld_calloc(sizeof (Ver_index), (count + 1))) == NULL) 5207c478bd9Sstevel@tonic-gate return ((Ver_index *)S_ERROR); 5217c478bd9Sstevel@tonic-gate 522*57ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx1, vdp)) { 523*57ef7aa9SRod Evans int ndx = vdp->vd_ndx; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate vip[ndx].vi_name = vdp->vd_name; 5267c478bd9Sstevel@tonic-gate vip[ndx].vi_desc = vdp; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * Any relocatable object versions, and the `base' version are 5307c478bd9Sstevel@tonic-gate * always available. 5317c478bd9Sstevel@tonic-gate */ 5327c478bd9Sstevel@tonic-gate if (avail || (vdp->vd_flags & VER_FLG_BASE)) 5337c478bd9Sstevel@tonic-gate vip[ndx].vi_flags |= FLG_VER_AVAIL; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* 5367c478bd9Sstevel@tonic-gate * If this is a weak version mark it as such. Weak versions 5377c478bd9Sstevel@tonic-gate * are always dragged into any version dependencies created, 5387c478bd9Sstevel@tonic-gate * and if a weak version is referenced it will be promoted to 5397c478bd9Sstevel@tonic-gate * a non-weak version dependency. 5407c478bd9Sstevel@tonic-gate */ 5417c478bd9Sstevel@tonic-gate if (vdp->vd_flags & VER_FLG_WEAK) 5427c478bd9Sstevel@tonic-gate vip[ndx].vi_flags |= VER_FLG_WEAK; 5437c478bd9Sstevel@tonic-gate /* 544090a8d9eSAli Bahrami * If this version is mentioned in a mapfile using 545090a8d9eSAli Bahrami * $ADDVERS or $SPECVERS syntax then check to see if 546090a8d9eSAli Bahrami * it corresponds to an actual version in the file. 5477c478bd9Sstevel@tonic-gate */ 548090a8d9eSAli Bahrami if (sdf && 549090a8d9eSAli Bahrami (sdf->sdf_flags & (FLG_SDF_SPECVER|FLG_SDF_ADDVER))) { 550*57ef7aa9SRod Evans Aliste idx2; 551*57ef7aa9SRod Evans 552*57ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_verneed, idx2, sdv)) { 553*57ef7aa9SRod Evans if (strcmp(vip[ndx].vi_name, sdv->sdv_name)) 554*57ef7aa9SRod Evans continue; 555*57ef7aa9SRod Evans 556*57ef7aa9SRod Evans vip[ndx].vi_flags |= FLG_VER_REFER; 557*57ef7aa9SRod Evans if (sdf->sdf_flags & FLG_SDF_SPECVER) 558*57ef7aa9SRod Evans vip[ndx].vi_flags |= FLG_VER_SPECVER; 559*57ef7aa9SRod Evans sdv->sdv_flags |= FLG_SDV_MATCHED; 560*57ef7aa9SRod Evans break; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * if $ADDVER was specified for this object verify that 5677c478bd9Sstevel@tonic-gate * all of it's dependent upon versions were refered to. 5687c478bd9Sstevel@tonic-gate */ 5697c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_ADDVER)) { 5707c478bd9Sstevel@tonic-gate int fail = 0; 571*57ef7aa9SRod Evans 572*57ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_verneed, idx1, sdv)) { 573*57ef7aa9SRod Evans if (sdv->sdv_flags & FLG_SDV_MATCHED) 574*57ef7aa9SRod Evans continue; 575*57ef7aa9SRod Evans 576*57ef7aa9SRod Evans if (fail++ == 0) { 5775aefb655Srie eprintf(ofl->ofl_lml, ERR_NONE, 578*57ef7aa9SRod Evans MSG_INTL(MSG_VER_ADDVERS), sdf->sdf_rfile, 579*57ef7aa9SRod Evans sdf->sdf_name); 5807c478bd9Sstevel@tonic-gate } 581*57ef7aa9SRod Evans eprintf(ofl->ofl_lml, ERR_NONE, 582*57ef7aa9SRod Evans MSG_INTL(MSG_VER_ADDVER), sdv->sdv_name); 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate if (fail) 5857c478bd9Sstevel@tonic-gate return ((Ver_index *)S_ERROR); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate return (vip); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate /* 5927c478bd9Sstevel@tonic-gate * Process a version symbol index section. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate int 5955aefb655Srie ld_vers_sym_process(Lm_list *lml, Is_desc *isp, Ifl_desc *ifl) 5967c478bd9Sstevel@tonic-gate { 5977c478bd9Sstevel@tonic-gate Shdr *symshdr; 5987c478bd9Sstevel@tonic-gate Shdr *vershdr = isp->is_shdr; 5995aefb655Srie 6007c478bd9Sstevel@tonic-gate /* 6015aefb655Srie * Verify that the versym is the same size as the linked symbol table. 6025aefb655Srie * If these two get out of sync the file is considered corrupted. 6037c478bd9Sstevel@tonic-gate */ 6047c478bd9Sstevel@tonic-gate symshdr = ifl->ifl_isdesc[vershdr->sh_link]->is_shdr; 6057c478bd9Sstevel@tonic-gate if ((symshdr->sh_size / symshdr->sh_entsize) != (vershdr->sh_size / 6067c478bd9Sstevel@tonic-gate vershdr->sh_entsize)) { 6075aefb655Srie eprintf(lml, ERR_WARNING, MSG_INTL(MSG_ELF_VERSYM), 6085aefb655Srie ifl->ifl_name, isp->is_name, 6095aefb655Srie EC_WORD(vershdr->sh_size / vershdr->sh_entsize), 6105aefb655Srie ifl->ifl_isdesc[vershdr->sh_link]->is_name, 6115aefb655Srie EC_WORD(symshdr->sh_size / symshdr->sh_entsize)); 6127c478bd9Sstevel@tonic-gate return (1); 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate ifl->ifl_versym = (Versym *)isp->is_indata->d_buf; 6157c478bd9Sstevel@tonic-gate return (1); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate /* 6197c478bd9Sstevel@tonic-gate * Process a version definition section from an input file. A list of version 6207c478bd9Sstevel@tonic-gate * descriptors is created and associated with the input files descriptor. If 6217c478bd9Sstevel@tonic-gate * this is a shared object these descriptors will be used to indicate the 6227c478bd9Sstevel@tonic-gate * availability of each version. If this is a relocatable object then these 6237c478bd9Sstevel@tonic-gate * descriptors will be promoted (concatenated) to the output files image. 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate uintptr_t 6265aefb655Srie ld_vers_def_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl) 6277c478bd9Sstevel@tonic-gate { 6287c478bd9Sstevel@tonic-gate const char *str, *file = ifl->ifl_name; 6297c478bd9Sstevel@tonic-gate Sdf_desc *sdf = ifl->ifl_sdfdesc; 6307c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 6317c478bd9Sstevel@tonic-gate Word num, _num; 6327c478bd9Sstevel@tonic-gate Verdef *vdf; 6337c478bd9Sstevel@tonic-gate int relobj; 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate /* 6367c478bd9Sstevel@tonic-gate * If there is no version section then simply indicate that all version 6377c478bd9Sstevel@tonic-gate * definitions asked for do not exist. 6387c478bd9Sstevel@tonic-gate */ 639*57ef7aa9SRod Evans if (isp == NULL) { 640*57ef7aa9SRod Evans Aliste idx; 6417c478bd9Sstevel@tonic-gate 642*57ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_vers, idx, sdv)) { 6435aefb655Srie eprintf(ofl->ofl_lml, ERR_FATAL, 6445aefb655Srie MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name, 6455aefb655Srie sdv->sdv_name, sdv->sdv_ref); 6467c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate return (0); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate vdf = (Verdef *)isp->is_indata->d_buf; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* 6547c478bd9Sstevel@tonic-gate * Verify the version revision. We only check the first version 6557c478bd9Sstevel@tonic-gate * structure as it is assumed all other version structures in this 6567c478bd9Sstevel@tonic-gate * data section will be of the same revision. 6577c478bd9Sstevel@tonic-gate */ 6587c478bd9Sstevel@tonic-gate if (vdf->vd_version > VER_DEF_CURRENT) 6595aefb655Srie (void) eprintf(ofl->ofl_lml, ERR_WARNING, 6605aefb655Srie MSG_INTL(MSG_VER_HIGHER), ifl->ifl_name, vdf->vd_version, 6615aefb655Srie VER_DEF_CURRENT); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate num = isp->is_shdr->sh_info; 6657c478bd9Sstevel@tonic-gate str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate if (ifl->ifl_ehdr->e_type == ET_REL) 6687c478bd9Sstevel@tonic-gate relobj = 1; 6697c478bd9Sstevel@tonic-gate else 6707c478bd9Sstevel@tonic-gate relobj = 0; 6717c478bd9Sstevel@tonic-gate 6725aefb655Srie DBG_CALL(Dbg_ver_def_title(ofl->ofl_lml, file)); 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate /* 6757c478bd9Sstevel@tonic-gate * Loop through the version information setting up a version descriptor 6767c478bd9Sstevel@tonic-gate * for each version definition. 6777c478bd9Sstevel@tonic-gate */ 6787c478bd9Sstevel@tonic-gate for (_num = 1; _num <= num; _num++, 6797c478bd9Sstevel@tonic-gate vdf = (Verdef *)((uintptr_t)vdf + vdf->vd_next)) { 6807c478bd9Sstevel@tonic-gate const char *name; 681*57ef7aa9SRod Evans Ver_desc *ivdp, *ovdp = NULL; 6827c478bd9Sstevel@tonic-gate Word hash; 6837c478bd9Sstevel@tonic-gate Half cnt = vdf->vd_cnt; 6847c478bd9Sstevel@tonic-gate Half ndx = vdf->vd_ndx; 6857c478bd9Sstevel@tonic-gate Verdaux *vdap = (Verdaux *)((uintptr_t)vdf + 68660758829Srie vdf->vd_aux); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * Keep track of the largest index for use in creating a 6907c478bd9Sstevel@tonic-gate * version index array later, and create a version descriptor. 6917c478bd9Sstevel@tonic-gate */ 6927c478bd9Sstevel@tonic-gate if (ndx > ifl->ifl_vercnt) 6937c478bd9Sstevel@tonic-gate ifl->ifl_vercnt = ndx; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate name = (char *)(str + vdap->vda_name); 6967c478bd9Sstevel@tonic-gate /* LINTED */ 6977c478bd9Sstevel@tonic-gate hash = (Word)elf_hash(name); 698*57ef7aa9SRod Evans if (((ivdp = ld_vers_find(name, hash, 699*57ef7aa9SRod Evans ifl->ifl_verdesc)) == NULL) && 700*57ef7aa9SRod Evans ((ivdp = ld_vers_desc(name, hash, 701*57ef7aa9SRod Evans &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR)) 702*57ef7aa9SRod Evans return (S_ERROR); 703*57ef7aa9SRod Evans 7047c478bd9Sstevel@tonic-gate ivdp->vd_ndx = ndx; 7057c478bd9Sstevel@tonic-gate ivdp->vd_file = ifl; 7067c478bd9Sstevel@tonic-gate ivdp->vd_flags = vdf->vd_flags; 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate /* 7097c478bd9Sstevel@tonic-gate * If we're processing a relocatable object then this version 7107c478bd9Sstevel@tonic-gate * definition needs to be propagated to the output file. 7117c478bd9Sstevel@tonic-gate * Generate a new output file version and associated this input 7127c478bd9Sstevel@tonic-gate * version to it. During symbol processing the version index of 7137c478bd9Sstevel@tonic-gate * the symbol will be promoted from the input file to the output 7147c478bd9Sstevel@tonic-gate * files version definition. 7157c478bd9Sstevel@tonic-gate */ 7167c478bd9Sstevel@tonic-gate if (relobj) { 7177c478bd9Sstevel@tonic-gate if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) 7187c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_PROCRED; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if ((ivdp->vd_flags & VER_FLG_BASE) == 0) { 7217c478bd9Sstevel@tonic-gate /* 7227c478bd9Sstevel@tonic-gate * If no version descriptors have yet been set 7237c478bd9Sstevel@tonic-gate * up, initialize a base version to represent 7247c478bd9Sstevel@tonic-gate * the output file itself. This `base' version 7257c478bd9Sstevel@tonic-gate * catches any internally generated symbols 7267c478bd9Sstevel@tonic-gate * (_end, _etext, etc.) and 7277c478bd9Sstevel@tonic-gate * serves to initialize the output version 7287c478bd9Sstevel@tonic-gate * descriptor count. 7297c478bd9Sstevel@tonic-gate */ 7307c478bd9Sstevel@tonic-gate if (ofl->ofl_vercnt == 0) { 7315aefb655Srie if (ld_vers_base(ofl) == 7327c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR) 7337c478bd9Sstevel@tonic-gate return (S_ERROR); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_VERDEF; 7365aefb655Srie if ((ovdp = ld_vers_find(name, hash, 737*57ef7aa9SRod Evans ofl->ofl_verdesc)) == NULL) { 7385aefb655Srie if ((ovdp = ld_vers_desc(name, hash, 7397c478bd9Sstevel@tonic-gate &ofl->ofl_verdesc)) == 7407c478bd9Sstevel@tonic-gate (Ver_desc *)S_ERROR) 7417c478bd9Sstevel@tonic-gate return (S_ERROR); 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate /* LINTED */ 7447c478bd9Sstevel@tonic-gate ovdp->vd_ndx = (Half)++ofl->ofl_vercnt; 7457c478bd9Sstevel@tonic-gate ovdp->vd_file = ifl; 7467c478bd9Sstevel@tonic-gate ovdp->vd_flags = vdf->vd_flags; 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate } 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate /* 7517c478bd9Sstevel@tonic-gate * Maintain the association between the input version 7527c478bd9Sstevel@tonic-gate * descriptor and the output version descriptor so that 7537c478bd9Sstevel@tonic-gate * an associated symbols will be assigned to the 7547c478bd9Sstevel@tonic-gate * correct version. 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate ivdp->vd_ref = ovdp; 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* 7607c478bd9Sstevel@tonic-gate * Process any dependencies this version may have. 7617c478bd9Sstevel@tonic-gate */ 7627c478bd9Sstevel@tonic-gate vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next); 7637c478bd9Sstevel@tonic-gate for (cnt--; cnt; cnt--, 7647c478bd9Sstevel@tonic-gate vdap = (Verdaux *)((uintptr_t)vdap + vdap->vda_next)) { 7657c478bd9Sstevel@tonic-gate Ver_desc *_ivdp; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate name = (char *)(str + vdap->vda_name); 7687c478bd9Sstevel@tonic-gate /* LINTED */ 7697c478bd9Sstevel@tonic-gate hash = (Word)elf_hash(name); 7707c478bd9Sstevel@tonic-gate 771*57ef7aa9SRod Evans if (((_ivdp = ld_vers_find(name, hash, 772*57ef7aa9SRod Evans ifl->ifl_verdesc)) == NULL) && 773*57ef7aa9SRod Evans ((_ivdp = ld_vers_desc(name, hash, 774*57ef7aa9SRod Evans &ifl->ifl_verdesc)) == (Ver_desc *)S_ERROR)) 775*57ef7aa9SRod Evans return (S_ERROR); 776*57ef7aa9SRod Evans 777*57ef7aa9SRod Evans if (aplist_append(&ivdp->vd_deps, _ivdp, 778*57ef7aa9SRod Evans AL_CNT_VERDESCS) == NULL) 7797c478bd9Sstevel@tonic-gate return (S_ERROR); 7807c478bd9Sstevel@tonic-gate } 7815aefb655Srie DBG_CALL(Dbg_ver_desc_entry(ofl->ofl_lml, ivdp)); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * Now that we know the total number of version definitions for this 7867c478bd9Sstevel@tonic-gate * file, build an index array for fast access when processing symbols. 7877c478bd9Sstevel@tonic-gate */ 7885aefb655Srie if ((ifl->ifl_verndx = 7895aefb655Srie vers_index(ofl, ifl, relobj)) == (Ver_index *)S_ERROR) 7907c478bd9Sstevel@tonic-gate return (S_ERROR); 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (relobj) 7937c478bd9Sstevel@tonic-gate return (1); 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* 7967c478bd9Sstevel@tonic-gate * If this object has version control definitions against it then these 7977c478bd9Sstevel@tonic-gate * must be processed so as to select those version definitions to which 7987c478bd9Sstevel@tonic-gate * symbol bindings can occur. Otherwise simply mark all versions as 7997c478bd9Sstevel@tonic-gate * available. 8007c478bd9Sstevel@tonic-gate */ 8015aefb655Srie DBG_CALL(Dbg_ver_avail_title(ofl->ofl_lml, file)); 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate if (sdf && (sdf->sdf_flags & FLG_SDF_SELECT)) { 804*57ef7aa9SRod Evans Aliste idx1; 8057c478bd9Sstevel@tonic-gate 806*57ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_vers, idx1, sdv)) { 807*57ef7aa9SRod Evans Aliste idx2; 8087c478bd9Sstevel@tonic-gate Ver_desc *vdp; 8097c478bd9Sstevel@tonic-gate int found = 0; 8107c478bd9Sstevel@tonic-gate 811*57ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx2, vdp)) { 8127c478bd9Sstevel@tonic-gate if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) { 8137c478bd9Sstevel@tonic-gate found++; 8147c478bd9Sstevel@tonic-gate break; 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate if (found) 8185aefb655Srie vers_select(ofl, ifl, vdp, sdv->sdv_ref); 8197c478bd9Sstevel@tonic-gate else { 8205aefb655Srie eprintf(ofl->ofl_lml, ERR_FATAL, 8215aefb655Srie MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name, 8225aefb655Srie sdv->sdv_name, sdv->sdv_ref); 8237c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate } else { 8277c478bd9Sstevel@tonic-gate Ver_index *vip; 8287c478bd9Sstevel@tonic-gate int cnt; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate for (cnt = VER_NDX_GLOBAL; cnt <= ifl->ifl_vercnt; cnt++) { 8317c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[cnt]; 8327c478bd9Sstevel@tonic-gate vip->vi_flags |= FLG_VER_AVAIL; 8335aefb655Srie DBG_CALL(Dbg_ver_avail_entry(ofl->ofl_lml, vip, 0)); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate /* 8387c478bd9Sstevel@tonic-gate * If this is an explict dependency indicate that this file is a 8397c478bd9Sstevel@tonic-gate * candidate for requiring version needed information to be recorded in 8407c478bd9Sstevel@tonic-gate * the image we're creating. 8417c478bd9Sstevel@tonic-gate */ 8427c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_NEEDED) 8437c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_VERNEED; 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate return (1); 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* 8497c478bd9Sstevel@tonic-gate * Process a version needed section. 8507c478bd9Sstevel@tonic-gate */ 8517c478bd9Sstevel@tonic-gate uintptr_t 8525aefb655Srie ld_vers_need_process(Is_desc *isp, Ifl_desc *ifl, Ofl_desc *ofl) 8537c478bd9Sstevel@tonic-gate { 8547c478bd9Sstevel@tonic-gate const char *str, *file = ifl->ifl_name; 8557c478bd9Sstevel@tonic-gate Word num, _num; 8567c478bd9Sstevel@tonic-gate Verneed *vnd; 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate vnd = (Verneed *)isp->is_indata->d_buf; 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * Verify the version revision. We only check the first version 8627c478bd9Sstevel@tonic-gate * structure as it is assumed all other version structures in this 8637c478bd9Sstevel@tonic-gate * data section will be of the same revision. 8647c478bd9Sstevel@tonic-gate */ 8655aefb655Srie if (vnd->vn_version > VER_DEF_CURRENT) { 8665aefb655Srie (void) eprintf(ofl->ofl_lml, ERR_WARNING, 8675aefb655Srie MSG_INTL(MSG_VER_HIGHER), ifl->ifl_name, vnd->vn_version, 8685aefb655Srie VER_DEF_CURRENT); 8695aefb655Srie } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate num = isp->is_shdr->sh_info; 8727c478bd9Sstevel@tonic-gate str = (char *)ifl->ifl_isdesc[isp->is_shdr->sh_link]->is_indata->d_buf; 8737c478bd9Sstevel@tonic-gate 8745aefb655Srie DBG_CALL(Dbg_ver_need_title(ofl->ofl_lml, file)); 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate /* 8777c478bd9Sstevel@tonic-gate * Loop through the version information setting up a version descriptor 8787c478bd9Sstevel@tonic-gate * for each version definition. 8797c478bd9Sstevel@tonic-gate */ 8807c478bd9Sstevel@tonic-gate for (_num = 1; _num <= num; _num++, 8817c478bd9Sstevel@tonic-gate vnd = (Verneed *)((uintptr_t)vnd + vnd->vn_next)) { 8827c478bd9Sstevel@tonic-gate Sdf_desc *sdf; 8837c478bd9Sstevel@tonic-gate const char *name; 8847c478bd9Sstevel@tonic-gate Half cnt = vnd->vn_cnt; 8857c478bd9Sstevel@tonic-gate Vernaux *vnap = (Vernaux *)((uintptr_t)vnd + 88660758829Srie vnd->vn_aux); 8877c478bd9Sstevel@tonic-gate Half _cnt; 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate name = (char *)(str + vnd->vn_file); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate /* 8927c478bd9Sstevel@tonic-gate * Set up a shared object descriptor and add to it the necessary 8937c478bd9Sstevel@tonic-gate * needed versions. This information may also have been added 8947c478bd9Sstevel@tonic-gate * by a mapfile (see map_dash()). 8957c478bd9Sstevel@tonic-gate */ 896*57ef7aa9SRod Evans if ((sdf = sdf_find(name, ofl->ofl_soneed)) == NULL) { 8977c478bd9Sstevel@tonic-gate if ((sdf = sdf_add(name, &ofl->ofl_soneed)) == 8987c478bd9Sstevel@tonic-gate (Sdf_desc *)S_ERROR) 8997c478bd9Sstevel@tonic-gate return (S_ERROR); 9007c478bd9Sstevel@tonic-gate sdf->sdf_rfile = file; 9017c478bd9Sstevel@tonic-gate sdf->sdf_flags |= FLG_SDF_VERIFY; 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate for (_cnt = 0; cnt; _cnt++, cnt--, 9057c478bd9Sstevel@tonic-gate vnap = (Vernaux *)((uintptr_t)vnap + vnap->vna_next)) { 906*57ef7aa9SRod Evans Sdv_desc sdv; 907*57ef7aa9SRod Evans 908*57ef7aa9SRod Evans sdv.sdv_name = str + vnap->vna_name; 909*57ef7aa9SRod Evans sdv.sdv_ref = file; 910*57ef7aa9SRod Evans sdv.sdv_flags = 0; 911*57ef7aa9SRod Evans 912*57ef7aa9SRod Evans if (alist_append(&sdf->sdf_vers, &sdv, 913*57ef7aa9SRod Evans sizeof (Sdv_desc), AL_CNT_SDF_VERSIONS) == NULL) 9147c478bd9Sstevel@tonic-gate return (S_ERROR); 915*57ef7aa9SRod Evans 9165aefb655Srie DBG_CALL(Dbg_ver_need_entry(ofl->ofl_lml, _cnt, name, 917*57ef7aa9SRod Evans sdv.sdv_name)); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate return (1); 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate /* 9247c478bd9Sstevel@tonic-gate * If a symbol is obtained from a versioned relocatable object then the symbols 9257c478bd9Sstevel@tonic-gate * version association must be promoted to the version definition as it will be 9267c478bd9Sstevel@tonic-gate * represented in the output file. 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate void 9295aefb655Srie ld_vers_promote(Sym_desc *sdp, Word ndx, Ifl_desc *ifl, Ofl_desc *ofl) 9307c478bd9Sstevel@tonic-gate { 9317c478bd9Sstevel@tonic-gate Half vndx; 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* 9347c478bd9Sstevel@tonic-gate * A version symbol index of 0 implies the symbol is local. A value of 9357c478bd9Sstevel@tonic-gate * VER_NDX_GLOBAL implies the symbol is global but has not been 9367c478bd9Sstevel@tonic-gate * assigned to a specfic version definition. 9377c478bd9Sstevel@tonic-gate */ 9387c478bd9Sstevel@tonic-gate vndx = ifl->ifl_versym[ndx]; 9397c478bd9Sstevel@tonic-gate if (vndx == 0) { 9407c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_REDUCED; 94160758829Srie sdp->sd_flags1 |= FLG_SY1_HIDDEN; 9427c478bd9Sstevel@tonic-gate return; 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate if (vndx == VER_NDX_ELIMINATE) { 9467c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_REDUCED; 94760758829Srie sdp->sd_flags1 |= (FLG_SY1_HIDDEN | FLG_SY1_ELIM); 9487c478bd9Sstevel@tonic-gate return; 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate if (vndx == VER_NDX_GLOBAL) { 95260758829Srie if ((sdp->sd_flags1 & FLG_SY1_HIDDEN) == 0) 95360758829Srie sdp->sd_flags1 |= (FLG_SY1_DEFAULT | FLG_SY1_EXPDEF); 95460758829Srie if (sdp->sd_aux->sa_overndx <= VER_NDX_GLOBAL) 9557c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = VER_NDX_GLOBAL; 9567c478bd9Sstevel@tonic-gate return; 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate /* 9607c478bd9Sstevel@tonic-gate * Any other version index requires association to the appropriate 9617c478bd9Sstevel@tonic-gate * version definition. 9627c478bd9Sstevel@tonic-gate */ 9637c478bd9Sstevel@tonic-gate if ((ifl->ifl_verndx == 0) || (vndx > ifl->ifl_vercnt)) { 9645aefb655Srie eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_VER_INVALNDX), 9655aefb655Srie sdp->sd_name, ifl->ifl_name, vndx); 9667c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 9677c478bd9Sstevel@tonic-gate return; 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 97060758829Srie if ((sdp->sd_flags1 & FLG_SY1_HIDDEN) == 0) 97160758829Srie sdp->sd_flags1 |= (FLG_SY1_DEFAULT | FLG_SY1_EXPDEF); 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate /* 9747c478bd9Sstevel@tonic-gate * Promote the symbols version index to the appropriate output version 9757c478bd9Sstevel@tonic-gate * definition. 9767c478bd9Sstevel@tonic-gate */ 9777c478bd9Sstevel@tonic-gate if (!(sdp->sd_flags & FLG_SY_VERSPROM)) { 9787c478bd9Sstevel@tonic-gate Ver_index *vip; 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vndx]; 9817c478bd9Sstevel@tonic-gate sdp->sd_aux->sa_overndx = vip->vi_desc->vd_ref->vd_ndx; 9827c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_VERSPROM; 9837c478bd9Sstevel@tonic-gate } 9847c478bd9Sstevel@tonic-gate } 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate /* 9877c478bd9Sstevel@tonic-gate * If any versioning is called for make sure an initial version descriptor is 9887c478bd9Sstevel@tonic-gate * assigned to represent the file itself. Known as the base version. 9897c478bd9Sstevel@tonic-gate */ 9907c478bd9Sstevel@tonic-gate Ver_desc * 9915aefb655Srie ld_vers_base(Ofl_desc *ofl) 9927c478bd9Sstevel@tonic-gate { 9937c478bd9Sstevel@tonic-gate Ver_desc *vdp; 9947c478bd9Sstevel@tonic-gate const char *name; 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate /* 9977c478bd9Sstevel@tonic-gate * Determine the filename to associate to the version descriptor. This 9987c478bd9Sstevel@tonic-gate * is either the SONAME (if one has been supplied) or the basename of 9997c478bd9Sstevel@tonic-gate * the output file. 10007c478bd9Sstevel@tonic-gate */ 1001*57ef7aa9SRod Evans if ((name = ofl->ofl_soname) == NULL) { 10027c478bd9Sstevel@tonic-gate const char *str = ofl->ofl_name; 10037c478bd9Sstevel@tonic-gate 10047c478bd9Sstevel@tonic-gate while (*str != '\0') { 10057c478bd9Sstevel@tonic-gate if (*str++ == '/') 10067c478bd9Sstevel@tonic-gate name = str; 10077c478bd9Sstevel@tonic-gate } 1008*57ef7aa9SRod Evans if (name == NULL) 10097c478bd9Sstevel@tonic-gate name = ofl->ofl_name; 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate 10127c478bd9Sstevel@tonic-gate /* 10137c478bd9Sstevel@tonic-gate * Generate the version descriptor. 10147c478bd9Sstevel@tonic-gate */ 10157c478bd9Sstevel@tonic-gate /* LINTED */ 10165aefb655Srie if ((vdp = ld_vers_desc(name, (Word)elf_hash(name), 10175aefb655Srie &ofl->ofl_verdesc)) == (Ver_desc *)S_ERROR) 10187c478bd9Sstevel@tonic-gate return ((Ver_desc *)S_ERROR); 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* 10217c478bd9Sstevel@tonic-gate * Assign the base index to this version and initialize the output file 10227c478bd9Sstevel@tonic-gate * descriptor with the number of version descriptors presently in use. 10237c478bd9Sstevel@tonic-gate */ 10247c478bd9Sstevel@tonic-gate vdp->vd_ndx = ofl->ofl_vercnt = VER_NDX_GLOBAL; 10257c478bd9Sstevel@tonic-gate vdp->vd_flags |= VER_FLG_BASE; 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate return (vdp); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate /* 10317c478bd9Sstevel@tonic-gate * Now that all input shared objects have been processed, verify that all 10327c478bd9Sstevel@tonic-gate * version requirements have been met. Any version control requirements will 10337c478bd9Sstevel@tonic-gate * have been specified by the user (and placed on the ofl_oscntl list) and are 10347c478bd9Sstevel@tonic-gate * verified at the time the object was processed (see ver_def_process()). 10357c478bd9Sstevel@tonic-gate * Here we process all version requirements established from shared objects 10367c478bd9Sstevel@tonic-gate * themselves (ie,. NEEDED dependencies). 10377c478bd9Sstevel@tonic-gate */ 10387c478bd9Sstevel@tonic-gate int 10395aefb655Srie ld_vers_verify(Ofl_desc *ofl) 10407c478bd9Sstevel@tonic-gate { 1041*57ef7aa9SRod Evans Aliste idx1; 10427c478bd9Sstevel@tonic-gate Sdf_desc *sdf; 10437c478bd9Sstevel@tonic-gate char *nv; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * As with the runtime environment, disable all version verification if 10477c478bd9Sstevel@tonic-gate * requested. 10487c478bd9Sstevel@tonic-gate */ 10497c478bd9Sstevel@tonic-gate #if defined(_ELF64) 10507c478bd9Sstevel@tonic-gate if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_64))) == NULL) 10517c478bd9Sstevel@tonic-gate #else 10527c478bd9Sstevel@tonic-gate if ((nv = getenv(MSG_ORIG(MSG_LD_NOVERSION_32))) == NULL) 10537c478bd9Sstevel@tonic-gate #endif 105460758829Srie nv = getenv(MSG_ORIG(MSG_LD_NOVERSION)); 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate if (nv && (*nv != '\0')) 10577c478bd9Sstevel@tonic-gate return (1); 10587c478bd9Sstevel@tonic-gate 1059*57ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_soneed, idx1, sdf)) { 1060*57ef7aa9SRod Evans Aliste idx2; 10617c478bd9Sstevel@tonic-gate Sdv_desc *sdv; 10627c478bd9Sstevel@tonic-gate Ifl_desc *ifl = sdf->sdf_file; 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate if (!(sdf->sdf_flags & FLG_SDF_VERIFY)) 10657c478bd9Sstevel@tonic-gate continue; 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate /* 10687c478bd9Sstevel@tonic-gate * If this file contains no version definitions then ignore 10697c478bd9Sstevel@tonic-gate * any versioning verification. This is the same model as 10707c478bd9Sstevel@tonic-gate * carried out by ld.so.1 and is intended to allow backward 10717c478bd9Sstevel@tonic-gate * compatibility should a shared object with a version 1072*57ef7aa9SRod Evans * requirement be returned to an older system on which a 10737c478bd9Sstevel@tonic-gate * non-versioned shared object exists. 10747c478bd9Sstevel@tonic-gate */ 1075*57ef7aa9SRod Evans if ((ifl == NULL) || (ifl->ifl_verdesc == NULL)) 10767c478bd9Sstevel@tonic-gate continue; 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate /* 10797c478bd9Sstevel@tonic-gate * If individual versions were specified for this file make 10807c478bd9Sstevel@tonic-gate * sure that they actually exist in the appropriate file, and 10817c478bd9Sstevel@tonic-gate * that they are available for binding. 10827c478bd9Sstevel@tonic-gate */ 1083*57ef7aa9SRod Evans for (ALIST_TRAVERSE(sdf->sdf_vers, idx2, sdv)) { 1084*57ef7aa9SRod Evans Aliste idx3; 10857c478bd9Sstevel@tonic-gate Ver_desc *vdp; 10867c478bd9Sstevel@tonic-gate int found = 0; 10877c478bd9Sstevel@tonic-gate 1088*57ef7aa9SRod Evans for (APLIST_TRAVERSE(ifl->ifl_verdesc, idx3, vdp)) { 10897c478bd9Sstevel@tonic-gate if (strcmp(sdv->sdv_name, vdp->vd_name) == 0) { 10907c478bd9Sstevel@tonic-gate found++; 10917c478bd9Sstevel@tonic-gate break; 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate if (found) { 10957c478bd9Sstevel@tonic-gate Ver_index *vip; 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate vip = &ifl->ifl_verndx[vdp->vd_ndx]; 10987c478bd9Sstevel@tonic-gate if (!(vip->vi_flags & FLG_VER_AVAIL)) { 10995aefb655Srie eprintf(ofl->ofl_lml, ERR_FATAL, 11007c478bd9Sstevel@tonic-gate MSG_INTL(MSG_VER_UNAVAIL), 11017c478bd9Sstevel@tonic-gate ifl->ifl_name, sdv->sdv_name, 11027c478bd9Sstevel@tonic-gate sdv->sdv_ref); 11037c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate } else { 11065aefb655Srie eprintf(ofl->ofl_lml, ERR_FATAL, 11075aefb655Srie MSG_INTL(MSG_VER_NOEXIST), ifl->ifl_name, 11085aefb655Srie sdv->sdv_name, sdv->sdv_ref); 11097c478bd9Sstevel@tonic-gate ofl->ofl_flags |= FLG_OF_FATAL; 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate return (1); 11147c478bd9Sstevel@tonic-gate } 1115