1 /* $NetBSD: libelf_allocate.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2006,2008,2010 Joseph Koshy
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #if HAVE_NBTOOL_CONFIG_H
30 # include "nbtool_config.h"
31 #endif
32
33 /*
34 * Internal APIs
35 */
36
37 #include <sys/cdefs.h>
38
39 #include <assert.h>
40 #include <errno.h>
41 #include <libelf.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "_libelf.h"
46
47 __RCSID("$NetBSD: libelf_allocate.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
48 ELFTC_VCSID("Id: libelf_allocate.c 2272 2011-12-03 17:07:31Z jkoshy ");
49
50 Elf *
_libelf_allocate_elf(void)51 _libelf_allocate_elf(void)
52 {
53 Elf *e;
54
55 if ((e = malloc(sizeof(*e))) == NULL) {
56 LIBELF_SET_ERROR(RESOURCE, errno);
57 return NULL;
58 }
59
60 e->e_activations = 1;
61 e->e_hdr.e_rawhdr = NULL;
62 e->e_byteorder = ELFDATANONE;
63 e->e_class = ELFCLASSNONE;
64 e->e_cmd = ELF_C_NULL;
65 e->e_fd = -1;
66 e->e_flags = 0;
67 e->e_kind = ELF_K_NONE;
68 e->e_parent = NULL;
69 e->e_rawfile = NULL;
70 e->e_rawsize = 0;
71 e->e_version = LIBELF_PRIVATE(version);
72
73 (void) memset(&e->e_u, 0, sizeof(e->e_u));
74
75 return (e);
76 }
77
78 void
_libelf_init_elf(Elf * e,Elf_Kind kind)79 _libelf_init_elf(Elf *e, Elf_Kind kind)
80 {
81 assert(e != NULL);
82 assert(e->e_kind == ELF_K_NONE);
83
84 e->e_kind = kind;
85
86 switch (kind) {
87 case ELF_K_ELF:
88 STAILQ_INIT(&e->e_u.e_elf.e_scn);
89 break;
90 default:
91 break;
92 }
93 }
94
95 #define FREE(P) do { \
96 if (P) \
97 free(P); \
98 } while (/*CONSTCOND*/0)
99
100
101 Elf *
_libelf_release_elf(Elf * e)102 _libelf_release_elf(Elf *e)
103 {
104 Elf_Arhdr *arh;
105
106 switch (e->e_kind) {
107 case ELF_K_AR:
108 FREE(e->e_u.e_ar.e_symtab);
109 break;
110
111 case ELF_K_ELF:
112 switch (e->e_class) {
113 case ELFCLASS32:
114 FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
115 FREE(e->e_u.e_elf.e_phdr.e_phdr32);
116 break;
117 case ELFCLASS64:
118 FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
119 FREE(e->e_u.e_elf.e_phdr.e_phdr64);
120 break;
121 }
122
123 assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
124
125 if (e->e_flags & LIBELF_F_AR_HEADER) {
126 arh = e->e_hdr.e_arhdr;
127 FREE(arh->ar_name);
128 FREE(arh->ar_rawname);
129 free(arh);
130 }
131
132 break;
133
134 default:
135 break;
136 }
137
138 free(e);
139
140 return (NULL);
141 }
142
143 struct _Libelf_Data *
_libelf_allocate_data(Elf_Scn * s)144 _libelf_allocate_data(Elf_Scn *s)
145 {
146 struct _Libelf_Data *d;
147
148 if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
149 LIBELF_SET_ERROR(RESOURCE, 0);
150 return (NULL);
151 }
152
153 d->d_scn = s;
154
155 return (d);
156 }
157
158 struct _Libelf_Data *
_libelf_release_data(struct _Libelf_Data * d)159 _libelf_release_data(struct _Libelf_Data *d)
160 {
161
162 if (d->d_flags & LIBELF_F_DATA_MALLOCED)
163 free(d->d_data.d_buf);
164
165 free(d);
166
167 return (NULL);
168 }
169
170 Elf_Scn *
_libelf_allocate_scn(Elf * e,size_t ndx)171 _libelf_allocate_scn(Elf *e, size_t ndx)
172 {
173 Elf_Scn *s;
174
175 if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
176 LIBELF_SET_ERROR(RESOURCE, errno);
177 return (NULL);
178 }
179
180 s->s_elf = e;
181 s->s_ndx = ndx;
182
183 STAILQ_INIT(&s->s_data);
184 STAILQ_INIT(&s->s_rawdata);
185
186 STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
187
188 return (s);
189 }
190
191 Elf_Scn *
_libelf_release_scn(Elf_Scn * s)192 _libelf_release_scn(Elf_Scn *s)
193 {
194 Elf *e;
195 struct _Libelf_Data *d, *td;
196
197 assert(s != NULL);
198
199 STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
200 STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next);
201 d = _libelf_release_data(d);
202 }
203
204 STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
205 assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0);
206 STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next);
207 d = _libelf_release_data(d);
208 }
209
210 e = s->s_elf;
211
212 assert(e != NULL);
213
214 STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
215
216 free(s);
217
218 return (NULL);
219 }
220