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