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 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
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
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
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.
25 : :
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/>. */
29 : :
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 : :
42 : : int
43 : 16117 : elf_end (Elf *elf)
44 : : {
45 : 16117 : Elf *parent;
46 : :
47 [ + + ]: 16117 : if (elf == NULL)
48 : : /* This is allowed and is a no-op. */
49 : : return 0;
50 : :
51 : : /* Make sure we are alone. */
52 : 15828 : rwlock_wrlock (elf->lock);
53 : :
54 [ + - ][ + - ]: 15828 : if (elf->ref_count != 0 && --elf->ref_count != 0)
55 : : {
56 : : /* Not yet the last activation. */
57 : : int result = elf->ref_count;
58 : : rwlock_unlock (elf->lock);
59 : : return result;
60 : : }
61 : :
62 [ + + ]: 15828 : if (elf->kind == ELF_K_AR)
63 : : {
64 : : /* We cannot remove the descriptor now since we still have some
65 : : descriptors which depend on it. But we can free the archive
66 : : symbol table since this is only available via the archive ELF
67 : : descriptor. The long name table cannot be freed yet since
68 : : the archive headers for the ELF files in the archive point
69 : : into this array. */
70 [ + - ]: 137 : if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
71 : 137 : free (elf->state.ar.ar_sym);
72 : 137 : elf->state.ar.ar_sym = NULL;
73 : :
74 [ + - ]: 137 : if (elf->state.ar.children != NULL)
75 : : return 0;
76 : : }
77 : :
78 : : /* Remove this structure from the children list. */
79 : 15828 : parent = elf->parent;
80 [ + + ]: 15828 : if (parent != NULL)
81 : : {
82 : : /* This is tricky. Lock must be acquire from the father to
83 : : the child but here we already have the child lock. We
84 : : solve this problem by giving free the child lock. The
85 : : state of REF_COUNT==0 is handled all over the library, so
86 : : this should be ok. */
87 : 7230 : rwlock_unlock (elf->lock);
88 : 7230 : rwlock_rdlock (parent->lock);
89 : 7230 : rwlock_wrlock (elf->lock);
90 : :
91 [ + - ]: 7230 : if (parent->state.ar.children == elf)
92 : 7230 : parent->state.ar.children = elf->next;
93 : : else
94 : : {
95 : : struct Elf *child = parent->state.ar.children;
96 : :
97 [ # # ]: 0 : while (child->next != elf)
98 : : child = child->next;
99 : :
100 : 0 : child->next = elf->next;
101 : : }
102 : :
103 : 15828 : rwlock_unlock (parent->lock);
104 : : }
105 : :
106 : : /* This was the last activation. Free all resources. */
107 [ + + + ]: 15828 : switch (elf->kind)
108 : : {
109 : 137 : case ELF_K_AR:
110 [ + + ]: 137 : if (elf->state.ar.long_names != NULL)
111 : 102 : free (elf->state.ar.long_names);
112 : : break;
113 : :
114 : 15384 : case ELF_K_ELF:
115 : 15384 : {
116 : 15384 : Elf_Data_Chunk *rawchunks
117 : : = (elf->class == ELFCLASS32
118 : : || (offsetof (struct Elf, state.elf32.rawchunks)
119 : : == offsetof (struct Elf, state.elf64.rawchunks))
120 : : ? elf->state.elf32.rawchunks
121 : : : elf->state.elf64.rawchunks);
122 [ + + ]: 16505 : while (rawchunks != NULL)
123 : : {
124 : 1121 : Elf_Data_Chunk *next = rawchunks->next;
125 [ + + ]: 1121 : if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
126 : 582 : free (rawchunks->data.d.d_buf);
127 : 1121 : free (rawchunks);
128 : 1121 : rawchunks = next;
129 : : }
130 : :
131 : 15384 : Elf_ScnList *list = (elf->class == ELFCLASS32
132 : : || (offsetof (struct Elf, state.elf32.scns)
133 : : == offsetof (struct Elf, state.elf64.scns))
134 : : ? &elf->state.elf32.scns
135 : : : &elf->state.elf64.scns);
136 : :
137 : 16328 : do
138 : : {
139 : : /* Free all separately allocated section headers. */
140 : 16328 : size_t cnt = list->max;
141 : :
142 [ + + ]: 10860137 : while (cnt-- > 0)
143 : : {
144 : : /* These pointers can be NULL; it's safe to use
145 : : 'free' since it will check for this. */
146 : 10843809 : Elf_Scn *scn = &list->data[cnt];
147 : 10843809 : Elf_Data_List *runp;
148 : :
149 [ + + ]: 10843809 : if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
150 : : /* It doesn't matter which pointer. */
151 : 2699244 : free (scn->shdr.e32);
152 : :
153 : : /* Free zdata if uncompressed, but not yet used as
154 : : rawdata_base. If it is already used it will be
155 : : freed below. */
156 [ + + ]: 10843809 : if (scn->zdata_base != scn->rawdata_base)
157 : 3209739 : free (scn->zdata_base);
158 : :
159 : : /* If the file has the same byte order and the
160 : : architecture doesn't require overly stringent
161 : : alignment the raw data buffer is the same as the
162 : : one used for presenting to the caller. */
163 [ + + ]: 10843809 : if (scn->data_base != scn->rawdata_base)
164 : 529343 : free (scn->data_base);
165 : :
166 : : /* The section data is allocated if we couldn't mmap
167 : : the file. Or if we had to decompress. */
168 [ + + ]: 10843809 : if (elf->map_address == NULL
169 [ + + ]: 6808517 : || scn->rawdata_base == scn->zdata_base
170 [ - + ]: 1955298 : || (scn->flags & ELF_F_MALLOCED) != 0)
171 : 8888511 : free (scn->rawdata_base);
172 : :
173 : : /* Free the list of data buffers for the section.
174 : : We don't free the buffers themselves since this
175 : : is the users job. */
176 : 10843809 : runp = scn->data_list.next;
177 [ + + ]: 10843903 : while (runp != NULL)
178 : : {
179 : 94 : Elf_Data_List *oldp = runp;
180 : 94 : runp = runp->next;
181 [ + - ]: 94 : if ((oldp->flags & ELF_F_MALLOCED) != 0)
182 : 94 : free (oldp);
183 : : }
184 : : }
185 : :
186 : : /* Free the memory for the array. */
187 : 16328 : Elf_ScnList *oldp = list;
188 : 16328 : list = list->next;
189 [ + + ][ - + ]: 16328 : assert (list == NULL || oldp->cnt == oldp->max);
190 [ + + ]: 16328 : if (oldp != (elf->class == ELFCLASS32
191 : : || (offsetof (struct Elf, state.elf32.scns)
192 : : == offsetof (struct Elf, state.elf64.scns))
193 : : ? &elf->state.elf32.scns
194 : : : &elf->state.elf64.scns))
195 : 944 : free (oldp);
196 : : }
197 [ + + ]: 16328 : while (list != NULL);
198 : : }
199 : :
200 : : /* Free the section header. */
201 [ + + ]: 15384 : if (elf->state.elf.shdr_malloced != 0)
202 : 4070 : free (elf->class == ELFCLASS32
203 : : || (offsetof (struct Elf, state.elf32.shdr)
204 : : == offsetof (struct Elf, state.elf64.shdr))
205 : 2035 : ? (void *) elf->state.elf32.shdr
206 : : : (void *) elf->state.elf64.shdr);
207 : :
208 : : /* Free the program header. */
209 [ + + ]: 15384 : if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
210 : 2378 : free (elf->class == ELFCLASS32
211 : : || (offsetof (struct Elf, state.elf32.phdr)
212 : : == offsetof (struct Elf, state.elf64.phdr))
213 : 1189 : ? (void *) elf->state.elf32.phdr
214 : : : (void *) elf->state.elf64.phdr);
215 : : break;
216 : :
217 : : default:
218 : : break;
219 : : }
220 : :
221 [ + + ][ + + ]: 15828 : if (elf->map_address != NULL && parent == NULL)
222 : : {
223 : : /* The file was read or mapped for this descriptor. */
224 [ + + ]: 7001 : if ((elf->flags & ELF_F_MALLOCED) != 0)
225 : 36 : free (elf->map_address);
226 [ + + ]: 6965 : else if ((elf->flags & ELF_F_MMAPPED) != 0)
227 : 6929 : munmap (elf->map_address, elf->maximum_size);
228 : : }
229 : :
230 : 15828 : rwlock_unlock (elf->lock);
231 : 15828 : rwlock_fini (elf->lock);
232 : :
233 : : /* Finally the descriptor itself. */
234 : 15828 : free (elf);
235 : :
236 [ - + ]: 7230 : return (parent != NULL && parent->ref_count == 0
237 [ + + ]: 15828 : ? INTUSE(elf_end) (parent) : 0);
238 : : }
239 : : INTDEF(elf_end)
|