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