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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #include <ar.h> 31 #include <stdlib.h> 32 #include "libelf.h" 33 #include "decl.h" 34 #include "member.h" 35 36 int 37 elf_end(Elf *elf) 38 { 39 Elf_Scn *s; 40 Dnode *d; 41 Elf_Void *trail = NULL; 42 int rc; 43 44 if (elf == NULL) 45 return (0); 46 47 ELFWLOCK(elf) 48 if (--elf->ed_activ != 0) { 49 rc = elf->ed_activ; 50 ELFUNLOCK(elf) 51 return (rc); 52 } 53 54 while (elf->ed_activ == 0) { 55 for (s = elf->ed_hdscn; s != NULL; s = s->s_next) { 56 if (s->s_myflags & SF_ALLOC) { 57 if (trail != NULL) 58 free(trail); 59 trail = (Elf_Void *)s; 60 } 61 62 if ((s->s_myflags & SF_READY) == 0) 63 continue; 64 for (d = s->s_hdnode; d != NULL; ) { 65 register Dnode *t; 66 67 if (d->db_buf != NULL) 68 free(d->db_buf); 69 if ((t = d->db_raw) != NULL) { 70 if (t->db_buf != NULL) 71 free(t->db_buf); 72 if (t->db_myflags & DBF_ALLOC) 73 free(t); 74 } 75 t = d->db_next; 76 if (d->db_myflags & DBF_ALLOC) 77 free(d); 78 d = t; 79 } 80 } 81 if (trail != NULL) { 82 free(trail); 83 trail = NULL; 84 } 85 86 { 87 register Memlist *l; 88 register Memident *i; 89 90 for (l = elf->ed_memlist; l != NULL; 91 l = (Memlist *)trail) { 92 trail = (Elf_Void *)l->m_next; 93 for (i = (Memident *)(l + 1); i < l->m_free; 94 i++) 95 free(i->m_member); 96 free(l); 97 } 98 } 99 if (elf->ed_myflags & EDF_EHALLOC) 100 free(elf->ed_ehdr); 101 if (elf->ed_myflags & EDF_PHALLOC) 102 free(elf->ed_phdr); 103 if (elf->ed_myflags & EDF_SHALLOC) 104 free(elf->ed_shdr); 105 if (elf->ed_myflags & EDF_RAWALLOC) 106 free(elf->ed_raw); 107 if (elf->ed_myflags & EDF_ASALLOC) 108 free(elf->ed_arsym); 109 if (elf->ed_myflags & EDF_ASTRALLOC) 110 free(elf->ed_arstr); 111 112 /* 113 * Don't release the image until the last reference dies. 114 * If the image was introduced via elf_memory() then 115 * we don't release it at all, it's not ours to release. 116 */ 117 118 if (elf->ed_parent == NULL) { 119 if (elf->ed_vm != NULL) 120 free(elf->ed_vm); 121 else if ((elf->ed_myflags & EDF_MEMORY) == 0) 122 _elf_unmap(elf->ed_image, elf->ed_imagesz); 123 } 124 125 trail = (Elf_Void *)elf; 126 elf = elf->ed_parent; 127 ELFUNLOCK(trail) 128 free(trail); 129 trail = NULL; 130 131 if (elf == NULL) 132 break; 133 /* 134 * If parent is inactive we close 135 * it too, so we need to lock it too. 136 */ 137 ELFWLOCK(elf) 138 --elf->ed_activ; 139 } 140 141 if (elf != NULL) { 142 ELFUNLOCK(elf) 143 } 144 145 return (0); 146 } 147