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 14998 : elf_end (Elf *elf)
44 : {
45 : Elf *parent;
46 :
47 14998 : if (elf == NULL)
48 : /* This is allowed and is a no-op. */
49 : return 0;
50 :
51 : /* Make sure we are alone. */
52 : rwlock_wrlock (elf->lock);
53 :
54 14723 : 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 14723 : 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 127 : if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
71 127 : free (elf->state.ar.ar_sym);
72 127 : elf->state.ar.ar_sym = NULL;
73 :
74 127 : if (elf->state.ar.children != NULL)
75 : return 0;
76 : }
77 :
78 : /* Remove this structure from the children list. */
79 14723 : parent = elf->parent;
80 14723 : 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 : rwlock_unlock (elf->lock);
88 : rwlock_rdlock (parent->lock);
89 : rwlock_wrlock (elf->lock);
90 :
91 7232 : if (parent->state.ar.children == elf)
92 7232 : 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 : rwlock_unlock (parent->lock);
104 : }
105 :
106 : /* This was the last activation. Free all resources. */
107 14723 : switch (elf->kind)
108 : {
109 127 : case ELF_K_AR:
110 127 : if (elf->state.ar.long_names != NULL)
111 102 : free (elf->state.ar.long_names);
112 : break;
113 :
114 14351 : case ELF_K_ELF:
115 14351 : {
116 14351 : 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 29556 : while (rawchunks != NULL)
123 : {
124 854 : Elf_Data_Chunk *next = rawchunks->next;
125 854 : if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED)
126 336 : free (rawchunks->data.d.d_buf);
127 854 : free (rawchunks);
128 854 : rawchunks = next;
129 : }
130 :
131 14351 : 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 : do
138 : {
139 : /* Free all separately allocated section headers. */
140 15225 : size_t cnt = list->max;
141 :
142 10776958 : while (cnt-- > 0)
143 : {
144 : /* These pointers can be NULL; it's safe to use
145 : 'free' since it will check for this. */
146 10746508 : Elf_Scn *scn = &list->data[cnt];
147 : Elf_Data_List *runp;
148 :
149 10746508 : if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
150 : /* It doesn't matter which pointer. */
151 2697354 : 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 10746508 : if (scn->zdata_base != scn->rawdata_base)
157 2803726 : 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 10746508 : if (scn->data_base != scn->rawdata_base)
164 1054598 : 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 10746508 : if (elf->map_address == NULL
169 6733058 : || scn->rawdata_base == scn->zdata_base
170 1551450 : || (scn->flags & ELF_F_MALLOCED) != 0)
171 9195063 : 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 10746508 : runp = scn->data_list.next;
177 21493110 : 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 15225 : Elf_ScnList *oldp = list;
188 15225 : list = list->next;
189 15225 : assert (list == NULL || oldp->cnt == oldp->max);
190 15225 : 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 874 : free (oldp);
196 : }
197 15225 : while (list != NULL);
198 : }
199 :
200 : /* Free the section header. */
201 14351 : if (elf->state.elf.shdr_malloced != 0)
202 1361 : free (elf->class == ELFCLASS32
203 : || (offsetof (struct Elf, state.elf32.shdr)
204 : == offsetof (struct Elf, state.elf64.shdr))
205 1361 : ? (void *) elf->state.elf32.shdr
206 : : (void *) elf->state.elf64.shdr);
207 :
208 : /* Free the program header. */
209 14351 : if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
210 727 : free (elf->class == ELFCLASS32
211 : || (offsetof (struct Elf, state.elf32.phdr)
212 : == offsetof (struct Elf, state.elf64.phdr))
213 727 : ? (void *) elf->state.elf32.phdr
214 : : (void *) elf->state.elf64.phdr);
215 : break;
216 :
217 : default:
218 : break;
219 : }
220 :
221 14723 : if (elf->map_address != NULL && parent == NULL)
222 : {
223 : /* The file was read or mapped for this descriptor. */
224 6690 : if ((elf->flags & ELF_F_MALLOCED) != 0)
225 20 : free (elf->map_address);
226 6670 : else if ((elf->flags & ELF_F_MMAPPED) != 0)
227 6634 : munmap (elf->map_address, elf->maximum_size);
228 : }
229 :
230 : rwlock_unlock (elf->lock);
231 : rwlock_fini (elf->lock);
232 :
233 : /* Finally the descriptor itself. */
234 14723 : free (elf);
235 :
236 7232 : return (parent != NULL && parent->ref_count == 0
237 14723 : ? INTUSE(elf_end) (parent) : 0);
238 : }
239 : INTDEF(elf_end)
|