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