xref: /onnv-gate/usr/src/cmd/sgs/libelf/common/end.c (revision 6812:febeba71273d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*6812Sraf  * Common Development and Distribution License (the "License").
6*6812Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*6812Sraf 
22*6812Sraf /*
23*6812Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*6812Sraf  * Use is subject to license terms.
25*6812Sraf  */
26*6812Sraf 
270Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
30*6812Sraf #pragma ident	"%Z%%M%	%I%	%E% SMI"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <ar.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include "libelf.h"
350Sstevel@tonic-gate #include "decl.h"
360Sstevel@tonic-gate #include "member.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate int
elf_end(Elf * elf)390Sstevel@tonic-gate elf_end(Elf * elf)
400Sstevel@tonic-gate {
410Sstevel@tonic-gate 	Elf_Scn *	s;
420Sstevel@tonic-gate 	Dnode *	d;
430Sstevel@tonic-gate 	Elf_Void *		trail = 0;
440Sstevel@tonic-gate 	int			rc;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 	if (elf == 0)
470Sstevel@tonic-gate 		return (0);
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	ELFWLOCK(elf)
500Sstevel@tonic-gate 	if (--elf->ed_activ != 0) {
510Sstevel@tonic-gate 		rc = elf->ed_activ;
520Sstevel@tonic-gate 		ELFUNLOCK(elf)
530Sstevel@tonic-gate 		return (rc);
540Sstevel@tonic-gate 	}
550Sstevel@tonic-gate 
560Sstevel@tonic-gate #ifndef __lock_lint
570Sstevel@tonic-gate 	while (elf->ed_activ == 0) {
580Sstevel@tonic-gate 		for (s = elf->ed_hdscn; s != 0; s = s->s_next) {
590Sstevel@tonic-gate 			if (s->s_myflags & SF_ALLOC) {
600Sstevel@tonic-gate 				if (trail != 0)
610Sstevel@tonic-gate 					free(trail);
620Sstevel@tonic-gate 				trail = (Elf_Void *)s;
630Sstevel@tonic-gate 			}
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 			if ((s->s_myflags & SF_READY) == 0)
660Sstevel@tonic-gate 				continue;
670Sstevel@tonic-gate 			for (d = s->s_hdnode; d != 0; ) {
680Sstevel@tonic-gate 				register Dnode	*t;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 				if (d->db_buf != 0)
710Sstevel@tonic-gate 					free(d->db_buf);
720Sstevel@tonic-gate 				if ((t = d->db_raw) != 0) {
730Sstevel@tonic-gate 					if (t->db_buf != 0)
740Sstevel@tonic-gate 						free(t->db_buf);
750Sstevel@tonic-gate 					if (t->db_myflags & DBF_ALLOC)
760Sstevel@tonic-gate 						free(t);
770Sstevel@tonic-gate 				}
780Sstevel@tonic-gate 				t = d->db_next;
790Sstevel@tonic-gate 				if (d->db_myflags & DBF_ALLOC)
800Sstevel@tonic-gate 					free(d);
810Sstevel@tonic-gate 				d = t;
820Sstevel@tonic-gate 			}
830Sstevel@tonic-gate 		}
840Sstevel@tonic-gate 		if (trail != 0) {
850Sstevel@tonic-gate 			free(trail);
860Sstevel@tonic-gate 			trail = 0;
870Sstevel@tonic-gate 		}
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 		{
900Sstevel@tonic-gate 			register Memlist	*l;
910Sstevel@tonic-gate 			register Memident	*i;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 			for (l = elf->ed_memlist; l; l = (Memlist *)trail) {
940Sstevel@tonic-gate 				trail = (Elf_Void *)l->m_next;
950Sstevel@tonic-gate 				for (i = (Memident *)(l + 1); i < l->m_free;
960Sstevel@tonic-gate 				    i++)
970Sstevel@tonic-gate 					free(i->m_member);
980Sstevel@tonic-gate 				free(l);
990Sstevel@tonic-gate 			}
1000Sstevel@tonic-gate 		}
1010Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_EHALLOC)
1020Sstevel@tonic-gate 			free(elf->ed_ehdr);
1030Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_PHALLOC)
1040Sstevel@tonic-gate 			free(elf->ed_phdr);
1050Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_SHALLOC)
1060Sstevel@tonic-gate 			free(elf->ed_shdr);
1070Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_RAWALLOC)
1080Sstevel@tonic-gate 			free(elf->ed_raw);
1090Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_ASALLOC)
1100Sstevel@tonic-gate 			free(elf->ed_arsym);
1110Sstevel@tonic-gate 		if (elf->ed_myflags & EDF_ASTRALLOC)
1120Sstevel@tonic-gate 			free(elf->ed_arstr);
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 		/*
1150Sstevel@tonic-gate 		 * Don't release the image until the last reference dies.
1160Sstevel@tonic-gate 		 * If the image was introduced via elf_memory() then
1170Sstevel@tonic-gate 		 * we don't release it at all, it's not ours to release.
1180Sstevel@tonic-gate 		 */
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 		if (elf->ed_parent == 0) {
1210Sstevel@tonic-gate 			if (elf->ed_vm != 0)
1220Sstevel@tonic-gate 				free(elf->ed_vm);
1230Sstevel@tonic-gate 			else if ((elf->ed_myflags & EDF_MEMORY) == 0)
1240Sstevel@tonic-gate 				_elf_unmap(elf->ed_image, elf->ed_imagesz);
1250Sstevel@tonic-gate 		}
1260Sstevel@tonic-gate 		trail = (Elf_Void *)elf;
1270Sstevel@tonic-gate 		elf = elf->ed_parent;
1280Sstevel@tonic-gate 		ELFUNLOCK(trail)
1290Sstevel@tonic-gate 		free(trail);
1300Sstevel@tonic-gate 		if (elf == 0)
1310Sstevel@tonic-gate 			break;
1320Sstevel@tonic-gate 		/*
1330Sstevel@tonic-gate 		 * If parent is inactive we close
1340Sstevel@tonic-gate 		 * it too, so we need to lock it too.
1350Sstevel@tonic-gate 		 */
1360Sstevel@tonic-gate 		ELFWLOCK(elf)
1370Sstevel@tonic-gate 		--elf->ed_activ;
1380Sstevel@tonic-gate 	}
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	if (elf) {
1410Sstevel@tonic-gate 		ELFUNLOCK(elf)
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate #else
1440Sstevel@tonic-gate 	/*
1450Sstevel@tonic-gate 	 * This sill stuff is here to make warlock happy
1460Sstevel@tonic-gate 	 * durring it's lock checking.  The problem is that it
1470Sstevel@tonic-gate 	 * just can't track the multiple dynamic paths through
1480Sstevel@tonic-gate 	 * the above loop so we just give it a simple one it can
1490Sstevel@tonic-gate 	 * look at.
1500Sstevel@tonic-gate 	 */
1510Sstevel@tonic-gate 	_elf_unmap(elf->ed_image, elf->ed_imagesz);
1520Sstevel@tonic-gate 	ELFUNLOCK(elf)
1530Sstevel@tonic-gate #endif
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	return (0);
1560Sstevel@tonic-gate }
157