xref: /netbsd-src/external/bsd/elftoolchain/dist/libelf/libelf_allocate.c (revision 5ac3bc719ce6e70593039505b491894133237d12)
1 /*	$NetBSD: libelf_allocate.c,v 1.5 2024/03/03 17:37:34 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.5 2024/03/03 17:37:34 christos Exp $");
48 ELFTC_VCSID("Id: libelf_allocate.c 3977 2022-05-01 06:45:34Z jkoshy");
49 
50 Elf *
_libelf_allocate_elf(void)51 _libelf_allocate_elf(void)
52 {
53 	Elf *e;
54 
55 	if ((e = calloc((size_t) 1, sizeof(*e))) == NULL) {
56 		LIBELF_SET_ERROR(RESOURCE, errno);
57 		return NULL;
58 	}
59 
60 	e->e_activations = 1;
61 	e->e_byteorder   = ELFDATANONE;
62 	e->e_class       = ELFCLASSNONE;
63 	e->e_cmd         = ELF_C_NULL;
64 	e->e_fd          = -1;
65 	e->e_kind        = ELF_K_NONE;
66 	e->e_version     = LIBELF_PRIVATE(version);
67 
68 	return (e);
69 }
70 
71 void
_libelf_init_elf(Elf * e,Elf_Kind kind)72 _libelf_init_elf(Elf *e, Elf_Kind kind)
73 {
74 	assert(e != NULL);
75 	assert(e->e_kind == ELF_K_NONE);
76 
77 	e->e_kind = kind;
78 
79 	switch (kind) {
80 	case ELF_K_ELF:
81 		STAILQ_INIT(&e->e_u.e_elf.e_scn);
82 		break;
83 	default:
84 		break;
85 	}
86 }
87 
88 void
_libelf_release_elf(Elf * e)89 _libelf_release_elf(Elf *e)
90 {
91 	Elf_Arhdr *arh;
92 
93 	switch (e->e_kind) {
94 	case ELF_K_AR:
95 		free(e->e_u.e_ar.e_symtab);
96 		break;
97 
98 	case ELF_K_ELF:
99 		switch (e->e_class) {
100 		case ELFCLASS32:
101 			free(e->e_u.e_elf.e_ehdr.e_ehdr32);
102 			free(e->e_u.e_elf.e_phdr.e_phdr32);
103 			break;
104 		case ELFCLASS64:
105 			free(e->e_u.e_elf.e_ehdr.e_ehdr64);
106 			free(e->e_u.e_elf.e_phdr.e_phdr64);
107 			break;
108 		}
109 
110 		assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
111 
112 		if (e->e_flags & LIBELF_F_AR_HEADER) {
113 			arh = e->e_hdr.e_arhdr;
114 			free(arh->ar_name);
115 			free(arh->ar_rawname);
116 			free(arh);
117 		}
118 
119 		break;
120 
121 	default:
122 		break;
123 	}
124 
125 	free(e);
126 }
127 
128 struct _Libelf_Data *
_libelf_allocate_data(Elf_Scn * s)129 _libelf_allocate_data(Elf_Scn *s)
130 {
131 	struct _Libelf_Data *d;
132 
133 	if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
134 		LIBELF_SET_ERROR(RESOURCE, 0);
135 		return (NULL);
136 	}
137 
138 	d->d_scn = s;
139 
140 	return (d);
141 }
142 
143 struct _Libelf_Data *
_libelf_release_data(struct _Libelf_Data * d)144 _libelf_release_data(struct _Libelf_Data *d)
145 {
146 
147 	if (d->d_flags & LIBELF_F_DATA_MALLOCED)
148 		free(d->d_data.d_buf);
149 
150 	free(d);
151 
152 	return (NULL);
153 }
154 
155 Elf_Scn *
_libelf_allocate_scn(Elf * e,size_t ndx)156 _libelf_allocate_scn(Elf *e, size_t ndx)
157 {
158 	Elf_Scn *s;
159 
160 	if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
161 		LIBELF_SET_ERROR(RESOURCE, errno);
162 		return (NULL);
163 	}
164 
165 	s->s_elf = e;
166 	s->s_ndx = ndx;
167 
168 	STAILQ_INIT(&s->s_data);
169 	STAILQ_INIT(&s->s_rawdata);
170 
171 	STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
172 
173 	return (s);
174 }
175 
176 Elf_Scn *
_libelf_release_scn(Elf_Scn * s)177 _libelf_release_scn(Elf_Scn *s)
178 {
179 	Elf *e;
180 	struct _Libelf_Data *d, *td;
181 
182 	assert(s != NULL);
183 
184 	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
185 		STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next);
186 		d = _libelf_release_data(d);
187 	}
188 
189 	STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
190 		assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0);
191 		STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next);
192 		d = _libelf_release_data(d);
193 	}
194 
195 	e = s->s_elf;
196 
197 	assert(e != NULL);
198 
199 	STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
200 
201 	free(s);
202 
203 	return (NULL);
204 }
205