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 : 36130 : elf_end (Elf *elf)
54 : : {
55 : 36138 : Elf *parent;
56 : :
57 [ + + ]: 36138 : if (elf == NULL)
58 : : /* This is allowed and is a no-op. */
59 : : return 0;
60 : :
61 : : /* Make sure we are alone. */
62 : 35350 : rwlock_wrlock (elf->lock);
63 : :
64 [ + + + - ]: 35350 : 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 [ + + ]: 35350 : 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 [ + - ]: 400 : if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
81 : 400 : free (elf->state.ar.ar_sym);
82 : 400 : elf->state.ar.ar_sym = NULL;
83 : :
84 [ + + ]: 400 : 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 : 35342 : parent = elf->parent;
93 [ + + ]: 35342 : 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 : 14818 : rwlock_unlock (elf->lock);
101 : 14818 : rwlock_rdlock (parent->lock);
102 : 14818 : rwlock_wrlock (elf->lock);
103 : :
104 [ + + ]: 14818 : if (parent->state.ar.children == elf)
105 : 14810 : 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 : 35342 : rwlock_unlock (parent->lock);
117 : : }
118 : :
119 [ + + ]: 35342 : if (elf->elf_ar_hdr.ar_name != NULL)
120 : 14818 : free (elf->elf_ar_hdr.ar_name);
121 : :
122 [ + + ]: 35342 : if (elf->elf_ar_hdr.ar_rawname != NULL)
123 : 14818 : free (elf->elf_ar_hdr.ar_rawname);
124 : :
125 : : /* This was the last activation. Free all resources. */
126 [ + + + ]: 35342 : switch (elf->kind)
127 : : {
128 : 392 : case ELF_K_AR:
129 [ + + ]: 392 : if (elf->state.ar.long_names != NULL)
130 : 210 : free (elf->state.ar.long_names);
131 : : break;
132 : :
133 : 33446 : case ELF_K_ELF:
134 : : {
135 : 33446 : search_tree *rawchunk_tree
136 : : = (elf->class == ELFCLASS32
137 : : || (offsetof (struct Elf, state.elf32.rawchunk_tree)
138 : : == offsetof (struct Elf, state.elf64.rawchunk_tree))
139 : : ? &elf->state.elf32.rawchunk_tree
140 : : : &elf->state.elf64.rawchunk_tree);
141 : :
142 : 33446 : eu_search_tree_fini (rawchunk_tree, free_chunk);
143 : :
144 : 33446 : Elf_ScnList *list = (elf->class == ELFCLASS32
145 : : || (offsetof (struct Elf, state.elf32.scns)
146 : : == offsetof (struct Elf, state.elf64.scns))
147 : : ? &elf->state.elf32.scns
148 : : : &elf->state.elf64.scns);
149 : :
150 : 35412 : do
151 : : {
152 : : /* Free all separately allocated section headers. */
153 : 35412 : size_t cnt = list->max;
154 : :
155 [ + + ]: 14499620 : while (cnt-- > 0)
156 : : {
157 : : /* These pointers can be NULL; it's safe to use
158 : : 'free' since it will check for this. */
159 : 14464208 : Elf_Scn *scn = &list->data[cnt];
160 : 14464208 : Elf_Data_List *runp;
161 : :
162 [ + + ]: 14464208 : if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
163 : : /* It doesn't matter which pointer. */
164 : 3305822 : free (scn->shdr.e32);
165 : :
166 : : /* Free zdata if uncompressed, but not yet used as
167 : : rawdata_base. If it is already used it will be
168 : : freed below. */
169 [ + + ]: 14464208 : if (scn->zdata_base != scn->rawdata_base)
170 : : {
171 : 4782148 : free (scn->zdata_base);
172 : 4782148 : scn->zdata_base = NULL;
173 : : }
174 : :
175 : : /* If the file has the same byte order and the
176 : : architecture doesn't require overly stringent
177 : : alignment the raw data buffer is the same as the
178 : : one used for presenting to the caller. */
179 [ + + ]: 14464208 : if (scn->data_base != scn->rawdata_base)
180 : 540528 : free (scn->data_base);
181 : :
182 : : /* The section data is allocated if we couldn't mmap
183 : : the file. Or if we had to decompress. */
184 [ + + ]: 14464208 : if (elf->map_address == NULL
185 [ + + ]: 9233310 : || scn->rawdata_base == scn->zdata_base
186 [ + + ]: 3317906 : || (scn->flags & ELF_F_MALLOCED) != 0)
187 : 11146306 : free (scn->rawdata_base);
188 : :
189 : : /* Free the list of data buffers for the section.
190 : : We don't free the buffers themselves since this
191 : : is the users job. */
192 : 14464208 : runp = scn->data_list.next;
193 [ + + ]: 14464428 : while (runp != NULL)
194 : : {
195 : 220 : Elf_Data_List *oldp = runp;
196 : 220 : runp = runp->next;
197 [ + - ]: 220 : if ((oldp->flags & ELF_F_MALLOCED) != 0)
198 : 220 : free (oldp);
199 : : }
200 : : }
201 : :
202 : : /* Free the memory for the array. */
203 : 35412 : Elf_ScnList *oldp = list;
204 : 35412 : list = list->next;
205 [ + + - + ]: 35412 : assert (list == NULL || oldp->cnt == oldp->max);
206 [ + + ]: 35412 : if (oldp != (elf->class == ELFCLASS32
207 : : || (offsetof (struct Elf, state.elf32.scns)
208 : : == offsetof (struct Elf, state.elf64.scns))
209 : : ? &elf->state.elf32.scns
210 : : : &elf->state.elf64.scns))
211 : 1966 : free (oldp);
212 : : }
213 [ + + ]: 35412 : while (list != NULL);
214 : : }
215 : :
216 : : /* Free the section header. */
217 [ + + ]: 33446 : if (elf->state.elf.shdr_malloced != 0)
218 : 5146 : free (elf->class == ELFCLASS32
219 : : || (offsetof (struct Elf, state.elf32.shdr)
220 : : == offsetof (struct Elf, state.elf64.shdr))
221 : 5146 : ? (void *) elf->state.elf32.shdr
222 : : : (void *) elf->state.elf64.shdr);
223 : :
224 : : /* Free the program header. */
225 [ + + ]: 33446 : if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
226 : 2986 : free (elf->class == ELFCLASS32
227 : : || (offsetof (struct Elf, state.elf32.phdr)
228 : : == offsetof (struct Elf, state.elf64.phdr))
229 : 2986 : ? (void *) elf->state.elf32.phdr
230 : : : (void *) elf->state.elf64.phdr);
231 : : break;
232 : :
233 : : default:
234 : : break;
235 : : }
236 : :
237 [ + + + + ]: 35342 : if (elf->map_address != NULL && parent == NULL)
238 : : {
239 : : /* The file was read or mapped for this descriptor. */
240 [ + + ]: 16814 : if ((elf->flags & ELF_F_MALLOCED) != 0)
241 : 120 : free (elf->map_address);
242 [ + + ]: 16694 : else if ((elf->flags & ELF_F_MMAPPED) != 0)
243 : 16590 : munmap (elf->map_address, elf->maximum_size);
244 : : }
245 : :
246 : 35342 : rwlock_unlock (elf->lock);
247 : 35342 : rwlock_fini (elf->lock);
248 : :
249 : : /* Finally the descriptor itself. */
250 : 35342 : free (elf);
251 : :
252 [ + + ]: 14818 : return (parent != NULL && parent->ref_count == 0
253 [ + + ]: 35342 : ? INTUSE(elf_end) (parent) : 0);
254 : : }
255 : : INTDEF(elf_end)
|