Home | History | Annotate | Download | only in common
      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  *  -	a dlclose() request
     31  *
     32  *  -	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 	Aliste	_lmco = lmco;
    469 #if	DEBUG
    470 	Lm_cntl	*lmc;
    471 
    472 	lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
    473 
    474 	/*
    475 	 * This element should be empty.
    476 	 */
    477 	ASSERT(lmc->lc_head == NULL);
    478 #endif
    479 	alist_delete_by_offset(lml->lm_lists, &_lmco);
    480 }
    481 
    482 /*
    483  * If a lazy loaded object, or filtee fails to load, possibly because it, or
    484  * one of its dependencies can't be relocated, then tear down any objects
    485  * that are apart of this link-map control list.
    486  */
    487 static void
    488 remove_incomplete(Lm_list *lml, Aliste lmco)
    489 {
    490 	Rt_map	*lmp;
    491 	Lm_cntl	*lmc;
    492 
    493 	/* LINTED */
    494 	lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
    495 
    496 	/*
    497 	 * First, remove any lists that may point between objects.
    498 	 */
    499 	for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp))
    500 		remove_lists(lmp, 1);
    501 
    502 	/*
    503 	 * Finally, remove each object.  remove_so() calls lm_delete(), thus
    504 	 * effectively the link-map control head gets updated to point to the
    505 	 * next link-map.
    506 	 */
    507 	while ((lmp = lmc->lc_head) != NULL)
    508 		remove_so(lml, lmp);
    509 
    510 	lmc->lc_head = lmc->lc_tail = NULL;
    511 }
    512 
    513 /*
    514  * Determine whether an object is deletable.
    515  */
    516 static int
    517 is_deletable(APlist **lmalp, APlist **ghalp, Rt_map *lmp)
    518 {
    519 	Aliste		idx;
    520 	Bnd_desc	*bdp;
    521 	Grp_hdl		*ghp;
    522 
    523 	/*
    524 	 * If the object hasn't yet been relocated take this as a sign that
    525 	 * it's loading failed, thus we're here to cleanup.  If the object is
    526 	 * relocated it will only be retained if it was marked non-deletable,
    527 	 * and exists on the main link-map control list.
    528 	 */
    529 	if ((FLAGS(lmp) & FLG_RT_RELOCED) &&
    530 	    (MODE(lmp) & RTLD_NODELETE) && (CNTL(lmp) == ALIST_OFF_DATA))
    531 		return (0);
    532 
    533 	/*
    534 	 * If this object is the head of a handle that has not been captured as
    535 	 * a candidate for deletion, then this object is in use from a dlopen()
    536 	 * outside of the scope of this dlclose() family.  Dlopen'ed objects,
    537 	 * and filtees, have group descriptors for their callers.  Typically
    538 	 * this parent will have callers that are not apart of this dlclose()
    539 	 * family, and thus would be caught by the CALLERS test below.  However,
    540 	 * if the caller had itself been dlopen'ed, it may not have any explicit
    541 	 * callers registered for itself.  Thus, but looking for objects with
    542 	 * handles we can ferret out these outsiders.
    543 	 */
    544 	for (APLIST_TRAVERSE(HANDLES(lmp), idx, ghp)) {
    545 		/*
    546 		 * If this is a private handle, then the handle isn't referenced
    547 		 * from outside of the group of objects being deleted, and can
    548 		 * be ignored when evaluating objects for deletion.
    549 		 */
    550 		if (ghp->gh_flags & GPH_PRIVATE)
    551 			continue;
    552 		if (aplist_test(ghalp, ghp, 0) != ALE_EXISTS)
    553 			return (0);
    554 	}
    555 
    556 	/*
    557 	 * If this object is called by any object outside of the family of
    558 	 * objects selected for deletion, it can't be deleted.
    559 	 */
    560 	for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) {
    561 		if (aplist_test(lmalp, bdp->b_caller, 0) != ALE_EXISTS)
    562 			return (0);
    563 	}
    564 
    565 	/*
    566 	 * This object is a candidate for deletion.
    567 	 */
    568 	return (1);
    569 }
    570 
    571 /*
    572  * Collect the groups (handles) and associated objects that are candidates for
    573  * deletion.  The criteria for deleting an object is whether it is only refer-
    574  * enced from the objects within the groups that are candidates for deletion.
    575  */
    576 static int
    577 gdp_collect(APlist **ghalpp, APlist **lmalpp, Grp_hdl *ghp1)
    578 {
    579 	Aliste		idx1;
    580 	Grp_desc	*gdp;
    581 	int		action;
    582 
    583 	/*
    584 	 * Add this group to our group collection.  If it isn't added either an
    585 	 * allocation has failed, or it already exists.
    586 	 */
    587 	if ((action = aplist_test(ghalpp, ghp1, AL_CNT_GRPCLCT)) !=
    588 	    ALE_CREATE)
    589 		return (action);
    590 
    591 	/*
    592 	 * Traverse the dependencies of the group and collect the associated
    593 	 * objects.
    594 	 */
    595 	for (ALIST_TRAVERSE(ghp1->gh_depends, idx1, gdp)) {
    596 		Rt_map	*lmp = gdp->gd_depend;
    597 
    598 		/*
    599 		 * We only want to process dependencies for deletion.  Although
    600 		 * we want to purge group descriptors for parents, we don't want
    601 		 * to analyze the parent itself for additional filters or
    602 		 * deletion.
    603 		 */
    604 		if ((gdp->gd_flags & GPD_PARENT) ||
    605 		    ((gdp->gd_flags & GPD_ADDEPS) == 0))
    606 			continue;
    607 
    608 		if ((action = aplist_test(lmalpp, lmp, AL_CNT_GRPCLCT)) ==
    609 		    ALE_ALLOCFAIL)
    610 			return (0);
    611 		if (action == ALE_EXISTS)
    612 			continue;
    613 
    614 		/*
    615 		 * If this object is a candidate for deletion, determine if the
    616 		 * object provides any filtees.  If so, the filter groups are
    617 		 * added to the group collection.
    618 		 *
    619 		 * An object is a candidate for deletion if:
    620 		 *
    621 		 *  -	the object hasn't yet been relocated, in which case
    622 		 *	we're here to clean up a failed load, or
    623 		 *  -	the object doesn't reside on the base link-map control
    624 		 *	list, in which case a group of objects, typically
    625 		 *	lazily loaded, or filtees, need cleaning up, or
    626 		 *  -	the object isn't tagged as non-deletable.
    627 		 */
    628 		if ((((FLAGS(lmp) & FLG_RT_RELOCED) == 0) ||
    629 		    (CNTL(lmp) != ALIST_OFF_DATA) ||
    630 		    ((MODE(lmp) & RTLD_NODELETE) == 0)) &&
    631 		    (FLAGS1(lmp) & MSK_RT_FILTER)) {
    632 			Dyninfo	*dip = DYNINFO(lmp);
    633 			uint_t	cnt, max = DYNINFOCNT(lmp);
    634 
    635 			for (cnt = 0; cnt < max; cnt++, dip++) {
    636 				Alist	*falp;
    637 				Aliste	idx2;
    638 				Pdesc	*pdp;
    639 
    640 				if (((falp = (Alist *)dip->di_info) == NULL) ||
    641 				    ((dip->di_flags & MSK_DI_FILTER) == 0))
    642 					continue;
    643 
    644 				for (ALIST_TRAVERSE(falp, idx2, pdp)) {
    645 					Grp_hdl	*ghp2;
    646 
    647 					if ((pdp->pd_plen == 0) || ((ghp2 =
    648 					    (Grp_hdl *)pdp->pd_info) == NULL))
    649 						continue;
    650 
    651 					if (gdp_collect(ghalpp, lmalpp,
    652 					    ghp2) == 0)
    653 						return (0);
    654 				}
    655 			}
    656 		}
    657 	}
    658 	return (1);
    659 }
    660 
    661 /*
    662  * Traverse the list of deletable candidates.  If an object can't be deleted
    663  * then neither can its dependencies or filtees.  Any object that is cleared
    664  * from being deleted drops the deletion count, plus, if there are no longer
    665  * any deletions pending we can discontinue any further processing.
    666  */
    667 static int
    668 remove_rescan(APlist *lmalp, APlist *ghalp, int *delcnt)
    669 {
    670 	Aliste		idx1;
    671 	Rt_map		*lmp;
    672 	int		rescan = 0;
    673 
    674 	for (APLIST_TRAVERSE(lmalp, idx1, lmp)) {
    675 		Aliste		idx2;
    676 		Bnd_desc	*bdp;
    677 		Dyninfo		*dip;
    678 		uint_t		cnt, max;
    679 
    680 		if (FLAGS(lmp) & FLG_RT_DELETE)
    681 			continue;
    682 
    683 		/*
    684 		 * As this object can't be deleted, make sure its dependencies
    685 		 * aren't deleted either.
    686 		 */
    687 		for (APLIST_TRAVERSE(DEPENDS(lmp), idx2, bdp)) {
    688 			Rt_map	*dlmp = bdp->b_depend;
    689 
    690 			if (FLAGS(dlmp) & FLG_RT_DELETE) {
    691 				FLAGS(dlmp) &= ~FLG_RT_DELETE;
    692 				if (--(*delcnt) == 0)
    693 					return (0);
    694 				rescan = 1;
    695 			}
    696 		}
    697 
    698 		/*
    699 		 * If this object is a filtee and one of its filters is outside
    700 		 * of this dlclose family, then it can't be deleted either.
    701 		 */
    702 		if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0)
    703 			continue;
    704 
    705 		dip = DYNINFO(lmp);
    706 		max = DYNINFOCNT(lmp);
    707 
    708 		for (cnt = 0; cnt < max; cnt++, dip++) {
    709 			Alist	*falp;
    710 			Pdesc	*pdp;
    711 
    712 			if (((falp = (Alist *)dip->di_info) == NULL) ||
    713 			    ((dip->di_flags & MSK_DI_FILTER) == 0))
    714 				continue;
    715 
    716 			for (ALIST_TRAVERSE(falp, idx2, pdp)) {
    717 				Aliste		idx3;
    718 				Grp_hdl		*ghp;
    719 				Grp_desc	*gdp;
    720 
    721 				if ((pdp->pd_plen == 0) ||
    722 				    ((ghp = (Grp_hdl *)pdp->pd_info) == NULL))
    723 					continue;
    724 
    725 				if (aplist_test(&ghalp, ghp, 0) ==
    726 				    ALE_EXISTS)
    727 					continue;
    728 
    729 				for (ALIST_TRAVERSE(ghp->gh_depends, idx3,
    730 				    gdp)) {
    731 					Rt_map	*dlmp = gdp->gd_depend;
    732 
    733 					if (FLAGS(dlmp) & FLG_RT_DELETE) {
    734 						FLAGS(dlmp) &= ~FLG_RT_DELETE;
    735 						if (--(*delcnt) == 0)
    736 							return (0);
    737 						rescan = 1;
    738 					}
    739 				}
    740 
    741 				/*
    742 				 * Remove this group handle from our dynamic
    743 				 * deletion list.
    744 				 */
    745 				(void) aplist_delete_value(ghalp, ghp);
    746 			}
    747 		}
    748 	}
    749 	return (rescan);
    750 }
    751 
    752 /*
    753  * Cleanup any collection alists we've created.
    754  */
    755 static void
    756 remove_collect(APlist *ghalp, APlist *lmalp)
    757 {
    758 	if (ghalp)
    759 		free(ghalp);
    760 	if (lmalp)
    761 		free(lmalp);
    762 }
    763 
    764 /*
    765  * Remove a handle, leaving the associated objects intact.
    766  */
    767 void
    768 free_hdl(Grp_hdl *ghp)
    769 {
    770 	if (--(ghp->gh_refcnt) == 0) {
    771 		Grp_desc	*gdp;
    772 		Aliste		idx;
    773 		uintptr_t	ndx;
    774 
    775 		for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
    776 			Rt_map	*lmp = gdp->gd_depend;
    777 
    778 			if (ghp->gh_ownlmp == lmp)
    779 				(void) aplist_delete_value(HANDLES(lmp), ghp);
    780 			(void) aplist_delete_value(GROUPS(lmp), ghp);
    781 		}
    782 		(void) free(ghp->gh_depends);
    783 
    784 		/* LINTED */
    785 		ndx = (uintptr_t)ghp % HDLIST_SZ;
    786 		(void) aplist_delete_value(hdl_alp[ndx], ghp);
    787 
    788 		(void) free(ghp);
    789 	}
    790 }
    791 
    792 /*
    793  * If a load operation, using a new link-map control list, has failed, then
    794  * forcibly remove the failed objects.  This failure can occur as a result
    795  * of a lazy load, a dlopen(), or a filtee load, once the application is
    796  * running.  If the link-map control list has not yet started relocation, then
    797  * cleanup is simply a process of removing all the objects from the control
    798  * list.  If relocation has begun, then other loads may have been triggered to
    799  * satisfy the relocations, and thus we need to break down the control list
    800  * using handles.
    801  *
    802  * The objects associated with this load must be part of a unique handle.  In
    803  * the case of a dlopen() or filtee request, a handle will have been created.
    804  * For a lazyload request, a handle must be generated so that the remove
    805  * process can use the handle.
    806  *
    807  * During the course of processing these objects, other objects (handles) may
    808  * have been loaded to satisfy relocation requirements.  After these families
    809  * have successfully loaded, they will have been propagated to the same link-map
    810  * control list.  The failed objects need to be removed from this list, while
    811  * any successfully loaded families can be left alone, and propagated to the
    812  * previous link-map control list.  By associating each load request with a
    813  * handle, we can isolate the failed objects while not interfering with any
    814  * successfully loaded families.
    815  */
    816 void
    817 remove_lmc(Lm_list *lml, Rt_map *clmp, Aliste lmco, const char *name)
    818 {
    819 	Grp_hdl		*ghp;
    820 	Grp_desc	*gdp;
    821 	Aliste		idx;
    822 	Lm_cntl		*lmc;
    823 	Rt_map		*lmp;
    824 
    825 	/*
    826 	 * Determine the link-map control list, and whether any object has been
    827 	 * added to this list.
    828 	 */
    829 	/* LINTED */
    830 	lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
    831 	if (lmc->lc_head == NULL)
    832 		return;
    833 
    834 	DBG_CALL(Dbg_file_cleanup(lml, name, lmco));
    835 
    836 	/*
    837 	 * Obtain a handle for the first object on the link-map control list.
    838 	 * If none exists (which would occur from a lazy load request), and
    839 	 * the link-map control list is being relocated, create a handle.
    840 	 */
    841 	lmp = lmc->lc_head;
    842 	if (HANDLES(lmp)) {
    843 		ghp = (Grp_hdl *)HANDLES(lmp)->apl_data[0];
    844 
    845 		/*
    846 		 * If this is a private handle, remove this state, so as to
    847 		 * prevent any attempt to remove the handle more than once.
    848 		 */
    849 		ghp->gh_flags &= ~GPH_PRIVATE;
    850 
    851 	} else if (lmc->lc_flags & LMC_FLG_RELOCATING) {
    852 		/*
    853 		 * Establish a handle, and should anything fail, fall through
    854 		 * to remove the link-map control list.
    855 		 */
    856 		if (((ghp = hdl_create(lml, lmc->lc_head, NULL, GPH_PUBLIC,
    857 		    GPD_ADDEPS, 0)) == NULL) ||
    858 		    (hdl_initialize(ghp, lmc->lc_head, 0, 0) == 0))
    859 			lmc->lc_flags &= ~LMC_FLG_RELOCATING;
    860 	} else {
    861 		ghp = NULL;
    862 	}
    863 
    864 	/*
    865 	 * If relocation hasn't begun, simply remove all the objects from this
    866 	 * list, and any handle that may have been created.
    867 	 */
    868 	if ((lmc->lc_flags & LMC_FLG_RELOCATING) == 0) {
    869 		remove_incomplete(lml, lmco);
    870 
    871 		if (ghp) {
    872 			ghp->gh_refcnt = 1;
    873 			free_hdl(ghp);
    874 		}
    875 		return;
    876 	}
    877 
    878 	ASSERT(ghp != NULL);
    879 
    880 	/*
    881 	 * As the objects of this handle are being forcibly removed, first
    882 	 * remove any associations to objects on parent link-map control
    883 	 * lists.  This breaks the bond between a caller and a hierarchy of
    884 	 * dependencies represented by the handle, thus the caller doesn't lock
    885 	 * the hierarchy and prevent their deletion from the generic handle
    886 	 * processing or remove_hdl().
    887 	 *
    888 	 * This scenario can be produced when the relocation of a object
    889 	 * results in vectoring through a filter that is already loaded.  The
    890 	 * filtee may be on the link-map list that is presently being processed,
    891 	 * however an association between the filter and filtee would have been
    892 	 * established during filtee processing.  It is this association that
    893 	 * must be broken to allow the objects on this link-map list to be
    894 	 * removed.
    895 	 */
    896 	for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
    897 		Rt_map	*lmp = gdp->gd_depend;
    898 
    899 		/*
    900 		 * If this object has not been relocated, break down any
    901 		 * dependency relationships the object might have established.
    902 		 */
    903 		if ((FLAGS(lmp) & FLG_RT_RELOCED) == 0)
    904 			remove_lists(lmp, 1);
    905 
    906 		if (CNTL(lmp) == lmco)
    907 			continue;
    908 
    909 		if (gdp->gd_flags & GPD_FILTER) {
    910 			Dyninfo	*dip = DYNINFO(lmp);
    911 			uint_t	cnt, max = DYNINFOCNT(lmp);
    912 
    913 			for (cnt = 0; cnt < max; cnt++, dip++) {
    914 				Alist	*falp;
    915 				Aliste	idx2;
    916 				Pdesc	*pdp;
    917 
    918 				if (((falp = (Alist *)dip->di_info) == NULL) ||
    919 				    ((dip->di_flags & MSK_DI_FILTER) == 0))
    920 					continue;
    921 
    922 				for (ALIST_TRAVERSE(falp, idx2, pdp)) {
    923 					if ((Grp_hdl *)pdp->pd_info == ghp) {
    924 						pdp->pd_info = NULL;
    925 						break;
    926 					}
    927 				}
    928 			}
    929 		}
    930 		(void) aplist_delete_value(GROUPS(lmp), ghp);
    931 		alist_delete(ghp->gh_depends, &idx);
    932 	}
    933 
    934 	/*
    935 	 * Having removed any callers, set the group handle reference count to
    936 	 * one, and let the generic handle remover delete the associated
    937 	 * objects.
    938 	 */
    939 	ghp->gh_refcnt = 1;
    940 	(void) remove_hdl(ghp, clmp, NULL);
    941 
    942 	/*
    943 	 * If this link-map control list still contains objects, determine the
    944 	 * previous control list and move the objects.
    945 	 */
    946 	if (lmc->lc_head) {
    947 		Lm_cntl *plmc;
    948 		Aliste  plmco;
    949 
    950 		plmco = lmco - lml->lm_lists->al_size;
    951 		/* LINTED */
    952 		plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco);
    953 
    954 		lm_move(lml, lmco, plmco, lmc, plmc);
    955 	}
    956 }
    957 
    958 /*
    959  * Remove the objects associated with a handle.  There are two goals here, to
    960  * delete the objects associated with the handle, and to remove the handle
    961  * itself.  Things get a little more complex if the objects selected for
    962  * deletion are filters, in this case we also need to collect their filtees,
    963  * and process the combined groups as a whole.  But, care still must be exer-
    964  * cised to make sure any filtees found aren't being used by filters outside of
    965  * the groups we've collect.  The series of events is basically:
    966  *
    967  *  -	Determine the groups (handles) that might be deletable.
    968  *
    969  *  -	Determine the objects of these handles that can be deleted.
    970  *
    971  *  -	Fire the fini's of those objects selected for deletion.
    972  *
    973  *  -	Remove all inter-dependency linked lists while the objects link-maps
    974  *	are still available.
    975  *
    976  *  -	Remove all deletable objects link-maps and unmap the objects themselves.
    977  *
    978  *  -	Remove the handle descriptors for each deleted object, and hopefully
    979  *	the whole handle.
    980  *
    981  * An handle that can't be deleted is added to an orphans list.  This list is
    982  * revisited any time another dlclose() request results in handle descriptors
    983  * being deleted.  These deleted descriptors can be sufficient to allow the
    984  * final deletion of the orphaned handles.
    985  */
    986 int
    987 remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
    988 {
    989 	Rt_map		*lmp;
    990 	int		rescan = 0;
    991 	int		delcnt = 0, rmcnt = 0, error = 0, orphans;
    992 	APlist		*lmalp = NULL, *ghalp = NULL;
    993 	Aliste		idx1, idx2;
    994 	Grp_hdl		*ghp2;
    995 	Grp_desc	*gdp;
    996 	Lm_list		*lml = NULL;
    997 
    998 	/*
    999 	 * Generate the family of groups and objects that are candidates for
   1000 	 * deletion.  This consists of the objects that are explicitly defined
   1001 	 * as dependencies of this handle, plus any filtee handles and their
   1002 	 * associated objects.
   1003 	 */
   1004 	if (gdp_collect(&ghalp, &lmalp, ghp) == 0) {
   1005 		remove_collect(ghalp, lmalp);
   1006 		return (0);
   1007 	}
   1008 
   1009 	DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE));
   1010 
   1011 	/*
   1012 	 * Traverse the groups we've collected to determine if any filtees are
   1013 	 * included.  If so, and the filtee handle is in use by a filter outside
   1014 	 * of the family of objects collected for this deletion, it can not be
   1015 	 * removed.
   1016 	 */
   1017 	for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
   1018 		Grp_hdl	*ghp = ghp2;
   1019 
   1020 		DBG_CALL(Dbg_file_hdl_collect(ghp, 0));
   1021 
   1022 		if ((ghp->gh_flags & GPH_FILTEE) == 0)
   1023 			continue;
   1024 
   1025 		/*
   1026 		 * Special case for ld.so.1.  There can be multiple instances of
   1027 		 * libdl.so.1 using this handle, so although we want the handles
   1028 		 * reference count to be decremented, we don't want the handle
   1029 		 * removed.
   1030 		 */
   1031 		if (ghp->gh_flags & GPH_LDSO) {
   1032 			DBG_CALL(Dbg_file_hdl_collect(ghp,
   1033 			    NAME(lml_rtld.lm_head)));
   1034 			aplist_delete(ghalp, &idx1);
   1035 			continue;
   1036 		}
   1037 
   1038 		for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
   1039 			Grp_hdl	*ghp3;
   1040 			Aliste	idx3;
   1041 
   1042 			/*
   1043 			 * Determine whether this dependency is the filtee's
   1044 			 * parent filter, and that it isn't also an explicit
   1045 			 * dependency (in which case it would have added its own
   1046 			 * dependencies to the handle).
   1047 			 */
   1048 			if ((gdp->gd_flags &
   1049 			    (GPD_FILTER | GPD_ADDEPS)) != GPD_FILTER)
   1050 				continue;
   1051 
   1052 			lmp = gdp->gd_depend;
   1053 
   1054 			if (FLAGS(lmp) & FLG_RT_DELETE)
   1055 				continue;
   1056 
   1057 			if (aplist_test(&lmalp, lmp, 0) == ALE_EXISTS)
   1058 				continue;
   1059 
   1060 			/*
   1061 			 * Remove this group handle from our dynamic deletion
   1062 			 * list.  In addition, recompute the list of objects
   1063 			 * that are candidates for deletion to continue this
   1064 			 * group verification.
   1065 			 */
   1066 			DBG_CALL(Dbg_file_hdl_collect(ghp, NAME(lmp)));
   1067 			aplist_delete(ghalp, &idx1);
   1068 
   1069 			free(lmalp);
   1070 			lmalp = NULL;
   1071 			for (APLIST_TRAVERSE(ghalp, idx3, ghp3)) {
   1072 				Aliste		idx4;
   1073 				Grp_desc	*gdp4;
   1074 
   1075 				for (ALIST_TRAVERSE(ghp3->gh_depends,
   1076 				    idx4, gdp4))  {
   1077 					if ((gdp4->gd_flags & GPD_ADDEPS) == 0)
   1078 						continue;
   1079 					if (aplist_test(&lmalp, gdp4->gd_depend,
   1080 					    AL_CNT_GRPCLCT) == ALE_ALLOCFAIL) {
   1081 						remove_collect(ghalp, lmalp);
   1082 						return (0);
   1083 					}
   1084 				}
   1085 			}
   1086 			break;
   1087 		}
   1088 	}
   1089 
   1090 	/*
   1091 	 * Now that we've collected all the handles dependencies, traverse the
   1092 	 * collection determining whether they are a candidate for deletion.
   1093 	 */
   1094 	for (APLIST_TRAVERSE(lmalp, idx1, lmp)) {
   1095 		/*
   1096 		 * Establish which link-map list we're dealing with for later
   1097 		 * .fini processing.
   1098 		 */
   1099 		if (lml == NULL)
   1100 			lml = LIST(lmp);
   1101 
   1102 		/*
   1103 		 * If an object isn't a candidate for deletion we'll have to
   1104 		 * rescan the handle insuring that this objects dependencies
   1105 		 * aren't deleted either.
   1106 		 */
   1107 		if (is_deletable(&lmalp, &ghalp, lmp)) {
   1108 			FLAGS(lmp) |= FLG_RT_DELETE;
   1109 			delcnt++;
   1110 		} else
   1111 			rescan = 1;
   1112 	}
   1113 
   1114 	/*
   1115 	 * Rescan the handle if any objects where found non-deletable.
   1116 	 */
   1117 	while (rescan)
   1118 		rescan = remove_rescan(lmalp, ghalp, &delcnt);
   1119 
   1120 	/*
   1121 	 * Now that we have determined the number of groups that are candidates
   1122 	 * for removal, mark each group descriptor as a candidate for removal
   1123 	 * from the group.
   1124 	 */
   1125 	for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
   1126 		for (ALIST_TRAVERSE(ghp2->gh_depends, idx2, gdp))
   1127 			gdp->gd_flags |= GPD_REMOVE;
   1128 	}
   1129 
   1130 	/*
   1131 	 * Now that we know which objects on this handle can't be deleted
   1132 	 * determine whether they still need to remain identified as belonging
   1133 	 * to this group to be able to continue binding to one another.
   1134 	 */
   1135 	for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
   1136 		Grp_hdl	*ghp = ghp2;
   1137 
   1138 		for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
   1139 			Aliste		idx3;
   1140 			Bnd_desc	*bdp;
   1141 
   1142 			lmp = gdp->gd_depend;
   1143 
   1144 			if (FLAGS(lmp) & FLG_RT_DELETE)
   1145 				continue;
   1146 
   1147 			for (APLIST_TRAVERSE(DEPENDS(lmp), idx3, bdp)) {
   1148 				Aliste 		idx4;
   1149 				Grp_desc	*gdp4;
   1150 				Rt_map		*dlmp = bdp->b_depend;
   1151 
   1152 				/*
   1153 				 * If this dependency (dlmp) can be referenced
   1154 				 * by the caller (clmp) without being part of
   1155 				 * this group (ghp) then belonging to this group
   1156 				 * is no longer necessary.  This can occur when
   1157 				 * objects are part of multiple handles, or if a
   1158 				 * previously deleted handle was moved to the
   1159 				 * orphan list and has been reopened.  Note,
   1160 				 * first make sure the caller can reference the
   1161 				 * dependency with this group, if it can't we
   1162 				 * must be bound to a filtee, so there's no need
   1163 				 * to remain a part of this group either.
   1164 				 */
   1165 				if ((callable(lmp, dlmp, 0, 0) == 0) ||
   1166 				    callable(lmp, dlmp, ghp, 0))
   1167 					continue;
   1168 
   1169 				if (gdp->gd_flags & GPD_REMOVE)
   1170 					gdp->gd_flags &= ~GPD_REMOVE;
   1171 
   1172 				for (ALIST_TRAVERSE(ghp->gh_depends,
   1173 				    idx4, gdp4)) {
   1174 					if (gdp4->gd_depend != dlmp)
   1175 						continue;
   1176 
   1177 					if (gdp4->gd_flags & GPD_REMOVE)
   1178 						gdp4->gd_flags &= ~GPD_REMOVE;
   1179 				}
   1180 			}
   1181 		}
   1182 	}
   1183 
   1184 	/*
   1185 	 * If the owner of a handle can't be deleted and it's handle descriptor
   1186 	 * must remain also, don't delete the handle at all.  Leave it for
   1187 	 * possible later use.  Although it's left intact, it will still be
   1188 	 * moved to the orphans list, as we might be able to revisit it on later
   1189 	 * dlclose() operations and finally remove the underlying objects.  Note
   1190 	 * that the handle still remains attached to the owner via the HANDLES
   1191 	 * list, so that it can be re-associated to the owner if a dlopen()
   1192 	 * of this object reoccurs.
   1193 	 */
   1194 	for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
   1195 		Grp_hdl	*ghp = ghp2;
   1196 
   1197 		/*
   1198 		 * If this handle is already an orphan, or if it's owner is
   1199 		 * deletable there's no need to inspect its dependencies.
   1200 		 */
   1201 		if ((ghp->gh_ownlmp == NULL) ||
   1202 		    (FLAGS(ghp->gh_ownlmp) & FLG_RT_DELETE))
   1203 			continue;
   1204 
   1205 		/*
   1206 		 * Make sure all handle dependencies aren't removed or the
   1207 		 * dependencies themselves aren't deleted.
   1208 		 */
   1209 		for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
   1210 			lmp = gdp->gd_depend;
   1211 
   1212 			/*
   1213 			 * The first dependency of a non-orphaned handle is the
   1214 			 * owner.  If the handle descriptor for this isn't
   1215 			 * required there's no need to look at any other of the
   1216 			 * handles dependencies.
   1217 			 */
   1218 			if ((lmp == ghp->gh_ownlmp) &&
   1219 			    (gdp->gd_flags & GPD_REMOVE))
   1220 				break;
   1221 
   1222 			if (gdp->gd_flags & GPD_REMOVE)
   1223 				gdp->gd_flags &= ~GPD_REMOVE;
   1224 			if (FLAGS(lmp) & FLG_RT_DELETE) {
   1225 				FLAGS(lmp) &= ~FLG_RT_DELETE;
   1226 				delcnt--;
   1227 			}
   1228 		}
   1229 	}
   1230 
   1231 	/*
   1232 	 * Final scan of objects to see if any objects are to to be deleted.
   1233 	 * Also - display diagnostic information on what operations are to be
   1234 	 * performed on the collected handles before firing .fini's (which
   1235 	 * produces additional diagnostics).
   1236 	 */
   1237 	for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
   1238 		Grp_hdl	*ghp = ghp2;
   1239 
   1240 		DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE));
   1241 
   1242 		for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
   1243 			Grp_hdl	*ghp3;
   1244 			Aliste	idx3;
   1245 			int	flag;
   1246 
   1247 			lmp = gdp->gd_depend;
   1248 
   1249 			/*
   1250 			 * Note, we must never delete a parent.  The parent
   1251 			 * may already be tagged for deletion from a previous
   1252 			 * dlclose(). That dlclose has triggered this dlclose(),
   1253 			 * but the parents deletion is the responsibility of the
   1254 			 * previous dlclose(), not this one.
   1255 			 */
   1256 			if ((FLAGS(lmp) & FLG_RT_DELETE) &&
   1257 			    ((gdp->gd_flags & GPD_PARENT) == 0)) {
   1258 				flag = DBG_DEP_DELETE;
   1259 
   1260 				/*
   1261 				 * Remove any pathnames from the FullpathNode
   1262 				 * AVL tree.  As we're about to fire .fini's,
   1263 				 * it's possible this object will be required
   1264 				 * again, in which case we want to make sure a
   1265 				 * new version of the object gets loaded.
   1266 				 */
   1267 				if (FPNODE(lmp))
   1268 					fpavl_remove(lmp);
   1269 			} else if (gdp->gd_flags & GPD_REMOVE)
   1270 				flag = DBG_DEP_REMOVE;
   1271 			else
   1272 				flag = DBG_DEP_REMAIN;
   1273 
   1274 			DBG_CALL(Dbg_file_hdl_action(ghp, lmp, flag, 0));
   1275 
   1276 			/*
   1277 			 * If this object contains any private handles, remove
   1278 			 * them now.
   1279 			 */
   1280 			for (APLIST_TRAVERSE(HANDLES(lmp), idx3, ghp3)) {
   1281 				if (ghp3->gh_flags & GPH_PRIVATE)
   1282 					free_hdl(ghp3);
   1283 			}
   1284 		}
   1285 	}
   1286 
   1287 	/*
   1288 	 * If there are objects to be deleted process their .fini's.
   1289 	 */
   1290 	if (delcnt) {
   1291 		Rt_map	**tobj;
   1292 
   1293 		/*
   1294 		 * If we're being audited tell the audit library that we're
   1295 		 * about to go deleting dependencies.
   1296 		 */
   1297 		if (clmp && ((LIST(clmp)->lm_tflags | AFLAGS(clmp)) &
   1298 		    LML_TFLG_AUD_ACTIVITY))
   1299 			audit_activity(clmp, LA_ACT_DELETE);
   1300 
   1301 		/*
   1302 		 * Sort and fire all fini's of the objects selected for
   1303 		 * deletion.  Note that we have to start our search from the
   1304 		 * link-map head - there's no telling whether this object has
   1305 		 * dependencies on objects that were loaded before it and which
   1306 		 * can now be deleted.  If the tsort() fails because of an
   1307 		 * allocation error then that might just be a symptom of why
   1308 		 * we're here in the first place - forgo the fini's but
   1309 		 * continue to try cleaning up.
   1310 		 */
   1311 		lml->lm_flags |= LML_FLG_OBJDELETED;
   1312 
   1313 		if (((tobj = tsort(lml->lm_head, delcnt,
   1314 		    (RT_SORT_DELETE | RT_SORT_FWD))) != NULL) &&
   1315 		    (tobj != (Rt_map **)S_ERROR)) {
   1316 			error = purge_exit_handlers(lml, tobj);
   1317 			call_fini(lml, tobj);
   1318 		}
   1319 
   1320 		/*
   1321 		 * Audit the closure of the dlopen'ed object to any local
   1322 		 * auditors.  Any global auditors would have been caught by
   1323 		 * call_fini(), but as the link-maps CALLERS was removed
   1324 		 * already we do the local auditors explicitly.
   1325 		 */
   1326 		for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
   1327 			Grp_hdl	*ghp = ghp2;
   1328 			Rt_map	*dlmp = ghp->gh_ownlmp;
   1329 
   1330 			if (clmp && dlmp &&
   1331 			    ((LIST(dlmp)->lm_flags & LML_FLG_NOAUDIT) == 0) &&
   1332 			    (AFLAGS(clmp) & LML_TFLG_AUD_OBJCLOSE))
   1333 				_audit_objclose(AUDITORS(clmp)->ad_list, dlmp);
   1334 		}
   1335 	}
   1336 
   1337 	/*
   1338 	 * Now that .fini processing (which may have involved new bindings)
   1339 	 * is complete, remove all inter-dependency lists from those objects
   1340 	 * selected for deletion.
   1341 	 */
   1342 	for (APLIST_TRAVERSE(lmalp, idx1, lmp)) {
   1343 		Dyninfo	*dip;
   1344 		uint_t	cnt, max;
   1345 
   1346 		if (FLAGS(lmp) & FLG_RT_DELETE)
   1347 			remove_lists(lmp, 0);
   1348 
   1349 		/*
   1350 		 * Determine whether we're dealing with a filter, and if so
   1351 		 * process any inter-dependencies with its filtee's.
   1352 		 */
   1353 		if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0)
   1354 			continue;
   1355 
   1356 		dip = DYNINFO(lmp);
   1357 		max = DYNINFOCNT(lmp);
   1358 
   1359 		for (cnt = 0; cnt < max; cnt++, dip++) {
   1360 			Alist	*falp;
   1361 			Aliste	idx2;
   1362 			Pdesc	*pdp;
   1363 
   1364 			if (((falp = (Alist *)dip->di_info) == NULL) ||
   1365 			    ((dip->di_flags & MSK_DI_FILTER) == 0))
   1366 				continue;
   1367 
   1368 			for (ALIST_TRAVERSE(falp, idx2, pdp)) {
   1369 				Grp_hdl	*ghp;
   1370 
   1371 				if ((pdp->pd_plen == 0) ||
   1372 				    ((ghp = (Grp_hdl *)pdp->pd_info) == NULL))
   1373 					continue;
   1374 
   1375 				/*
   1376 				 * Determine whether this filtee's handle is a
   1377 				 * part of the list of handles being deleted.
   1378 				 */
   1379 				if (aplist_test(&ghalp, ghp, 0) == ALE_EXISTS) {
   1380 					/*
   1381 					 * If this handle exists on the deletion
   1382 					 * list, then it has been removed.  If
   1383 					 * this filter isn't going to be
   1384 					 * deleted, sever its reference to the
   1385 					 * handle.
   1386 					 */
   1387 					pdp->pd_info = NULL;
   1388 				} else {
   1389 					/*
   1390 					 * If this handle isn't on the deletion
   1391 					 * list, then it must still exist.  If
   1392 					 * this filter is being deleted, make
   1393 					 * sure the filtees reference count
   1394 					 * gets decremented.
   1395 					 */
   1396 					if (FLAGS(lmp) & FLG_RT_DELETE) {
   1397 						(void) dlclose_core(ghp,
   1398 						    lmp, lml);
   1399 					}
   1400 				}
   1401 			}
   1402 		}
   1403 	}
   1404 
   1405 	/*
   1406 	 * If called from dlclose(), determine if there are already handles on
   1407 	 * the orphans list that we can reinvestigate.
   1408 	 */
   1409 	if ((removed == 0) && aplist_nitems(hdl_alp[HDLIST_ORP]))
   1410 		orphans = 1;
   1411 	else
   1412 		orphans = 0;
   1413 
   1414 	/*
   1415 	 * Finally remove any handle infrastructure and remove any objects
   1416 	 * marked for deletion.
   1417 	 */
   1418 	for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
   1419 		Grp_hdl	*ghp = ghp2;
   1420 
   1421 		/*
   1422 		 * If we're not dealing with orphaned handles remove this handle
   1423 		 * from its present handle list.
   1424 		 */
   1425 		if (removed == 0) {
   1426 			uintptr_t ndx;
   1427 
   1428 			/* LINTED */
   1429 			ndx = (uintptr_t)ghp % HDLIST_SZ;
   1430 			(void) aplist_delete_value(hdl_alp[ndx], ghp);
   1431 		}
   1432 
   1433 		/*
   1434 		 * Traverse each handle dependency.  Retain the dependencies
   1435 		 * flags to insure we don't delete any parents (the flags
   1436 		 * information is deleted as part of the alist removal that
   1437 		 * occurs before we inspect the object for deletion).
   1438 		 */
   1439 		for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
   1440 			uint_t	flags = gdp->gd_flags;
   1441 
   1442 			if ((flags & GPD_REMOVE) == 0)
   1443 				continue;
   1444 
   1445 			lmp = gdp->gd_depend;
   1446 			rmcnt++;
   1447 
   1448 			/*
   1449 			 * If this object is the owner of the handle break that
   1450 			 * association in case the handle is retained.
   1451 			 */
   1452 			if (ghp->gh_ownlmp == lmp) {
   1453 				(void) aplist_delete_value(HANDLES(lmp), ghp);
   1454 				ghp->gh_ownlmp = NULL;
   1455 			}
   1456 
   1457 			(void) aplist_delete_value(GROUPS(lmp), ghp);
   1458 			alist_delete(ghp->gh_depends, &idx2);
   1459 
   1460 			/*
   1461 			 * Complete the link-map deletion if appropriate.
   1462 			 */
   1463 			if ((FLAGS(lmp) & FLG_RT_DELETE) &&
   1464 			    ((flags & GPD_PARENT) == 0)) {
   1465 				tls_modaddrem(lmp, TM_FLG_MODREM);
   1466 				remove_so(LIST(lmp), lmp);
   1467 			}
   1468 		}
   1469 
   1470 		/*
   1471 		 * If we've deleted all the dependencies of the handle, finalize
   1472 		 * the cleanup by removing the handle itself.
   1473 		 *
   1474 		 * Otherwise we're left with a handle containing one or more
   1475 		 * objects that can not be deleted (they're in use by other
   1476 		 * handles, non-deletable, etc.), but require to remain a part
   1477 		 * of this group to allow them to continue binding to one
   1478 		 * another.
   1479 		 *
   1480 		 * If the handles reference count is zero, or represents a
   1481 		 * link-map list (dlopen(0)), then move that handle to the
   1482 		 * orphans list.  Should another dlclose() operation occur that
   1483 		 * results in the removal of handle descriptors, these orphan
   1484 		 * handles are re-examined to determine if their deletion can
   1485 		 * be completed.
   1486 		 */
   1487 		if (ghp->gh_depends->al_nitems == 0) {
   1488 			free(ghp->gh_depends);
   1489 			free(ghp);
   1490 
   1491 		} else if ((ghp->gh_refcnt == 0) &&
   1492 		    ((ghp->gh_flags & GPH_ZERO) == 0)) {
   1493 			/*
   1494 			 * Move this handle to the orphans list.
   1495 			 */
   1496 			(void) aplist_append(&hdl_alp[HDLIST_ORP], ghp,
   1497 			    AL_CNT_HANDLES);
   1498 
   1499 			if (DBG_ENABLED) {
   1500 				DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ORPHAN));
   1501 				for (ALIST_TRAVERSE(ghp->gh_depends, idx1, gdp))
   1502 					DBG_CALL(Dbg_file_hdl_action(ghp,
   1503 					    gdp->gd_depend, DBG_DEP_ORPHAN, 0));
   1504 			}
   1505 		}
   1506 	}
   1507 
   1508 	/*
   1509 	 * If no handle descriptors got removed there's no point in looking for
   1510 	 * orphans to process.
   1511 	 */
   1512 	if (rmcnt == 0)
   1513 		orphans = 0;
   1514 
   1515 	/*
   1516 	 * Cleanup any alists we've created.
   1517 	 */
   1518 	remove_collect(ghalp, lmalp);
   1519 
   1520 	/*
   1521 	 * If orphan processing isn't required we're done.  If our processing
   1522 	 * originated from investigating orphans, return the number of handle
   1523 	 * descriptors removed as an indication whether orphan processing
   1524 	 * should continue.
   1525 	 */
   1526 	if (orphans == 0) {
   1527 		if (removed)
   1528 			*removed = rmcnt;
   1529 		return (error);
   1530 	}
   1531 
   1532 	/*
   1533 	 * Traverse the orphans list as many times as necessary until no
   1534 	 * handle removals occur.
   1535 	 */
   1536 	do {
   1537 		APlist		*alp;
   1538 		Aliste		idx;
   1539 		Grp_hdl		*ghp, *oghp = NULL;
   1540 		int		title = 0;
   1541 
   1542 		/*
   1543 		 * Effectively clean the HDLIST_ORP list.  Any object that can't
   1544 		 * be removed will be re-added to the list.
   1545 		 */
   1546 		alp = hdl_alp[HDLIST_ORP];
   1547 		hdl_alp[HDLIST_ORP] = NULL;
   1548 
   1549 		rescan = 0;
   1550 		for (APLIST_TRAVERSE(alp, idx, ghp)) {
   1551 			int	_error, _remove;
   1552 
   1553 			if (title++ == 0)
   1554 				DBG_CALL(Dbg_file_del_rescan(ghp->gh_ownlml));
   1555 
   1556 			if (oghp) {
   1557 				(void) aplist_delete_value(alp, oghp);
   1558 				oghp = NULL;
   1559 			}
   1560 
   1561 			if (((_error = remove_hdl(ghp, clmp, &_remove)) != 0) &&
   1562 			    (error == 0))
   1563 				error = _error;
   1564 
   1565 			if (_remove)
   1566 				rescan++;
   1567 
   1568 			oghp = ghp;
   1569 		}
   1570 		if (oghp) {
   1571 			(void) aplist_delete_value(alp, oghp);
   1572 			oghp = NULL;
   1573 		}
   1574 		if (alp)
   1575 			free((void *)alp);
   1576 
   1577 	} while (rescan && aplist_nitems(hdl_alp[HDLIST_ORP]));
   1578 
   1579 	return (error);
   1580 }
   1581