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 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <ar.h> 33 #include <stdlib.h> 34 #include "libelf.h" 35 #include "decl.h" 36 #include "member.h" 37 38 int elf_end(Elf * elf)39elf_end(Elf * elf) 40 { 41 Elf_Scn * s; 42 Dnode * d; 43 Elf_Void * trail = 0; 44 int rc; 45 46 if (elf == 0) 47 return (0); 48 49 ELFWLOCK(elf) 50 if (--elf->ed_activ != 0) { 51 rc = elf->ed_activ; 52 ELFUNLOCK(elf) 53 return (rc); 54 } 55 56 #ifndef __lock_lint 57 while (elf->ed_activ == 0) { 58 for (s = elf->ed_hdscn; s != 0; s = s->s_next) { 59 if (s->s_myflags & SF_ALLOC) { 60 if (trail != 0) 61 free(trail); 62 trail = (Elf_Void *)s; 63 } 64 65 if ((s->s_myflags & SF_READY) == 0) 66 continue; 67 for (d = s->s_hdnode; d != 0; ) { 68 register Dnode *t; 69 70 if (d->db_buf != 0) 71 free(d->db_buf); 72 if ((t = d->db_raw) != 0) { 73 if (t->db_buf != 0) 74 free(t->db_buf); 75 if (t->db_myflags & DBF_ALLOC) 76 free(t); 77 } 78 t = d->db_next; 79 if (d->db_myflags & DBF_ALLOC) 80 free(d); 81 d = t; 82 } 83 } 84 if (trail != 0) { 85 free(trail); 86 trail = 0; 87 } 88 89 { 90 register Memlist *l; 91 register Memident *i; 92 93 for (l = elf->ed_memlist; l; l = (Memlist *)trail) { 94 trail = (Elf_Void *)l->m_next; 95 for (i = (Memident *)(l + 1); i < l->m_free; 96 i++) 97 free(i->m_member); 98 free(l); 99 } 100 } 101 if (elf->ed_myflags & EDF_EHALLOC) 102 free(elf->ed_ehdr); 103 if (elf->ed_myflags & EDF_PHALLOC) 104 free(elf->ed_phdr); 105 if (elf->ed_myflags & EDF_SHALLOC) 106 free(elf->ed_shdr); 107 if (elf->ed_myflags & EDF_RAWALLOC) 108 free(elf->ed_raw); 109 if (elf->ed_myflags & EDF_ASALLOC) 110 free(elf->ed_arsym); 111 if (elf->ed_myflags & EDF_ASTRALLOC) 112 free(elf->ed_arstr); 113 114 /* 115 * Don't release the image until the last reference dies. 116 * If the image was introduced via elf_memory() then 117 * we don't release it at all, it's not ours to release. 118 */ 119 120 if (elf->ed_parent == 0) { 121 if (elf->ed_vm != 0) 122 free(elf->ed_vm); 123 else if ((elf->ed_myflags & EDF_MEMORY) == 0) 124 _elf_unmap(elf->ed_image, elf->ed_imagesz); 125 } 126 trail = (Elf_Void *)elf; 127 elf = elf->ed_parent; 128 ELFUNLOCK(trail) 129 free(trail); 130 if (elf == 0) 131 break; 132 /* 133 * If parent is inactive we close 134 * it too, so we need to lock it too. 135 */ 136 ELFWLOCK(elf) 137 --elf->ed_activ; 138 } 139 140 if (elf) { 141 ELFUNLOCK(elf) 142 } 143 #else 144 /* 145 * This sill stuff is here to make warlock happy 146 * durring it's lock checking. The problem is that it 147 * just can't track the multiple dynamic paths through 148 * the above loop so we just give it a simple one it can 149 * look at. 150 */ 151 _elf_unmap(elf->ed_image, elf->ed_imagesz); 152 ELFUNLOCK(elf) 153 #endif 154 155 return (0); 156 } 157