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