Branch data Line data Source code
1 : : /* Free resources associated with Elf descriptor.
2 : : Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015,2016 Red Hat, Inc.
3 : : Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
4 : : This file is part of elfutils.
5 : : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6 : :
7 : : This file is free software; you can redistribute it and/or modify
8 : : it under the terms of either
9 : :
10 : : * the GNU Lesser General Public License as published by the Free
11 : : Software Foundation; either version 3 of the License, or (at
12 : : your option) any later version
13 : :
14 : : or
15 : :
16 : : * the GNU General Public License as published by the Free
17 : : Software Foundation; either version 2 of the License, or (at
18 : : your option) any later version
19 : :
20 : : or both in parallel, as here.
21 : :
22 : : elfutils is distributed in the hope that it will be useful, but
23 : : WITHOUT ANY WARRANTY; without even the implied warranty of
24 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 : : General Public License for more details.
26 : :
27 : : You should have received copies of the GNU General Public License and
28 : : the GNU Lesser General Public License along with this program. If
29 : : not, see <http://www.gnu.org/licenses/>. */
30 : :
31 : : #ifdef HAVE_CONFIG_H
32 : : # include <config.h>
33 : : #endif
34 : :
35 : : #include <assert.h>
36 : : #include <search.h>
37 : : #include <stddef.h>
38 : : #include <stdlib.h>
39 : :
40 : : #include "libelfP.h"
41 : :
42 : :
43 : : static void
44 : 2304 : free_chunk (void *n)
45 : : {
46 : 2304 : Elf_Data_Chunk *rawchunk = (Elf_Data_Chunk *)n;
47 [ + + ]: 2304 : if (rawchunk->dummy_scn.flags & ELF_F_MALLOCED)
48 : 1168 : free (rawchunk->data.d.d_buf);
49 : 2304 : free (rawchunk);
50 : 2304 : }
51 : :
52 : : int
53 : 35978 : elf_end (Elf *elf)
54 : : {
55 : 35986 : Elf *parent;
56 : :
57 [ + + ]: 35986 : if (elf == NULL)
58 : : /* This is allowed and is a no-op. */
59 : : return 0;
60 : :
61 : : /* Make sure we are alone. */
62 : 35204 : rwlock_wrlock (elf->lock);
63 : :
64 [ + + + - ]: 35204 : if (elf->ref_count != 0 && --elf->ref_count != 0)
65 : : {
66 : : /* Not yet the last activation. */
67 : : int result = elf->ref_count;
68 : : rwlock_unlock (elf->lock);
69 : : return result;
70 : : }
71 : :
72 [ + + ]: 35204 : if (elf->kind == ELF_K_AR)
73 : : {
74 : : /* We cannot remove the descriptor now since we still have some
75 : : descriptors which depend on it. But we can free the archive
76 : : symbol table since this is only available via the archive ELF
77 : : descriptor. The long name table cannot be freed yet since
78 : : the archive headers for the ELF files in the archive point
79 : : into this array. */
80 [ + - ]: 350 : if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
81 : 350 : free (elf->state.ar.ar_sym);
82 : 350 : elf->state.ar.ar_sym = NULL;
83 : :
84 [ + + ]: 350 : if (elf->state.ar.children != NULL)
85 : : {
86 : : rwlock_unlock(elf->lock);
87 : : return 0;
88 : : }
89 : : }
90 : :
91 : : /* Remove this structure from the children list. */
92 : 35196 : parent = elf->parent;
93 [ + + ]: 35196 : if (parent != NULL)
94 : : {
95 : : /* This is tricky. Lock must be acquire from the father to
96 : : the child but here we already have the child lock. We
97 : : solve this problem by giving free the child lock. The
98 : : state of REF_COUNT==0 is handled all over the library, so
99 : : this should be ok. */
100 : 14712 : rwlock_unlock (elf->lock);
101 : 14712 : rwlock_rdlock (parent->lock);
102 : 14712 : rwlock_wrlock (elf->lock);
103 : :
104 [ + + ]: 14712 : if (parent->state.ar.children == elf)
105 : 14704 : parent->state.ar.children = elf->next;
106 : : else
107 : : {
108 : : struct Elf *child = parent->state.ar.children;
109 : :
110 [ + + ]: 10 : while (child->next != elf)
111 : : child = child->next;
112 : :
113 : 8 : child->next = elf->next;
114 : : }
115 : :
116 : 35196 : rwlock_unlock (parent->lock);
117 : : }
118 : :
119 [ + + ]: 35196 : if (elf->kind != ELF_K_AR)
120 : : {
121 [ + + ]: 34854 : if (elf->state.elf.elf_ar_hdr.ar_name != NULL)
122 : 14712 : free (elf->state.elf.elf_ar_hdr.ar_name);
123 : :
124 [ + + ]: 34854 : if (elf->state.elf.elf_ar_hdr.ar_rawname != NULL)
125 : 14712 : free (elf->state.elf.elf_ar_hdr.ar_rawname);
126 : : }
127 : :
128 : : /* This was the last activation. Free all resources. */
129 [ + + + ]: 35196 : switch (elf->kind)
130 : : {
131 : 342 : case ELF_K_AR:
132 [ + + ]: 342 : if (elf->state.ar.long_names != NULL)
133 : 204 : free (elf->state.ar.long_names);
134 : : break;
135 : :
136 : 33374 : case ELF_K_ELF:
137 : : {
138 : 33374 : search_tree *rawchunk_tree
139 : : = (elf->class == ELFCLASS32
140 : : || (offsetof (struct Elf, state.elf32.rawchunk_tree)
141 : : == offsetof (struct Elf, state.elf64.rawchunk_tree))
142 : : ? &elf->state.elf32.rawchunk_tree
143 : : : &elf->state.elf64.rawchunk_tree);
144 : :
145 : 33374 : eu_search_tree_fini (rawchunk_tree, free_chunk);
146 : :
147 : 33374 : Elf_ScnList *list = (elf->class == ELFCLASS32
148 : : || (offsetof (struct Elf, state.elf32.scns)
149 : : == offsetof (struct Elf, state.elf64.scns))
150 : : ? &elf->state.elf32.scns
151 : : : &elf->state.elf64.scns);
152 : :
153 : 35340 : do
154 : : {
155 : : /* Free all separately allocated section headers. */
156 : 35340 : size_t cnt = list->max;
157 : :
158 [ + + ]: 14498756 : while (cnt-- > 0)
159 : : {
160 : : /* These pointers can be NULL; it's safe to use
161 : : 'free' since it will check for this. */
162 : 14463416 : Elf_Scn *scn = &list->data[cnt];
163 : 14463416 : Elf_Data_List *runp;
164 : :
165 [ + + ]: 14463416 : if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
166 : : /* It doesn't matter which pointer. */
167 : 3305822 : free (scn->shdr.e32);
168 : :
169 : : /* Free zdata if uncompressed, but not yet used as
170 : : rawdata_base. If it is already used it will be
171 : : freed below. */
172 [ + + ]: 14463416 : if (scn->zdata_base != scn->rawdata_base)
173 : : {
174 : 4782076 : free (scn->zdata_base);
175 : 4782076 : scn->zdata_base = NULL;
176 : : }
177 : :
178 : : /* If the file has the same byte order and the
179 : : architecture doesn't require overly stringent
180 : : alignment the raw data buffer is the same as the
181 : : one used for presenting to the caller. */
182 [ + + ]: 14463416 : if (scn->data_base != scn->rawdata_base)
183 : 540478 : free (scn->data_base);
184 : :
185 : : /* The section data is allocated if we couldn't mmap
186 : : the file. Or if we had to decompress. */
187 [ + + ]: 14463416 : if (elf->map_address == NULL
188 [ + + ]: 9232716 : || scn->rawdata_base == scn->zdata_base
189 [ + + ]: 3317834 : || (scn->flags & ELF_F_MALLOCED) != 0)
190 : 11145586 : free (scn->rawdata_base);
191 : :
192 : : /* Free the list of data buffers for the section.
193 : : We don't free the buffers themselves since this
194 : : is the users job. */
195 : 14463416 : runp = scn->data_list.next;
196 [ + + ]: 14463636 : while (runp != NULL)
197 : : {
198 : 220 : Elf_Data_List *oldp = runp;
199 : 220 : runp = runp->next;
200 [ + - ]: 220 : if ((oldp->flags & ELF_F_MALLOCED) != 0)
201 : 220 : free (oldp);
202 : : }
203 : : }
204 : :
205 : : /* Free the memory for the array. */
206 : 35340 : Elf_ScnList *oldp = list;
207 : 35340 : list = list->next;
208 [ + + - + ]: 35340 : assert (list == NULL || oldp->cnt == oldp->max);
209 [ + + ]: 35340 : if (oldp != (elf->class == ELFCLASS32
210 : : || (offsetof (struct Elf, state.elf32.scns)
211 : : == offsetof (struct Elf, state.elf64.scns))
212 : : ? &elf->state.elf32.scns
213 : : : &elf->state.elf64.scns))
214 : 1966 : free (oldp);
215 : : }
216 [ + + ]: 35340 : while (list != NULL);
217 : : }
218 : :
219 : : /* Free the section header. */
220 [ + + ]: 33374 : if (elf->state.elf.shdr_malloced != 0)
221 : 5110 : free (elf->class == ELFCLASS32
222 : : || (offsetof (struct Elf, state.elf32.shdr)
223 : : == offsetof (struct Elf, state.elf64.shdr))
224 : 5110 : ? (void *) elf->state.elf32.shdr
225 : : : (void *) elf->state.elf64.shdr);
226 : :
227 : : /* Free the program header. */
228 [ + + ]: 33374 : if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
229 : 2986 : free (elf->class == ELFCLASS32
230 : : || (offsetof (struct Elf, state.elf32.phdr)
231 : : == offsetof (struct Elf, state.elf64.phdr))
232 : 2986 : ? (void *) elf->state.elf32.phdr
233 : : : (void *) elf->state.elf64.phdr);
234 : : break;
235 : :
236 : : default:
237 : : break;
238 : : }
239 : :
240 [ + + + + ]: 35196 : if (elf->map_address != NULL && parent == NULL)
241 : : {
242 : : /* The file was read or mapped for this descriptor. */
243 [ + + ]: 16776 : if ((elf->flags & ELF_F_MALLOCED) != 0)
244 : 120 : free (elf->map_address);
245 [ + + ]: 16656 : else if ((elf->flags & ELF_F_MMAPPED) != 0)
246 : 16552 : munmap (elf->map_address, elf->maximum_size);
247 : : }
248 : :
249 : 35196 : rwlock_unlock (elf->lock);
250 : 35196 : rwlock_fini (elf->lock);
251 : :
252 : : /* Finally the descriptor itself. */
253 : 35196 : free (elf);
254 : :
255 [ + + ]: 14712 : return (parent != NULL && parent->ref_count == 0
256 [ + + ]: 35196 : ? INTUSE(elf_end) (parent) : 0);
257 : : }
258 : : INTDEF(elf_end)
|