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