blob: d4ae051755c3825b948a8a957cf0cf19b9bf1d2d [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Free resources associated with Elf descriptor.
Roland McGrath59ea7f32007-10-04 08:50:09 +00002 Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008
Mark Wielaardde2ed972012-06-05 17:15:16 +02009 * 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
12
13 or
14
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
18
19 or both in parallel, as here.
20
21 elfutils is distributed in the hope that it will be useful, but
Ulrich Drepper361df7d2006-04-04 21:38:57 +000022 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.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000025
Mark Wielaardde2ed972012-06-05 17:15:16 +020026 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/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000029
30#ifdef HAVE_CONFIG_H
31# include <config.h>
32#endif
33
34#include <assert.h>
35#include <stddef.h>
36#include <stdlib.h>
37#include <sys/mman.h>
38
39#include "libelfP.h"
40
41
42int
43elf_end (elf)
44 Elf *elf;
45{
46 Elf *parent;
47
48 if (elf == NULL)
49 /* This is allowed and is a no-op. */
50 return 0;
51
52 /* Make sure we are alone. */
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000053 rwlock_wrlock (elf->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000054
55 if (elf->ref_count != 0 && --elf->ref_count != 0)
56 {
57 /* Not yet the last activation. */
58 int result = elf->ref_count;
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000059 rwlock_unlock (elf->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000060 return result;
61 }
62
63 if (elf->kind == ELF_K_AR)
64 {
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
70 into this array. */
Roland McGrath59ea7f32007-10-04 08:50:09 +000071 if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
72 free (elf->state.ar.ar_sym);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000073 elf->state.ar.ar_sym = NULL;
74
75 if (elf->state.ar.children != NULL)
76 return 0;
77 }
78
79 /* Remove this structure from the children list. */
80 parent = elf->parent;
81 if (parent != NULL)
82 {
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
87 this should be ok. */
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000088 rwlock_unlock (elf->lock);
89 rwlock_rdlock (parent->lock);
90 rwlock_wrlock (elf->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000091
92 if (parent->state.ar.children == elf)
93 parent->state.ar.children = elf->next;
94 else
95 {
96 struct Elf *child = parent->state.ar.children;
97
98 while (child->next != elf)
99 child = child->next;
100
101 child->next = elf->next;
102 }
103
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000104 rwlock_unlock (parent->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000105 }
106
107 /* This was the last activation. Free all resources. */
108 switch (elf->kind)
109 {
110 case ELF_K_AR:
111 if (elf->state.ar.long_names != NULL)
112 free (elf->state.ar.long_names);
113 break;
114
115 case ELF_K_ELF:
116 {
Roland McGrath59ea7f32007-10-04 08:50:09 +0000117 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)
124 {
125 Elf_Data_Chunk *next = rawchunks->next;
126 if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
127 free (rawchunks->data.d.d_buf);
128 free (rawchunks);
129 rawchunks = next;
130 }
131
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000132 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);
137
138 do
139 {
140 /* Free all separately allocated section headers. */
141 size_t cnt = list->max;
142
143 while (cnt-- > 0)
144 {
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];
148 Elf_Data_List *runp;
149
150 if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
151 /* It doesn't matter which pointer. */
152 free (scn->shdr.e32);
153
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);
160
161 /* The section data is allocated if we couldn't mmap
162 the file. */
163 if (elf->map_address == NULL)
164 free (scn->rawdata_base);
165
166 /* Free the list of data buffers for the section.
167 We don't free the buffers themselves since this
168 is the users job. */
169 runp = scn->data_list.next;
170 while (runp != NULL)
171 {
172 Elf_Data_List *oldp = runp;
173 runp = runp->next;
174 if ((oldp->flags & ELF_F_MALLOCED) != 0)
175 free (oldp);
176 }
177 }
178
179 /* Free the memory for the array. */
180 Elf_ScnList *oldp = list;
181 list = list->next;
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))
188 free (oldp);
189 }
190 while (list != NULL);
191 }
192
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);
200
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);
208 break;
209
210 default:
211 break;
212 }
213
214 if (elf->map_address != NULL && parent == NULL)
215 {
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);
221 }
222
Mark Wielaard49550162012-02-26 13:14:32 +0100223 rwlock_unlock (elf->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000224 rwlock_fini (elf->lock);
225
226 /* Finally the descriptor itself. */
227 free (elf);
228
229 return (parent != NULL && parent->ref_count == 0
230 ? INTUSE(elf_end) (parent) : 0);
231}
232INTDEF(elf_end)