dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / sgs / rtld / common / remove.c
blobe60c05adb2b294d685592933f9685b9d60be88c6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Remove objects. Objects need removal from a process as part of:
29 * - a dlclose() request
31 * - tearing down a dlopen(), lazy-load, or filter hierarchy that failed to
32 * completely load
34 * Any other failure condition will result in process exit (in which case all
35 * we have to do is execute the fini's - tear down is unnecessary).
37 * Any removal of objects is therefore associated with a dlopen() handle. There
38 * is a small window between creation of the first dlopen() object and creating
39 * its handle (in which case remove_so() can get rid of the new link-map if
40 * necessary), but other than this all object removal is driven by inspecting
41 * the components of a handle.
43 * Things to note. The creation of a link-map, and its addition to the link-map
44 * list occurs in {elf|aout}_new_lm(), if this returns success the link-map is
45 * valid and added, otherwise any steps (allocations) in the process of creating
46 * the link-map would have been undone. If a failure occurs between creating
47 * the link-map and adding it to a handle, remove_so() is called to remove the
48 * link-map. If a failures occurs after a handle have been created,
49 * remove_hdl() is called to remove the handle and the link-map.
52 #include <string.h>
53 #include <stdio.h>
54 #include <unistd.h>
55 #include <dlfcn.h>
56 #include <sys/debug.h>
57 #include <sys/avl.h>
58 #include <libc_int.h>
59 #include <debug.h>
60 #include "_rtld.h"
61 #include "_audit.h"
62 #include "_elf.h"
63 #include "msg.h"
66 * Atexit callback provided by libc. As part of dlclose() determine the address
67 * ranges of all objects that are to be deleted. Pass this information to
68 * libc's pre-atexit routine. Libc will purge any registered atexit() calls
69 * related to those objects about to be deleted.
71 static int
72 purge_exit_handlers(Lm_list *lml, Rt_map **tobj)
74 uint_t num;
75 Rt_map **_tobj;
76 Lc_addr_range_t *addr, *_addr;
77 int error;
78 int (*fptr)(Lc_addr_range_t *, uint_t);
81 * Has a callback been established?
83 if ((fptr = lml->lm_lcs[CI_ATEXIT].lc_un.lc_func) == NULL)
84 return (0);
87 * Determine the total number of mapped segments that will be unloaded.
89 for (num = 0, _tobj = tobj; *_tobj != NULL; _tobj++) {
90 Rt_map *lmp = *_tobj;
92 num += MMAPCNT(lmp);
96 * Account for a null entry at the end of the address range array.
98 if (num++ == 0)
99 return (0);
102 * Allocate an array for the address range.
104 if ((addr = malloc(num * sizeof (Lc_addr_range_t))) == NULL)
105 return (1);
108 * Fill the address range with each loadable segments size and address.
110 for (_tobj = tobj, _addr = addr; *_tobj != NULL; _tobj++) {
111 Rt_map *lmp = *_tobj;
112 mmapobj_result_t *mpp = MMAPS(lmp);
113 uint_t ndx;
115 for (ndx = 0; ndx < MMAPCNT(lmp); ndx++, mpp++) {
116 _addr->lb = (void *)(uintptr_t)(mpp->mr_addr +
117 mpp->mr_offset);
118 _addr->ub = (void *)(uintptr_t)(mpp->mr_addr +
119 mpp->mr_msize);
120 _addr++;
123 _addr->lb = _addr->ub = 0;
125 leave(LIST(*tobj), 0);
126 error = (*fptr)(addr, (num - 1));
127 (void) enter(0);
130 * If we fail to converse with libc, generate an error message to
131 * satisfy any dlerror() usage.
133 if (error)
134 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_ATEXIT), error);
136 free(addr);
137 return (error);
141 * Break down an Alist containing pathname descriptors. In most instances, the
142 * Alist is removed completely. However, in some instances the alist is cleaned
143 * of all entries, but retained for later use.
145 void
146 remove_alist(Alist **alpp, int complete)
148 Alist *alp = *alpp;
150 if (alp) {
151 if (complete) {
152 free((void *)alp);
153 *alpp = NULL;
154 } else {
155 alist_reset(alp);
161 * Remove a link-map list descriptor. This is called to finalize the removal
162 * of an entire link-map list, after all link-maps have been removed, or none
163 * got added. As load_one() can process a list of potential candidate objects,
164 * the link-map descriptor must be maintained as each object is processed. Only
165 * after all objects have been processed can a failure condition finally tear
166 * down the link-map list descriptor.
168 void
169 remove_lml(Lm_list *lml)
171 if (lml && (lml->lm_head == NULL)) {
172 free(lml->lm_lmidstr);
173 free(lml->lm_alp);
174 free(lml->lm_lists);
175 free(lml->lm_aud_cookies);
178 * Cleanup any pending RTLDINFO in the case where it was
179 * allocated but not called (see _relocate_lmc()).
181 free(lml->lm_rti);
182 if (lml->lm_fpavl) {
184 * As we are freeing the link-map list, all nodes must
185 * have previously been removed.
187 ASSERT(avl_numnodes(lml->lm_fpavl) == 0);
188 free(lml->lm_fpavl);
190 (void) aplist_delete_value(dynlm_list, lml);
191 free(lml);
196 * Remove a link-map. This removes a link-map from its associated list and
197 * free's up the link-map itself. Note, all components that are freed are local
198 * to the link-map, no inter-link-map lists are operated on as these are all
199 * broken down by dlclose() while all objects are still mapped.
201 * This routine is called from dlclose() to zap individual link-maps after their
202 * interdependencies (DEPENDS(), CALLER(), handles, etc.) have been removed.
203 * This routine is also called from the bowels of load_one() in the case of a
204 * link-map creation failure.
206 void
207 remove_so(Lm_list *lml, Rt_map *lmp, Rt_map *clmp)
209 Dyninfo *dip;
211 if (lmp == NULL)
212 return;
215 * Unlink the link map from the link-map list.
217 if (lml && lmp)
218 lm_delete(lml, lmp, clmp);
221 * If this object contributed any local external vectors for the current
222 * link-map list, remove the vectors. If this object contributed any
223 * global external vectors we should find some new candidates, or leave
224 * this object lying around.
226 if (lml) {
227 int tag;
229 for (tag = 0; tag < CI_MAX; tag++) {
230 if (lml->lm_lcs[tag].lc_lmp == lmp) {
231 lml->lm_lcs[tag].lc_lmp = NULL;
232 lml->lm_lcs[tag].lc_un.lc_val = 0;
234 if (glcs[tag].lc_lmp == lmp) {
235 ASSERT(glcs[tag].lc_lmp != NULL);
236 glcs[tag].lc_lmp = NULL;
237 glcs[tag].lc_un.lc_val = 0;
242 DBG_CALL(Dbg_file_delete(lmp));
245 * If this object is an auditor, determine whether any link-map lists
246 * are maintaining cookies to represent this auditor. These cookies
247 * are established for local auditing preinit and activity events.
249 if (FLAGS(lmp) & FLG_RT_AUDIT) {
250 Lm_list *nlml;
251 Aliste idx1;
253 for (APLIST_TRAVERSE(dynlm_list, idx1, nlml)) {
254 Rt_map *hlmp = nlml->lm_head;
255 Audit_client *acp;
256 Aliste idx2;
258 if ((hlmp == NULL) || (FLAGS(hlmp) & FLG_RT_AUDIT))
259 continue;
261 for (ALIST_TRAVERSE(nlml->lm_aud_cookies, idx2, acp)) {
262 if (acp->ac_lmp != lmp) {
263 alist_delete(nlml->lm_aud_cookies,
264 &idx2);
265 break;
272 * If this is a temporary link-map, put in place to facilitate the
273 * link-edit or a relocatable object, then the link-map contains no
274 * information that needs to be cleaned up.
276 if (FLAGS(lmp) & FLG_RT_OBJECT)
277 return;
280 * Remove any FullpathNode AVL names if they still exist.
282 if (FPNODE(lmp))
283 fpavl_remove(lmp);
286 * Remove any alias names.
288 if (ALIAS(lmp))
289 free(ALIAS(lmp));
292 * Remove any of this objects filtee infrastructure. The filtees them-
293 * selves have already been removed.
295 if (((dip = DYNINFO(lmp)) != NULL) && (FLAGS1(lmp) & MSK_RT_FILTER)) {
296 uint_t cnt, max = DYNINFOCNT(lmp);
298 for (cnt = 0; cnt < max; cnt++, dip++) {
299 if ((dip->di_info == NULL) ||
300 ((dip->di_flags & MSK_DI_FILTER) == 0))
301 continue;
303 remove_alist((Alist **)&(dip->di_info), 1);
308 * Deallocate any remaining cruft and free the link-map.
310 if (RLIST(lmp))
311 remove_alist(&RLIST(lmp), 1);
313 if (AUDITORS(lmp))
314 audit_desc_cleanup(lmp);
315 if (AUDINFO(lmp))
316 audit_info_cleanup(lmp);
319 * Note that COPY_R() and COPY_S() reference the same memory
320 * location, and that we want to release the memory referenced
321 * without regard to which list it logically belongs to. We can
322 * use either pointer to do this.
324 if (COPY_R(lmp))
325 free(COPY_R(lmp));
328 * During a dlclose() any groups this object was a part of will have
329 * been torn down. However, we can get here to remove an object that
330 * has failed to load, perhaps because its addition to a handle failed.
331 * Therefore if this object indicates that its part of a group tear
332 * these associations down.
334 if (GROUPS(lmp) != NULL) {
335 Aliste idx1;
336 Grp_hdl *ghp;
338 for (APLIST_TRAVERSE(GROUPS(lmp), idx1, ghp)) {
339 Grp_desc *gdp;
340 Aliste idx2;
342 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
343 if (gdp->gd_depend != lmp)
344 continue;
346 alist_delete(ghp->gh_depends, &idx2);
347 break;
350 free(GROUPS(lmp));
352 if (HANDLES(lmp))
353 free(HANDLES(lmp));
356 * Clean up reglist if needed
358 if (reglist) {
359 Reglist *cur, *prv, *del;
361 cur = prv = reglist;
362 while (cur) {
363 if (cur->rl_lmp == lmp) {
364 del = cur;
365 if (cur == reglist) {
366 reglist = cur->rl_next;
367 cur = prv = reglist;
368 } else {
369 prv->rl_next = cur->rl_next;
370 cur = cur->rl_next;
372 free(del);
373 } else {
374 prv = cur;
375 cur = cur->rl_next;
381 * If this link map represents a relocatable object concatenation, then
382 * the image was simply generated in allocated memory. Free the memory.
383 * Note: memory maps were fabricated for the relocatable object, and
384 * the mapping infrastructure must be free'd, but there are no address
385 * mappings that must be unmapped.
387 * Otherwise, unmap the object.
389 if (FLAGS(lmp) & FLG_RT_IMGALLOC)
390 free((void *)ADDR(lmp));
392 if (CAPCHAIN(lmp))
393 free((void *)CAPCHAIN(lmp));
395 if (MMAPS(lmp)) {
396 if ((FLAGS(lmp) & FLG_RT_IMGALLOC) == 0)
397 unmap_obj(MMAPS(lmp), MMAPCNT(lmp));
398 free(MMAPS(lmp));
401 free(lmp);
405 * Traverse an objects dependency list removing callers and dependencies.
406 * There's a chicken and egg problem with tearing down link-maps. Any
407 * relationship between link-maps is maintained on a DEPENDS list, and an
408 * associated CALLERS list. These lists can't be broken down at the time a
409 * single link-map is removed, as any related link-map may have already been
410 * removed. Thus, lists between link-maps must be broken down before the
411 * individual link-maps themselves.
413 static void
414 remove_lists(Rt_map *lmp, int lazy)
416 Aliste idx1;
417 Bnd_desc *bdp;
420 * First, traverse this objects dependencies.
422 for (APLIST_TRAVERSE(DEPENDS(lmp), idx1, bdp)) {
423 Rt_map *dlmp = bdp->b_depend;
426 * Remove this object from the dependencies callers.
428 (void) aplist_delete_value(CALLERS(dlmp), bdp);
429 free(bdp);
431 if (DEPENDS(lmp)) {
432 free(DEPENDS(lmp));
433 DEPENDS(lmp) = NULL;
437 * Second, traverse this objects callers.
439 for (APLIST_TRAVERSE(CALLERS(lmp), idx1, bdp)) {
440 Rt_map *clmp = bdp->b_caller;
441 Dyninfo *dip;
444 * If we're removing an object that was triggered by a lazyload,
445 * remove the callers DYNINFO() entry and bump the lazy counts.
446 * This reinitialization of the lazy information allows a lazy
447 * object to be reloaded again later. Although we may be
448 * breaking down a group of lazyloaded objects because one has
449 * failed to relocate, it's possible that one or more of the
450 * individual objects can be reloaded without a problem.
452 if (lazy && ((dip = DYNINFO(clmp)) != NULL)) {
453 uint_t cnt, max = DYNINFOCNT(clmp);
455 for (cnt = 0; cnt < max; cnt++, dip++) {
456 if ((dip->di_flags & FLG_DI_LAZY) == 0)
457 continue;
459 if (dip->di_info == (void *)lmp) {
460 dip->di_info = NULL;
462 if (LAZY(clmp)++ == 0)
463 LIST(clmp)->lm_lazy++;
468 (void) aplist_delete_value(DEPENDS(clmp), bdp);
469 free(bdp);
471 if (CALLERS(lmp)) {
472 free(CALLERS(lmp));
473 CALLERS(lmp) = NULL;
478 * Delete any temporary link-map control list.
480 void
481 remove_cntl(Lm_list *lml, Aliste lmco)
483 Aliste _lmco = lmco;
484 #if DEBUG
485 Lm_cntl *lmc;
487 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
490 * This element should be empty.
492 ASSERT(lmc->lc_head == NULL);
493 #endif
494 alist_delete_by_offset(lml->lm_lists, &_lmco);
498 * If a lazy loaded object, or filtee fails to load, possibly because it, or
499 * one of its dependencies can't be relocated, then tear down any objects
500 * that are apart of this link-map control list.
502 static void
503 remove_incomplete(Lm_list *lml, Aliste lmco, Rt_map *clmp)
505 Rt_map *lmp;
506 Lm_cntl *lmc;
508 /* LINTED */
509 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
512 * If auditing is in effect, the loading of these objects might have
513 * resulted in la_objopen() events being posted. Normally, an
514 * la_objclose() event is posted after an object's .fini is executed,
515 * just before the objects are unloaded. These failed objects do not
516 * have their .fini's executed, but an la_objclose() event should still
517 * be posted to any auditors.
519 if ((lml->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_OBJCLOSE) {
520 for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp))
521 audit_objclose(lmp, clmp);
525 * Remove any lists that may point between objects.
527 for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp))
528 remove_lists(lmp, 1);
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.
535 while ((lmp = lmc->lc_head) != NULL)
536 remove_so(lml, lmp, clmp);
538 lmc->lc_head = lmc->lc_tail = NULL;
542 * Determine whether an object is deletable.
544 static int
545 is_deletable(APlist **lmalp, APlist **ghalp, Rt_map *lmp)
547 Aliste idx;
548 Bnd_desc *bdp;
549 Grp_hdl *ghp;
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.
557 if ((FLAGS(lmp) & FLG_RT_RELOCED) &&
558 (MODE(lmp) & RTLD_NODELETE) && (CNTL(lmp) == ALIST_OFF_DATA))
559 return (0);
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, by looking for objects with
570 * handles we can ferret out these outsiders.
572 for (APLIST_TRAVERSE(HANDLES(lmp), idx, ghp)) {
574 * If this is a private handle, then the handle isn't referenced
575 * from outside of the group of objects being deleted, and can
576 * be ignored when evaluating objects for deletion.
578 if (ghp->gh_flags & GPH_PRIVATE)
579 continue;
580 if (aplist_test(ghalp, ghp, 0) != ALE_EXISTS)
581 return (0);
585 * If this object is called by any object outside of the family of
586 * objects selected for deletion, it can't be deleted.
588 for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) {
589 if (aplist_test(lmalp, bdp->b_caller, 0) != ALE_EXISTS)
590 return (0);
594 * This object is a candidate for deletion.
596 return (1);
600 * Collect the groups (handles) and associated objects that are candidates for
601 * deletion. The criteria for deleting an object is whether it is only refer-
602 * enced from the objects within the groups that are candidates for deletion.
604 static int
605 gdp_collect(APlist **ghalpp, APlist **lmalpp, Grp_hdl *ghp1)
607 Aliste idx1;
608 Grp_desc *gdp;
609 int action;
612 * Add this group to our group collection. If it isn't added either an
613 * allocation has failed, or it already exists.
615 if ((action = aplist_test(ghalpp, ghp1, AL_CNT_GRPCLCT)) !=
616 ALE_CREATE)
617 return (action);
620 * Traverse the dependencies of the group and collect the associated
621 * objects.
623 for (ALIST_TRAVERSE(ghp1->gh_depends, idx1, gdp)) {
624 Rt_map *lmp = gdp->gd_depend;
627 * We only want to process dependencies for deletion. Although
628 * we want to purge group descriptors for parents, we don't want
629 * to analyze the parent itself for additional filters or
630 * deletion.
632 if ((gdp->gd_flags & GPD_PARENT) ||
633 ((gdp->gd_flags & GPD_ADDEPS) == 0))
634 continue;
636 if ((action = aplist_test(lmalpp, lmp, AL_CNT_GRPCLCT)) ==
637 ALE_ALLOCFAIL)
638 return (0);
639 if (action == ALE_EXISTS)
640 continue;
643 * If this object is a candidate for deletion, determine if the
644 * object provides any filtees. If so, the filter groups are
645 * added to the group collection.
647 * An object is a candidate for deletion if:
649 * - the object hasn't yet been relocated, in which case
650 * we're here to clean up a failed load, or
651 * - the object doesn't reside on the base link-map control
652 * list, in which case a group of objects, typically
653 * lazily loaded, or filtees, need cleaning up, or
654 * - the object isn't tagged as non-deletable.
656 if ((((FLAGS(lmp) & FLG_RT_RELOCED) == 0) ||
657 (CNTL(lmp) != ALIST_OFF_DATA) ||
658 ((MODE(lmp) & RTLD_NODELETE) == 0)) &&
659 (FLAGS1(lmp) & MSK_RT_FILTER)) {
660 Dyninfo *dip = DYNINFO(lmp);
661 uint_t cnt, max = DYNINFOCNT(lmp);
663 for (cnt = 0; cnt < max; cnt++, dip++) {
664 Alist *falp;
665 Aliste idx2;
666 Pdesc *pdp;
668 if (((falp = (Alist *)dip->di_info) == NULL) ||
669 ((dip->di_flags & MSK_DI_FILTER) == 0))
670 continue;
672 for (ALIST_TRAVERSE(falp, idx2, pdp)) {
673 Grp_hdl *ghp2;
675 if ((pdp->pd_plen == 0) || ((ghp2 =
676 (Grp_hdl *)pdp->pd_info) == NULL))
677 continue;
679 if (gdp_collect(ghalpp, lmalpp,
680 ghp2) == 0)
681 return (0);
686 return (1);
690 * Traverse the list of deletable candidates. If an object can't be deleted
691 * then neither can its dependencies or filtees. Any object that is cleared
692 * from being deleted drops the deletion count, plus, if there are no longer
693 * any deletions pending we can discontinue any further processing.
695 static int
696 remove_rescan(APlist *lmalp, APlist *ghalp, int *delcnt)
698 Aliste idx1;
699 Rt_map *lmp;
700 int rescan = 0;
702 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) {
703 Aliste idx2;
704 Bnd_desc *bdp;
705 Dyninfo *dip;
706 uint_t cnt, max;
708 if (FLAGS(lmp) & FLG_RT_DELETE)
709 continue;
712 * As this object can't be deleted, make sure its dependencies
713 * aren't deleted either.
715 for (APLIST_TRAVERSE(DEPENDS(lmp), idx2, bdp)) {
716 Rt_map *dlmp = bdp->b_depend;
718 if (FLAGS(dlmp) & FLG_RT_DELETE) {
719 FLAGS(dlmp) &= ~FLG_RT_DELETE;
720 if (--(*delcnt) == 0)
721 return (0);
722 rescan = 1;
727 * If this object is a filtee and one of its filters is outside
728 * of this dlclose family, then it can't be deleted either.
730 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0)
731 continue;
733 dip = DYNINFO(lmp);
734 max = DYNINFOCNT(lmp);
736 for (cnt = 0; cnt < max; cnt++, dip++) {
737 Alist *falp;
738 Pdesc *pdp;
740 if (((falp = (Alist *)dip->di_info) == NULL) ||
741 ((dip->di_flags & MSK_DI_FILTER) == 0))
742 continue;
744 for (ALIST_TRAVERSE(falp, idx2, pdp)) {
745 Aliste idx3;
746 Grp_hdl *ghp;
747 Grp_desc *gdp;
749 if ((pdp->pd_plen == 0) ||
750 ((ghp = (Grp_hdl *)pdp->pd_info) == NULL))
751 continue;
753 if (aplist_test(&ghalp, ghp, 0) ==
754 ALE_EXISTS)
755 continue;
757 for (ALIST_TRAVERSE(ghp->gh_depends, idx3,
758 gdp)) {
759 Rt_map *dlmp = gdp->gd_depend;
761 if (FLAGS(dlmp) & FLG_RT_DELETE) {
762 FLAGS(dlmp) &= ~FLG_RT_DELETE;
763 if (--(*delcnt) == 0)
764 return (0);
765 rescan = 1;
770 * Remove this group handle from our dynamic
771 * deletion list.
773 (void) aplist_delete_value(ghalp, ghp);
777 return (rescan);
781 * Cleanup any collection alists we've created.
783 static void
784 remove_collect(APlist *ghalp, APlist *lmalp)
786 free(ghalp);
787 free(lmalp);
791 * Remove a handle, leaving the associated objects intact.
793 void
794 free_hdl(Grp_hdl *ghp)
796 if (--(ghp->gh_refcnt) == 0) {
797 Grp_desc *gdp;
798 Aliste idx;
799 uintptr_t ndx;
801 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
802 Rt_map *lmp = gdp->gd_depend;
804 if (ghp->gh_ownlmp == lmp)
805 (void) aplist_delete_value(HANDLES(lmp), ghp);
806 (void) aplist_delete_value(GROUPS(lmp), ghp);
808 (void) free(ghp->gh_depends);
810 /* LINTED */
811 ndx = (uintptr_t)ghp % HDLIST_SZ;
812 (void) aplist_delete_value(hdl_alp[ndx], ghp);
814 (void) free(ghp);
819 * If a load operation, using a new link-map control list, has failed, then
820 * forcibly remove the failed objects. This failure can occur as a result
821 * of a lazy load, a dlopen(), or a filtee load, once the application is
822 * running. If the link-map control list has not yet started relocation, then
823 * cleanup is simply a process of removing all the objects from the control
824 * list. If relocation has begun, then other loads may have been triggered to
825 * satisfy the relocations, and thus we need to break down the control list
826 * using handles.
828 * The objects associated with this load must be part of a unique handle. In
829 * the case of a dlopen() or filtee request, a handle will have been created.
830 * For a lazyload request, a handle must be generated so that the remove
831 * process can use the handle.
833 * During the course of processing these objects, other objects (handles) may
834 * have been loaded to satisfy relocation requirements. After these families
835 * have successfully loaded, they will have been propagated to the same link-map
836 * control list. The failed objects need to be removed from this list, while
837 * any successfully loaded families can be left alone, and propagated to the
838 * previous link-map control list. By associating each load request with a
839 * handle, we can isolate the failed objects while not interfering with any
840 * successfully loaded families.
842 void
843 remove_lmc(Lm_list *lml, Rt_map *clmp, Aliste lmco, const char *name)
845 Grp_hdl *ghp;
846 Grp_desc *gdp;
847 Aliste idx;
848 Lm_cntl *lmc;
849 Rt_map *lmp;
852 * Determine the link-map control list, and whether any object has been
853 * added to this list.
855 /* LINTED */
856 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
857 if (lmc->lc_head == NULL)
858 return;
860 DBG_CALL(Dbg_file_cleanup(lml, name, lmco));
863 * Obtain a handle for the first object on the link-map control list.
864 * If none exists (which would occur from a lazy load request), and
865 * the link-map control list is being relocated, create a handle.
867 lmp = lmc->lc_head;
868 if (HANDLES(lmp)) {
869 ghp = (Grp_hdl *)HANDLES(lmp)->apl_data[0];
872 * If this is a private handle, remove this state, so as to
873 * prevent any attempt to remove the handle more than once.
875 ghp->gh_flags &= ~GPH_PRIVATE;
877 } else if (lmc->lc_flags & LMC_FLG_RELOCATING) {
879 * Establish a handle, and should anything fail, fall through
880 * to remove the link-map control list.
882 if (((ghp = hdl_create(lml, lmc->lc_head, NULL, GPH_PUBLIC,
883 GPD_ADDEPS, 0)) == NULL) ||
884 (hdl_initialize(ghp, lmc->lc_head, 0, 0) == 0))
885 lmc->lc_flags &= ~LMC_FLG_RELOCATING;
886 } else {
887 ghp = NULL;
891 * If relocation hasn't begun, simply remove all the objects from this
892 * list, and any handle that may have been created.
894 if ((lmc->lc_flags & LMC_FLG_RELOCATING) == 0) {
895 remove_incomplete(lml, lmco, clmp);
897 if (ghp) {
898 ghp->gh_refcnt = 1;
899 free_hdl(ghp);
901 return;
904 ASSERT(ghp != NULL);
907 * As the objects of this handle are being forcibly removed, first
908 * remove any associations to objects on parent link-map control
909 * lists. This breaks the bond between a caller and a hierarchy of
910 * dependencies represented by the handle, thus the caller doesn't lock
911 * the hierarchy and prevent their deletion from the generic handle
912 * processing or remove_hdl().
914 * This scenario can be produced when the relocation of a object
915 * results in vectoring through a filter that is already loaded. The
916 * filtee may be on the link-map list that is presently being processed,
917 * however an association between the filter and filtee would have been
918 * established during filtee processing. It is this association that
919 * must be broken to allow the objects on this link-map list to be
920 * removed.
922 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) {
923 Rt_map *lmp = gdp->gd_depend;
926 * If this object has not been relocated, break down any
927 * dependency relationships the object might have established.
929 if ((FLAGS(lmp) & FLG_RT_RELOCED) == 0)
930 remove_lists(lmp, 1);
932 if (CNTL(lmp) == lmco)
933 continue;
935 if (gdp->gd_flags & GPD_FILTER) {
936 Dyninfo *dip = DYNINFO(lmp);
937 uint_t cnt, max = DYNINFOCNT(lmp);
939 for (cnt = 0; cnt < max; cnt++, dip++) {
940 Alist *falp;
941 Aliste idx2;
942 Pdesc *pdp;
944 if (((falp = (Alist *)dip->di_info) == NULL) ||
945 ((dip->di_flags & MSK_DI_FILTER) == 0))
946 continue;
948 for (ALIST_TRAVERSE(falp, idx2, pdp)) {
949 if ((Grp_hdl *)pdp->pd_info == ghp) {
950 pdp->pd_info = NULL;
951 break;
956 (void) aplist_delete_value(GROUPS(lmp), ghp);
957 alist_delete(ghp->gh_depends, &idx);
961 * Having removed any callers, set the group handle reference count to
962 * one, and let the generic handle remover delete the associated
963 * objects.
965 ghp->gh_refcnt = 1;
966 (void) remove_hdl(ghp, clmp, NULL);
969 * If this link-map control list still contains objects, determine the
970 * previous control list and move the objects.
972 if (lmc->lc_head) {
973 Lm_cntl *plmc;
974 Aliste plmco;
976 plmco = lmco - lml->lm_lists->al_size;
977 /* LINTED */
978 plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco);
980 lm_move(lml, lmco, plmco, lmc, plmc);
985 * Remove the objects associated with a handle. There are two goals here, to
986 * delete the objects associated with the handle, and to remove the handle
987 * itself. Things get a little more complex if the objects selected for
988 * deletion are filters, in this case we also need to collect their filtees,
989 * and process the combined groups as a whole. But, care still must be exer-
990 * cised to make sure any filtees found aren't being used by filters outside of
991 * the groups we've collect. The series of events is basically:
993 * - Determine the groups (handles) that might be deletable.
995 * - Determine the objects of these handles that can be deleted.
997 * - Fire the fini's of those objects selected for deletion.
999 * - Remove all inter-dependency linked lists while the objects link-maps
1000 * are still available.
1002 * - Remove all deletable objects link-maps and unmap the objects themselves.
1004 * - Remove the handle descriptors for each deleted object, and hopefully
1005 * the whole handle.
1007 * A handle that can't be deleted is added to an orphans list. This list is
1008 * revisited any time another dlclose() request results in handle descriptors
1009 * being deleted. These deleted descriptors can be sufficient to allow the
1010 * final deletion of the orphaned handles.
1013 remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
1015 Rt_map *lmp;
1016 int rescan = 0;
1017 int delcnt = 0, rmcnt = 0, error = 0, orphans;
1018 APlist *lmalp = NULL, *ghalp = NULL;
1019 Aliste idx1, idx2;
1020 Grp_hdl *ghp2;
1021 Grp_desc *gdp;
1022 Lm_list *lml = NULL;
1025 * Generate the family of groups and objects that are candidates for
1026 * deletion. This consists of the objects that are explicitly defined
1027 * as dependencies of this handle, plus any filtee handles and their
1028 * associated objects.
1030 if (gdp_collect(&ghalp, &lmalp, ghp) == 0) {
1031 remove_collect(ghalp, lmalp);
1032 return (0);
1035 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE));
1038 * Traverse the groups we've collected to determine if any filtees are
1039 * included. If so, and the filtee handle is in use by a filter outside
1040 * of the family of objects collected for this deletion, it can not be
1041 * removed.
1043 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
1044 Grp_hdl *ghp = ghp2;
1046 DBG_CALL(Dbg_file_hdl_collect(ghp, 0));
1048 if ((ghp->gh_flags & GPH_FILTEE) == 0)
1049 continue;
1052 * Special case for ld.so.1. There can be multiple instances of
1053 * libdl.so.1 using this handle, so although we want the handles
1054 * reference count to be decremented, we don't want the handle
1055 * removed.
1057 if (ghp->gh_flags & GPH_LDSO) {
1058 DBG_CALL(Dbg_file_hdl_collect(ghp,
1059 NAME(lml_rtld.lm_head)));
1060 aplist_delete(ghalp, &idx1);
1061 continue;
1064 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
1065 Grp_hdl *ghp3;
1066 Aliste idx3;
1069 * Determine whether this dependency is the filtee's
1070 * parent filter, and that it isn't also an explicit
1071 * dependency (in which case it would have added its own
1072 * dependencies to the handle).
1074 if ((gdp->gd_flags &
1075 (GPD_FILTER | GPD_ADDEPS)) != GPD_FILTER)
1076 continue;
1078 lmp = gdp->gd_depend;
1080 if (FLAGS(lmp) & FLG_RT_DELETE)
1081 continue;
1083 if (aplist_test(&lmalp, lmp, 0) == ALE_EXISTS)
1084 continue;
1087 * Remove this group handle from our dynamic deletion
1088 * list. In addition, recompute the list of objects
1089 * that are candidates for deletion to continue this
1090 * group verification.
1092 DBG_CALL(Dbg_file_hdl_collect(ghp, NAME(lmp)));
1093 aplist_delete(ghalp, &idx1);
1095 free(lmalp);
1096 lmalp = NULL;
1097 for (APLIST_TRAVERSE(ghalp, idx3, ghp3)) {
1098 Aliste idx4;
1099 Grp_desc *gdp4;
1101 for (ALIST_TRAVERSE(ghp3->gh_depends,
1102 idx4, gdp4)) {
1103 if ((gdp4->gd_flags & GPD_ADDEPS) == 0)
1104 continue;
1105 if (aplist_test(&lmalp, gdp4->gd_depend,
1106 AL_CNT_GRPCLCT) == ALE_ALLOCFAIL) {
1107 remove_collect(ghalp, lmalp);
1108 return (0);
1112 break;
1117 * Now that we've collected all the handles dependencies, traverse the
1118 * collection determining whether they are a candidate for deletion.
1120 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) {
1122 * Establish which link-map list we're dealing with for later
1123 * .fini processing.
1125 if (lml == NULL)
1126 lml = LIST(lmp);
1129 * If an object isn't a candidate for deletion we'll have to
1130 * rescan the handle insuring that this objects dependencies
1131 * aren't deleted either.
1133 if (is_deletable(&lmalp, &ghalp, lmp)) {
1134 FLAGS(lmp) |= FLG_RT_DELETE;
1135 delcnt++;
1136 } else
1137 rescan = 1;
1141 * Rescan the handle if any objects where found non-deletable.
1143 while (rescan)
1144 rescan = remove_rescan(lmalp, ghalp, &delcnt);
1147 * Now that we have determined the number of groups that are candidates
1148 * for removal, mark each group descriptor as a candidate for removal
1149 * from the group.
1151 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
1152 for (ALIST_TRAVERSE(ghp2->gh_depends, idx2, gdp))
1153 gdp->gd_flags |= GPD_REMOVE;
1157 * Now that we know which objects on this handle can't be deleted
1158 * determine whether they still need to remain identified as belonging
1159 * to this group to be able to continue binding to one another.
1161 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
1162 Grp_hdl *ghp = ghp2;
1164 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
1165 Aliste idx3;
1166 Bnd_desc *bdp;
1168 lmp = gdp->gd_depend;
1170 if (FLAGS(lmp) & FLG_RT_DELETE)
1171 continue;
1173 for (APLIST_TRAVERSE(DEPENDS(lmp), idx3, bdp)) {
1174 Aliste idx4;
1175 Grp_desc *gdp4;
1176 Rt_map *dlmp = bdp->b_depend;
1179 * If this dependency (dlmp) can be referenced
1180 * by the caller (clmp) without being part of
1181 * this group (ghp) then belonging to this group
1182 * is no longer necessary. This can occur when
1183 * objects are part of multiple handles, or if a
1184 * previously deleted handle was moved to the
1185 * orphan list and has been reopened. Note,
1186 * first make sure the caller can reference the
1187 * dependency with this group, if it can't we
1188 * must be bound to a filtee, so there's no need
1189 * to remain a part of this group either.
1191 if ((callable(lmp, dlmp, 0, 0) == 0) ||
1192 callable(lmp, dlmp, ghp, 0))
1193 continue;
1195 if (gdp->gd_flags & GPD_REMOVE)
1196 gdp->gd_flags &= ~GPD_REMOVE;
1198 for (ALIST_TRAVERSE(ghp->gh_depends,
1199 idx4, gdp4)) {
1200 if (gdp4->gd_depend != dlmp)
1201 continue;
1203 if (gdp4->gd_flags & GPD_REMOVE)
1204 gdp4->gd_flags &= ~GPD_REMOVE;
1211 * If the owner of a handle can't be deleted and it's handle descriptor
1212 * must remain also, don't delete the handle at all. Leave it for
1213 * possible later use. Although it's left intact, it will still be
1214 * moved to the orphans list, as we might be able to revisit it on later
1215 * dlclose() operations and finally remove the underlying objects. Note
1216 * that the handle still remains attached to the owner via the HANDLES
1217 * list, so that it can be re-associated to the owner if a dlopen()
1218 * of this object reoccurs.
1220 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
1221 Grp_hdl *ghp = ghp2;
1224 * If this handle is already an orphan, or if it's owner is
1225 * deletable there's no need to inspect its dependencies.
1227 if ((ghp->gh_ownlmp == NULL) ||
1228 (FLAGS(ghp->gh_ownlmp) & FLG_RT_DELETE))
1229 continue;
1232 * Make sure all handle dependencies aren't removed or the
1233 * dependencies themselves aren't deleted.
1235 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
1236 lmp = gdp->gd_depend;
1239 * The first dependency of a non-orphaned handle is the
1240 * owner. If the handle descriptor for this isn't
1241 * required there's no need to look at any other of the
1242 * handles dependencies.
1244 if ((lmp == ghp->gh_ownlmp) &&
1245 (gdp->gd_flags & GPD_REMOVE))
1246 break;
1248 if (gdp->gd_flags & GPD_REMOVE)
1249 gdp->gd_flags &= ~GPD_REMOVE;
1250 if (FLAGS(lmp) & FLG_RT_DELETE) {
1251 FLAGS(lmp) &= ~FLG_RT_DELETE;
1252 delcnt--;
1258 * Final scan of objects to see if any objects are to to be deleted.
1259 * Also - display diagnostic information on what operations are to be
1260 * performed on the collected handles before firing .fini's (which
1261 * produces additional diagnostics).
1263 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
1264 Grp_hdl *ghp = ghp2;
1266 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE));
1268 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
1269 Grp_hdl *ghp3;
1270 Aliste idx3;
1271 int flag;
1273 lmp = gdp->gd_depend;
1276 * Note, we must never delete a parent. The parent
1277 * may already be tagged for deletion from a previous
1278 * dlclose(). That dlclose has triggered this dlclose(),
1279 * but the parents deletion is the responsibility of the
1280 * previous dlclose(), not this one.
1282 if ((FLAGS(lmp) & FLG_RT_DELETE) &&
1283 ((gdp->gd_flags & GPD_PARENT) == 0)) {
1284 flag = DBG_DEP_DELETE;
1287 * Remove any pathnames from the FullpathNode
1288 * AVL tree. As we're about to fire .fini's,
1289 * it's possible this object will be required
1290 * again, in which case we want to make sure a
1291 * new version of the object gets loaded.
1293 if (FPNODE(lmp))
1294 fpavl_remove(lmp);
1295 } else if (gdp->gd_flags & GPD_REMOVE)
1296 flag = DBG_DEP_REMOVE;
1297 else
1298 flag = DBG_DEP_REMAIN;
1300 DBG_CALL(Dbg_file_hdl_action(ghp, lmp, flag, 0));
1303 * If this object contains any private handles, remove
1304 * them now.
1306 for (APLIST_TRAVERSE(HANDLES(lmp), idx3, ghp3)) {
1307 if (ghp3->gh_flags & GPH_PRIVATE)
1308 free_hdl(ghp3);
1314 * If there are objects to be deleted process their .fini's.
1316 if (delcnt) {
1317 Rt_map **tobj;
1320 * Sort and fire all fini's of the objects selected for
1321 * deletion. Note that we have to start our search from the
1322 * link-map head - there's no telling whether this object has
1323 * dependencies on objects that were loaded before it and which
1324 * can now be deleted. If the tsort() fails because of an
1325 * allocation error then that might just be a symptom of why
1326 * we're here in the first place - forgo the fini's but
1327 * continue to try cleaning up.
1329 lml->lm_flags |= LML_FLG_OBJDELETED;
1331 if (((tobj = tsort(lml->lm_head, delcnt,
1332 (RT_SORT_DELETE | RT_SORT_FWD))) != NULL) &&
1333 (tobj != (Rt_map **)S_ERROR)) {
1334 error = purge_exit_handlers(lml, tobj);
1335 call_fini(lml, tobj, clmp);
1340 * Now that .fini processing (which may have involved new bindings)
1341 * is complete, remove all inter-dependency lists from those objects
1342 * selected for deletion.
1344 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) {
1345 Dyninfo *dip;
1346 uint_t cnt, max;
1348 if (FLAGS(lmp) & FLG_RT_DELETE)
1349 remove_lists(lmp, 0);
1352 * Determine whether we're dealing with a filter, and if so
1353 * process any inter-dependencies with its filtee's.
1355 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0)
1356 continue;
1358 dip = DYNINFO(lmp);
1359 max = DYNINFOCNT(lmp);
1361 for (cnt = 0; cnt < max; cnt++, dip++) {
1362 Alist *falp;
1363 Aliste idx2;
1364 Pdesc *pdp;
1366 if (((falp = (Alist *)dip->di_info) == NULL) ||
1367 ((dip->di_flags & MSK_DI_FILTER) == 0))
1368 continue;
1370 for (ALIST_TRAVERSE(falp, idx2, pdp)) {
1371 Grp_hdl *ghp;
1373 if ((pdp->pd_plen == 0) ||
1374 ((ghp = (Grp_hdl *)pdp->pd_info) == NULL))
1375 continue;
1378 * Determine whether this filtee's handle is a
1379 * part of the list of handles being deleted.
1381 if (aplist_test(&ghalp, ghp, 0) == ALE_EXISTS) {
1383 * If this handle exists on the deletion
1384 * list, then it has been removed. If
1385 * this filter isn't going to be
1386 * deleted, sever its reference to the
1387 * handle.
1389 pdp->pd_info = NULL;
1390 } else {
1392 * If this handle isn't on the deletion
1393 * list, then it must still exist. If
1394 * this filter is being deleted, make
1395 * sure the filtees reference count
1396 * gets decremented.
1398 if (FLAGS(lmp) & FLG_RT_DELETE) {
1399 (void) dlclose_core(ghp,
1400 lmp, lml);
1408 * If called from dlclose(), determine if there are already handles on
1409 * the orphans list that we can reinvestigate.
1411 if ((removed == 0) && aplist_nitems(hdl_alp[HDLIST_ORP]))
1412 orphans = 1;
1413 else
1414 orphans = 0;
1417 * Finally remove any handle infrastructure and remove any objects
1418 * marked for deletion.
1420 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) {
1421 Grp_hdl *ghp = ghp2;
1424 * If we're not dealing with orphaned handles remove this handle
1425 * from its present handle list.
1427 if (removed == 0) {
1428 uintptr_t ndx;
1430 /* LINTED */
1431 ndx = (uintptr_t)ghp % HDLIST_SZ;
1432 (void) aplist_delete_value(hdl_alp[ndx], ghp);
1436 * Traverse each handle dependency. Retain the dependencies
1437 * flags to insure we don't delete any parents (the flags
1438 * information is deleted as part of the alist removal that
1439 * occurs before we inspect the object for deletion).
1441 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) {
1442 uint_t flags = gdp->gd_flags;
1444 if ((flags & GPD_REMOVE) == 0)
1445 continue;
1447 lmp = gdp->gd_depend;
1448 rmcnt++;
1451 * If this object is the owner of the handle break that
1452 * association in case the handle is retained.
1454 if (ghp->gh_ownlmp == lmp) {
1455 (void) aplist_delete_value(HANDLES(lmp), ghp);
1456 ghp->gh_ownlmp = NULL;
1459 (void) aplist_delete_value(GROUPS(lmp), ghp);
1460 alist_delete(ghp->gh_depends, &idx2);
1463 * Complete the link-map deletion if appropriate.
1465 if ((FLAGS(lmp) & FLG_RT_DELETE) &&
1466 ((flags & GPD_PARENT) == 0)) {
1467 tls_modaddrem(lmp, TM_FLG_MODREM);
1468 remove_so(LIST(lmp), lmp, clmp);
1473 * If we've deleted all the dependencies of the handle, finalize
1474 * the cleanup by removing the handle itself.
1476 * Otherwise we're left with a handle containing one or more
1477 * objects that can not be deleted (they're in use by other
1478 * handles, non-deletable, etc.), but require to remain a part
1479 * of this group to allow them to continue binding to one
1480 * another.
1482 * If the handles reference count is zero, or represents a
1483 * link-map list (dlopen(0)), then move that handle to the
1484 * orphans list. Should another dlclose() operation occur that
1485 * results in the removal of handle descriptors, these orphan
1486 * handles are re-examined to determine if their deletion can
1487 * be completed.
1489 if (ghp->gh_depends->al_nitems == 0) {
1490 free(ghp->gh_depends);
1491 free(ghp);
1493 } else if ((ghp->gh_refcnt == 0) &&
1494 ((ghp->gh_flags & GPH_ZERO) == 0)) {
1496 * Move this handle to the orphans list.
1498 (void) aplist_append(&hdl_alp[HDLIST_ORP], ghp,
1499 AL_CNT_HANDLES);
1501 if (DBG_ENABLED) {
1502 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ORPHAN));
1503 for (ALIST_TRAVERSE(ghp->gh_depends, idx1, gdp))
1504 DBG_CALL(Dbg_file_hdl_action(ghp,
1505 gdp->gd_depend, DBG_DEP_ORPHAN, 0));
1511 * If no handle descriptors got removed there's no point in looking for
1512 * orphans to process.
1514 if (rmcnt == 0)
1515 orphans = 0;
1518 * Cleanup any alists we've created.
1520 remove_collect(ghalp, lmalp);
1523 * If orphan processing isn't required we're done. If our processing
1524 * originated from investigating orphans, return the number of handle
1525 * descriptors removed as an indication whether orphan processing
1526 * should continue.
1528 if (orphans == 0) {
1529 if (removed)
1530 *removed = rmcnt;
1531 return (error);
1535 * Traverse the orphans list as many times as necessary until no
1536 * handle removals occur.
1538 do {
1539 APlist *alp;
1540 Aliste idx;
1541 Grp_hdl *ghp, *oghp = NULL;
1542 int title = 0;
1545 * Effectively clean the HDLIST_ORP list. Any object that can't
1546 * be removed will be re-added to the list.
1548 alp = hdl_alp[HDLIST_ORP];
1549 hdl_alp[HDLIST_ORP] = NULL;
1551 rescan = 0;
1552 for (APLIST_TRAVERSE(alp, idx, ghp)) {
1553 int _error, _remove;
1555 if (title++ == 0)
1556 DBG_CALL(Dbg_file_del_rescan(ghp->gh_ownlml));
1558 if (oghp) {
1559 (void) aplist_delete_value(alp, oghp);
1560 oghp = NULL;
1563 if (((_error = remove_hdl(ghp, clmp, &_remove)) != 0) &&
1564 (error == 0))
1565 error = _error;
1567 if (_remove)
1568 rescan++;
1570 oghp = ghp;
1572 if (oghp) {
1573 (void) aplist_delete_value(alp, oghp);
1574 oghp = NULL;
1576 if (alp)
1577 free((void *)alp);
1579 } while (rescan && aplist_nitems(hdl_alp[HDLIST_ORP]));
1581 return (error);