Branch data Line data Source code
1 : : /* Free resources associated with Elf descriptor.
2 : : Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007 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 : 12949 : elf_end (elf)
44 : : Elf *elf;
45 : : {
46 : : Elf *parent;
47 : :
48 [ + - ]: 12949 : if (elf == NULL)
49 : : /* This is allowed and is a no-op. */
50 : : return 0;
51 : :
52 : : /* Make sure we are alone. */
53 : : rwlock_wrlock (elf->lock);
54 : :
55 [ + - ][ + - ]: 12949 : if (elf->ref_count != 0 && --elf->ref_count != 0)
56 : : {
57 : : /* Not yet the last activation. */
58 : : int result = elf->ref_count;
59 : : rwlock_unlock (elf->lock);
60 : : return result;
61 : : }
62 : :
63 [ + + ]: 12949 : 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. */
71 [ + - ]: 118 : if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
72 : 118 : free (elf->state.ar.ar_sym);
73 : 118 : elf->state.ar.ar_sym = NULL;
74 : :
75 [ + - ]: 118 : if (elf->state.ar.children != NULL)
76 : : return 0;
77 : : }
78 : :
79 : : /* Remove this structure from the children list. */
80 : 12949 : parent = elf->parent;
81 [ + + ]: 12949 : 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. */
88 : : rwlock_unlock (elf->lock);
89 : : rwlock_rdlock (parent->lock);
90 : : rwlock_wrlock (elf->lock);
91 : :
92 [ + - ]: 6597 : if (parent->state.ar.children == elf)
93 : 6597 : parent->state.ar.children = elf->next;
94 : : else
95 : : {
96 : : struct Elf *child = parent->state.ar.children;
97 : :
98 [ # # ]: 0 : while (child->next != elf)
99 : : child = child->next;
100 : :
101 : 0 : child->next = elf->next;
102 : : }
103 : :
104 : : rwlock_unlock (parent->lock);
105 : : }
106 : :
107 : : /* This was the last activation. Free all resources. */
108 [ + + + ]: 12949 : switch (elf->kind)
109 : : {
110 : : case ELF_K_AR:
111 [ + + ]: 118 : if (elf->state.ar.long_names != NULL)
112 : 97 : free (elf->state.ar.long_names);
113 : : break;
114 : :
115 : : case ELF_K_ELF:
116 : : {
117 : 12603 : 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 [ + + ]: 12638 : while (rawchunks != NULL)
124 : : {
125 : 35 : Elf_Data_Chunk *next = rawchunks->next;
126 [ + + ]: 35 : if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
127 : 3 : free (rawchunks->data.d.d_buf);
128 : 35 : free (rawchunks);
129 : 35 : rawchunks = next;
130 : : }
131 : :
132 : 12603 : 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 : 12708 : size_t cnt = list->max;
142 : :
143 [ + + ]: 906889 : while (cnt-- > 0)
144 : : {
145 : : /* These pointers can be NULL; it's safe to use
146 : : 'free' since it will check for this. */
147 : 894181 : Elf_Scn *scn = &list->data[cnt];
148 : : Elf_Data_List *runp;
149 : :
150 [ + + ]: 894181 : if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
151 : : /* It doesn't matter which pointer. */
152 : 199349 : 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 [ + + ]: 894181 : if (scn->data_base != scn->rawdata_base)
159 : 6424 : free (scn->data_base);
160 : :
161 : : /* The section data is allocated if we couldn't mmap
162 : : the file. */
163 [ + + ]: 894181 : if (elf->map_address == NULL)
164 : 213693 : 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 : 894181 : runp = scn->data_list.next;
170 [ + + ]: 894183 : while (runp != NULL)
171 : : {
172 : 2 : Elf_Data_List *oldp = runp;
173 : 2 : runp = runp->next;
174 [ + - ]: 2 : if ((oldp->flags & ELF_F_MALLOCED) != 0)
175 : 2 : free (oldp);
176 : : }
177 : : }
178 : :
179 : : /* Free the memory for the array. */
180 : 12708 : Elf_ScnList *oldp = list;
181 : 12708 : list = list->next;
182 [ + + ][ - + ]: 12708 : assert (list == NULL || oldp->cnt == oldp->max);
183 [ + + ]: 12708 : 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 : 105 : free (oldp);
189 : : }
190 [ + + ]: 12708 : while (list != NULL);
191 : : }
192 : :
193 : : /* Free the section header. */
194 [ + + ]: 12603 : if (elf->state.elf.shdr_malloced != 0)
195 : 102 : free (elf->class == ELFCLASS32
196 : : || (offsetof (struct Elf, state.elf32.shdr)
197 : : == offsetof (struct Elf, state.elf64.shdr))
198 : 102 : ? (void *) elf->state.elf32.shdr
199 : : : (void *) elf->state.elf64.shdr);
200 : :
201 : : /* Free the program header. */
202 [ + + ]: 12603 : if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
203 : 59 : free (elf->class == ELFCLASS32
204 : : || (offsetof (struct Elf, state.elf32.phdr)
205 : : == offsetof (struct Elf, state.elf64.phdr))
206 : 59 : ? (void *) elf->state.elf32.phdr
207 : : : (void *) elf->state.elf64.phdr);
208 : : break;
209 : :
210 : : default:
211 : : break;
212 : : }
213 : :
214 [ + + ][ + + ]: 12949 : if (elf->map_address != NULL && parent == NULL)
215 : : {
216 : : /* The file was read or mapped for this descriptor. */
217 [ + + ]: 6166 : if ((elf->flags & ELF_F_MALLOCED) != 0)
218 : 3 : free (elf->map_address);
219 [ + + ]: 6163 : else if ((elf->flags & ELF_F_MMAPPED) != 0)
220 : 6110 : munmap (elf->map_address, elf->maximum_size);
221 : : }
222 : :
223 : : rwlock_unlock (elf->lock);
224 : : rwlock_fini (elf->lock);
225 : :
226 : : /* Finally the descriptor itself. */
227 : 12949 : free (elf);
228 : :
229 [ - + ]: 12949 : return (parent != NULL && parent->ref_count == 0
230 [ + + ]: 12949 : ? INTUSE(elf_end) (parent) : 0);
231 : : }
232 : : INTDEF(elf_end)
|