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