1/* Free resources associated with Elf descriptor. 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper@redhat.com>, 1998. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, version 2. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <assert.h> 23#include <stddef.h> 24#include <stdlib.h> 25#include <sys/mman.h> 26 27#include "libelfP.h" 28 29 30int 31elf_end (elf) 32 Elf *elf; 33{ 34 Elf *parent; 35 36 if (elf == NULL) 37 /* This is allowed and is a no-op. */ 38 return 0; 39 40 /* Make sure we are alone. */ 41 rwlock_wrlock (elf->lock); 42 43 if (elf->ref_count != 0 && --elf->ref_count != 0) 44 { 45 /* Not yet the last activation. */ 46 int result = elf->ref_count; 47 rwlock_unlock (elf->lock); 48 return result; 49 } 50 51 if (elf->kind == ELF_K_AR) 52 { 53 /* We cannot remove the descriptor now since we still have some 54 descriptors which depend on it. But we can free the archive 55 symbol table since this is only available via the archive ELF 56 descriptor. The long name table cannot be freed yet since 57 the archive headers for the ELF files in the archive point 58 into this array. */ 59 free (elf->state.ar.ar_sym); 60 elf->state.ar.ar_sym = NULL; 61 62 if (elf->state.ar.children != NULL) 63 return 0; 64 } 65 66 /* Remove this structure from the children list. */ 67 parent = elf->parent; 68 if (parent != NULL) 69 { 70 /* This is tricky. Lock must be acquire from the father to 71 the child but here we already have the child lock. We 72 solve this problem by giving free the child lock. The 73 state of REF_COUNT==0 is handled all over the library, so 74 this should be ok. */ 75 rwlock_unlock (elf->lock); 76 rwlock_rdlock (parent->lock); 77 rwlock_wrlock (elf->lock); 78 79 if (parent->state.ar.children == elf) 80 parent->state.ar.children = elf->next; 81 else 82 { 83 struct Elf *child = parent->state.ar.children; 84 85 while (child->next != elf) 86 child = child->next; 87 88 child->next = elf->next; 89 } 90 91 rwlock_unlock (parent->lock); 92 } 93 94 /* This was the last activation. Free all resources. */ 95 switch (elf->kind) 96 { 97 case ELF_K_AR: 98 if (elf->state.ar.long_names != NULL) 99 free (elf->state.ar.long_names); 100 break; 101 102 case ELF_K_ELF: 103 { 104 Elf_ScnList *list = (elf->class == ELFCLASS32 105 || (offsetof (struct Elf, state.elf32.scns) 106 == offsetof (struct Elf, state.elf64.scns)) 107 ? &elf->state.elf32.scns 108 : &elf->state.elf64.scns); 109 110 do 111 { 112 /* Free all separately allocated section headers. */ 113 size_t cnt = list->max; 114 115 while (cnt-- > 0) 116 { 117 /* These pointers can be NULL; it's safe to use 118 'free' since it will check for this. */ 119 Elf_Scn *scn = &list->data[cnt]; 120 Elf_Data_List *runp; 121 122 if ((scn->shdr_flags & ELF_F_MALLOCED) != 0) 123 /* It doesn't matter which pointer. */ 124 free (scn->shdr.e32); 125 126 /* If the file has the same byte order and the 127 architecture doesn't require overly stringent 128 alignment the raw data buffer is the same as the 129 one used for presenting to the caller. */ 130 if (scn->data_base != scn->rawdata_base) 131 free (scn->data_base); 132 133 /* The section data is allocated if we couldn't mmap 134 the file. */ 135 if (elf->map_address == NULL) 136 free (scn->rawdata_base); 137 138 /* Free the list of data buffers for the section. 139 We don't free the buffers themselves since this 140 is the users job. */ 141 runp = scn->data_list.next; 142 while (runp != NULL) 143 { 144 Elf_Data_List *oldp = runp; 145 runp = runp->next; 146 if ((oldp->flags & ELF_F_MALLOCED) != 0) 147 free (oldp); 148 } 149 } 150 151 /* Free the memory for the array. */ 152 Elf_ScnList *oldp = list; 153 list = list->next; 154 assert (list == NULL || oldp->cnt == oldp->max); 155 if (oldp != (elf->class == ELFCLASS32 156 || (offsetof (struct Elf, state.elf32.scns) 157 == offsetof (struct Elf, state.elf64.scns)) 158 ? &elf->state.elf32.scns 159 : &elf->state.elf64.scns)) 160 free (oldp); 161 } 162 while (list != NULL); 163 } 164 165 /* Free the section header. */ 166 if (elf->state.elf.shdr_malloced != 0) 167 free (elf->class == ELFCLASS32 168 || (offsetof (struct Elf, state.elf32.shdr) 169 == offsetof (struct Elf, state.elf64.shdr)) 170 ? (void *) elf->state.elf32.shdr 171 : (void *) elf->state.elf64.shdr); 172 173 /* Free the program header. */ 174 if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0) 175 free (elf->class == ELFCLASS32 176 || (offsetof (struct Elf, state.elf32.phdr) 177 == offsetof (struct Elf, state.elf64.phdr)) 178 ? (void *) elf->state.elf32.phdr 179 : (void *) elf->state.elf64.phdr); 180 break; 181 182 default: 183 break; 184 } 185 186 if (elf->map_address != NULL && parent == NULL) 187 { 188 /* The file was read or mapped for this descriptor. */ 189 if ((elf->flags & ELF_F_MALLOCED) != 0) 190 free (elf->map_address); 191 else if ((elf->flags & ELF_F_MMAPPED) != 0) 192 munmap (elf->map_address, elf->maximum_size); 193 } 194 195 rwlock_fini (elf->lock); 196 197 /* Finally the descriptor itself. */ 198 free (elf); 199 200 return parent != NULL && parent->ref_count == 0 ? elf_end (parent) : 0; 201} 202