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 (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * 27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include "_synonyms.h" 33 34 #include <string.h> 35 #include <stdio.h> 36 #include <unistd.h> 37 #include <sys/stat.h> 38 #include <sys/mman.h> 39 #include <fcntl.h> 40 #include <limits.h> 41 #include <dlfcn.h> 42 #include <errno.h> 43 #include <link.h> 44 #include "_rtld.h" 45 #include "_audit.h" 46 #include "_elf.h" 47 #include "msg.h" 48 #include "debug.h" 49 #include "conv.h" 50 51 static Fct * vector[] = { 52 &elf_fct, 53 #ifdef A_OUT 54 &aout_fct, 55 #endif 56 0 57 }; 58 59 /* 60 * If a load filter flag is in effect, and this object is a filter, trigger the 61 * loading of all its filtees. The load filter flag is in effect when creating 62 * configuration files, or when under the control of ldd(1), or the LD_LOADFLTR 63 * environment variable is set, or this object was built with the -zloadfltr 64 * flag. Otherwise, filtee loading is deferred until triggered by a relocation. 65 */ 66 static void 67 load_filtees(Rt_map *lmp) 68 { 69 if ((FLAGS1(lmp) & MSK_RT_FILTER) && 70 ((FLAGS(lmp) & FLG_RT_LOADFLTR) || 71 (LIST(lmp)->lm_tflags & LML_TFLG_LOADFLTR))) { 72 Dyninfo * dip = DYNINFO(lmp); 73 uint_t cnt, max = DYNINFOCNT(lmp); 74 Slookup sl; 75 76 sl.sl_name = 0; 77 sl.sl_hash = 0; 78 sl.sl_imap = sl.sl_cmap = lmp; 79 80 for (cnt = 0; cnt < max; cnt++, dip++) { 81 if (((dip->di_flags & MSK_DI_FILTER) == 0) || 82 ((dip->di_flags & FLG_DI_AUXFLTR) && 83 (rtld_flags & RT_FL_NOAUXFLTR))) 84 continue; 85 (void) elf_lookup_filtee(&sl, 0, 0, cnt); 86 } 87 } 88 } 89 90 /* 91 * Analyze one or more link-maps of a link map control list. This routine is 92 * called at startup to continue the processing of the main executable. It is 93 * also called each time a new set of objects are loaded, ie. from filters, 94 * lazy-loaded objects, or dlopen(). 95 * 96 * In each instance we traverse the link-map control list starting with the 97 * initial object. As dependencies are analyzed they are added to the link-map 98 * control list. Thus the list grows as we traverse it - this results in the 99 * breadth first ordering of all needed objects. 100 */ 101 int 102 analyze_lmc(Lm_list *lml, Aliste nlmco, Rt_map *nlmp) 103 { 104 Rt_map *lmp = nlmp; 105 Lm_cntl *nlmc; 106 int ret = 1; 107 108 /* 109 * If this link-map control list is being analyzed, return. The object 110 * that has just been added will be picked up by the existing analysis 111 * thread. Note, this is only really meaningful during process init- 112 * ialization, as objects are added to the main link-map control list. 113 * Following this initialization, each family of objects that are loaded 114 * are added to a new link-map control list. 115 */ 116 /* LINTED */ 117 nlmc = (Lm_cntl *)((char *)lml->lm_lists + nlmco); 118 if (nlmc->lc_flags & LMC_FLG_ANALYZING) 119 return (1); 120 121 /* 122 * If this object doesn't belong to the present link-map control list 123 * then it must already have been analyzed, or it is in the process of 124 * being analyzed prior to us recursing into this analysis. In either 125 * case, ignore the object as it's already being taken care of. 126 */ 127 if (nlmco != CNTL(nlmp)) 128 return (1); 129 130 nlmc->lc_flags |= LMC_FLG_ANALYZING; 131 132 for (; lmp; lmp = (Rt_map *)NEXT(lmp)) { 133 if (FLAGS(lmp) & 134 (FLG_RT_ANALZING | FLG_RT_ANALYZED | FLG_RT_DELETE)) 135 continue; 136 137 /* 138 * Indicate that analyzing is under way. 139 */ 140 FLAGS(lmp) |= FLG_RT_ANALZING; 141 142 /* 143 * If this link map represents a relocatable object, then we 144 * need to finish the link-editing of the object at this point. 145 */ 146 if (FLAGS(lmp) & FLG_RT_OBJECT) { 147 if (elf_obj_fini(lml, lmp) == 0) { 148 if (lml->lm_flags & LML_FLG_TRC_ENABLE) 149 continue; 150 ret = 0; 151 break; 152 } 153 } 154 155 DBG_CALL(Dbg_file_analyze(lmp)); 156 157 /* 158 * Establish any dependencies this object requires. 159 */ 160 if (LM_NEEDED(lmp)(lml, nlmco, lmp) == 0) { 161 if (lml->lm_flags & LML_FLG_TRC_ENABLE) 162 continue; 163 ret = 0; 164 break; 165 } 166 167 FLAGS(lmp) &= ~FLG_RT_ANALZING; 168 FLAGS(lmp) |= FLG_RT_ANALYZED; 169 170 /* 171 * If we're building a configuration file, determine if this 172 * object is a filter and if so load its filtees. This 173 * traversal is only necessary for crle(1), as typical use of 174 * an object will load filters as part of relocation processing. 175 */ 176 if (MODE(nlmp) & RTLD_CONFGEN) 177 load_filtees(lmp); 178 179 /* 180 * If an interposer has been added, it will have been inserted 181 * in the link-map before the link we're presently analyzing. 182 * Break out of this analysis loop and return to the head of 183 * the link-map control list to analyze the interposer. Note 184 * that this rescan preserves the breadth first loading of 185 * dependencies. 186 */ 187 if (nlmc->lc_flags & LMC_FLG_REANALYZE) { 188 nlmc->lc_flags &= ~LMC_FLG_REANALYZE; 189 lmp = nlmc->lc_head; 190 } 191 } 192 193 nlmc->lc_flags &= ~LMC_FLG_ANALYZING; 194 195 return (ret); 196 } 197 198 /* 199 * Copy relocation test. If the symbol definition is within .bss, then it's 200 * zero filled, and as the destination is within .bss, we can skip copying 201 * zero's to zero's. However, if the destination object has a MOVE table, it's 202 * .bss might contain non-zero data, in which case copy it regardless. 203 */ 204 static int 205 copy_zerobits(Rt_map *dlmp, Sym *dsym) 206 { 207 if ((FLAGS(dlmp) & FLG_RT_MOVE) == 0) { 208 Mmap *mmaps; 209 caddr_t daddr = (caddr_t)dsym->st_value; 210 211 if ((FLAGS(dlmp) & FLG_RT_FIXED) == 0) 212 daddr += ADDR(dlmp); 213 214 for (mmaps = MMAPS(dlmp); mmaps->m_vaddr; mmaps++) { 215 if ((mmaps->m_fsize != mmaps->m_msize) && 216 (daddr >= (mmaps->m_vaddr + mmaps->m_fsize)) && 217 (daddr < (mmaps->m_vaddr + mmaps->m_msize))) 218 return (1); 219 } 220 } 221 return (0); 222 } 223 224 /* 225 * Relocate an individual object. 226 */ 227 static int 228 relocate_so(Lm_list *lml, Rt_map *lmp, int *relocated, int now) 229 { 230 /* 231 * If we're running under ldd(1), and haven't been asked to trace any 232 * warnings, skip any actual relocation processing. 233 */ 234 if (((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) || 235 (lml->lm_flags & LML_FLG_TRC_WARN)) { 236 237 if (relocated) 238 (*relocated)++; 239 240 if ((LM_RELOC(lmp)(lmp, now) == 0) && 241 ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0)) 242 return (0); 243 } 244 return (1); 245 } 246 247 /* 248 * Relocate the objects on a link-map control list. 249 */ 250 static int 251 _relocate_lmc(Lm_list *lml, Rt_map *nlmp, int *relocated) 252 { 253 Rt_map *lmp; 254 255 for (lmp = nlmp; lmp; lmp = (Rt_map *)NEXT(lmp)) { 256 /* 257 * If this object has already been relocated, we're done. If 258 * this object is being deleted, skip it, there's probably a 259 * relocation error somewhere that's causing this deletion. 260 */ 261 if (FLAGS(lmp) & 262 (FLG_RT_RELOCING | FLG_RT_RELOCED | FLG_RT_DELETE)) 263 continue; 264 265 /* 266 * Indicate that relocation processing is under way. 267 */ 268 FLAGS(lmp) |= FLG_RT_RELOCING; 269 270 /* 271 * Relocate the object. 272 */ 273 if (relocate_so(lml, lmp, relocated, 0) == 0) 274 return (0); 275 276 /* 277 * Indicate that the objects relocation is complete. 278 */ 279 FLAGS(lmp) &= ~FLG_RT_RELOCING; 280 FLAGS(lmp) |= FLG_RT_RELOCED; 281 282 /* 283 * Mark this object's init is available for harvesting. Under 284 * ldd(1) this marking is necessary for -i (tsort) gathering. 285 */ 286 lml->lm_init++; 287 288 /* 289 * None of the following processing is necessary under ldd(). 290 */ 291 if ((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) { 292 /* 293 * Process any move data. 294 */ 295 if (FLAGS(lmp) & FLG_RT_MOVE) 296 move_data(lmp); 297 298 /* 299 * Process any DT_SUNW_RTLDINFO information now the 300 * object is relocated, and remove the RTLDINFO 301 * infrastructure as it won't be needed anymore. 302 * 303 * We wait until lmp == lm_info_lmp, as it's at this 304 * stage we know the object contributing RTLDINFO has 305 * been properly relocated. 306 */ 307 if ((FCT(lmp) == &elf_fct) && (lml->lm_rtldinfo) && 308 (lmp == lml->lm_info_lmp)) { 309 Aliste off; 310 Lc_interface ** funcs; 311 312 for (ALIST_TRAVERSE(lml->lm_rtldinfo, 313 off, funcs)) 314 get_lcinterface(lmp, *funcs); 315 free(lml->lm_rtldinfo); 316 lml->lm_rtldinfo = 0; 317 } 318 } 319 320 /* 321 * Determine if this object is a filter, and if a load filter 322 * flag is in effect, trigger the loading of all its filtees. 323 */ 324 load_filtees(lmp); 325 } 326 327 /* 328 * Perform special copy relocations. These are only meaningful for 329 * dynamic executables (fixed and head of their link-map list). If 330 * this ever has to change then the infrastructure of COPY() has to 331 * change as presently this element is used to capture both receiver 332 * and supplier of copy data. 333 */ 334 if ((FLAGS(nlmp) & FLG_RT_FIXED) && (nlmp == LIST(nlmp)->lm_head) && 335 (((lml->lm_flags & LML_FLG_TRC_ENABLE) == 0) || 336 (lml->lm_flags & LML_FLG_TRC_WARN))) { 337 Rt_map ** lmpp; 338 Aliste off1; 339 Word tracing; 340 341 #if defined(__sparc) || defined(__amd64) 342 /* XX64 don't need this once the compilers are fixed */ 343 #elif defined(i386) 344 if (elf_copy_gen(nlmp) == 0) 345 return (0); 346 #endif 347 348 if (COPY(nlmp) == 0) 349 return (1); 350 351 if ((LIST(nlmp)->lm_flags & LML_FLG_TRC_ENABLE) && 352 (((rtld_flags & RT_FL_SILENCERR) == 0) || 353 (LIST(nlmp)->lm_flags & LML_FLG_TRC_VERBOSE))) 354 tracing = 1; 355 else 356 tracing = 0; 357 358 DBG_CALL(Dbg_util_nl()); 359 360 for (ALIST_TRAVERSE(COPY(nlmp), off1, lmpp)) { 361 Rt_map * lmp = *lmpp; 362 Rel_copy * rcp; 363 Aliste off2; 364 365 for (ALIST_TRAVERSE(COPY(lmp), off2, rcp)) { 366 int zero; 367 368 /* 369 * Only copy the bits if it's from non-zero 370 * filled memory. 371 */ 372 zero = copy_zerobits(rcp->r_dlmp, rcp->r_dsym); 373 DBG_CALL(Dbg_reloc_copy(NAME(rcp->r_dlmp), 374 NAME(nlmp), rcp->r_name, zero)); 375 if (zero) 376 continue; 377 378 (void) memcpy(rcp->r_radd, rcp->r_dadd, 379 rcp->r_size); 380 381 if ((tracing == 0) || ((FLAGS1(rcp->r_dlmp) & 382 FL1_RT_DISPREL) == 0)) 383 continue; 384 385 (void) printf(MSG_INTL(MSG_LDD_REL_CPYDISP), 386 demangle(rcp->r_name), NAME(rcp->r_dlmp)); 387 } 388 } 389 390 DBG_CALL(Dbg_util_nl()); 391 392 free(COPY(nlmp)); 393 COPY(nlmp) = 0; 394 } 395 return (1); 396 } 397 398 int 399 relocate_lmc(Lm_list *lml, Aliste nlmco, Rt_map *nlmp) 400 { 401 int lret = 1, pret = 1; 402 Alist *alp; 403 Aliste plmco; 404 Lm_cntl *plmc, *nlmc; 405 406 /* 407 * If this link-map control list is being relocated, return. The object 408 * that has just been added will be picked up by the existing relocation 409 * thread. Note, this is only really meaningful during process init- 410 * ialization, as objects are added to the main link-map control list. 411 * Following this initialization, each family of objects that are loaded 412 * are added to a new link-map control list. 413 */ 414 /* LINTED */ 415 nlmc = (Lm_cntl *)((char *)lml->lm_lists + nlmco); 416 417 if (nlmc->lc_flags & LMC_FLG_RELOCATING) 418 return (1); 419 420 nlmc->lc_flags |= LMC_FLG_RELOCATING; 421 422 /* 423 * Relocate one or more link-maps of a link map control list. If this 424 * object doesn't belong to the present link-map control list then it 425 * must already have been relocated, or it is in the process of being 426 * relocated prior to us recursing into this relocation. In either 427 * case, ignore the object as it's already being taken care of, however, 428 * fall through and capture any relocation promotions that might have 429 * been established from the reference mode of this object. 430 * 431 * If we're generating a configuration file using crle(1), two passes 432 * may be involved. Under the first pass, RTLD_CONFGEN is set. Under 433 * this pass, crle() loads objects into the process address space. No 434 * relocation is necessary at this point, we simply need to analyze the 435 * objects to insure any directly bound dependencies, filtees, etc. 436 * get loaded. Although we skip the relocation, fall through to insure 437 * any control lists are maintained appropriately. 438 * 439 * If objects are to be dldump(3c)'ed, crle(1) makes a second pass, 440 * using RTLD_NOW and RTLD_CONFGEN. The RTLD_NOW effectively carries 441 * out the relocations of all loaded objects. 442 */ 443 if ((nlmco == CNTL(nlmp)) && 444 ((MODE(nlmp) & (RTLD_NOW | RTLD_CONFGEN)) != RTLD_CONFGEN)) { 445 int relocated = 0; 446 447 /* 448 * Determine whether the initial link-map control list has 449 * started relocation. From this point, should any interposing 450 * objects be added to this link-map control list, the objects 451 * are demoted to standard objects. Their interposition can't 452 * be guaranteed once relocations have been carried out. 453 */ 454 if (nlmco == ALO_DATA) 455 lml->lm_flags |= LML_FLG_STARTREL; 456 457 /* 458 * Relocate the link-map control list. 459 */ 460 lret = _relocate_lmc(lml, nlmp, &relocated); 461 462 /* 463 * At this point we've completed the addition of a new group of 464 * objects, either the initial objects that start the process 465 * (called from setup()), a group added through lazy loading or 466 * filters, or from a dlopen() request. Indicate to the 467 * debuggers that new objects have been added. 468 */ 469 if (relocated && lret && 470 ((lml->lm_flags & LML_FLG_DBNOTIF) == 0)) 471 rd_event(lml, RD_DLACTIVITY, RT_ADD); 472 } 473 474 /* 475 * Determine the new, and previous link-map control lists. 476 */ 477 if (nlmco == ALO_DATA) 478 plmc = nlmc; 479 else { 480 plmco = nlmco - lml->lm_lists->al_size; 481 /* LINTED */ 482 plmc = (Lm_cntl *)((char *)lml->lm_lists + plmco); 483 } 484 485 /* 486 * Having completed this control list of objects, they can now be bound 487 * to from other objects. Move this control list to the control list 488 * that precedes it. Although this control list may have only bound to 489 * controls lists much higher up the control list stack, it must only 490 * be moved up one control list so as to preserve the link-map order 491 * that may have already been traversed in search of symbols. 492 */ 493 if (lret && (nlmco != ALO_DATA) && nlmc->lc_head) 494 lm_move(lml, nlmco, plmco, nlmc, plmc); 495 496 /* 497 * Determine whether existing objects that have already been relocated, 498 * need any additional relocations performed. This can occur when new 499 * objects are loaded with RTLD_NOW, and these new objects have 500 * dependencies on objects that are already loaded. Note, that we peel 501 * any relocation promotions off of one control list at a time. This 502 * prevents relocations from being bound to objects that might yet fail 503 * to relocate themselves. 504 */ 505 while ((alp = plmc->lc_now) != 0) { 506 Aliste off; 507 Rt_map **lmpp; 508 509 /* 510 * Remove the relocation promotion list, as performing more 511 * relocations may result in discovering more objects that need 512 * promotion. 513 */ 514 plmc->lc_now = 0; 515 516 for (ALIST_TRAVERSE(alp, off, lmpp)) { 517 Rt_map *lmp = *lmpp; 518 519 /* 520 * If the original relocation of the link-map control 521 * list failed, or one of the relocation promotions of 522 * this loop has failed, demote any pending objects 523 * relocation mode. 524 */ 525 if ((lret == 0) || (pret == 0)) { 526 MODE(lmp) &= ~RTLD_NOW; 527 MODE(lmp) |= RTLD_LAZY; 528 continue; 529 } 530 531 /* 532 * If a relocation fails, save the error condition. 533 * It's possible that all new objects on the original 534 * link-map control list have been relocated 535 * successfully, but if the user request requires 536 * promoting objects that have already been loaded, we 537 * have to indicate that this operation couldn't be 538 * performed. The unrelocated objects are in use on 539 * another control list, and may continue to be used. 540 * If the .plt that resulted in the error is called, 541 * then the process will receive a fatal error at that 542 * time. But, the .plt may never be called. 543 */ 544 if (relocate_so(lml, lmp, 0, 1) == 0) 545 pret = 0; 546 } 547 548 /* 549 * Having promoted any objects, determine whether additional 550 * dependencies were added, and if so move them to the previous 551 * link-map control list. 552 */ 553 if ((nlmco != ALO_DATA) && nlmc->lc_head) 554 lm_move(lml, nlmco, plmco, nlmc, plmc); 555 556 (void) free(alp); 557 } 558 559 nlmc->lc_flags &= ~LMC_FLG_RELOCATING; 560 561 if (lret && pret) 562 return (1); 563 else 564 return (0); 565 } 566 567 /* 568 * Inherit the first rejection message for possible later diagnostics. 569 * 570 * Any attempt to process a file that is unsuccessful, should be accompanied 571 * with an error diagnostic. However, some operations like searching for a 572 * simple filename, involve trying numerous paths, and an error message for each 573 * lookup is not required. Although a multiple search can fail, it's possible 574 * that a file was found, but was rejected because it was the wrong type. 575 * To satisfy these possibilities, the first failure is recorded as a rejection 576 * message, and this message is used later for a more specific diagnostic. 577 * 578 * File searches are focused at load_one(), and from here a rejection descriptor 579 * is passed down to various child routines. If these child routines can 580 * process multiple files, then they will maintain their own rejection desc- 581 * riptor. This is filled in for any failures, and a diagnostic produced to 582 * reflect the failure. The child routines then employ rejection_inherit() to 583 * pass the first rejection message back to load_one(). 584 * 585 * Note that the name, and rejection string must be duplicated, as the name 586 * buffer and error string buffer (see conv_ routines) may be reused for 587 * additional processing or rejection messages. 588 * 589 * As this routine is called to clean up after a failed open, remove any 590 * resolved pathname that might have been allocated as the file was processed. 591 */ 592 void 593 rejection_inherit(Rej_desc *rej1, Rej_desc *rej2, Fdesc *fdp) 594 { 595 if (rej2->rej_type && (rej1->rej_type == 0)) { 596 rej1->rej_type = rej2->rej_type; 597 rej1->rej_info = rej2->rej_info; 598 rej1->rej_flag = rej2->rej_flag; 599 if (rej2->rej_name) 600 rej1->rej_name = strdup(rej2->rej_name); 601 if (rej2->rej_str) { 602 if ((rej1->rej_str = strdup(rej2->rej_str)) == 0) 603 rej1->rej_str = MSG_ORIG(MSG_EMG_ENOMEM); 604 } 605 } 606 if (fdp && fdp->fd_nname && fdp->fd_pname && 607 (fdp->fd_pname != fdp->fd_nname)) { 608 free((void *)fdp->fd_pname); 609 fdp->fd_pname = 0; 610 } 611 } 612 613 /* 614 * Determine the object type of a file. 615 */ 616 Fct * 617 are_u_this(Rej_desc *rej, int fd, struct stat *status, const char *name) 618 { 619 int i; 620 char *maddr = 0; 621 622 fmap->fm_fsize = status->st_size; 623 624 /* 625 * If this is a directory (which can't be mmap()'ed) generate a precise 626 * error message. 627 */ 628 if ((status->st_mode & S_IFMT) == S_IFDIR) { 629 rej->rej_type = SGS_REJ_STR; 630 rej->rej_str = strerror(EISDIR); 631 return (0); 632 } 633 634 /* 635 * Map in the first page of the file. When this buffer is first used, 636 * the mapping is a single system page. This is typically enough to 637 * inspect the ehdr and phdrs of the file, and can be reused for each 638 * file that get loaded. If a larger mapping is required to read the 639 * ehdr and phdrs, a new mapping is created (see elf_map_it()). This 640 * new mapping is again used for each new file loaded. Some objects, 641 * such as filters, only take up one page, and in this case this mapping 642 * will suffice for the file. 643 */ 644 maddr = mmap(fmap->fm_maddr, fmap->fm_msize, (PROT_READ | PROT_EXEC), 645 fmap->fm_mflags, fd, 0); 646 #if defined(MAP_ALIGN) 647 if ((maddr == MAP_FAILED) && (errno == EINVAL)) { 648 /* 649 * If the mapping failed, and we used MAP_ALIGN, assume we're 650 * on a system that doesn't support this option. Try again 651 * without MAP_ALIGN. 652 */ 653 if (fmap->fm_mflags & MAP_ALIGN) { 654 rtld_flags2 |= RT_FL2_NOMALIGN; 655 fmap_setup(); 656 657 maddr = (char *)mmap(fmap->fm_maddr, fmap->fm_msize, 658 (PROT_READ | PROT_EXEC), fmap->fm_mflags, fd, 0); 659 } 660 } 661 #endif 662 if (maddr == MAP_FAILED) { 663 rej->rej_type = SGS_REJ_STR; 664 rej->rej_str = strerror(errno); 665 return (0); 666 } 667 668 /* 669 * From now on we will re-use fmap->fm_maddr as the mapping address 670 * so we augment the flags with MAP_FIXED and drop any MAP_ALIGN. 671 */ 672 fmap->fm_maddr = maddr; 673 fmap->fm_mflags |= MAP_FIXED; 674 #if defined(MAP_ALIGN) 675 fmap->fm_mflags &= ~MAP_ALIGN; 676 #endif 677 678 /* 679 * Search through the object vectors to determine what kind of 680 * object we have. 681 */ 682 for (i = 0; vector[i]; i++) { 683 if ((vector[i]->fct_are_u_this)(rej)) 684 return (vector[i]); 685 else if (rej->rej_type) { 686 Rt_map *lmp; 687 688 /* 689 * If this object is an explicitly defined shared 690 * object under inspection by ldd, and contains a 691 * incompatible hardware capabilities requirement, then 692 * inform the user, but continue processing. 693 * 694 * XXXX - ldd -v for any rej failure. 695 */ 696 if ((rej->rej_type == SGS_REJ_HWCAP_1) && 697 (lml_main.lm_flags & LML_FLG_TRC_LDDSTUB) && 698 ((lmp = lml_main.lm_head) != 0) && 699 (FLAGS1(lmp) & FL1_RT_LDDSTUB) && 700 (NEXT(lmp) == 0)) { 701 (void) printf(MSG_INTL(MSG_LDD_GEN_HWCAP_1), 702 name, rej->rej_str); 703 return (vector[i]); 704 } 705 return (0); 706 } 707 } 708 709 /* 710 * Unknown file type. 711 */ 712 rej->rej_type = SGS_REJ_UNKFILE; 713 return (0); 714 } 715 716 717 /* 718 * Function that determines whether a file name has already been loaded; if so, 719 * returns a pointer to its link map structure; else returns a NULL pointer. 720 */ 721 static int 722 _is_so_matched(const char *name, const char *str, int base) 723 { 724 const char *_str; 725 726 if (base && ((_str = strrchr(str, '/')) != NULL)) 727 _str++; 728 else 729 _str = str; 730 731 return (strcmp(name, _str)); 732 } 733 734 static Rt_map * 735 is_so_matched(Rt_map *lmp, const char *name, int base) 736 { 737 Aliste off; 738 const char **cpp; 739 740 /* 741 * Typically, dependencies are specified as simple file names 742 * (DT_NEEDED == libc.so.1), which are expanded to full pathnames to 743 * open the file. The full pathname is NAME(), and the original name 744 * is maintained on the ALIAS() list. Look through the ALIAS list first, 745 * as this is most likely to match other dependency uses. 746 */ 747 for (ALIST_TRAVERSE(ALIAS(lmp), off, cpp)) { 748 if (_is_so_matched(name, *cpp, base) == 0) 749 return (lmp); 750 } 751 752 /* 753 * Finally compare full paths, this is sometimes useful for catching 754 * filter names, or for those that dlopen() the dynamic executable. 755 */ 756 if (_is_so_matched(name, NAME(lmp), base) == 0) 757 return (lmp); 758 759 if (PATHNAME(lmp) != NAME(lmp)) { 760 if (_is_so_matched(name, PATHNAME(lmp), base) == 0) 761 return (lmp); 762 } 763 return (0); 764 } 765 766 Rt_map * 767 is_so_loaded(Lm_list *lml, const char *name, int base) 768 { 769 Rt_map *lmp; 770 const char *_name; 771 avl_index_t where; 772 Lm_cntl *lmc; 773 Aliste off; 774 775 /* 776 * If we've been asked to do a basename search, first determine if 777 * the pathname is registered in the FullpathNode AVL tree. 778 */ 779 if (base && (name[0] == '/') && 780 ((lmp = fpavl_loaded(lml, name, &where)) != NULL) && 781 ((FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE)) == 0)) 782 return (lmp); 783 784 /* 785 * If we've been asked to do a basename search reduce the input name 786 * to its basename. 787 */ 788 if (base && ((_name = strrchr(name, '/')) != NULL)) 789 _name++; 790 else 791 _name = name; 792 793 /* 794 * Loop through the callers link-map lists. 795 */ 796 for (ALIST_TRAVERSE(lml->lm_lists, off, lmc)) { 797 for (lmp = lmc->lc_head; lmp; lmp = (Rt_map *)NEXT(lmp)) { 798 if (FLAGS(lmp) & (FLG_RT_OBJECT | FLG_RT_DELETE)) 799 continue; 800 801 if (is_so_matched(lmp, _name, base)) 802 return (lmp); 803 } 804 } 805 return ((Rt_map *)0); 806 } 807 808 809 /* 810 * Tracing is enabled by the LD_TRACE_LOADED_OPTIONS environment variable which 811 * is normally set from ldd(1). For each link map we load, print the load name 812 * and the full pathname of the shared object. 813 */ 814 /* ARGSUSED4 */ 815 static void 816 trace_so(Rt_map *clmp, Rej_desc *rej, const char *name, const char *path, 817 int alter, const char *nfound) 818 { 819 const char *str = MSG_ORIG(MSG_STR_EMPTY); 820 const char *reject = MSG_ORIG(MSG_STR_EMPTY); 821 char _reject[PATH_MAX]; 822 823 /* 824 * The first time through trace_so() will only have lddstub on the 825 * link-map list and the preloaded shared object is supplied as "path". 826 * As we don't want to print this shared object as a dependency, but 827 * instead inspect *its* dependencies, return. 828 */ 829 if (FLAGS1(clmp) & FL1_RT_LDDSTUB) 830 return; 831 832 /* 833 * Without any rejection info, this is a supplied not-found condition. 834 */ 835 if (rej && (rej->rej_type == 0)) { 836 (void) printf(nfound, name); 837 return; 838 } 839 840 /* 841 * If rejection information exists then establish what object was 842 * found and the reason for its rejection. 843 */ 844 if (rej) { 845 /* LINTED */ 846 (void) snprintf(_reject, PATH_MAX, 847 MSG_INTL(ldd_reject[rej->rej_type]), conv_reject_str(rej)); 848 if (rej->rej_name) 849 path = rej->rej_name; 850 reject = (char *)_reject; 851 852 /* 853 * Was an alternative pathname defined (from a configuration 854 * file). 855 */ 856 if (rej->rej_flag & FLG_FD_ALTER) 857 str = MSG_INTL(MSG_LDD_FIL_ALTER); 858 } else { 859 if (alter) 860 str = MSG_INTL(MSG_LDD_FIL_ALTER); 861 } 862 863 /* 864 * If the load name isn't a full pathname print its associated pathname 865 * together with all the other information we've gathered. 866 */ 867 if (*name == '/') 868 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH), path, str, reject); 869 else 870 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV), name, path, str, reject); 871 } 872 873 874 /* 875 * Establish a link-map mode, initializing it if it has just been loaded, or 876 * potentially updating it if it already exists. 877 */ 878 int 879 update_mode(Rt_map *lmp, int omode, int nmode) 880 { 881 int pmode = 0; 882 883 /* 884 * A newly loaded object hasn't had its mode set yet. Modes are used to 885 * load dependencies, so don't propagate any parent or no-load flags, as 886 * these would adversely affect this objects ability to load any of its 887 * dependencies that aren't already loaded. RTLD_FIRST is applicable to 888 * this objects handle creation only, and should not be propagated. 889 */ 890 if ((FLAGS(lmp) & FLG_RT_MODESET) == 0) { 891 MODE(lmp) |= nmode & ~(RTLD_PARENT | RTLD_NOLOAD | RTLD_FIRST); 892 FLAGS(lmp) |= FLG_RT_MODESET; 893 return (1); 894 } 895 896 /* 897 * Establish any new overriding modes. RTLD_LAZY and RTLD_NOW should be 898 * represented individually (this is historic, as these two flags were 899 * the only flags originally available to dlopen()). Other flags are 900 * accumulative, but have a hierarchy of preference. 901 */ 902 if ((omode & RTLD_LAZY) && (nmode & RTLD_NOW)) { 903 MODE(lmp) &= ~RTLD_LAZY; 904 pmode |= RTLD_NOW; 905 } 906 907 pmode |= ((~omode & nmode) & 908 (RTLD_GLOBAL | RTLD_WORLD | RTLD_NODELETE)); 909 if (pmode) { 910 DBG_CALL(Dbg_file_mode_promote(NAME(lmp), pmode)); 911 MODE(lmp) |= pmode; 912 } 913 914 /* 915 * If this load is an RTLD_NOW request and the object has already been 916 * loaded non-RTLD_NOW, append this object to the relocation-now list 917 * of the objects associated control list. Note, if the object hasn't 918 * yet been relocated, setting its MODE() to RTLD_NOW will establish 919 * full relocation processing when it eventually gets relocated. 920 */ 921 if ((pmode & RTLD_NOW) && 922 (FLAGS(lmp) & (FLG_RT_RELOCED | FLG_RT_RELOCING))) { 923 Lm_cntl *lmc; 924 925 /* LINTED */ 926 lmc = (Lm_cntl *)((char *)(LIST(lmp)->lm_lists) + CNTL(lmp)); 927 (void) alist_append(&(lmc->lc_now), &lmp, sizeof (Rt_map *), 928 AL_CNT_LMNOW); 929 } 930 931 #ifdef SIEBEL_DISABLE 932 /* 933 * For patch backward compatibility the following .init collection 934 * is disabled. 935 */ 936 if (rtld_flags & RT_FL_DISFIX_1) 937 return (pmode); 938 #endif 939 940 /* 941 * If this objects init has been collected but not yet been called, mark 942 * it as uncollected. This object will be added to the tsort() that 943 * follows this operation which may compensate for insufficient binding 944 * information used by the tsort() it was originally part of. For 945 * example, a new dlopen() hierarchy may bind to uninitialized objects 946 * that are already loaded, or a dlopen(RTLD_NOW) can establish new 947 * bindings between already loaded objects that require the tsort() 948 * information be recomputed. 949 */ 950 if ((FLAGS(lmp) & (FLG_RT_INITCLCT | FLG_RT_INITCALL)) == 951 FLG_RT_INITCLCT) { 952 FLAGS(lmp) &= ~FLG_RT_INITCLCT; 953 LIST(lmp)->lm_init++; 954 LIST(lmp)->lm_flags |= LML_FLG_BNDUNINIT; 955 } 956 957 return (pmode); 958 } 959 960 /* 961 * Determine whether an alias name already exists, and if not create one. This 962 * is typically used to retain dependency names, such as "libc.so.1", which 963 * would have been expanded to full path names when they were loaded. The 964 * full path names (NAME() and possibly PATHNAME()) are maintained as Fullpath 965 * AVL nodes, and thus would have been matched by fpavl_loaded() during 966 * file_open(). 967 */ 968 int 969 append_alias(Rt_map *lmp, const char *str, int *added) 970 { 971 Aliste off; 972 char **cpp, *cp; 973 974 /* 975 * Determine if this filename is already on the alias list. 976 */ 977 for (ALIST_TRAVERSE(ALIAS(lmp), off, cpp)) { 978 if (strcmp(*cpp, str) == 0) 979 return (1); 980 } 981 982 /* 983 * This is a new alias, append it to the alias list. 984 */ 985 if ((cp = strdup(str)) == 0) 986 return (0); 987 988 if (alist_append(&ALIAS(lmp), &cp, sizeof (char *), 989 AL_CNT_ALIAS) == 0) { 990 free(cp); 991 return (0); 992 } 993 if (added) 994 *added = 1; 995 return (1); 996 } 997 998 /* 999 * Determine whether a file is already loaded by comparing device and inode 1000 * values. 1001 */ 1002 static Rt_map * 1003 is_devinode_loaded(struct stat *status, Lm_list *lml, const char *name, 1004 uint_t flags) 1005 { 1006 Lm_cntl *lmc; 1007 Aliste off; 1008 1009 /* 1010 * If this is an auditor, it will have been opened on a new link-map. 1011 * To prevent multiple occurrances of the same auditor on multiple 1012 * link-maps, search the head of each link-map list and see if this 1013 * object is already loaded as an auditor. 1014 */ 1015 if (flags & FLG_RT_AUDIT) { 1016 Lm_list * lml; 1017 Listnode * lnp; 1018 1019 for (LIST_TRAVERSE(&dynlm_list, lnp, lml)) { 1020 Rt_map *nlmp = lml->lm_head; 1021 1022 if (nlmp && ((FLAGS(nlmp) & 1023 (FLG_RT_AUDIT | FLG_RT_DELETE)) == FLG_RT_AUDIT) && 1024 (STDEV(nlmp) == status->st_dev) && 1025 (STINO(nlmp) == status->st_ino)) 1026 return (nlmp); 1027 } 1028 return ((Rt_map *)0); 1029 } 1030 1031 /* 1032 * If the file has been found determine from the new files status 1033 * information if this file is actually linked to one we already have 1034 * mapped. This catches symlink names not caught by is_so_loaded(). 1035 */ 1036 for (ALIST_TRAVERSE(lml->lm_lists, off, lmc)) { 1037 Rt_map *nlmp; 1038 1039 for (nlmp = lmc->lc_head; nlmp; nlmp = (Rt_map *)NEXT(nlmp)) { 1040 if ((FLAGS(nlmp) & FLG_RT_DELETE) || 1041 (FLAGS1(nlmp) & FL1_RT_LDDSTUB)) 1042 continue; 1043 1044 if ((STDEV(nlmp) != status->st_dev) || 1045 (STINO(nlmp) != status->st_ino)) 1046 continue; 1047 1048 if (lml->lm_flags & LML_FLG_TRC_VERBOSE) { 1049 if (*name == '/') 1050 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH), 1051 name, MSG_ORIG(MSG_STR_EMPTY), 1052 MSG_ORIG(MSG_STR_EMPTY)); 1053 else 1054 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV), 1055 name, NAME(nlmp), 1056 MSG_ORIG(MSG_STR_EMPTY), 1057 MSG_ORIG(MSG_STR_EMPTY)); 1058 } 1059 return (nlmp); 1060 } 1061 } 1062 return ((Rt_map *)0); 1063 } 1064 1065 /* 1066 * Generate any error messages indicating a file could not be found. When 1067 * preloading or auditing a secure application, it can be a little more helpful 1068 * to indicate that a search of secure directories has failed, so adjust the 1069 * messages accordingly. 1070 */ 1071 void 1072 file_notfound(Lm_list *lml, const char *name, Rt_map *clmp, uint_t flags, 1073 Rej_desc * rej) 1074 { 1075 int secure = 0; 1076 1077 if ((rtld_flags & RT_FL_SECURE) && 1078 (flags & (FLG_RT_PRELOAD | FLG_RT_AUDIT))) 1079 secure++; 1080 1081 if (lml->lm_flags & LML_FLG_TRC_ENABLE) { 1082 /* 1083 * Under ldd(1), auxiliary filtees that can't be loaded are 1084 * ignored, unless verbose errors are requested. 1085 */ 1086 if ((rtld_flags & RT_FL_SILENCERR) && 1087 ((lml->lm_flags & LML_FLG_TRC_VERBOSE) == 0)) 1088 return; 1089 1090 if (secure) 1091 trace_so(clmp, rej, name, 0, 0, 1092 MSG_INTL(MSG_LDD_SEC_NFOUND)); 1093 else 1094 trace_so(clmp, rej, name, 0, 0, 1095 MSG_INTL(MSG_LDD_FIL_NFOUND)); 1096 return; 1097 } 1098 1099 if (rej->rej_type) { 1100 eprintf(ERR_FATAL, MSG_INTL(err_reject[rej->rej_type]), 1101 rej->rej_name ? rej->rej_name : MSG_INTL(MSG_STR_UNKNOWN), 1102 conv_reject_str(rej)); 1103 return; 1104 } 1105 1106 if (secure) 1107 eprintf(ERR_FATAL, MSG_INTL(MSG_SEC_OPEN), name); 1108 else 1109 eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), name, 1110 strerror(ENOENT)); 1111 } 1112 1113 static int 1114 file_open(int err, Lm_list *lml, const char *oname, const char *nname, 1115 Rt_map *clmp, uint_t flags, Fdesc * fdesc, Rej_desc *rej) 1116 { 1117 struct stat status; 1118 Rt_map *nlmp; 1119 1120 fdesc->fd_oname = oname; 1121 1122 if ((err == 0) && (fdesc->fd_flags & FLG_FD_ALTER)) 1123 DBG_CALL(Dbg_file_config_obj(oname, 0, nname)); 1124 1125 /* 1126 * If we're dealing with a full pathname, determine whether this 1127 * pathname is already known. Other pathnames fall through to the 1128 * dev/inode check, as even though the pathname may look the same as 1129 * one previously used, the process may have changed directory. 1130 */ 1131 if ((err == 0) && (nname[0] == '/')) { 1132 if ((nlmp = fpavl_loaded(lml, nname, 1133 &(fdesc->fd_avlwhere))) != NULL) { 1134 fdesc->fd_nname = nname; 1135 fdesc->fd_lmp = nlmp; 1136 return (1); 1137 } 1138 } 1139 1140 if ((err == 0) && ((stat(nname, &status)) != -1)) { 1141 char path[PATH_MAX]; 1142 int fd, size, added; 1143 1144 /* 1145 * If this path has been constructed as part of expanding a 1146 * HWCAP directory, ignore any subdirectories. For any other 1147 * reference that expands to a directory, fall through to 1148 * contruct a meaningful rejection message. 1149 */ 1150 if ((flags & FLG_RT_HWCAP) && 1151 ((status.st_mode & S_IFMT) == S_IFDIR)) 1152 return (0); 1153 1154 /* 1155 * Resolve the filename and determine whether the resolved name 1156 * is already known. Typically, the previous fpavl_loaded() 1157 * will have caught this, as both NAME() and PATHNAME() for a 1158 * link-map are recorded in the FullNode AVL tree. However, 1159 * instances exist where a file can be replaced (loop-back 1160 * mounts, bfu, etc.), and reference is made to the original 1161 * file through a symbolic link. By checking the pathname here, 1162 * we don't fall through to the dev/inode check and conclude 1163 * that a new file should be loaded. 1164 */ 1165 if ((nname[0] == '/') && (rtld_flags & RT_FL_EXECNAME) && 1166 ((size = resolvepath(nname, path, (PATH_MAX - 1))) > 0)) { 1167 path[size] = '\0'; 1168 1169 if (strcmp(nname, path)) { 1170 if ((nlmp = fpavl_loaded(lml, path, 1171 &(fdesc->fd_avlwhere))) != NULL) { 1172 added = 0; 1173 1174 if (append_alias(nlmp, nname, 1175 &added) == 0) 1176 return (0); 1177 if (added) 1178 DBG_CALL(Dbg_file_skip(nname, 1179 NAME(nlmp))); 1180 fdesc->fd_nname = nname; 1181 fdesc->fd_lmp = nlmp; 1182 return (1); 1183 } 1184 1185 /* 1186 * If this pathname hasn't been loaded, save 1187 * the resolved pathname so that it doesn't 1188 * have to be recomputed as part of fullpath() 1189 * processing. 1190 */ 1191 if ((fdesc->fd_pname = strdup(path)) == 0) 1192 return (0); 1193 } else { 1194 /* 1195 * If the resolved name doesn't differ from the 1196 * original, save it without duplication. 1197 * Having fd_pname set indicates that no further 1198 * resolvepath processing is necessary. 1199 */ 1200 fdesc->fd_pname = nname; 1201 } 1202 } 1203 1204 if (nlmp = is_devinode_loaded(&status, lml, nname, flags)) { 1205 added = 0; 1206 1207 if (append_alias(nlmp, nname, &added) == 0) 1208 return (0); 1209 if (added) { 1210 if ((nname[0] == '/') && (fpavl_insert(lml, 1211 nlmp, nname, 0) == 0)) 1212 return (0); 1213 DBG_CALL(Dbg_file_skip(nname, NAME(nlmp))); 1214 } 1215 fdesc->fd_nname = nname; 1216 fdesc->fd_lmp = nlmp; 1217 return (1); 1218 } 1219 1220 if ((fd = open(nname, O_RDONLY, 0)) == -1) { 1221 /* 1222 * As the file must exist for the previous stat() to 1223 * have succeeded, record the error condition. 1224 */ 1225 rej->rej_type = SGS_REJ_STR; 1226 rej->rej_str = strerror(errno); 1227 } else { 1228 Fct *ftp; 1229 1230 if ((ftp = are_u_this(rej, fd, &status, nname)) != 0) { 1231 fdesc->fd_nname = nname; 1232 fdesc->fd_ftp = ftp; 1233 fdesc->fd_dev = status.st_dev; 1234 fdesc->fd_ino = status.st_ino; 1235 fdesc->fd_fd = fd; 1236 1237 /* 1238 * Trace that this open has succeeded. 1239 */ 1240 if (lml->lm_flags & LML_FLG_TRC_ENABLE) { 1241 trace_so(clmp, 0, oname, nname, 1242 (fdesc->fd_flags & FLG_FD_ALTER), 0); 1243 } 1244 return (1); 1245 } 1246 (void) close(fd); 1247 } 1248 1249 } else if (errno != ENOENT) { 1250 /* 1251 * If the open() failed for anything other than the file not 1252 * existing, record the error condition. 1253 */ 1254 rej->rej_type = SGS_REJ_STR; 1255 rej->rej_str = strerror(errno); 1256 } 1257 1258 /* 1259 * Indicate any rejection. 1260 */ 1261 if (rej->rej_type) { 1262 rej->rej_name = nname; 1263 rej->rej_flag = (fdesc->fd_flags & FLG_FD_ALTER); 1264 DBG_CALL(Dbg_file_rejected(rej)); 1265 } 1266 return (0); 1267 } 1268 1269 /* 1270 * Find a full pathname (it contains a "/"). 1271 */ 1272 int 1273 find_path(Lm_list *lml, const char *oname, Rt_map *clmp, uint_t flags, 1274 Fdesc * fdesc, Rej_desc *rej) 1275 { 1276 int err = 0; 1277 1278 /* 1279 * If directory configuration exists determine if this path is known. 1280 */ 1281 if (rtld_flags & RT_FL_DIRCFG) { 1282 Rtc_obj *obj; 1283 const char *aname; 1284 1285 if ((obj = elf_config_ent(oname, (Word)elf_hash(oname), 1286 0, &aname)) != 0) { 1287 /* 1288 * If the configuration file states that this path is a 1289 * directory, or the path is explicitly defined as 1290 * non-existent (ie. a unused platform specific 1291 * library), then go no further. 1292 */ 1293 if (obj->co_flags & RTC_OBJ_DIRENT) { 1294 err = EISDIR; 1295 } else if ((obj->co_flags & 1296 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == 1297 RTC_OBJ_NOEXIST) { 1298 err = ENOENT; 1299 } else if ((obj->co_flags & RTC_OBJ_ALTER) && 1300 (rtld_flags & RT_FL_OBJALT) && (lml == &lml_main)) { 1301 int ret; 1302 1303 fdesc->fd_flags |= FLG_FD_ALTER; 1304 /* 1305 * Attempt to open the alternative path. If 1306 * this fails, and the alternative is flagged 1307 * as optional, fall through to open the 1308 * original path. 1309 */ 1310 DBG_CALL(Dbg_libs_found(aname, FLG_FD_ALTER)); 1311 if (((ret = file_open(0, lml, oname, aname, 1312 clmp, flags, fdesc, rej)) != 0) || 1313 ((obj->co_flags & RTC_OBJ_OPTINAL) == 0)) 1314 return (ret); 1315 1316 fdesc->fd_flags &= ~FLG_FD_ALTER; 1317 } 1318 } 1319 } 1320 DBG_CALL(Dbg_libs_found(oname, 0)); 1321 return (file_open(err, lml, oname, oname, clmp, flags, fdesc, rej)); 1322 } 1323 1324 /* 1325 * Find a simple filename (it doesn't contain a "/"). 1326 */ 1327 static int 1328 _find_file(Lm_list *lml, const char *oname, const char *nname, Rt_map *clmp, 1329 uint_t flags, Fdesc * fdesc, Rej_desc *rej, Pnode * dir, int aflag) 1330 { 1331 DBG_CALL(Dbg_libs_found(nname, aflag)); 1332 if ((lml->lm_flags & LML_FLG_TRC_SEARCH) && 1333 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) { 1334 (void) printf(MSG_INTL(MSG_LDD_PTH_TRYING), nname, aflag ? 1335 MSG_INTL(MSG_LDD_FIL_ALTER) : MSG_ORIG(MSG_STR_EMPTY)); 1336 } 1337 1338 /* 1339 * If we're being audited tell the audit library of the file we're about 1340 * to go search for. The audit library may offer an alternative 1341 * dependency, or indicate that this dependency should be ignored. 1342 */ 1343 if ((lml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_OBJSEARCH) { 1344 char *aname = audit_objsearch(clmp, nname, dir->p_orig); 1345 1346 if (aname == 0) 1347 return (0); 1348 nname = aname; 1349 } 1350 return (file_open(0, lml, oname, nname, clmp, flags, fdesc, rej)); 1351 } 1352 1353 int 1354 find_file(Lm_list *lml, const char *oname, Rt_map *clmp, uint_t flags, 1355 Fdesc * fdesc, Rej_desc *rej, Pnode * dir, Word * strhash, size_t olen) 1356 { 1357 static Rtc_obj Obj = { 0 }; 1358 Rtc_obj * dobj; 1359 const char *nname = oname; 1360 1361 if (dir->p_name == 0) 1362 return (0); 1363 if (dir->p_info) { 1364 dobj = (Rtc_obj *)dir->p_info; 1365 if ((dobj->co_flags & 1366 (RTC_OBJ_NOEXIST | RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST) 1367 return (0); 1368 } else 1369 dobj = 0; 1370 1371 /* 1372 * If configuration information exists see if this directory/file 1373 * combination exists. 1374 */ 1375 if ((rtld_flags & RT_FL_DIRCFG) && 1376 ((dobj == 0) || (dobj->co_id != 0))) { 1377 Rtc_obj *fobj; 1378 const char *alt = 0; 1379 1380 /* 1381 * If this pnode has not yet been searched for in the 1382 * configuration file go find it. 1383 */ 1384 if (dobj == 0) { 1385 dobj = elf_config_ent(dir->p_name, 1386 (Word)elf_hash(dir->p_name), 0, 0); 1387 if (dobj == 0) 1388 dobj = &Obj; 1389 dir->p_info = (void *)dobj; 1390 1391 if ((dobj->co_flags & (RTC_OBJ_NOEXIST | 1392 RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST) 1393 return (0); 1394 } 1395 1396 /* 1397 * If we found a directory search for the file. 1398 */ 1399 if (dobj->co_id != 0) { 1400 if (*strhash == 0) 1401 *strhash = (Word)elf_hash(nname); 1402 fobj = elf_config_ent(nname, *strhash, 1403 dobj->co_id, &alt); 1404 1405 /* 1406 * If this object specifically does not exist, or the 1407 * object can't be found in a know-all-entries 1408 * directory, continue looking. If the object does 1409 * exist determine if an alternative object exists. 1410 */ 1411 if (fobj == 0) { 1412 if (dobj->co_flags & RTC_OBJ_ALLENTS) 1413 return (0); 1414 } else { 1415 if ((fobj->co_flags & (RTC_OBJ_NOEXIST | 1416 RTC_OBJ_ALTER)) == RTC_OBJ_NOEXIST) 1417 return (0); 1418 1419 if ((fobj->co_flags & RTC_OBJ_ALTER) && 1420 (rtld_flags & RT_FL_OBJALT) && 1421 (lml == &lml_main)) { 1422 int ret; 1423 1424 fdesc->fd_flags |= FLG_FD_ALTER; 1425 /* 1426 * Attempt to open the alternative path. 1427 * If this fails, and the alternative is 1428 * flagged as optional, fall through to 1429 * open the original path. 1430 */ 1431 ret = _find_file(lml, oname, alt, clmp, 1432 flags, fdesc, rej, dir, 1); 1433 if (ret || ((fobj->co_flags & 1434 RTC_OBJ_OPTINAL) == 0)) 1435 return (ret); 1436 1437 fdesc->fd_flags &= ~FLG_FD_ALTER; 1438 } 1439 } 1440 } 1441 } 1442 1443 /* 1444 * Protect ourselves from building an invalid pathname. 1445 */ 1446 if ((olen + dir->p_len + 1) >= PATH_MAX) { 1447 eprintf(ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), nname, 1448 strerror(ENAMETOOLONG)); 1449 return (0); 1450 } 1451 if ((nname = (LM_GET_SO(clmp)(dir->p_name, nname))) == 0) 1452 return (0); 1453 1454 return (_find_file(lml, oname, nname, clmp, flags, fdesc, rej, dir, 0)); 1455 } 1456 1457 /* 1458 * A unique file has been opened. Create a link-map to represent it, and 1459 * process the various names by which it can be referenced. 1460 */ 1461 static Rt_map * 1462 load_file(Lm_list *lml, Aliste lmco, Rt_map *clmp, Fdesc * fdesc) 1463 { 1464 const char *oname = fdesc->fd_oname; 1465 const char *nname = fdesc->fd_nname; 1466 Rt_map *nlmp; 1467 1468 /* 1469 * Typically we call fct_map_so() with the full pathname of the opened 1470 * file (nname) and the name that started the search (oname), thus for 1471 * a typical dependency on libc this would be /usr/lib/libc.so.1 and 1472 * libc.so.1 (DT_NEEDED). The original name is maintained on an ALIAS 1473 * list for comparison when bringing in new dependencies. If the user 1474 * specified name as a full path (from a dlopen() for example) then 1475 * there's no need to create an ALIAS. 1476 */ 1477 if (strcmp(oname, nname) == 0) 1478 oname = 0; 1479 1480 /* 1481 * A new file has been opened, now map it into the process. Close the 1482 * original file so as not to accumulate file descriptors. 1483 */ 1484 nlmp = ((fdesc->fd_ftp)->fct_map_so)(lml, lmco, nname, oname, 1485 fdesc->fd_fd); 1486 (void) close(fdesc->fd_fd); 1487 fdesc->fd_fd = 0; 1488 1489 if (nlmp == 0) 1490 return (0); 1491 1492 /* 1493 * Save the dev/inode information for later comparisons. 1494 */ 1495 STDEV(nlmp) = fdesc->fd_dev; 1496 STINO(nlmp) = fdesc->fd_ino; 1497 1498 /* 1499 * Insert the names of this link-map into the FullpathNode AVL tree. 1500 * Save both the NAME() and PATHNAME() is they differ. 1501 * 1502 * If this is an OBJECT file, don't insert it yet as this is only a 1503 * temporary link-map. During elf_obj_fini() the final link-map is 1504 * created, and its names will be inserted in the FullpathNode AVL 1505 * tree at that time. 1506 */ 1507 if ((FLAGS(nlmp) & FLG_RT_OBJECT) == 0) { 1508 /* 1509 * Update the objects full path information if necessary. 1510 */ 1511 if (FLAGS1(nlmp) & FL1_RT_RELATIVE) { 1512 (void) fullpath(nlmp, fdesc->fd_pname); 1513 fdesc->fd_pname = 0; 1514 } 1515 1516 if ((NAME(nlmp)[0] == '/') && (fpavl_insert(lml, nlmp, 1517 NAME(nlmp), fdesc->fd_avlwhere) == 0)) { 1518 remove_so(lml, nlmp); 1519 return (0); 1520 } 1521 if (((NAME(nlmp)[0] != '/') || 1522 (NAME(nlmp) != PATHNAME(nlmp))) && 1523 (fpavl_insert(lml, nlmp, PATHNAME(nlmp), 0) == 0)) { 1524 remove_so(lml, nlmp); 1525 return (0); 1526 } 1527 } 1528 1529 /* 1530 * If we're processing an alternative object reset the original name 1531 * for possible $ORIGIN processing. 1532 */ 1533 if (fdesc->fd_flags & FLG_FD_ALTER) { 1534 const char *odir; 1535 char *ndir; 1536 size_t olen; 1537 1538 FLAGS(nlmp) |= FLG_RT_ALTER; 1539 1540 /* 1541 * If we were given a pathname containing a slash then the 1542 * original name is still in oname. Otherwise the original 1543 * directory is in dir->p_name (which is all we need for 1544 * $ORIGIN). 1545 */ 1546 if (fdesc->fd_flags & FLG_FD_SLASH) { 1547 char *ofil; 1548 1549 odir = oname; 1550 ofil = strrchr(oname, '/'); 1551 olen = ofil - odir + 1; 1552 } else { 1553 odir = fdesc->fd_odir; 1554 olen = strlen(odir) + 1; 1555 } 1556 1557 if ((ndir = (char *)malloc(olen)) == 0) { 1558 remove_so(lml, nlmp); 1559 return (0); 1560 } 1561 (void) strncpy(ndir, odir, olen); 1562 ndir[--olen] = '\0'; 1563 1564 ORIGNAME(nlmp) = ndir; 1565 DIRSZ(nlmp) = olen; 1566 } 1567 1568 /* 1569 * If we're being audited tell the audit library of the file we've 1570 * just opened. Note, if the new link-map requires local auditing of 1571 * its dependencies we also register its opening. 1572 */ 1573 if (((lml->lm_tflags | FLAGS1(clmp) | FLAGS1(nlmp)) & 1574 LML_TFLG_AUD_MASK) && (((lml->lm_flags | LIST(clmp)->lm_flags) & 1575 LML_FLG_NOAUDIT) == 0)) { 1576 if (audit_objopen(clmp, nlmp) == 0) { 1577 remove_so(lml, nlmp); 1578 return (0); 1579 } 1580 } 1581 1582 /* 1583 * Report module loads to TLS module activity. 1584 */ 1585 if (nlmp) 1586 tls_modactivity(nlmp, TM_FLG_MODADD); 1587 1588 return (nlmp); 1589 } 1590 1591 /* 1592 * This function loads the named file and returns a pointer to its link map. 1593 * It is assumed that the caller has already checked that the file is not 1594 * already loaded before calling this function (refer is_so_loaded()). 1595 * Find and open the file, map it into memory, add it to the end of the list 1596 * of link maps and return a pointer to the new link map. Return 0 on error. 1597 */ 1598 static Rt_map * 1599 load_so(Lm_list *lml, Aliste lmco, const char *oname, Rt_map *clmp, 1600 uint_t flags, Fdesc *fdp, Rej_desc *rej) 1601 { 1602 char *name; 1603 uint_t slash = 0; 1604 size_t olen; 1605 Fdesc fdesc, _fdesc = { 0 }; 1606 Pnode *dir; 1607 Rt_map *nlmp; 1608 1609 /* 1610 * If the file is the run time linker then it's already loaded. 1611 */ 1612 if (interp && (strcmp(oname, NAME(lml_rtld.lm_head)) == 0)) 1613 return (lml_rtld.lm_head); 1614 1615 /* 1616 * If this isn't a hardware capabilites pathname, which is already a 1617 * full, duplicated pathname, determine whether the pathname contains 1618 * a slash, and if not determine the input filename (for max path 1619 * length verification). 1620 */ 1621 if ((flags & FLG_RT_HWCAP) == 0) { 1622 const char *str; 1623 1624 for (str = oname; *str; str++) { 1625 if (*str == '/') { 1626 slash++; 1627 break; 1628 } 1629 } 1630 if (slash == 0) 1631 olen = (str - oname) + 1; 1632 } 1633 1634 /* 1635 * If we are passed a 'null' link-map this means that this is the first 1636 * object to be loaded on this link-map list. In that case we set the 1637 * link-map to ld.so.1's link-map. 1638 * 1639 * This link-map is referenced to determine what lookup rules to use 1640 * when searching for files. By using ld.so.1's we are defaulting to 1641 * ELF look-up rules. 1642 * 1643 * Note: This case happens when loading the first object onto 1644 * the plt_tracing link-map. 1645 */ 1646 if (clmp == 0) 1647 clmp = lml_rtld.lm_head; 1648 1649 /* 1650 * If this path resulted from a $HWCAP specification, then the best 1651 * hardware capability object has already been establish, and is 1652 * available in the calling file descriptor. Perform some minor book- 1653 * keeping so that we can fall through into common code. 1654 */ 1655 if (flags & FLG_RT_HWCAP) { 1656 fdesc = *fdp; 1657 1658 /* 1659 * Restablish the Fmap structure to reflect this objects 1660 * original initial page mapping. Make sure any present Fmap 1661 * mapping is removed before overwriting the structure. 1662 */ 1663 if (fdesc.fd_lmp == 0) { 1664 #if defined(MAP_ALIGN) 1665 if (fmap->fm_maddr && 1666 ((fmap->fm_mflags & MAP_ALIGN) == 0)) 1667 #else 1668 if (fmap->fm_maddr) 1669 #endif 1670 (void) munmap(fmap->fm_maddr, fmap->fm_msize); 1671 *fmap = fdesc.fd_fmap; 1672 1673 /* 1674 * Obtain the avl index for this object. 1675 */ 1676 (void) fpavl_loaded(lml, fdesc.fd_nname, 1677 &(fdesc.fd_avlwhere)); 1678 } else { 1679 /* 1680 * If this object is already loaded, we're done. 1681 */ 1682 return (fdesc.fd_lmp); 1683 } 1684 1685 } else if (slash) { 1686 Rej_desc _rej = { 0 }; 1687 1688 fdesc = _fdesc; 1689 fdesc.fd_flags = FLG_FD_SLASH; 1690 1691 if (find_path(lml, oname, clmp, flags, &fdesc, &_rej) == 0) { 1692 rejection_inherit(rej, &_rej, &fdesc); 1693 return (0); 1694 } 1695 1696 /* 1697 * If this object is already loaded, we're done. 1698 */ 1699 if (fdesc.fd_lmp) 1700 return (fdesc.fd_lmp); 1701 1702 } else { 1703 /* 1704 * No '/' - for each directory on list, make a pathname using 1705 * that directory and filename and try to open that file. 1706 */ 1707 Pnode * dirlist = (Pnode *)0; 1708 Word strhash = 0; 1709 1710 DBG_CALL(Dbg_libs_find(oname)); 1711 1712 #if !defined(ISSOLOAD_BASENAME_DISABLED) 1713 if ((nlmp = is_so_loaded(lml, oname, 0))) 1714 return (nlmp); 1715 #endif 1716 /* 1717 * Make sure we clear the file descriptor new name in case the 1718 * following directory search doesn't provide any directories 1719 * (odd, but this can be forced with a -znodefaultlib test). 1720 */ 1721 fdesc = _fdesc; 1722 for (dir = get_next_dir(&dirlist, clmp, flags); dir; 1723 dir = get_next_dir(&dirlist, clmp, flags)) { 1724 Rej_desc _rej = { 0 }; 1725 1726 fdesc = _fdesc; 1727 1728 /* 1729 * Try and locate this file. Make sure to clean up 1730 * any rejection information should the file have 1731 * been found, but not appropriate. 1732 */ 1733 if (find_file(lml, oname, clmp, flags, &fdesc, &_rej, 1734 dir, &strhash, olen) == 0) { 1735 rejection_inherit(rej, &_rej, &fdesc); 1736 continue; 1737 } 1738 1739 /* 1740 * If this object is already loaded, we're done. 1741 */ 1742 if (fdesc.fd_lmp) 1743 return (fdesc.fd_lmp); 1744 1745 fdesc.fd_odir = dir->p_name; 1746 break; 1747 } 1748 1749 /* 1750 * If the file couldn't be loaded, do another comparison of 1751 * loaded files using just the basename. This catches folks 1752 * who may have loaded multiple full pathname files (possibly 1753 * from setxid applications) to satisfy dependency relationships 1754 * (i.e., a file might have a dependency on foo.so.1 which has 1755 * already been opened using its full pathname). 1756 */ 1757 if (fdesc.fd_nname == 0) 1758 return (is_so_loaded(lml, oname, 1)); 1759 } 1760 1761 /* 1762 * Duplicate the file name so that NAME() is available in core files. 1763 * Note, that hardware capability names are already duplicated, but 1764 * they get duplicated once more to insure consistent cleanup in the 1765 * event of an error condition. 1766 */ 1767 if ((name = strdup(fdesc.fd_nname)) == 0) { 1768 (void) close(fdesc.fd_fd); 1769 return (0); 1770 } 1771 if (fdesc.fd_nname == fdesc.fd_pname) 1772 fdesc.fd_nname = fdesc.fd_pname = name; 1773 else 1774 fdesc.fd_nname = name; 1775 1776 /* 1777 * Finish mapping the file and return the link-map descriptor. Note, 1778 * if this request originated from a HWCAP request, re-establish the 1779 * fdesc information. For single paged objects, such as filters, the 1780 * original mapping may have been sufficient to capture the file, thus 1781 * this mapping needs to be reset to insure it doesn't mistakenly get 1782 * unmapped as part of HWCAP cleanup. 1783 */ 1784 nlmp = load_file(lml, lmco, clmp, &fdesc); 1785 1786 if (flags & FLG_RT_HWCAP) { 1787 fdp->fd_fmap.fm_maddr = fmap->fm_maddr; 1788 fdp->fd_fmap.fm_mflags = fmap->fm_mflags; 1789 fdp->fd_pname = fdesc.fd_pname; 1790 fdp->fd_fd = fdesc.fd_fd; 1791 } 1792 1793 return (nlmp); 1794 } 1795 1796 /* 1797 * Trace an attempt to load an object. 1798 */ 1799 const char * 1800 load_trace(Lm_list *lml, const char *name, Rt_map *clmp) 1801 { 1802 /* 1803 * First generate any ldd(1) diagnostics. 1804 */ 1805 if ((lml->lm_flags & (LML_FLG_TRC_VERBOSE | LML_FLG_TRC_SEARCH)) && 1806 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) 1807 (void) printf(MSG_INTL(MSG_LDD_FIL_FIND), name, NAME(clmp)); 1808 1809 /* 1810 * If we're being audited tell the audit library of the file we're 1811 * about to go search for. 1812 */ 1813 if (((lml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_ACTIVITY) && 1814 (lml == LIST(clmp))) 1815 audit_activity(clmp, LA_ACT_ADD); 1816 1817 if ((lml->lm_tflags | FLAGS1(clmp)) & LML_TFLG_AUD_OBJSEARCH) { 1818 char *_name; 1819 1820 /* 1821 * The auditor can indicate that this object should be ignored. 1822 */ 1823 if ((_name = audit_objsearch(clmp, name, LA_SER_ORIG)) == 0) { 1824 eprintf(ERR_FATAL, MSG_INTL(MSG_GEN_AUDITERM), name); 1825 return (0); 1826 } 1827 1828 /* 1829 * The auditor can provide an alternative name. 1830 */ 1831 if (_name != name) { 1832 free((void *)name); 1833 name = strdup(_name); 1834 } 1835 } 1836 return (name); 1837 } 1838 1839 /* 1840 * Having loaded an object and created a link-map to describe it, finish 1841 * processing this stage, including verifying any versioning requirements, 1842 * updating the objects mode, creating a handle if necessary, and adding this 1843 * object to existing handles if required. 1844 */ 1845 int 1846 load_finish(Lm_list *lml, const char *name, Rt_map * clmp, int nmode, 1847 uint_t flags, Grp_hdl ** hdl, Rt_map * nlmp) 1848 { 1849 Aliste off; 1850 Grp_hdl *ghp, **ghpp; 1851 int promote; 1852 1853 /* 1854 * If this dependency is associated with a required version insure that 1855 * the version is present in the loaded file. 1856 */ 1857 if (((rtld_flags & RT_FL_NOVERSION) == 0) && 1858 (FCT(clmp) == &elf_fct) && VERNEED(clmp) && 1859 (LM_VERIFY_VERS(clmp)(name, clmp, nlmp) == 0)) 1860 return (0); 1861 1862 /* 1863 * If this object has indicated that it should be isolated as a group 1864 * (DT_FLAGS_1 contains DF_1_GROUP - object was built with -B group), 1865 * or if the callers direct bindings indicate it should be isolated as 1866 * a group (DYNINFO flags contains FLG_DI_GROUP - dependency followed 1867 * -zgroupperm), establish the appropriate mode. 1868 * 1869 * The intent of an object defining itself as a group is to isolate the 1870 * relocation of the group within its own members, however, unless 1871 * opened through dlopen(), in which case we assume dlsym() will be used 1872 * to located symbols in the new object, we still need to associate it 1873 * with the caller for it to be bound with. This is equivalent to a 1874 * dlopen(RTLD_GROUP) and dlsym() using the returned handle. 1875 */ 1876 if ((FLAGS(nlmp) | flags) & FLG_RT_SETGROUP) { 1877 nmode &= ~RTLD_WORLD; 1878 nmode |= RTLD_GROUP; 1879 1880 /* 1881 * If the object wasn't explicitly dlopen()'ed associate it with 1882 * the parent. 1883 */ 1884 if (flags != FLG_RT_HANDLE) 1885 nmode |= RTLD_PARENT; 1886 } 1887 1888 /* 1889 * Establish new mode and flags. 1890 * 1891 * For patch backward compatibility, the following use of update_mode() 1892 * is disabled. 1893 */ 1894 #ifdef SIEBEL_DISABLE 1895 if (rtld_flags & RT_FL_DISFIX_1) 1896 promote = MODE(nlmp) |= 1897 (nmode & ~(RTLD_PARENT | RTLD_NOLOAD | RTLD_FIRST)); 1898 else 1899 #endif 1900 promote = update_mode(nlmp, MODE(nlmp), nmode); 1901 1902 FLAGS(nlmp) |= flags; 1903 1904 /* 1905 * If we've been asked to establish a handle create one for this object. 1906 * Or, if this object has already been analyzed, but this reference 1907 * requires that the mode of the object be promoted, also create a 1908 * handle to propagate the new modes to all this objects dependencies. 1909 */ 1910 if (((FLAGS(nlmp) | flags) & FLG_RT_HANDLE) || (promote && 1911 (FLAGS(nlmp) & FLG_RT_ANALYZED))) { 1912 uint_t oflags, hflags = 0; 1913 1914 if (nmode & RTLD_PARENT) 1915 hflags |= GPH_PARENT; 1916 if (nmode & RTLD_FIRST) 1917 hflags |= GPH_FIRST; 1918 1919 /* 1920 * Now that a handle is being created, remove this state from 1921 * the object so that it doesn't mistakenly get inherited by 1922 * a dependency. 1923 */ 1924 oflags = FLAGS(nlmp); 1925 FLAGS(nlmp) &= ~FLG_RT_HANDLE; 1926 1927 if ((ghp = hdl_create(lml, nlmp, clmp, hflags)) == 0) 1928 return (0); 1929 1930 /* 1931 * Add any dependencies that are already loaded, to the handle. 1932 */ 1933 if (hdl_initialize(ghp, nlmp, clmp, nmode, promote) == 0) 1934 return (0); 1935 1936 if (hdl) 1937 *hdl = ghp; 1938 1939 /* 1940 * If we were asked to create a handle, we're done. Otherwise, 1941 * remove the handle. The handle was only used to establish this 1942 * objects dependencies and promote any modes, so we don't want 1943 * this handle preventing the objects deletion. Fall through to 1944 * carry out any group processing. 1945 */ 1946 if ((oflags | flags) & FLG_RT_HANDLE) 1947 return (1); 1948 1949 free_hdl(ghp); 1950 } 1951 1952 /* 1953 * If the caller isn't part of a group we're done. 1954 */ 1955 if (GROUPS(clmp) == 0) 1956 return (1); 1957 1958 /* 1959 * Determine if our caller is already associated with a handle, if so 1960 * we need to add this object to any handles that already exist. 1961 * Traverse the list of groups our caller is a member of and add this 1962 * new link-map to those groups. 1963 */ 1964 DBG_CALL(Dbg_file_hdl_title(DBG_DEP_ADD)); 1965 for (ALIST_TRAVERSE(GROUPS(clmp), off, ghpp)) { 1966 Aliste off1; 1967 Grp_desc *gdp; 1968 int exist; 1969 Rt_map **lmpp; 1970 Alist *lmalp = 0; 1971 1972 ghp = *ghpp; 1973 1974 /* 1975 * If the caller doesn't indicate that its dependencies should 1976 * be added to a handle, ignore it. This case identifies a 1977 * parent of a dlopen(RTLD_PARENT) request. 1978 */ 1979 for (ALIST_TRAVERSE(ghp->gh_depends, off1, gdp)) { 1980 if (gdp->gd_depend == clmp) 1981 break; 1982 } 1983 if ((gdp->gd_flags & GPD_ADDEPS) == 0) 1984 continue; 1985 1986 if ((exist = hdl_add(ghp, nlmp, 1987 (GPD_AVAIL | GPD_ADDEPS))) == 0) 1988 return (0); 1989 1990 /* 1991 * If this member already exists then its dependencies will 1992 * have already been processed. 1993 */ 1994 if (exist == ALE_EXISTS) 1995 continue; 1996 1997 /* 1998 * If the object we've added has just been opened, it will not 1999 * yet have been processed for its dependencies, these will be 2000 * added on later calls to load_one(). If it doesn't have any 2001 * dependencies we're also done. 2002 */ 2003 if (((FLAGS(nlmp) & FLG_RT_ANALYZED) == 0) || 2004 (DEPENDS(nlmp) == 0)) 2005 continue; 2006 2007 /* 2008 * Otherwise, this object exists and has dependencies, so add 2009 * all of its dependencies to the handle were operating on. 2010 */ 2011 if (alist_append(&lmalp, &nlmp, sizeof (Rt_map *), 2012 AL_CNT_DEPCLCT) == 0) 2013 return (0); 2014 2015 for (ALIST_TRAVERSE(lmalp, off1, lmpp)) { 2016 Rt_map * dlmp1 = *lmpp; 2017 Aliste off2; 2018 Bnd_desc ** bdpp; 2019 2020 /* 2021 * Add any dependencies of this dependency to the 2022 * dynamic dependency list so they can be further 2023 * processed. 2024 */ 2025 for (ALIST_TRAVERSE(DEPENDS(dlmp1), off2, bdpp)) { 2026 Bnd_desc * bdp = *bdpp; 2027 Rt_map * dlmp2 = bdp->b_depend; 2028 2029 if ((bdp->b_flags & BND_NEEDED) == 0) 2030 continue; 2031 2032 if (alist_test(&lmalp, dlmp2, sizeof (Rt_map *), 2033 AL_CNT_DEPCLCT) == 0) { 2034 free(lmalp); 2035 return (0); 2036 } 2037 } 2038 2039 if (nlmp == dlmp1) 2040 continue; 2041 2042 if ((exist = hdl_add(ghp, dlmp1, 2043 (GPD_AVAIL | GPD_ADDEPS))) != 0) { 2044 if (exist == ALE_CREATE) 2045 (void) update_mode(dlmp1, MODE(dlmp1), 2046 nmode); 2047 continue; 2048 } 2049 free(lmalp); 2050 return (0); 2051 } 2052 free(lmalp); 2053 } 2054 return (1); 2055 } 2056 2057 /* 2058 * The central routine for loading shared objects. Insures ldd() diagnostics, 2059 * handles and any other related additions are all done in one place. 2060 */ 2061 Rt_map * 2062 load_path(Lm_list *lml, Aliste lmco, const char *name, Rt_map *clmp, 2063 int nmode, uint_t flags, Grp_hdl ** hdl, Fdesc *fdp, Rej_desc *rej) 2064 { 2065 Rt_map *nlmp; 2066 2067 if ((nmode & RTLD_NOLOAD) == 0) { 2068 /* 2069 * If this isn't a noload request attempt to load the file. 2070 */ 2071 if ((name = load_trace(lml, name, clmp)) == 0) 2072 return (0); 2073 2074 if ((nlmp = load_so(lml, lmco, name, clmp, flags, 2075 fdp, rej)) == 0) 2076 return (0); 2077 2078 /* 2079 * If we've loaded a library which identifies itself as not 2080 * being dlopen()'able catch it here. Let non-dlopen()'able 2081 * objects through under RTLD_CONFGEN as they're only being 2082 * mapped to be dldump()'ed. 2083 */ 2084 if ((rtld_flags & RT_FL_APPLIC) && ((FLAGS(nlmp) & 2085 (FLG_RT_NOOPEN | FLG_RT_RELOCED)) == FLG_RT_NOOPEN) && 2086 ((nmode & RTLD_CONFGEN) == 0)) { 2087 Rej_desc _rej = { 0 }; 2088 2089 _rej.rej_name = name; 2090 _rej.rej_type = SGS_REJ_STR; 2091 _rej.rej_str = MSG_INTL(MSG_GEN_NOOPEN); 2092 DBG_CALL(Dbg_file_rejected(&_rej)); 2093 rejection_inherit(rej, &_rej, fdp); 2094 remove_so(lml, nlmp); 2095 return (0); 2096 } 2097 } else { 2098 /* 2099 * If it's a NOLOAD request - check to see if the object 2100 * has already been loaded. 2101 */ 2102 /* LINTED */ 2103 if ((nlmp = is_so_loaded(lml, name, 0)) || 2104 (nlmp = is_so_loaded(lml, name, 1))) { 2105 if ((lml->lm_flags & LML_FLG_TRC_VERBOSE) && 2106 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) { 2107 (void) printf(MSG_INTL(MSG_LDD_FIL_FIND), name, 2108 NAME(clmp)); 2109 if (*name == '/') 2110 (void) printf(MSG_ORIG(MSG_LDD_FIL_PATH), 2111 name, MSG_ORIG(MSG_STR_EMPTY), 2112 MSG_ORIG(MSG_STR_EMPTY)); 2113 else 2114 (void) printf(MSG_ORIG(MSG_LDD_FIL_EQUIV), 2115 name, NAME(nlmp), 2116 MSG_ORIG(MSG_STR_EMPTY), 2117 MSG_ORIG(MSG_STR_EMPTY)); 2118 } 2119 } else { 2120 Rej_desc _rej = { 0 }; 2121 2122 _rej.rej_name = name; 2123 _rej.rej_type = SGS_REJ_STR; 2124 _rej.rej_str = strerror(ENOENT); 2125 DBG_CALL(Dbg_file_rejected(&_rej)); 2126 rejection_inherit(rej, &_rej, 0); 2127 return (0); 2128 } 2129 } 2130 2131 /* 2132 * Finish processing this loaded object. 2133 */ 2134 if (load_finish(lml, name, clmp, nmode, flags, hdl, nlmp) != 0) 2135 return (nlmp); 2136 2137 /* 2138 * If this object has already been analyzed, then it is in use, so even 2139 * though this operation has failed, it should not be torn down. 2140 */ 2141 if ((FLAGS(nlmp) & FLG_RT_ANALYZED) == 0) 2142 remove_so(lml, nlmp); 2143 2144 return (0); 2145 } 2146 2147 /* 2148 * Load one object from a possible list of objects. Typically, for requests 2149 * such as NEEDED's, only one object is specified. However, this object could 2150 * be specified using $ISALIST or $HWCAP, in which case only the first object 2151 * that can be loaded is used (ie. the best). 2152 */ 2153 Rt_map * 2154 load_one(Lm_list *lml, Aliste lmco, Pnode *pnp, Rt_map *clmp, int mode, 2155 uint_t flags, Grp_hdl ** hdl) 2156 { 2157 Rej_desc rej = { 0 }; 2158 Pnode *tpnp; 2159 const char *name; 2160 Rt_map *tlmp; 2161 2162 for (tpnp = pnp; tpnp && tpnp->p_name; tpnp = tpnp->p_next) { 2163 /* 2164 * A Hardware capabilities requirement can itself expand into 2165 * a number of candidates. 2166 */ 2167 if (tpnp->p_orig & PN_TKN_HWCAP) { 2168 if ((tlmp = load_hwcap(lml, lmco, tpnp->p_name, clmp, 2169 mode, (flags | FLG_RT_HWCAP), hdl, &rej)) != 0) { 2170 remove_rej(&rej); 2171 return (tlmp); 2172 } 2173 } else { 2174 if ((tlmp = load_path(lml, lmco, tpnp->p_name, clmp, 2175 mode, flags, hdl, 0, &rej)) != 0) { 2176 remove_rej(&rej); 2177 return (tlmp); 2178 } 2179 } 2180 } 2181 2182 /* 2183 * If this pathname originated from an expanded token, use the original 2184 * for any diagnostic output. 2185 */ 2186 if ((name = pnp->p_oname) == 0) 2187 name = pnp->p_name; 2188 2189 file_notfound(lml, name, clmp, flags, &rej); 2190 remove_rej(&rej); 2191 return (0); 2192 } 2193 2194 /* 2195 * While processing direct or group bindings, determine whether the object to 2196 * which we've bound can be interposed upon. In this context, copy relocations 2197 * are a form of interposition. 2198 */ 2199 static Sym * 2200 lookup_sym_interpose(Slookup *slp, Rt_map **dlmp, uint_t *binfo, Lm_list * lml, 2201 Sym * sym) 2202 { 2203 Rt_map * lmp; 2204 Slookup sl; 2205 2206 /* 2207 * If we've bound to a copy relocation definition then we need to assign 2208 * this binding to the original copy reference. Fabricate an inter- 2209 * position diagnostic, as this is a legitimate form of interposition. 2210 */ 2211 if (FLAGS1(*dlmp) & FL1_RT_COPYTOOK) { 2212 Rel_copy *rcp; 2213 Aliste off; 2214 2215 for (ALIST_TRAVERSE(COPY(*dlmp), off, rcp)) { 2216 if ((sym == rcp->r_dsym) || (sym->st_value && 2217 (sym->st_value == rcp->r_dsym->st_value))) { 2218 *dlmp = rcp->r_rlmp; 2219 *binfo |= 2220 (DBG_BINFO_INTERPOSE | DBG_BINFO_COPYREF); 2221 return (rcp->r_rsym); 2222 } 2223 } 2224 } 2225 2226 if ((lml->lm_flags & LML_FLG_INTRPOSE) == 0) 2227 return ((Sym *)0); 2228 2229 /* 2230 * Traverse the list of known interposers to determine whether any 2231 * offer the same symbol. Note, the head of the link-map could be 2232 * identified as an interposer. If it is, make sure we only look for 2233 * symbol definitions. Otherwise, skip the head of the link-map, so 2234 * that we don't bind to any .plt references, or copy-relocations 2235 * unintentionally. 2236 */ 2237 lmp = lml->lm_head; 2238 sl = *slp; 2239 if (((FLAGS(lmp) & FLG_RT_INTRPOSE) == 0) || (sl.sl_flags & LKUP_COPY)) 2240 lmp = (Rt_map *)NEXT(lmp); 2241 else 2242 sl.sl_flags &= ~LKUP_SPEC; 2243 2244 for (; lmp; lmp = (Rt_map *)NEXT(lmp)) { 2245 if (FLAGS(lmp) & FLG_RT_DELETE) 2246 continue; 2247 if ((FLAGS(lmp) & FLG_RT_INTRPOSE) == 0) 2248 break; 2249 2250 if (callable(lmp, *dlmp, 0)) { 2251 sl.sl_imap = lmp; 2252 if (sym = SYMINTP(lmp)(&sl, dlmp, binfo)) { 2253 *binfo |= DBG_BINFO_INTERPOSE; 2254 return (sym); 2255 } 2256 } 2257 } 2258 return ((Sym *)0); 2259 } 2260 2261 /* 2262 * If an object specifies direct bindings (it contains a syminfo structure 2263 * describing where each binding was established during link-editing, and the 2264 * object was built -Bdirect), then look for the symbol in the specific object. 2265 */ 2266 static Sym * 2267 lookup_sym_direct(Slookup *slp, Rt_map **dlmp, uint_t *binfo, Syminfo *sip, 2268 Rt_map *lmp) 2269 { 2270 Rt_map *clmp = slp->sl_cmap; 2271 Sym *sym; 2272 Slookup sl; 2273 2274 /* 2275 * If a direct binding resolves to the definition of a copy relocated 2276 * variable, it must be redirected to the copy (in the executable) that 2277 * will eventually be made. Typically, this redirection occurs in 2278 * lookup_sym_interpose(). But, there's an edge condition. If a 2279 * directly bound executable contains pic code, there may be a 2280 * reference to a definition that will eventually have a copy made. 2281 * However, this copy relocation may not yet have occurred, because 2282 * the relocation making this reference comes before the relocation 2283 * that will create the copy. 2284 * Under direct bindings, the syminfo indicates that a copy will be 2285 * taken (SYMINFO_FLG_COPY). This can only be set in an executable. 2286 * Thus, the caller must be the executable, so bind to the destination 2287 * of the copy within the executable. 2288 */ 2289 if (((slp->sl_flags & LKUP_COPY) == 0) && 2290 (sip->si_flags & SYMINFO_FLG_COPY)) { 2291 2292 slp->sl_imap = LIST(clmp)->lm_head; 2293 if (sym = SYMINTP(clmp)(slp, dlmp, binfo)) 2294 *binfo |= (DBG_BINFO_DIRECT | DBG_BINFO_COPYREF); 2295 return (sym); 2296 } 2297 2298 /* 2299 * If we need to direct bind to our parent start looking in each caller 2300 * link map. 2301 */ 2302 sl = *slp; 2303 sl.sl_flags |= LKUP_DIRECT; 2304 sym = 0; 2305 2306 if (sip->si_boundto == SYMINFO_BT_PARENT) { 2307 Aliste off; 2308 Bnd_desc ** bdpp; 2309 2310 for (ALIST_TRAVERSE(CALLERS(clmp), off, bdpp)) { 2311 sl.sl_imap = lmp = (*bdpp)->b_caller; 2312 if ((sym = SYMINTP(lmp)(&sl, dlmp, binfo)) != 0) 2313 break; 2314 } 2315 } else { 2316 /* 2317 * If we need to direct bind to anything else look in the 2318 * link map associated with this symbol reference. 2319 */ 2320 if (sip->si_boundto == SYMINFO_BT_SELF) 2321 sl.sl_imap = lmp = clmp; 2322 else 2323 sl.sl_imap = lmp; 2324 2325 if (lmp) 2326 sym = SYMINTP(lmp)(&sl, dlmp, binfo); 2327 } 2328 2329 if (sym) 2330 *binfo |= DBG_BINFO_DIRECT; 2331 2332 /* 2333 * If we've bound to an object, determine whether that object can be 2334 * interposed upon for this symbol. 2335 */ 2336 if (sym && (LIST(*dlmp)->lm_head != *dlmp) && 2337 (LIST(*dlmp) == LIST(clmp))) { 2338 Sym * isym; 2339 2340 if ((isym = lookup_sym_interpose(slp, dlmp, binfo, 2341 LIST(*dlmp), sym)) != 0) 2342 return (isym); 2343 } 2344 2345 return (sym); 2346 } 2347 2348 static Sym * 2349 _lookup_sym(Rt_map *ilmp, Slookup *slp, Rt_map **dlmp, uint_t *binfo, 2350 Aliste off) 2351 { 2352 Rt_map *lmp; 2353 2354 /* 2355 * Copy relocations should start their search after the head of the 2356 * main link-map control list. 2357 */ 2358 if ((off == ALO_DATA) && (slp->sl_flags & LKUP_COPY) && ilmp) 2359 lmp = (Rt_map *)NEXT(ilmp); 2360 else 2361 lmp = ilmp; 2362 2363 for (; lmp; lmp = (Rt_map *)NEXT(lmp)) { 2364 if (callable(slp->sl_cmap, lmp, 0)) { 2365 Sym *sym; 2366 2367 slp->sl_imap = lmp; 2368 if ((sym = SYMINTP(lmp)(slp, dlmp, binfo)) != 0) 2369 return (sym); 2370 } 2371 } 2372 return (0); 2373 } 2374 2375 static Sym * 2376 _lazy_find_sym(Rt_map *ilmp, Slookup *slp, Rt_map **dlmp, uint_t *binfo) 2377 { 2378 Rt_map *lmp; 2379 2380 for (lmp = ilmp; lmp; lmp = (Rt_map *)NEXT(lmp)) { 2381 if (LAZY(lmp) == 0) 2382 continue; 2383 if (callable(slp->sl_cmap, lmp, 0)) { 2384 Sym *sym; 2385 2386 slp->sl_imap = lmp; 2387 if ((sym = elf_lazy_find_sym(slp, dlmp, binfo)) != 0) 2388 return (sym); 2389 } 2390 } 2391 return (0); 2392 } 2393 2394 /* 2395 * Symbol lookup routine. Takes an ELF symbol name, and a list of link maps to 2396 * search (if the flag indicates LKUP_FIRST only the first link map of the list 2397 * is searched ie. we've been called from dlsym()). 2398 * If successful, return a pointer to the symbol table entry and a pointer to 2399 * the link map of the enclosing object. Else return a null pointer. 2400 * 2401 * To improve elf performance, we first compute the elf hash value and pass 2402 * it to each find_sym() routine. The elf function will use this value to 2403 * locate the symbol, the a.out function will simply ignore it. 2404 */ 2405 Sym * 2406 lookup_sym(Slookup *slp, Rt_map **dlmp, uint_t *binfo) 2407 { 2408 const char *name = slp->sl_name; 2409 Rt_map *clmp = slp->sl_cmap; 2410 Rt_map *ilmp = slp->sl_imap, *lmp; 2411 uint_t flags = slp->sl_flags; 2412 ulong_t rsymndx; 2413 Sym *sym = 0; 2414 Syminfo *sip; 2415 Slookup sl; 2416 2417 if (slp->sl_hash == 0) 2418 slp->sl_hash = elf_hash(name); 2419 *binfo = 0; 2420 2421 /* 2422 * Search the initial link map for the required symbol (this category is 2423 * selected by dlsym(), where individual link maps are searched for a 2424 * required symbol. Therefore, we know we have permission to look at 2425 * the link map). 2426 */ 2427 if (flags & LKUP_FIRST) 2428 return (SYMINTP(ilmp)(slp, dlmp, binfo)); 2429 2430 /* 2431 * Determine whether this lookup can be satisfied by an objects direct, 2432 * or lazy binding information. This is triggered by a relocation from 2433 * the object (hence rsymndx is set). 2434 */ 2435 if (((rsymndx = slp->sl_rsymndx) != 0) && 2436 ((sip = SYMINFO(clmp)) != 0)) { 2437 2438 /* 2439 * Find the corresponding Syminfo entry for the original 2440 * referencing symbol. 2441 */ 2442 /* LINTED */ 2443 sip = (Syminfo *)((char *)sip + (rsymndx * SYMINENT(clmp))); 2444 2445 /* 2446 * If the symbol information indicates a direct binding, 2447 * determine the link map that is required to satisfy the 2448 * binding. Note, if the dependency can not be found, but a 2449 * direct binding isn't required, we will still fall through 2450 * to perform any default symbol search. 2451 */ 2452 if (sip->si_flags & SYMINFO_FLG_DIRECT) { 2453 uint_t bound = sip->si_boundto; 2454 2455 lmp = 0; 2456 if (bound < SYMINFO_BT_LOWRESERVE) 2457 lmp = elf_lazy_load(clmp, bound, name); 2458 2459 /* 2460 * If direct bindings have been disabled, and this isn't 2461 * a translator, skip any direct binding now that we've 2462 * insured the resolving object has been loaded. 2463 * 2464 * If we need to direct bind to anything, we look in 2465 * ourselves, our parent, or in the link map we've just 2466 * loaded. Otherwise, even though we may have lazily 2467 * loaded an object we still continue to search for 2468 * symbols from the head of the link map list. 2469 */ 2470 if (((FLAGS(clmp) & FLG_RT_TRANS) || 2471 (!(LIST(clmp)->lm_tflags & LML_TFLG_NODIRECT))) && 2472 ((FLAGS(clmp) & FLG_RT_DIRECT) || 2473 (sip->si_flags & SYMINFO_FLG_DIRECTBIND))) { 2474 sym = lookup_sym_direct(slp, dlmp, binfo, 2475 sip, lmp); 2476 2477 /* 2478 * If this direct binding has been disabled 2479 * (presumably because the symbol definition has 2480 * been changed since the referring object was 2481 * built), fall back to a standard symbol 2482 * search. 2483 */ 2484 if ((*binfo & BINFO_DIRECTDIS) == 0) 2485 return (sym); 2486 } 2487 } 2488 } 2489 2490 sl = *slp; 2491 2492 /* 2493 * If the referencing object has the DF_SYMBOLIC flag set, look in the 2494 * referencing object for the symbol first. Failing that, fall back to 2495 * our generic search. 2496 */ 2497 if (FLAGS1(clmp) & FL1_RT_SYMBOLIC) { 2498 sl.sl_imap = clmp; 2499 if (sym = SYMINTP(clmp)(&sl, dlmp, binfo)) 2500 return (sym); 2501 } 2502 2503 /* 2504 * If this lookup originates from a standard relocation, then traverse 2505 * all link-map lists inspecting any object that is available to this 2506 * caller. Otherwise, traverse the link-map list associate with the 2507 * caller. 2508 */ 2509 if (flags & LKUP_ALLCNTLIST) { 2510 Aliste off; 2511 Lm_cntl *lmc; 2512 2513 sym = 0; 2514 2515 for (ALIST_TRAVERSE(LIST(clmp)->lm_lists, off, lmc)) { 2516 if ((sym = _lookup_sym(lmc->lc_head, &sl, dlmp, 2517 binfo, off)) != 0) 2518 break; 2519 } 2520 } else 2521 sym = _lookup_sym(ilmp, &sl, dlmp, binfo, ALO_DATA); 2522 2523 /* 2524 * To allow transitioning into a world of lazy loading dependencies see 2525 * if this link map contains objects that have lazy dependencies still 2526 * outstanding. If so, and we haven't been able to locate a non-weak 2527 * symbol reference, start bringing in any lazy dependencies to see if 2528 * the reference can be satisfied. Use of dlsym(RTLD_PROBE) sets the 2529 * LKUP_NOFALBACK flag, and this flag disables this fall back. 2530 */ 2531 if ((sym == 0) && ((sl.sl_flags & LKUP_NOFALBACK) == 0)) { 2532 if ((lmp = ilmp) == 0) 2533 lmp = LIST(clmp)->lm_head; 2534 if ((flags & LKUP_WEAK) || (LIST(lmp)->lm_lazy == 0)) 2535 return ((Sym *)0); 2536 2537 DBG_CALL(Dbg_syms_lazy_rescan(name)); 2538 2539 /* 2540 * If this request originated from a dlsym(RTLD_NEXT) then start 2541 * looking for dependencies from the caller, otherwise use the 2542 * initial link-map. 2543 */ 2544 if (flags & LKUP_NEXT) 2545 sym = _lazy_find_sym(clmp, &sl, dlmp, binfo); 2546 else { 2547 Aliste off; 2548 Lm_cntl *lmc; 2549 2550 for (ALIST_TRAVERSE(LIST(clmp)->lm_lists, off, lmc)) { 2551 sl.sl_flags |= LKUP_NOFALBACK; 2552 if ((sym = _lazy_find_sym(lmc->lc_head, &sl, 2553 dlmp, binfo)) != 0) 2554 break; 2555 } 2556 } 2557 } 2558 2559 /* 2560 * If the caller is restricted to a symbol search within its group, 2561 * determine if it is necessary to follow a binding from outside of 2562 * the group. 2563 */ 2564 if (sym && ((MODE(clmp) & (RTLD_GROUP | RTLD_WORLD)) == RTLD_GROUP)) { 2565 Sym * isym; 2566 2567 if ((isym = lookup_sym_interpose(slp, dlmp, binfo, LIST(*dlmp), 2568 sym)) != 0) 2569 return (isym); 2570 } 2571 return (sym); 2572 } 2573 2574 /* 2575 * Associate a binding descriptor with a caller and its dependency, or update 2576 * an existing descriptor. 2577 */ 2578 int 2579 bind_one(Rt_map * clmp, Rt_map * dlmp, uint_t flags) 2580 { 2581 Bnd_desc ** bdpp, * bdp; 2582 Aliste off; 2583 int found = ALE_CREATE; 2584 2585 /* 2586 * Determine whether a binding descriptor already exists between the 2587 * two objects. 2588 */ 2589 for (ALIST_TRAVERSE(DEPENDS(clmp), off, bdpp)) { 2590 bdp = *bdpp; 2591 2592 if (bdp->b_depend == dlmp) { 2593 found = ALE_EXISTS; 2594 break; 2595 } 2596 } 2597 2598 if (found == ALE_CREATE) { 2599 /* 2600 * Create a new binding descriptor. 2601 */ 2602 if ((bdp = malloc(sizeof (Bnd_desc))) == 0) 2603 return (0); 2604 2605 bdp->b_caller = clmp; 2606 bdp->b_depend = dlmp; 2607 bdp->b_flags = 0; 2608 2609 /* 2610 * Append the binding descriptor to the caller and the 2611 * dependency. 2612 */ 2613 if (alist_append(&DEPENDS(clmp), &bdp, 2614 sizeof (Bnd_desc *), AL_CNT_DEPENDS) == 0) 2615 return (0); 2616 2617 if (alist_append(&CALLERS(dlmp), &bdp, 2618 sizeof (Bnd_desc *), AL_CNT_CALLERS) == 0) 2619 return (0); 2620 } 2621 2622 if ((found == ALE_CREATE) || ((bdp->b_flags & flags) != flags)) { 2623 bdp->b_flags |= flags; 2624 2625 if (flags & BND_REFER) 2626 FLAGS1(dlmp) |= FL1_RT_USED; 2627 2628 DBG_CALL(Dbg_file_bind_entry(bdp)); 2629 } 2630 return (found); 2631 } 2632 2633 /* 2634 * Cleanup after relocation processing. 2635 */ 2636 int 2637 relocate_finish(Rt_map *lmp, Alist *bound, int textrel, int ret) 2638 { 2639 DBG_CALL(Dbg_reloc_run(NAME(lmp), 0, ret, DBG_REL_FINISH)); 2640 2641 /* 2642 * Establish bindings to all objects that have been bound to. 2643 */ 2644 if (bound) { 2645 Aliste off; 2646 Rt_map **lmpp; 2647 2648 if (ret) { 2649 for (ALIST_TRAVERSE(bound, off, lmpp)) { 2650 if (bind_one(lmp, *lmpp, BND_REFER) == 0) { 2651 ret = 0; 2652 break; 2653 } 2654 } 2655 } 2656 free(bound); 2657 } 2658 2659 /* 2660 * If we write enabled the text segment to perform these relocations 2661 * re-protect by disabling writes. 2662 */ 2663 if (textrel) 2664 (void) LM_SET_PROT(lmp)(lmp, 0); 2665 2666 return (ret); 2667 } 2668