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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Remove objects. Objects need removal from a process as part of: 29 * 30 * o a dlclose() request 31 * 32 * o tearing down a dlopen(), lazy-load, or filter hierarchy that failed to 33 * completely load 34 * 35 * Any other failure condition will result in process exit (in which case all 36 * we have to do is execute the fini's - tear down is unnecessary). 37 * 38 * Any removal of objects is therefore associated with a dlopen() handle. There 39 * is a small window between creation of the first dlopen() object and creating 40 * its handle (in which case remove_so() can get rid of the new link-map if 41 * necessary), but other than this all object removal is driven by inspecting 42 * the components of a handle. 43 * 44 * Things to note. The creation of a link-map, and its addition to the link-map 45 * list occurs in {elf|aout}_new_lm(), if this returns success the link-map is 46 * valid and added, otherwise any steps (allocations) in the process of creating 47 * the link-map would have been undone. If a failure occurs between creating 48 * the link-map and adding it to a handle, remove_so() is called to remove the 49 * link-map. If a failures occurs after a handle have been created, 50 * remove_hdl() is called to remove the handle and the link-map. 51 */ 52 53 #include <string.h> 54 #include <stdio.h> 55 #include <unistd.h> 56 #include <dlfcn.h> 57 #include <sys/debug.h> 58 #include <sys/avl.h> 59 #include <libc_int.h> 60 #include <debug.h> 61 #include "_rtld.h" 62 #include "_audit.h" 63 #include "_elf.h" 64 #include "msg.h" 65 66 /* 67 * Atexit callback provided by libc. As part of dlclose() determine the address 68 * ranges of all objects that are to be deleted. Pass this information to 69 * libc's pre-atexit routine. Libc will purge any registered atexit() calls 70 * related to those objects about to be deleted. 71 */ 72 static int 73 purge_exit_handlers(Lm_list *lml, Rt_map **tobj) 74 { 75 uint_t num; 76 Rt_map **_tobj; 77 Lc_addr_range_t *addr, *_addr; 78 int error; 79 int (*fptr)(Lc_addr_range_t *, uint_t); 80 81 /* 82 * Has a callback been established? 83 */ 84 if ((fptr = lml->lm_lcs[CI_ATEXIT].lc_un.lc_func) == NULL) 85 return (0); 86 87 /* 88 * Determine the total number of mapped segments that will be unloaded. 89 */ 90 for (num = 0, _tobj = tobj; *_tobj != NULL; _tobj++) { 91 Rt_map *lmp = *_tobj; 92 93 num += MMAPCNT(lmp); 94 } 95 96 /* 97 * Account for a null entry at the end of the address range array. 98 */ 99 if (num++ == 0) 100 return (0); 101 102 /* 103 * Allocate an array for the address range. 104 */ 105 if ((addr = malloc(num * sizeof (Lc_addr_range_t))) == NULL) 106 return (1); 107 108 /* 109 * Fill the address range with each loadable segments size and address. 110 */ 111 for (_tobj = tobj, _addr = addr; *_tobj != NULL; _tobj++) { 112 Rt_map *lmp = *_tobj; 113 mmapobj_result_t *mpp = MMAPS(lmp); 114 uint_t ndx; 115 116 for (ndx = 0; ndx < MMAPCNT(lmp); ndx++, mpp++) { 117 _addr->lb = (void *)(uintptr_t)(mpp->mr_addr + 118 mpp->mr_offset); 119 _addr->ub = (void *)(uintptr_t)(mpp->mr_addr + 120 mpp->mr_msize); 121 _addr++; 122 } 123 } 124 _addr->lb = _addr->ub = 0; 125 126 leave(LIST(*tobj), 0); 127 error = (*fptr)(addr, (num - 1)); 128 (void) enter(0); 129 130 /* 131 * If we fail to converse with libc, generate an error message to 132 * satisfy any dlerror() usage. 133 */ 134 if (error) 135 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_ATEXIT), error); 136 137 free(addr); 138 return (error); 139 } 140 141 /* 142 * Break down an Alist containing pathname descriptors. In most instances, the 143 * Alist is cleaned of all entries, but retained for later use. 144 */ 145 void 146 remove_plist(Alist **alpp, int complete) 147 { 148 Alist *alp = *alpp; 149 150 if (alp) { 151 if (complete) { 152 free((void *)alp); 153 *alpp = NULL; 154 } else { 155 alp->al_nitems = 0; 156 alp->al_next = ALIST_OFF_DATA; 157 } 158 } 159 } 160 161 /* 162 * Remove a link-map list descriptor. This is called to finalize the removal 163 * of an entire link-map list, after all link-maps have been removed, or none 164 * got added. As load_one() can process a list of potential candidate objects, 165 * the link-map descriptor must be maintained as each object is processed. Only 166 * after all objects have been processed can a failure condition finally tear 167 * down the link-map list descriptor. 168 */ 169 void 170 remove_lml(Lm_list *lml) 171 { 172 if (lml && (lml->lm_head == NULL)) { 173 /* 174 * As a whole link-map list is being removed, the debuggers 175 * would have been alerted of this deletion (or an addition 176 * in the case we're here to clean up from a failure). Set 177 * the main link-map list so that a consistent registration 178 * can be signaled to the debuggers when we leave ld.so.1. 179 */ 180 lml_main.lm_flags |= LML_FLG_DBNOTIF; 181 182 if (lml->lm_lmidstr) 183 free(lml->lm_lmidstr); 184 if (lml->lm_alp) 185 free(lml->lm_alp); 186 if (lml->lm_lists) 187 free(lml->lm_lists); 188 if (lml->lm_actaudit) 189 free(lml->lm_actaudit); 190 191 /* 192 * Cleanup any pending RTLDINFO in the case where it was 193 * allocated but not called (see _relocate_lmc()). 194 */ 195 if (lml->lm_rti) 196 free(lml->lm_rti); 197 if (lml->lm_fpavl) { 198 /* 199 * As we are freeing the link-map list, all nodes must 200 * have previously been removed. 201 */ 202 ASSERT(avl_numnodes(lml->lm_fpavl) == 0); 203 free(lml->lm_fpavl); 204 } 205 (void) aplist_delete_value(dynlm_list, lml); 206 free(lml); 207 } 208 } 209 210 /* 211 * Remove a link-map. This removes a link-map from its associated list and 212 * free's up the link-map itself. Note, all components that are freed are local 213 * to the link-map, no inter-link-map lists are operated on as these are all 214 * broken down by dlclose() while all objects are still mapped. 215 * 216 * This routine is called from dlclose() to zap individual link-maps after their 217 * interdependencies (DEPENDS(), CALLER(), handles, etc.) have been removed. 218 * This routine is also called from the bowels of load_one() in the case of a 219 * link-map creation failure. 220 */ 221 void 222 remove_so(Lm_list *lml, Rt_map *lmp) 223 { 224 Dyninfo *dip; 225 226 if (lmp == NULL) 227 return; 228 229 /* 230 * Unlink the link map from the link-map list. 231 */ 232 if (lml && lmp) 233 lm_delete(lml, lmp); 234 235 /* 236 * If this object contributed any local external vectors for the current 237 * link-map list, remove the vectors. If this object contributed any 238 * global external vectors we should find some new candidates, or leave 239 * this object lying around. 240 */ 241 if (lml) { 242 int tag; 243 244 for (tag = 0; tag < CI_MAX; tag++) { 245 if (lml->lm_lcs[tag].lc_lmp == lmp) { 246 lml->lm_lcs[tag].lc_lmp = NULL; 247 lml->lm_lcs[tag].lc_un.lc_val = 0; 248 } 249 if (glcs[tag].lc_lmp == lmp) { 250 ASSERT(glcs[tag].lc_lmp != NULL); 251 glcs[tag].lc_lmp = NULL; 252 glcs[tag].lc_un.lc_val = 0; 253 } 254 } 255 } 256 257 DBG_CALL(Dbg_file_delete(lmp)); 258 259 /* 260 * If this is a temporary link-map, put in place to facilitate the 261 * link-edit or a relocatable object, then the link-map contains no 262 * information that needs to be cleaned up. 263 */ 264 if (FLAGS(lmp) & FLG_RT_OBJECT) 265 return; 266 267 /* 268 * Remove any FullpathNode AVL names if they still exist. 269 */ 270 if (FPNODE(lmp)) 271 fpavl_remove(lmp); 272 273 /* 274 * Remove any alias names. 275 */ 276 if (ALIAS(lmp)) 277 free(ALIAS(lmp)); 278 279 /* 280 * Remove any of this objects filtee infrastructure. The filtees them- 281 * selves have already been removed. 282 */ 283 if (((dip = DYNINFO(lmp)) != NULL) && (FLAGS1(lmp) & MSK_RT_FILTER)) { 284 uint_t cnt, max = DYNINFOCNT(lmp); 285 286 for (cnt = 0; cnt < max; cnt++, dip++) { 287 if ((dip->di_info == NULL) || 288 ((dip->di_flags & MSK_DI_FILTER) == 0)) 289 continue; 290 291 remove_plist((Alist **)&(dip->di_info), 1); 292 } 293 } 294 295 /* 296 * Deallocate any remaining cruft and free the link-map. 297 */ 298 if (RLIST(lmp)) 299 remove_plist(&RLIST(lmp), 1); 300 301 if (AUDITORS(lmp)) 302 audit_desc_cleanup(lmp); 303 if (AUDINFO(lmp)) 304 audit_info_cleanup(lmp); 305 306 /* 307 * Note that COPY_R() and COPY_S() reference the same memory 308 * location, and that we want to release the memory referenced 309 * without regard to which list it logically belongs to. We can 310 * use either pointer to do this. 311 */ 312 if (COPY_R(lmp)) 313 free(COPY_R(lmp)); 314 315 /* 316 * During a dlclose() any groups this object was a part of will have 317 * been torn down. However, we can get here to remove an object that 318 * has failed to load, perhaps because its addition to a handle failed. 319 * Therefore if this object indicates that its part of a group tear 320 * these associations down. 321 */ 322 if (GROUPS(lmp) != NULL) { 323 Aliste idx1; 324 Grp_hdl *ghp; 325 326 for (APLIST_TRAVERSE(GROUPS(lmp), idx1, ghp)) { 327 Grp_desc *gdp; 328 Aliste idx2; 329 330 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 331 if (gdp->gd_depend != lmp) 332 continue; 333 334 alist_delete(ghp->gh_depends, &idx2); 335 break; 336 } 337 } 338 free(GROUPS(lmp)); 339 } 340 if (HANDLES(lmp)) 341 free(HANDLES(lmp)); 342 343 /* 344 * Clean up reglist if needed 345 */ 346 if (reglist) { 347 Reglist *cur, *prv, *del; 348 349 cur = prv = reglist; 350 while (cur) { 351 if (cur->rl_lmp == lmp) { 352 del = cur; 353 if (cur == reglist) { 354 reglist = cur->rl_next; 355 cur = prv = reglist; 356 } else { 357 prv->rl_next = cur->rl_next; 358 cur = cur->rl_next; 359 } 360 free(del); 361 } else { 362 prv = cur; 363 cur = cur->rl_next; 364 } 365 } 366 } 367 368 /* 369 * If this link map represents a relocatable object concatenation, then 370 * the image was simply generated in allocated memory. Free the memory. 371 * Note: memory maps were fabricated for the relocatable object, and 372 * the mapping infrastructure must be free'd, but there are no address 373 * mappings that must be unmapped. 374 * 375 * Otherwise, unmap the object. 376 */ 377 if (FLAGS(lmp) & FLG_RT_IMGALLOC) 378 free((void *)ADDR(lmp)); 379 380 if (MMAPS(lmp)) { 381 if ((FLAGS(lmp) & FLG_RT_IMGALLOC) == 0) 382 unmap_obj(MMAPS(lmp), MMAPCNT(lmp)); 383 free(MMAPS(lmp)); 384 } 385 386 free(lmp); 387 } 388 389 /* 390 * Traverse an objects dependency list removing callers and dependencies. 391 * There's a chicken and egg problem with tearing down link-maps. Any 392 * relationship between link-maps is maintained on a DEPENDS list, and an 393 * associated CALLERS list. These lists can't be broken down at the time a 394 * single link-map is removed, as any related link-map may have already been 395 * removed. Thus, lists between link-maps must be broken down before the 396 * individual link-maps themselves. 397 */ 398 static void 399 remove_lists(Rt_map *lmp, int lazy) 400 { 401 Aliste idx1; 402 Bnd_desc *bdp; 403 404 /* 405 * First, traverse this objects dependencies. 406 */ 407 for (APLIST_TRAVERSE(DEPENDS(lmp), idx1, bdp)) { 408 Rt_map *dlmp = bdp->b_depend; 409 410 /* 411 * Remove this object from the dependencies callers. 412 */ 413 (void) aplist_delete_value(CALLERS(dlmp), bdp); 414 free(bdp); 415 } 416 if (DEPENDS(lmp)) { 417 free(DEPENDS(lmp)); 418 DEPENDS(lmp) = NULL; 419 } 420 421 /* 422 * Second, traverse this objects callers. 423 */ 424 for (APLIST_TRAVERSE(CALLERS(lmp), idx1, bdp)) { 425 Rt_map *clmp = bdp->b_caller; 426 Dyninfo *dip; 427 428 /* 429 * If we're removing an object that was triggered by a lazyload, 430 * remove the callers DYNINFO() entry and bump the lazy counts. 431 * This reinitialization of the lazy information allows a lazy 432 * object to be reloaded again later. Although we may be 433 * breaking down a group of lazyloaded objects because one has 434 * failed to relocate, it's possible that one or more of the 435 * individual objects can be reloaded without a problem. 436 */ 437 if (lazy && ((dip = DYNINFO(clmp)) != NULL)) { 438 uint_t cnt, max = DYNINFOCNT(clmp); 439 440 for (cnt = 0; cnt < max; cnt++, dip++) { 441 if ((dip->di_flags & FLG_DI_LAZY) == 0) 442 continue; 443 444 if (dip->di_info == (void *)lmp) { 445 dip->di_info = NULL; 446 447 if (LAZY(clmp)++ == 0) 448 LIST(clmp)->lm_lazy++; 449 } 450 } 451 } 452 453 (void) aplist_delete_value(DEPENDS(clmp), bdp); 454 free(bdp); 455 } 456 if (CALLERS(lmp)) { 457 free(CALLERS(lmp)); 458 CALLERS(lmp) = NULL; 459 } 460 } 461 462 /* 463 * Delete any temporary link-map control list. 464 */ 465 void 466 remove_cntl(Lm_list *lml, Aliste lmco) 467 { 468 if (lmco && (lmco != ALIST_OFF_DATA)) { 469 Aliste _lmco = lmco; 470 #if DEBUG 471 Lm_cntl *lmc; 472 473 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco); 474 475 /* 476 * This element should be empty. 477 */ 478 ASSERT(lmc->lc_head == NULL); 479 #endif 480 alist_delete_by_offset(lml->lm_lists, &_lmco); 481 } 482 } 483 484 /* 485 * If a lazy loaded object, or filtee fails to load, possibly because it, or 486 * one of its dependencies can't be relocated, then tear down any objects 487 * that are apart of this link-map control list. 488 */ 489 static void 490 remove_incomplete(Lm_list *lml, Aliste lmco) 491 { 492 Rt_map *lmp; 493 Lm_cntl *lmc; 494 495 /* LINTED */ 496 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco); 497 498 /* 499 * First, remove any lists that may point between objects. 500 */ 501 for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) 502 remove_lists(lmp, 1); 503 504 /* 505 * Finally, remove each object. remove_so() calls lm_delete(), thus 506 * effectively the link-map control head gets updated to point to the 507 * next link-map. 508 */ 509 while ((lmp = lmc->lc_head) != NULL) 510 remove_so(lml, lmp); 511 512 lmc->lc_head = lmc->lc_tail = NULL; 513 } 514 515 /* 516 * Determine whether an object is deletable. 517 */ 518 static int 519 is_deletable(APlist **lmalp, APlist **ghalp, Rt_map *lmp) 520 { 521 Aliste idx; 522 Bnd_desc *bdp; 523 Grp_hdl *ghp; 524 525 /* 526 * If the object hasn't yet been relocated take this as a sign that 527 * it's loading failed, thus we're here to cleanup. If the object is 528 * relocated it will only be retained if it was marked non-deletable, 529 * and exists on the main link-map control list. 530 */ 531 if ((FLAGS(lmp) & FLG_RT_RELOCED) && 532 (MODE(lmp) & RTLD_NODELETE) && (CNTL(lmp) == ALIST_OFF_DATA)) 533 return (0); 534 535 /* 536 * If this object is the head of a handle that has not been captured as 537 * a candidate for deletion, then this object is in use from a dlopen() 538 * outside of the scope of this dlclose() family. Dlopen'ed objects, 539 * and filtees, have group descriptors for their callers. Typically 540 * this parent will have callers that are not apart of this dlclose() 541 * family, and thus would be caught by the CALLERS test below. However, 542 * if the caller had itself been dlopen'ed, it may not have any explicit 543 * callers registered for itself. Thus, but looking for objects with 544 * handles we can ferret out these outsiders. 545 */ 546 for (APLIST_TRAVERSE(HANDLES(lmp), idx, ghp)) { 547 if (aplist_test(ghalp, ghp, 0) != ALE_EXISTS) 548 return (0); 549 } 550 551 /* 552 * If this object is called by any object outside of the family of 553 * objects selected for deletion, it can't be deleted. 554 */ 555 for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) { 556 if (aplist_test(lmalp, bdp->b_caller, 0) != 557 ALE_EXISTS) 558 return (0); 559 } 560 561 /* 562 * This object is a candidate for deletion. 563 */ 564 return (1); 565 } 566 567 /* 568 * Collect the groups (handles) and associated objects that are candidates for 569 * deletion. The criteria for deleting an object is whether it is only refer- 570 * enced from the objects within the groups that are candidates for deletion. 571 */ 572 static int 573 gdp_collect(APlist **ghalpp, APlist **lmalpp, Grp_hdl *ghp1) 574 { 575 Aliste idx1; 576 Grp_desc *gdp; 577 int action; 578 579 /* 580 * Add this group to our group collection. If it isn't added either an 581 * allocation has failed, or it already exists. 582 */ 583 if ((action = aplist_test(ghalpp, ghp1, AL_CNT_GRPCLCT)) != 584 ALE_CREATE) 585 return (action); 586 587 /* 588 * Traverse the dependencies of the group and collect the associated 589 * objects. 590 */ 591 for (ALIST_TRAVERSE(ghp1->gh_depends, idx1, gdp)) { 592 Rt_map *lmp = gdp->gd_depend; 593 594 /* 595 * We only want to process dependencies for deletion. Although 596 * we want to purge group descriptors for parents, we don't want 597 * to analyze the parent itself for additional filters or 598 * deletion. 599 */ 600 if ((gdp->gd_flags & GPD_PARENT) || 601 ((gdp->gd_flags & GPD_ADDEPS) == 0)) 602 continue; 603 604 if ((action = aplist_test(lmalpp, lmp, AL_CNT_GRPCLCT)) == 605 ALE_ALLOCFAIL) 606 return (0); 607 if (action == ALE_EXISTS) 608 continue; 609 610 /* 611 * If this object is a candidate for deletion, determine if the 612 * object provides any filtees. If so, the filter groups are 613 * added to the group collection. 614 * 615 * An object is a candidate for deletion if: 616 * 617 * . the object hasn't yet been relocated, in which case 618 * we're here to clean up a failed load, or 619 * . the object doesn't reside on the base link-map control 620 * list, in which case a group of objects, typically 621 * lazily loaded, or filtees, need cleaning up, or 622 * . the object isn't tagged as non-deletable. 623 */ 624 if ((((FLAGS(lmp) & FLG_RT_RELOCED) == 0) || 625 (CNTL(lmp) != ALIST_OFF_DATA) || 626 ((MODE(lmp) & RTLD_NODELETE) == 0)) && 627 (FLAGS1(lmp) & MSK_RT_FILTER)) { 628 Dyninfo *dip = DYNINFO(lmp); 629 uint_t cnt, max = DYNINFOCNT(lmp); 630 631 for (cnt = 0; cnt < max; cnt++, dip++) { 632 Alist *falp; 633 Aliste idx2; 634 Pdesc *pdp; 635 636 if (((falp = (Alist *)dip->di_info) == NULL) || 637 ((dip->di_flags & MSK_DI_FILTER) == 0)) 638 continue; 639 640 for (ALIST_TRAVERSE(falp, idx2, pdp)) { 641 Grp_hdl *ghp2; 642 643 if ((pdp->pd_plen == 0) || ((ghp2 = 644 (Grp_hdl *)pdp->pd_info) == NULL)) 645 continue; 646 647 if (gdp_collect(ghalpp, lmalpp, 648 ghp2) == 0) 649 return (0); 650 } 651 } 652 } 653 } 654 return (1); 655 } 656 657 /* 658 * Traverse the list of deletable candidates. If an object can't be deleted 659 * then neither can its dependencies or filtees. Any object that is cleared 660 * from being deleted drops the deletion count, plus, if there are no longer 661 * any deletions pending we can discontinue any further processing. 662 */ 663 static int 664 remove_rescan(APlist *lmalp, APlist *ghalp, int *delcnt) 665 { 666 Aliste idx1; 667 Rt_map *lmp; 668 int rescan = 0; 669 670 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) { 671 Aliste idx2; 672 Bnd_desc *bdp; 673 Dyninfo *dip; 674 uint_t cnt, max; 675 676 if (FLAGS(lmp) & FLG_RT_DELETE) 677 continue; 678 679 /* 680 * As this object can't be deleted, make sure its dependencies 681 * aren't deleted either. 682 */ 683 for (APLIST_TRAVERSE(DEPENDS(lmp), idx2, bdp)) { 684 Rt_map *dlmp = bdp->b_depend; 685 686 if (FLAGS(dlmp) & FLG_RT_DELETE) { 687 FLAGS(dlmp) &= ~FLG_RT_DELETE; 688 if (--(*delcnt) == 0) 689 return (0); 690 rescan = 1; 691 } 692 } 693 694 /* 695 * If this object is a filtee and one of its filters is outside 696 * of this dlclose family, then it can't be deleted either. 697 */ 698 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0) 699 continue; 700 701 dip = DYNINFO(lmp); 702 max = DYNINFOCNT(lmp); 703 704 for (cnt = 0; cnt < max; cnt++, dip++) { 705 Alist *falp; 706 Pdesc *pdp; 707 708 if (((falp = (Alist *)dip->di_info) == NULL) || 709 ((dip->di_flags & MSK_DI_FILTER) == 0)) 710 continue; 711 712 for (ALIST_TRAVERSE(falp, idx2, pdp)) { 713 Aliste idx3; 714 Grp_hdl *ghp; 715 Grp_desc *gdp; 716 717 if ((pdp->pd_plen == 0) || 718 ((ghp = (Grp_hdl *)pdp->pd_info) == NULL)) 719 continue; 720 721 if (aplist_test(&ghalp, ghp, 0) == 722 ALE_EXISTS) 723 continue; 724 725 for (ALIST_TRAVERSE(ghp->gh_depends, idx3, 726 gdp)) { 727 Rt_map *dlmp = gdp->gd_depend; 728 729 if (FLAGS(dlmp) & FLG_RT_DELETE) { 730 FLAGS(dlmp) &= ~FLG_RT_DELETE; 731 if (--(*delcnt) == 0) 732 return (0); 733 rescan = 1; 734 } 735 } 736 737 /* 738 * Remove this group handle from our dynamic 739 * deletion list. 740 */ 741 (void) aplist_delete_value(ghalp, ghp); 742 } 743 } 744 } 745 return (rescan); 746 } 747 748 /* 749 * Cleanup any collection alists we've created. 750 */ 751 static void 752 remove_collect(APlist *ghalp, APlist *lmalp) 753 { 754 if (ghalp) 755 free(ghalp); 756 if (lmalp) 757 free(lmalp); 758 } 759 760 /* 761 * Remove a handle, leaving the associated objects intact. Besides the classic 762 * dlopen() usage, handles are used as a means of associating a group of objects 763 * and promoting modes. Once object promotion is completed, the handle should 764 * be discarded while leaving the associated objects intact. Leaving the handle 765 * would prevent the object from being deleted (as it looks like it's in use 766 * by another user). 767 */ 768 void 769 free_hdl(Grp_hdl *ghp, Rt_map *clmp, uint_t cdflags) 770 { 771 Grp_desc *gdp; 772 Aliste idx; 773 774 if (--(ghp->gh_refcnt) == 0) { 775 uintptr_t ndx; 776 777 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) { 778 Rt_map *lmp = gdp->gd_depend; 779 780 if (ghp->gh_ownlmp == lmp) 781 (void) aplist_delete_value(HANDLES(lmp), ghp); 782 (void) aplist_delete_value(GROUPS(lmp), ghp); 783 } 784 (void) free(ghp->gh_depends); 785 786 /* LINTED */ 787 ndx = (uintptr_t)ghp % HDLIST_SZ; 788 (void) aplist_delete_value(hdl_alp[ndx], ghp); 789 790 (void) free(ghp); 791 792 } else if (clmp) { 793 /* 794 * It's possible that an RTLD_NOW promotion (via GPD_PROMOTE) 795 * has associated a caller with a handle that is already in use. 796 * In this case, find the caller and either remove the caller 797 * from the handle, or if the caller is used for any other 798 * reason, clear the promotion flag. 799 */ 800 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) { 801 Rt_map *lmp = gdp->gd_depend; 802 803 if (lmp != clmp) 804 continue; 805 806 if (gdp->gd_flags == cdflags) { 807 alist_delete(ghp->gh_depends, &idx); 808 (void) aplist_delete_value(GROUPS(lmp), ghp); 809 } else { 810 gdp->gd_flags &= ~cdflags; 811 } 812 return; 813 } 814 } 815 } 816 817 /* 818 * If a load operation, using a new link-map control list, has failed, then 819 * forcibly remove the failed objects. This failure can occur as a result 820 * of a lazy load, a dlopen(), or a filtee load, once the application is 821 * running. If the link-map control list has not yet started relocation, then 822 * cleanup is simply a process of removing all the objects from the control 823 * list. If relocation has begun, then other loads may have been triggered to 824 * satisfy the relocations, and thus we need to break down the control list 825 * using handles. 826 * 827 * The objects associated with this load must be part of a unique handle. In 828 * the case of a dlopen() or filtee request, a handle will have been created. 829 * For a lazyload request, a handle must be generated so that the remove 830 * process can use the handle. 831 * 832 * During the course of processing these objects, other objects (handles) may 833 * have been loaded to satisfy relocation requirements. After these families 834 * have successfully loaded, they will have been propagated to the same link-map 835 * control list. The failed objects need to be removed from this list, while 836 * any successfully loaded families can be left alone, and propagated to the 837 * previous link-map control list. By associating each load request with a 838 * handle, we can isolate the failed objects while not interfering with any 839 * successfully loaded families. 840 */ 841 void 842 remove_lmc(Lm_list *lml, Rt_map *clmp, Aliste lmco, const char *name) 843 { 844 Grp_hdl *ghp; 845 Grp_desc *gdp; 846 Aliste idx; 847 Lm_cntl *lmc; 848 Rt_map *lmp; 849 850 /* 851 * Determine the link-map control list, and whether any object has been 852 * added to this list. 853 */ 854 /* LINTED */ 855 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco); 856 if (lmc->lc_head == NULL) 857 return; 858 859 DBG_CALL(Dbg_file_cleanup(lml, name, lmco)); 860 861 /* 862 * Obtain a handle for the first object on the link-map control list. 863 * If none exists (which would occur from a lazy load request), and 864 * the link-map control list is being relocated, create a handle. 865 */ 866 lmp = lmc->lc_head; 867 if (HANDLES(lmp)) { 868 ghp = (Grp_hdl *)HANDLES(lmp)->apl_data[0]; 869 870 } else if (lmc->lc_flags & LMC_FLG_RELOCATING) { 871 /* 872 * Establish a handle, and should anything fail, fall through 873 * to remove the link-map control list. 874 */ 875 if (((ghp = hdl_create(lml, lmc->lc_head, 0, 0, 876 GPD_ADDEPS, 0)) == NULL) || 877 (hdl_initialize(ghp, lmc->lc_head, 0, 0) == 0)) 878 lmc->lc_flags &= ~LMC_FLG_RELOCATING; 879 } else { 880 ghp = NULL; 881 } 882 883 /* 884 * If relocation hasn't begun, simply remove all the objects from this 885 * list, and any handle that may have been created. 886 */ 887 if ((lmc->lc_flags & LMC_FLG_RELOCATING) == 0) { 888 remove_incomplete(lml, lmco); 889 890 if (ghp) { 891 ghp->gh_refcnt = 1; 892 free_hdl(ghp, 0, 0); 893 } 894 return; 895 } 896 897 ASSERT(ghp != NULL); 898 899 /* 900 * As the objects of this handle are being forcibly removed, first 901 * remove any associations to objects on parent link-map control 902 * lists. This breaks the bond between a caller and a hierarchy of 903 * dependencies represented by the handle, thus the caller doesn't lock 904 * the hierarchy and prevent their deletion from the generic handle 905 * processing or remove_hdl(). 906 * 907 * This scenario can be produced when the relocation of a object 908 * results in vectoring through a filter that is already loaded. The 909 * filtee may be on the link-map list that is presently being processed, 910 * however an association between the filter and filtee would have been 911 * established during filtee processing. It is this association that 912 * must be broken to allow the objects on this link-map list to be 913 * removed. 914 */ 915 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) { 916 Rt_map *lmp = gdp->gd_depend; 917 918 /* 919 * If this object has not been relocated, break down any 920 * dependency relationships the object might have established. 921 */ 922 if ((FLAGS(lmp) & FLG_RT_RELOCED) == 0) 923 remove_lists(lmp, 1); 924 925 if (CNTL(lmp) == lmco) 926 continue; 927 928 if (gdp->gd_flags & GPD_FILTER) { 929 Dyninfo *dip = DYNINFO(lmp); 930 uint_t cnt, max = DYNINFOCNT(lmp); 931 932 for (cnt = 0; cnt < max; cnt++, dip++) { 933 Alist *falp; 934 Aliste idx2; 935 Pdesc *pdp; 936 937 if (((falp = (Alist *)dip->di_info) == NULL) || 938 ((dip->di_flags & MSK_DI_FILTER) == 0)) 939 continue; 940 941 for (ALIST_TRAVERSE(falp, idx2, pdp)) { 942 if ((Grp_hdl *)pdp->pd_info == ghp) { 943 pdp->pd_info = NULL; 944 break; 945 } 946 } 947 } 948 } 949 (void) aplist_delete_value(GROUPS(lmp), ghp); 950 alist_delete(ghp->gh_depends, &idx); 951 } 952 953 /* 954 * Having removed any callers, set the group handle reference count to 955 * one, and let the generic handle remover delete the associated 956 * objects. 957 */ 958 ghp->gh_refcnt = 1; 959 (void) remove_hdl(ghp, clmp, NULL); 960 961 /* 962 * If this link-map control list still contains objects, determine the 963 * previous control list and move the objects. 964 */ 965 if (lmc->lc_head) { 966 Lm_cntl *plmc; 967 Aliste plmco; 968 969 plmco = lmco - lml->lm_lists->al_size; 970 /* LINTED */ 971 plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco); 972 973 lm_move(lml, lmco, plmco, lmc, plmc); 974 } 975 } 976 977 /* 978 * Remove the objects associated with a handle. There are two goals here, to 979 * delete the objects associated with the handle, and to remove the handle 980 * itself. Things get a little more complex if the objects selected for 981 * deletion are filters, in this case we also need to collect their filtees, 982 * and process the combined groups as a whole. But, care still must be exer- 983 * cised to make sure any filtees found aren't being used by filters outside of 984 * the groups we've collect. The series of events is basically: 985 * 986 * o Determine the groups (handles) that might be deletable. 987 * 988 * o Determine the objects of these handles that can be deleted. 989 * 990 * o Fire the fini's of those objects selected for deletion. 991 * 992 * o Remove all inter-dependency linked lists while the objects link-maps 993 * are still available. 994 * 995 * o Remove all deletable objects link-maps and unmap the objects themselves. 996 * 997 * o Remove the handle descriptors for each deleted object, and hopefully 998 * the whole handle. 999 * 1000 * An handle that can't be deleted is added to an orphans list. This list is 1001 * revisited any time another dlclose() request results in handle descriptors 1002 * being deleted. These deleted descriptors can be sufficient to allow the 1003 * final deletion of the orphaned handles. 1004 */ 1005 int 1006 remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed) 1007 { 1008 Rt_map *lmp; 1009 int rescan = 0; 1010 int delcnt = 0, rmcnt = 0, error = 0, orphans; 1011 APlist *lmalp = NULL, *ghalp = NULL; 1012 Aliste idx1, idx2; 1013 Grp_hdl *ghp2; 1014 Grp_desc *gdp; 1015 Lm_list *lml = NULL; 1016 1017 /* 1018 * Generate the family of groups and objects that are candidates for 1019 * deletion. This consists of the objects that are explicitly defined 1020 * as dependencies of this handle, plus any filtee handles and their 1021 * associated objects. 1022 */ 1023 if (gdp_collect(&ghalp, &lmalp, ghp) == 0) { 1024 remove_collect(ghalp, lmalp); 1025 return (0); 1026 } 1027 1028 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE)); 1029 1030 /* 1031 * Traverse the groups we've collected to determine if any filtees are 1032 * included. If so, and the filtee handle is in use by a filter outside 1033 * of the family of objects collected for this deletion, it can not be 1034 * removed. 1035 */ 1036 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1037 Grp_hdl *ghp = ghp2; 1038 1039 DBG_CALL(Dbg_file_hdl_collect(ghp, 0)); 1040 1041 if ((ghp->gh_flags & GPH_FILTEE) == 0) 1042 continue; 1043 1044 /* 1045 * Special case for ld.so.1. There can be multiple instances of 1046 * libdl.so.1 using this handle, so although we want the handles 1047 * reference count to be decremented, we don't want the handle 1048 * removed. 1049 */ 1050 if (ghp->gh_flags & GPH_LDSO) { 1051 DBG_CALL(Dbg_file_hdl_collect(ghp, 1052 NAME(lml_rtld.lm_head))); 1053 aplist_delete(ghalp, &idx1); 1054 continue; 1055 } 1056 1057 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1058 Grp_hdl *ghp3; 1059 Aliste idx3; 1060 1061 /* 1062 * Determine whether this dependency is the filtee's 1063 * parent filter, and that it isn't also an explicit 1064 * dependency (in which case it would have added its own 1065 * dependencies to the handle). 1066 */ 1067 if ((gdp->gd_flags & 1068 (GPD_FILTER | GPD_ADDEPS)) != GPD_FILTER) 1069 continue; 1070 1071 if (aplist_test(&lmalp, gdp->gd_depend, 0) == 1072 ALE_EXISTS) 1073 continue; 1074 1075 /* 1076 * Remove this group handle from our dynamic deletion 1077 * list. In addition, recompute the list of objects 1078 * that are candidates for deletion to continue this 1079 * group verification. 1080 */ 1081 DBG_CALL(Dbg_file_hdl_collect(ghp, 1082 NAME(gdp->gd_depend))); 1083 aplist_delete(ghalp, &idx1); 1084 1085 free(lmalp); 1086 lmalp = NULL; 1087 for (APLIST_TRAVERSE(ghalp, idx3, ghp3)) { 1088 Aliste idx4; 1089 Grp_desc *gdp4; 1090 1091 for (ALIST_TRAVERSE(ghp3->gh_depends, 1092 idx4, gdp4)) { 1093 if ((gdp4->gd_flags & GPD_ADDEPS) == 0) 1094 continue; 1095 if (aplist_test(&lmalp, gdp4->gd_depend, 1096 AL_CNT_GRPCLCT) == ALE_ALLOCFAIL) { 1097 remove_collect(ghalp, lmalp); 1098 return (0); 1099 } 1100 } 1101 } 1102 break; 1103 } 1104 } 1105 1106 /* 1107 * Now that we've collected all the handles dependencies, traverse the 1108 * collection determining whether they are a candidate for deletion. 1109 */ 1110 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) { 1111 /* 1112 * Establish which link-map list we're dealing with for later 1113 * .fini processing. 1114 */ 1115 if (lml == NULL) 1116 lml = LIST(lmp); 1117 1118 /* 1119 * If an object isn't a candidate for deletion we'll have to 1120 * rescan the handle insuring that this objects dependencies 1121 * aren't deleted either. 1122 */ 1123 if (is_deletable(&lmalp, &ghalp, lmp)) { 1124 FLAGS(lmp) |= FLG_RT_DELETE; 1125 delcnt++; 1126 } else 1127 rescan = 1; 1128 } 1129 1130 /* 1131 * Rescan the handle if any objects where found non-deletable. 1132 */ 1133 while (rescan) 1134 rescan = remove_rescan(lmalp, ghalp, &delcnt); 1135 1136 /* 1137 * Now that we have determined the number of groups that are candidates 1138 * for removal, mark each group descriptor as a candidate for removal 1139 * from the group. 1140 */ 1141 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1142 for (ALIST_TRAVERSE(ghp2->gh_depends, idx2, gdp)) 1143 gdp->gd_flags |= GPD_REMOVE; 1144 } 1145 1146 /* 1147 * Now that we know which objects on this handle can't be deleted 1148 * determine whether they still need to remain identified as belonging 1149 * to this group to be able to continue binding to one another. 1150 */ 1151 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1152 Grp_hdl *ghp = ghp2; 1153 1154 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1155 Aliste idx3; 1156 Bnd_desc *bdp; 1157 1158 lmp = gdp->gd_depend; 1159 1160 if (FLAGS(lmp) & FLG_RT_DELETE) 1161 continue; 1162 1163 for (APLIST_TRAVERSE(DEPENDS(lmp), idx3, bdp)) { 1164 Aliste idx4; 1165 Grp_desc *gdp4; 1166 Rt_map *dlmp = bdp->b_depend; 1167 1168 /* 1169 * If this dependency (dlmp) can be referenced 1170 * by the caller (clmp) without being part of 1171 * this group (ghp) then belonging to this group 1172 * is no longer necessary. This can occur when 1173 * objects are part of multiple handles, or if a 1174 * previously deleted handle was moved to the 1175 * orphan list and has been reopened. Note, 1176 * first make sure the caller can reference the 1177 * dependency with this group, if it can't we 1178 * must be bound to a filtee, so there's no need 1179 * to remain a part of this group either. 1180 */ 1181 if ((callable(lmp, dlmp, 0, 0) == 0) || 1182 callable(lmp, dlmp, ghp, 0)) 1183 continue; 1184 1185 if (gdp->gd_flags & GPD_REMOVE) 1186 gdp->gd_flags &= ~GPD_REMOVE; 1187 1188 for (ALIST_TRAVERSE(ghp->gh_depends, 1189 idx4, gdp4)) { 1190 if (gdp4->gd_depend != dlmp) 1191 continue; 1192 1193 if (gdp4->gd_flags & GPD_REMOVE) 1194 gdp4->gd_flags &= ~GPD_REMOVE; 1195 } 1196 } 1197 } 1198 } 1199 1200 /* 1201 * If the owner of a handle can't be deleted and it's handle descriptor 1202 * must remain also, don't delete the handle at all. Leave it for 1203 * possible later use. Although it's left intact, it will still be 1204 * moved to the orphans list, as we might be able to revisit it on later 1205 * dlclose() operations and finally remove the underlying objects. Note 1206 * that the handle still remains attached to the owner via the HANDLES 1207 * list, so that it can be re-associated to the owner if a dlopen() 1208 * of this object reoccurs. 1209 */ 1210 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1211 Grp_hdl *ghp = ghp2; 1212 1213 /* 1214 * If this handle is already an orphan, or if it's owner is 1215 * deletable there's no need to inspect its dependencies. 1216 */ 1217 if ((ghp->gh_ownlmp == NULL) || 1218 (FLAGS(ghp->gh_ownlmp) & FLG_RT_DELETE)) 1219 continue; 1220 1221 /* 1222 * Make sure all handle dependencies aren't removed or the 1223 * dependencies themselves aren't deleted. 1224 */ 1225 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1226 lmp = gdp->gd_depend; 1227 1228 /* 1229 * The first dependency of a non-orphaned handle is the 1230 * owner. If the handle descriptor for this isn't 1231 * required there's no need to look at any other of the 1232 * handles dependencies. 1233 */ 1234 if ((lmp == ghp->gh_ownlmp) && 1235 (gdp->gd_flags & GPD_REMOVE)) 1236 break; 1237 1238 if (gdp->gd_flags & GPD_REMOVE) 1239 gdp->gd_flags &= ~GPD_REMOVE; 1240 if (FLAGS(lmp) & FLG_RT_DELETE) { 1241 FLAGS(lmp) &= ~FLG_RT_DELETE; 1242 delcnt--; 1243 } 1244 } 1245 } 1246 1247 /* 1248 * Final scan of objects to see if any objects are to to be deleted. 1249 * Also - display diagnostic information on what operations are to be 1250 * performed on the collected handles before firing .fini's (which 1251 * produces additional diagnostics). 1252 */ 1253 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1254 Grp_hdl *ghp = ghp2; 1255 1256 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE)); 1257 1258 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1259 int flag; 1260 1261 lmp = gdp->gd_depend; 1262 1263 /* 1264 * Note, we must never delete a parent. The parent 1265 * may already be tagged for deletion from a previous 1266 * dlclose(). That dlclose has triggered this dlclose(), 1267 * but the parents deletion is the responsibility of the 1268 * previous dlclose(), not this one. 1269 */ 1270 if ((FLAGS(lmp) & FLG_RT_DELETE) && 1271 ((gdp->gd_flags & GPD_PARENT) == 0)) { 1272 flag = DBG_DEP_DELETE; 1273 1274 /* 1275 * Remove any pathnames from the FullpathNode 1276 * AVL tree. As we're about to fire .fini's, 1277 * it's possible this object will be required 1278 * again, in which case we want to make sure a 1279 * new version of the object gets loaded. 1280 */ 1281 if (FPNODE(lmp)) 1282 fpavl_remove(lmp); 1283 } else if (gdp->gd_flags & GPD_REMOVE) 1284 flag = DBG_DEP_REMOVE; 1285 else 1286 flag = DBG_DEP_REMAIN; 1287 1288 DBG_CALL(Dbg_file_hdl_action(ghp, lmp, flag, 0)); 1289 } 1290 } 1291 1292 /* 1293 * If there are objects to be deleted process their .fini's. 1294 */ 1295 if (delcnt) { 1296 Rt_map **tobj; 1297 1298 /* 1299 * If we're being audited tell the audit library that we're 1300 * about to go deleting dependencies. 1301 */ 1302 if (clmp && ((LIST(clmp)->lm_tflags | AFLAGS(clmp)) & 1303 LML_TFLG_AUD_ACTIVITY)) 1304 audit_activity(clmp, LA_ACT_DELETE); 1305 1306 /* 1307 * Sort and fire all fini's of the objects selected for 1308 * deletion. Note that we have to start our search from the 1309 * link-map head - there's no telling whether this object has 1310 * dependencies on objects that were loaded before it and which 1311 * can now be deleted. If the tsort() fails because of an 1312 * allocation error then that might just be a symptom of why 1313 * we're here in the first place - forgo the fini's but 1314 * continue to try cleaning up. 1315 */ 1316 lml->lm_flags |= LML_FLG_OBJDELETED; 1317 1318 if (((tobj = tsort(lml->lm_head, delcnt, 1319 (RT_SORT_DELETE | RT_SORT_FWD))) != NULL) && 1320 (tobj != (Rt_map **)S_ERROR)) { 1321 error = purge_exit_handlers(lml, tobj); 1322 call_fini(lml, tobj); 1323 } 1324 1325 /* 1326 * Audit the closure of the dlopen'ed object to any local 1327 * auditors. Any global auditors would have been caught by 1328 * call_fini(), but as the link-maps CALLERS was removed 1329 * already we do the local auditors explicitly. 1330 */ 1331 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1332 Grp_hdl *ghp = ghp2; 1333 Rt_map *dlmp = ghp->gh_ownlmp; 1334 1335 if (clmp && dlmp && 1336 ((LIST(dlmp)->lm_flags & LML_FLG_NOAUDIT) == 0) && 1337 (AFLAGS(clmp) & LML_TFLG_AUD_OBJCLOSE)) 1338 _audit_objclose(AUDITORS(clmp)->ad_list, dlmp); 1339 } 1340 } 1341 1342 /* 1343 * Now that .fini processing (which may have involved new bindings) 1344 * is complete, remove all inter-dependency lists from those objects 1345 * selected for deletion. 1346 */ 1347 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) { 1348 Dyninfo *dip; 1349 uint_t cnt, max; 1350 1351 if (FLAGS(lmp) & FLG_RT_DELETE) 1352 remove_lists(lmp, 0); 1353 1354 /* 1355 * Determine whether we're dealing with a filter, and if so 1356 * process any inter-dependencies with its filtee's. 1357 */ 1358 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0) 1359 continue; 1360 1361 dip = DYNINFO(lmp); 1362 max = DYNINFOCNT(lmp); 1363 1364 for (cnt = 0; cnt < max; cnt++, dip++) { 1365 Alist *falp; 1366 Aliste idx2; 1367 Pdesc *pdp; 1368 1369 if (((falp = (Alist *)dip->di_info) == NULL) || 1370 ((dip->di_flags & MSK_DI_FILTER) == 0)) 1371 continue; 1372 1373 for (ALIST_TRAVERSE(falp, idx2, pdp)) { 1374 Grp_hdl *ghp; 1375 1376 if ((pdp->pd_plen == 0) || 1377 ((ghp = (Grp_hdl *)pdp->pd_info) == NULL)) 1378 continue; 1379 1380 /* 1381 * Determine whether this filtee's handle is a 1382 * part of the list of handles being deleted. 1383 */ 1384 if (aplist_test(&ghalp, ghp, 0) == ALE_EXISTS) { 1385 /* 1386 * If this handle exists on the deletion 1387 * list, then it has been removed. If 1388 * this filter isn't going to be 1389 * deleted, sever its reference to the 1390 * handle. 1391 */ 1392 pdp->pd_info = NULL; 1393 } else { 1394 /* 1395 * If this handle isn't on the deletion 1396 * list, then it must still exist. If 1397 * this filter is being deleted, make 1398 * sure the filtees reference count 1399 * gets decremented. 1400 */ 1401 if ((FLAGS(lmp) & FLG_RT_DELETE) && 1402 ((gdp->gd_flags & 1403 GPD_PARENT) == 0)) { 1404 (void) dlclose_core(ghp, 1405 lmp, lml); 1406 } 1407 } 1408 } 1409 } 1410 } 1411 1412 /* 1413 * If called from dlclose(), determine if there are already handles on 1414 * the orphans list that we can reinvestigate. 1415 */ 1416 if ((removed == 0) && aplist_nitems(hdl_alp[HDLIST_ORP])) 1417 orphans = 1; 1418 else 1419 orphans = 0; 1420 1421 /* 1422 * Finally remove any handle infrastructure and remove any objects 1423 * marked for deletion. 1424 */ 1425 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1426 Grp_hdl *ghp = ghp2; 1427 1428 /* 1429 * If we're not dealing with orphaned handles remove this handle 1430 * from its present handle list. 1431 */ 1432 if (removed == 0) { 1433 uintptr_t ndx; 1434 1435 /* LINTED */ 1436 ndx = (uintptr_t)ghp % HDLIST_SZ; 1437 (void) aplist_delete_value(hdl_alp[ndx], ghp); 1438 } 1439 1440 /* 1441 * Traverse each handle dependency. Retain the dependencies 1442 * flags to insure we don't delete any parents (the flags 1443 * information is deleted as part of the alist removal that 1444 * occurs before we inspect the object for deletion). 1445 */ 1446 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1447 uint_t flags = gdp->gd_flags; 1448 1449 if ((flags & GPD_REMOVE) == 0) 1450 continue; 1451 1452 lmp = gdp->gd_depend; 1453 rmcnt++; 1454 1455 /* 1456 * If this object is the owner of the handle break that 1457 * association in case the handle is retained. 1458 */ 1459 if (ghp->gh_ownlmp == lmp) { 1460 (void) aplist_delete_value(HANDLES(lmp), ghp); 1461 ghp->gh_ownlmp = NULL; 1462 } 1463 1464 (void) aplist_delete_value(GROUPS(lmp), ghp); 1465 alist_delete(ghp->gh_depends, &idx2); 1466 1467 /* 1468 * Complete the link-map deletion if appropriate. 1469 */ 1470 if ((FLAGS(lmp) & FLG_RT_DELETE) && 1471 ((flags & GPD_PARENT) == 0)) { 1472 tls_modaddrem(lmp, TM_FLG_MODREM); 1473 remove_so(LIST(lmp), lmp); 1474 } 1475 } 1476 1477 /* 1478 * If we've deleted all the dependencies of the handle, finalize 1479 * the cleanup by removing the handle itself. 1480 * 1481 * Otherwise we're left with a handle containing one or more 1482 * objects that can not be deleted (they're in use by other 1483 * handles, non-deletable, etc.), but require to remain a part 1484 * of this group to allow them to continue binding to one 1485 * another. 1486 * 1487 * If the handles reference count is zero, or represents a 1488 * link-map list (dlopen(0)), then move that handle to the 1489 * orphans list. Should another dlclose() operation occur that 1490 * results in the removal of handle descriptors, these orphan 1491 * handles are re-examined to determine if their deletion can 1492 * be completed. 1493 */ 1494 if (ghp->gh_depends->al_nitems == 0) { 1495 free(ghp->gh_depends); 1496 free(ghp); 1497 1498 } else if ((ghp->gh_refcnt == 0) && 1499 ((ghp->gh_flags & GPH_ZERO) == 0)) { 1500 /* 1501 * Move this handle to the orphans list. 1502 */ 1503 (void) aplist_append(&hdl_alp[HDLIST_ORP], ghp, 1504 AL_CNT_HANDLES); 1505 1506 if (DBG_ENABLED) { 1507 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ORPHAN)); 1508 for (ALIST_TRAVERSE(ghp->gh_depends, idx1, gdp)) 1509 DBG_CALL(Dbg_file_hdl_action(ghp, 1510 gdp->gd_depend, DBG_DEP_ORPHAN, 0)); 1511 } 1512 } 1513 } 1514 1515 /* 1516 * If no handle descriptors got removed there's no point in looking for 1517 * orphans to process. 1518 */ 1519 if (rmcnt == 0) 1520 orphans = 0; 1521 1522 /* 1523 * Cleanup any alists we've created. 1524 */ 1525 remove_collect(ghalp, lmalp); 1526 1527 /* 1528 * If orphan processing isn't required we're done. If our processing 1529 * originated from investigating orphans, return the number of handle 1530 * descriptors removed as an indication whether orphan processing 1531 * should continue. 1532 */ 1533 if (orphans == 0) { 1534 if (removed) 1535 *removed = rmcnt; 1536 return (error); 1537 } 1538 1539 /* 1540 * Traverse the orphans list as many times as necessary until no 1541 * handle removals occur. 1542 */ 1543 do { 1544 APlist *alp; 1545 Aliste idx; 1546 Grp_hdl *ghp, *oghp = NULL; 1547 int title = 0; 1548 1549 /* 1550 * Effectively clean the HDLIST_ORP list. Any object that can't 1551 * be removed will be re-added to the list. 1552 */ 1553 alp = hdl_alp[HDLIST_ORP]; 1554 hdl_alp[HDLIST_ORP] = NULL; 1555 1556 rescan = 0; 1557 for (APLIST_TRAVERSE(alp, idx, ghp)) { 1558 int _error, _remove; 1559 1560 if (title++ == 0) 1561 DBG_CALL(Dbg_file_del_rescan(ghp->gh_ownlml)); 1562 1563 if (oghp) { 1564 (void) aplist_delete_value(alp, oghp); 1565 oghp = NULL; 1566 } 1567 1568 if (((_error = remove_hdl(ghp, clmp, &_remove)) != 0) && 1569 (error == 0)) 1570 error = _error; 1571 1572 if (_remove) 1573 rescan++; 1574 1575 oghp = ghp; 1576 } 1577 if (oghp) { 1578 (void) aplist_delete_value(alp, oghp); 1579 oghp = NULL; 1580 } 1581 if (alp) 1582 free((void *)alp); 1583 1584 } while (rescan && aplist_nitems(hdl_alp[HDLIST_ORP])); 1585 1586 return (error); 1587 } 1588