blob: 33626f0729c3f1b2a0d42711450bf9588e75064d [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Free resources associated with Elf descriptor.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 2.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21
22#include <assert.h>
23#include <stddef.h>
24#include <stdlib.h>
25#include <sys/mman.h>
26
27#include "libelfP.h"
28
29
30int
31elf_end (elf)
32 Elf *elf;
33{
34 Elf *parent;
35
36 if (elf == NULL)
37 /* This is allowed and is a no-op. */
38 return 0;
39
40 /* Make sure we are alone. */
41 rwlock_wrlock (elf->lock);
42
43 if (elf->ref_count != 0 && --elf->ref_count != 0)
44 {
45 /* Not yet the last activation. */
46 int result = elf->ref_count;
47 rwlock_unlock (elf->lock);
48 return result;
49 }
50
51 if (elf->kind == ELF_K_AR)
52 {
53 /* We cannot remove the descriptor now since we still have some
54 descriptors which depend on it. But we can free the archive
55 symbol table since this is only available via the archive ELF
56 descriptor. The long name table cannot be freed yet since
57 the archive headers for the ELF files in the archive point
58 into this array. */
59 free (elf->state.ar.ar_sym);
60 elf->state.ar.ar_sym = NULL;
61
62 if (elf->state.ar.children != NULL)
63 return 0;
64 }
65
66 /* Remove this structure from the children list. */
67 parent = elf->parent;
68 if (parent != NULL)
69 {
70 /* This is tricky. Lock must be acquire from the father to
71 the child but here we already have the child lock. We
72 solve this problem by giving free the child lock. The
73 state of REF_COUNT==0 is handled all over the library, so
74 this should be ok. */
75 rwlock_unlock (elf->lock);
76 rwlock_rdlock (parent->lock);
77 rwlock_wrlock (elf->lock);
78
79 if (parent->state.ar.children == elf)
80 parent->state.ar.children = elf->next;
81 else
82 {
83 struct Elf *child = parent->state.ar.children;
84
85 while (child->next != elf)
86 child = child->next;
87
88 child->next = elf->next;
89 }
90
91 rwlock_unlock (parent->lock);
92 }
93
94 /* This was the last activation. Free all resources. */
95 switch (elf->kind)
96 {
97 case ELF_K_AR:
98 if (elf->state.ar.long_names != NULL)
99 free (elf->state.ar.long_names);
100 break;
101
102 case ELF_K_ELF:
103 {
104 Elf_ScnList *list = (elf->class == ELFCLASS32
105 || (offsetof (struct Elf, state.elf32.scns)
106 == offsetof (struct Elf, state.elf64.scns))
107 ? &elf->state.elf32.scns
108 : &elf->state.elf64.scns);
109
110 do
111 {
112 /* Free all separately allocated section headers. */
113 size_t cnt = list->max;
114
115 while (cnt-- > 0)
116 {
117 /* These pointers can be NULL; it's safe to use
118 'free' since it will check for this. */
119 Elf_Scn *scn = &list->data[cnt];
120 Elf_Data_List *runp;
121
122 if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
123 /* It doesn't matter which pointer. */
124 free (scn->shdr.e32);
125
126 /* If the file has the same byte order and the
127 architecture doesn't require overly stringent
128 alignment the raw data buffer is the same as the
129 one used for presenting to the caller. */
130 if (scn->data_base != scn->rawdata_base)
131 free (scn->data_base);
132
133 /* The section data is allocated if we couldn't mmap
134 the file. */
135 if (elf->map_address == NULL)
136 free (scn->rawdata_base);
137
138 /* Free the list of data buffers for the section.
139 We don't free the buffers themselves since this
140 is the users job. */
141 runp = scn->data_list.next;
142 while (runp != NULL)
143 {
144 Elf_Data_List *oldp = runp;
145 runp = runp->next;
146 if ((oldp->flags & ELF_F_MALLOCED) != 0)
147 free (oldp);
148 }
149 }
150
151 /* Free the memory for the array. */
152 Elf_ScnList *oldp = list;
153 list = list->next;
154 assert (list == NULL || oldp->cnt == oldp->max);
155 if (oldp != (elf->class == ELFCLASS32
156 || (offsetof (struct Elf, state.elf32.scns)
157 == offsetof (struct Elf, state.elf64.scns))
158 ? &elf->state.elf32.scns
159 : &elf->state.elf64.scns))
160 free (oldp);
161 }
162 while (list != NULL);
163 }
164
165 /* Free the section header. */
166 if (elf->state.elf.shdr_malloced != 0)
167 free (elf->class == ELFCLASS32
168 || (offsetof (struct Elf, state.elf32.shdr)
169 == offsetof (struct Elf, state.elf64.shdr))
170 ? (void *) elf->state.elf32.shdr
171 : (void *) elf->state.elf64.shdr);
172
173 /* Free the program header. */
174 if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
175 free (elf->class == ELFCLASS32
176 || (offsetof (struct Elf, state.elf32.phdr)
177 == offsetof (struct Elf, state.elf64.phdr))
178 ? (void *) elf->state.elf32.phdr
179 : (void *) elf->state.elf64.phdr);
180 break;
181
182 default:
183 break;
184 }
185
186 if (elf->map_address != NULL && parent == NULL)
187 {
188 /* The file was read or mapped for this descriptor. */
189 if ((elf->flags & ELF_F_MALLOCED) != 0)
190 free (elf->map_address);
191 else if ((elf->flags & ELF_F_MMAPPED) != 0)
192 munmap (elf->map_address, elf->maximum_size);
193 }
194
195 rwlock_fini (elf->lock);
196
197 /* Finally the descriptor itself. */
198 free (elf);
199
200 return (parent != NULL && parent->ref_count == 0
201 ? INTUSE(elf_end) (parent) : 0);
202}
203INTDEF(elf_end)