1 /* Free resources associated with Elf descriptor.
2 Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
9 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
19 or both in parallel, as here.
21 elfutils is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
49 /* This is allowed and is a no-op. */
52 /* Make sure we are alone. */
53 rwlock_wrlock (elf->lock);
55 if (elf->ref_count != 0 && --elf->ref_count != 0)
57 /* Not yet the last activation. */
58 int result = elf->ref_count;
59 rwlock_unlock (elf->lock);
63 if (elf->kind == ELF_K_AR)
65 /* We cannot remove the descriptor now since we still have some
66 descriptors which depend on it. But we can free the archive
67 symbol table since this is only available via the archive ELF
68 descriptor. The long name table cannot be freed yet since
69 the archive headers for the ELF files in the archive point
71 if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
72 free (elf->state.ar.ar_sym);
73 elf->state.ar.ar_sym = NULL;
75 if (elf->state.ar.children != NULL)
79 /* Remove this structure from the children list. */
83 /* This is tricky. Lock must be acquire from the father to
84 the child but here we already have the child lock. We
85 solve this problem by giving free the child lock. The
86 state of REF_COUNT==0 is handled all over the library, so
88 rwlock_unlock (elf->lock);
89 rwlock_rdlock (parent->lock);
90 rwlock_wrlock (elf->lock);
92 if (parent->state.ar.children == elf)
93 parent->state.ar.children = elf->next;
96 struct Elf *child = parent->state.ar.children;
98 while (child->next != elf)
101 child->next = elf->next;
104 rwlock_unlock (parent->lock);
107 /* This was the last activation. Free all resources. */
111 if (elf->state.ar.long_names != NULL)
112 free (elf->state.ar.long_names);
117 Elf_Data_Chunk *rawchunks
118 = (elf->class == ELFCLASS32
119 || (offsetof (struct Elf, state.elf32.rawchunks)
120 == offsetof (struct Elf, state.elf64.rawchunks))
121 ? elf->state.elf32.rawchunks
122 : elf->state.elf64.rawchunks);
123 while (rawchunks != NULL)
125 Elf_Data_Chunk *next = rawchunks->next;
126 if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
127 free (rawchunks->data.d.d_buf);
132 Elf_ScnList *list = (elf->class == ELFCLASS32
133 || (offsetof (struct Elf, state.elf32.scns)
134 == offsetof (struct Elf, state.elf64.scns))
135 ? &elf->state.elf32.scns
136 : &elf->state.elf64.scns);
140 /* Free all separately allocated section headers. */
141 size_t cnt = list->max;
145 /* These pointers can be NULL; it's safe to use
146 'free' since it will check for this. */
147 Elf_Scn *scn = &list->data[cnt];
150 if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
151 /* It doesn't matter which pointer. */
152 free (scn->shdr.e32);
154 /* If the file has the same byte order and the
155 architecture doesn't require overly stringent
156 alignment the raw data buffer is the same as the
157 one used for presenting to the caller. */
158 if (scn->data_base != scn->rawdata_base)
159 free (scn->data_base);
161 /* The section data is allocated if we couldn't mmap
163 if (elf->map_address == NULL)
164 free (scn->rawdata_base);
166 /* Free the list of data buffers for the section.
167 We don't free the buffers themselves since this
169 runp = scn->data_list.next;
172 Elf_Data_List *oldp = runp;
174 if ((oldp->flags & ELF_F_MALLOCED) != 0)
179 /* Free the memory for the array. */
180 Elf_ScnList *oldp = list;
182 assert (list == NULL || oldp->cnt == oldp->max);
183 if (oldp != (elf->class == ELFCLASS32
184 || (offsetof (struct Elf, state.elf32.scns)
185 == offsetof (struct Elf, state.elf64.scns))
186 ? &elf->state.elf32.scns
187 : &elf->state.elf64.scns))
190 while (list != NULL);
193 /* Free the section header. */
194 if (elf->state.elf.shdr_malloced != 0)
195 free (elf->class == ELFCLASS32
196 || (offsetof (struct Elf, state.elf32.shdr)
197 == offsetof (struct Elf, state.elf64.shdr))
198 ? (void *) elf->state.elf32.shdr
199 : (void *) elf->state.elf64.shdr);
201 /* Free the program header. */
202 if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
203 free (elf->class == ELFCLASS32
204 || (offsetof (struct Elf, state.elf32.phdr)
205 == offsetof (struct Elf, state.elf64.phdr))
206 ? (void *) elf->state.elf32.phdr
207 : (void *) elf->state.elf64.phdr);
214 if (elf->map_address != NULL && parent == NULL)
216 /* The file was read or mapped for this descriptor. */
217 if ((elf->flags & ELF_F_MALLOCED) != 0)
218 free (elf->map_address);
219 else if ((elf->flags & ELF_F_MMAPPED) != 0)
220 munmap (elf->map_address, elf->maximum_size);
223 rwlock_unlock (elf->lock);
224 rwlock_fini (elf->lock);
226 /* Finally the descriptor itself. */
229 return (parent != NULL && parent->ref_count == 0
230 ? INTUSE(elf_end) (parent) : 0);