head/libexec/rtld-elf/rtld.c
/*
 * Call the finalization functions for each of the objects in "list"
 * belonging to the DAG of "root" and referenced once. If NULL "root"
 * is specified, every finalization function will be called regardless
 * of the reference count and the list elements won't be freed. All of
 * the objects are expected to have non-NULL fini functions.
 */
Call the finalization functions for each of the objects in "list"
belonging to the DAG of "root" and referenced once. If NULL "root"
is specified, every finalization function will be called regardless
of the reference count and the list elements won't be freed. All of
the objects are expected to have non-NULL fini functions.
Call the finalization functions for each of the objects in " list " belonging to the DAG of " root " and referenced once . If NULL " root " is specified every finalization function will be called regardless of the reference count and the list elements won ' t be freed . All of the objects are expected to have non - NULL fini functions .
static void
objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate)
{
    Objlist_Entry *elm;
    char *saved_msg;
    Elf_Addr *fini_addr;
    int index;
    assert(root == NULL || root->refcount == 1);
    saved_msg = errmsg_save();
    do {
	STAILQ_FOREACH(elm, list, link) {
	    if (root != NULL && (elm->obj->refcount != 1 ||
	      objlist_find(&root->dagmembers, elm->obj) == NULL))
		continue;
	    STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
	    lock_release(rtld_bind_lock, lockstate);
	    fini_addr = (Elf_Addr *)elm->obj->fini_array;
	    if (fini_addr != NULL && elm->obj->fini_array_num > 0) {
		for (index = elm->obj->fini_array_num - 1; index >= 0;
		  index--) {
		    if (fini_addr[index] != 0 && fini_addr[index] != 1) {
			dbg("calling fini function for %s at %p",
			    elm->obj->path, (void *)fini_addr[index]);
			LD_UTRACE(UTRACE_FINI_CALL, elm->obj,
			    (void *)fini_addr[index], 0, 0, elm->obj->path);
			call_initfini_pointer(elm->obj, fini_addr[index]);
		    }
		}
	    }
	    if (elm->obj->fini != (Elf_Addr)NULL) {
		dbg("calling fini function for %s at %p", elm->obj->path,
		    (void *)elm->obj->fini);
		LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini,
		    0, 0, elm->obj->path);
		call_initfini_pointer(elm->obj, elm->obj->fini);
	    }
	    wlock_acquire(rtld_bind_lock, lockstate);
	    if (root != NULL)
	    	free(elm);
	    break;
	}
    } while (elm != NULL);
    errmsg_restore(saved_msg);
}
static void objlist_call_fini ( Objlist * list , Obj_Entry * root , RtldLockState * lockstate ) { Objlist_Entry * elm ; char * saved_msg ; Elf_Addr * fini_addr ; int index ; assert ( root == NULL || root -> refcount == 1 ) ; saved_msg = errmsg_save ( ) ; do { STAILQ_FOREACH ( elm , list , link ) { if ( root != NULL && ( elm -> obj -> refcount != 1 || objlist_find ( & root -> dagmembers , elm -> obj ) == NULL ) ) continue ; STAILQ_REMOVE ( list , elm , Struct_Objlist_Entry , link ) ; lock_release ( rtld_bind_lock , lockstate ) ; fini_addr = ( Elf_Addr * ) elm -> obj -> fini_array ; if ( fini_addr != NULL && elm -> obj -> fini_array_num > 0 ) { for ( index = elm -> obj -> fini_array_num - 1 ; index >= 0 ; index -- ) { if ( fini_addr [ index ] != 0 && fini_addr [ index ] != 1 ) { dbg ( " " , elm -> obj -> path , ( void * ) fini_addr [ index ] ) ; LD_UTRACE ( UTRACE_FINI_CALL , elm -> obj , ( void * ) fini_addr [ index ] , 0 , 0 , elm -> obj -> path ) ; call_initfini_pointer ( elm -> obj , fini_addr [ index ] ) ; } } } if ( elm -> obj -> fini != ( Elf_Addr ) NULL ) { dbg ( " " , elm -> obj -> path , ( void * ) elm -> obj -> fini ) ; LD_UTRACE ( UTRACE_FINI_CALL , elm -> obj , ( void * ) elm -> obj -> fini , 0 , 0 , elm -> obj -> path ) ; call_initfini_pointer ( elm -> obj , elm -> obj -> fini ) ; } wlock_acquire ( rtld_bind_lock , lockstate ) ; if ( root != NULL ) free ( elm ) ; break ; } } while ( elm != NULL ) ; errmsg_restore ( saved_msg ) ; }
Call the finalization functions for each of the objects in "list"
 belonging to the DAG of "root" and referenced once.
Call the finalization functions for each of the objects in " list " belonging to the DAG of " root " and referenced once .
/*
     * Preserve the current error message since a fini function might
     * call into the dynamic linker and overwrite it.
     */ /* Remove object from fini list to prevent recursive invocation. */ /*
	     * XXX: If a dlopen() call references an object while the
	     * fini function is in progress, we might end up trying to
	     * unload the referenced object in dlclose() or the object
	     * won't be unloaded although its fini function has been
	     * called.
	     */ /*
	     * It is legal to have both DT_FINI and DT_FINI_ARRAY defined.
	     * When this happens, DT_FINI_ARRAY is processed first.
	     */ /* No need to free anything if process is going down. */ /*
	     * We must restart the list traversal after every fini call
	     * because a dlclose() call from the fini function or from
	     * another thread might have modified the reference counts.
	     */