|
1 /* |
|
2 * end.c - implementation of the elf_end(3) function. |
|
3 * Copyright (C) 1995 - 2004 Michael Riepe |
|
4 * |
|
5 * This library is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU Library General Public |
|
7 * License as published by the Free Software Foundation; either |
|
8 * version 2 of the License, or (at your option) any later version. |
|
9 * |
|
10 * This library is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 * Library General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Library General Public |
|
16 * License along with this library; if not, write to the Free Software |
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 */ |
|
19 |
|
20 #include <private.h> |
|
21 |
|
22 #ifndef lint |
|
23 static const char rcsid[] = "@(#) $Id: end.c,v 1.11 2005/05/21 15:39:21 michael Exp $"; |
|
24 #endif /* lint */ |
|
25 |
|
26 #if HAVE_MMAP |
|
27 #include <sys/mman.h> |
|
28 #endif /* HAVE_MMAP */ |
|
29 |
|
30 static void |
|
31 _elf_free(void *ptr) { |
|
32 if (ptr) { |
|
33 free(ptr); |
|
34 } |
|
35 } |
|
36 |
|
37 static void |
|
38 _elf_free_scns(Elf *elf, Elf_Scn *scn) { |
|
39 Scn_Data *sd, *tmp; |
|
40 Elf_Scn *freescn; |
|
41 |
|
42 for (freescn = NULL; scn; scn = scn->s_link) { |
|
43 elf_assert(scn->s_magic == SCN_MAGIC); |
|
44 elf_assert(scn->s_elf == elf); |
|
45 for (sd = scn->s_data_1; sd; sd = tmp) { |
|
46 elf_assert(sd->sd_magic == DATA_MAGIC); |
|
47 elf_assert(sd->sd_scn == scn); |
|
48 tmp = sd->sd_link; |
|
49 if (sd->sd_free_data) { |
|
50 _elf_free(sd->sd_memdata); |
|
51 } |
|
52 if (sd->sd_freeme) { |
|
53 free(sd); |
|
54 } |
|
55 } |
|
56 if ((sd = scn->s_rawdata)) { |
|
57 elf_assert(sd->sd_magic == DATA_MAGIC); |
|
58 elf_assert(sd->sd_scn == scn); |
|
59 if (sd->sd_free_data) { |
|
60 _elf_free(sd->sd_memdata); |
|
61 } |
|
62 if (sd->sd_freeme) { |
|
63 free(sd); |
|
64 } |
|
65 } |
|
66 if (scn->s_freeme) { |
|
67 _elf_free(freescn); |
|
68 freescn = scn; |
|
69 } |
|
70 } |
|
71 _elf_free(freescn); |
|
72 } |
|
73 |
|
74 int |
|
75 elf_end(Elf *elf) { |
|
76 Elf **siblings; |
|
77 |
|
78 if (!elf) { |
|
79 return 0; |
|
80 } |
|
81 elf_assert(elf->e_magic == ELF_MAGIC); |
|
82 if (--elf->e_count) { |
|
83 return elf->e_count; |
|
84 } |
|
85 if (elf->e_parent) { |
|
86 elf_assert(elf->e_parent->e_magic == ELF_MAGIC); |
|
87 elf_assert(elf->e_parent->e_kind == ELF_K_AR); |
|
88 siblings = &elf->e_parent->e_members; |
|
89 while (*siblings) { |
|
90 if (*siblings == elf) { |
|
91 *siblings = elf->e_link; |
|
92 break; |
|
93 } |
|
94 siblings = &(*siblings)->e_link; |
|
95 } |
|
96 elf_end(elf->e_parent); |
|
97 _elf_free(elf->e_arhdr); |
|
98 } |
|
99 #if HAVE_MMAP |
|
100 else if (elf->e_unmap_data) { |
|
101 munmap(elf->e_data, elf->e_size); |
|
102 } |
|
103 #endif /* HAVE_MMAP */ |
|
104 else if (!elf->e_memory) { |
|
105 _elf_free(elf->e_data); |
|
106 } |
|
107 _elf_free_scns(elf, elf->e_scn_1); |
|
108 if (elf->e_rawdata != elf->e_data) { |
|
109 _elf_free(elf->e_rawdata); |
|
110 } |
|
111 if (elf->e_free_syms) { |
|
112 _elf_free(elf->e_symtab); |
|
113 } |
|
114 _elf_free(elf->e_ehdr); |
|
115 _elf_free(elf->e_phdr); |
|
116 free(elf); |
|
117 return 0; |
|
118 } |