libelf_allocate.c revision 261246
150764Smarkm/*-
250764Smarkm * Copyright (c) 2006,2008,2010 Joseph Koshy
3233294Sstas * All rights reserved.
4233294Sstas *
5233294Sstas * Redistribution and use in source and binary forms, with or without
650764Smarkm * modification, are permitted provided that the following conditions
7233294Sstas * are met:
8233294Sstas * 1. Redistributions of source code must retain the above copyright
9233294Sstas *    notice, this list of conditions and the following disclaimer.
1050764Smarkm * 2. Redistributions in binary form must reproduce the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer in the
12233294Sstas *    documentation and/or other materials provided with the distribution.
1350764Smarkm *
14233294Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1750764Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2150764Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24233294Sstas * SUCH DAMAGE.
25233294Sstas */
26233294Sstas
27233294Sstas/*
28233294Sstas * Internal APIs
29233294Sstas */
30233294Sstas
31233294Sstas#include <sys/cdefs.h>
32233294Sstas
3350764Smarkm#include <assert.h>
3450764Smarkm#include <errno.h>
3550764Smarkm#include <libelf.h>
36127807Snectar#include <stdlib.h>
3750764Smarkm#include <string.h>
3850764Smarkm
39127807Snectar#include "_libelf.h"
4050764Smarkm
4150764SmarkmELFTC_VCSID("$Id: libelf_allocate.c 2272 2011-12-03 17:07:31Z jkoshy $");
4250764Smarkm
4350764SmarkmElf *
4450764Smarkm_libelf_allocate_elf(void)
4550764Smarkm{
4650764Smarkm	Elf *e;
4750764Smarkm
4850764Smarkm	if ((e = malloc(sizeof(*e))) == NULL) {
49233294Sstas		LIBELF_SET_ERROR(RESOURCE, errno);
50233294Sstas		return NULL;
51233294Sstas	}
5250764Smarkm
5350764Smarkm	e->e_activations = 1;
5450764Smarkm	e->e_hdr.e_rawhdr = NULL;
5550764Smarkm	e->e_byteorder   = ELFDATANONE;
5650764Smarkm	e->e_class       = ELFCLASSNONE;
5750764Smarkm	e->e_cmd         = ELF_C_NULL;
5850764Smarkm	e->e_fd          = -1;
5950764Smarkm	e->e_flags	 = 0;
6050764Smarkm	e->e_kind        = ELF_K_NONE;
6150764Smarkm	e->e_parent      = NULL;
6250764Smarkm	e->e_rawfile     = NULL;
6350764Smarkm	e->e_rawsize     = 0;
6450764Smarkm	e->e_version     = LIBELF_PRIVATE(version);
65233294Sstas
6650764Smarkm	(void) memset(&e->e_u, 0, sizeof(e->e_u));
6750764Smarkm
6850764Smarkm	return (e);
6950764Smarkm}
7050764Smarkm
7150764Smarkmvoid
7250764Smarkm_libelf_init_elf(Elf *e, Elf_Kind kind)
7350764Smarkm{
7450764Smarkm	assert(e != NULL);
7550764Smarkm	assert(e->e_kind == ELF_K_NONE);
7650764Smarkm
7750764Smarkm	e->e_kind = kind;
7850764Smarkm
7950764Smarkm	switch (kind) {
8050764Smarkm	case ELF_K_ELF:
81178846Sdfr		STAILQ_INIT(&e->e_u.e_elf.e_scn);
82178846Sdfr		break;
8350764Smarkm	default:
8450764Smarkm		break;
8550764Smarkm	}
8650764Smarkm}
87178846Sdfr
88178846Sdfr#define	FREE(P)		do {				\
8950764Smarkm		if (P)					\
9050764Smarkm			free(P);			\
9150764Smarkm	} while (0)
9250764Smarkm
9350764Smarkm
9450764SmarkmElf *
9550764Smarkm_libelf_release_elf(Elf *e)
9650764Smarkm{
9750764Smarkm	Elf_Arhdr *arh;
98233294Sstas
9950764Smarkm	switch (e->e_kind) {
10050764Smarkm	case ELF_K_AR:
10150764Smarkm		FREE(e->e_u.e_ar.e_symtab);
10250764Smarkm		break;
10350764Smarkm
104178846Sdfr	case ELF_K_ELF:
105178846Sdfr		switch (e->e_class) {
106178846Sdfr		case ELFCLASS32:
107178846Sdfr			FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
10850764Smarkm			FREE(e->e_u.e_elf.e_phdr.e_phdr32);
10950764Smarkm			break;
11050764Smarkm		case ELFCLASS64:
11150764Smarkm			FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
11250764Smarkm			FREE(e->e_u.e_elf.e_phdr.e_phdr64);
113178846Sdfr			break;
114178846Sdfr		}
11550764Smarkm
11650764Smarkm		assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
11750764Smarkm
11850764Smarkm		if (e->e_flags & LIBELF_F_AR_HEADER) {
11950764Smarkm			arh = e->e_hdr.e_arhdr;
120233294Sstas			FREE(arh->ar_name);
121178846Sdfr			FREE(arh->ar_rawname);
122178846Sdfr			free(arh);
12350764Smarkm		}
12450764Smarkm
12550764Smarkm		break;
12650764Smarkm
12750764Smarkm	default:
128178846Sdfr		break;
129178846Sdfr	}
13050764Smarkm
13150764Smarkm	free(e);
13250764Smarkm
13350764Smarkm	return (NULL);
13450764Smarkm}
13550764Smarkm
13650764Smarkmstruct _Libelf_Data *
13750764Smarkm_libelf_allocate_data(Elf_Scn *s)
13850764Smarkm{
13950764Smarkm	struct _Libelf_Data *d;
14050764Smarkm
14150764Smarkm	if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) {
14250764Smarkm		LIBELF_SET_ERROR(RESOURCE, 0);
14350764Smarkm		return (NULL);
14450764Smarkm	}
145127807Snectar
14650764Smarkm	d->d_scn = s;
14750764Smarkm
14850764Smarkm	return (d);
149178846Sdfr}
15050764Smarkm
15150764Smarkmstruct _Libelf_Data *
15250764Smarkm_libelf_release_data(struct _Libelf_Data *d)
15350764Smarkm{
15450764Smarkm
15550764Smarkm	if (d->d_flags & LIBELF_F_DATA_MALLOCED)
15650764Smarkm		free(d->d_data.d_buf);
15750764Smarkm
15850764Smarkm	free(d);
15950764Smarkm
16050764Smarkm	return (NULL);
16150764Smarkm}
162178846Sdfr
16350764SmarkmElf_Scn *
164178846Sdfr_libelf_allocate_scn(Elf *e, size_t ndx)
165178846Sdfr{
166178846Sdfr	Elf_Scn *s;
167178846Sdfr
16850764Smarkm	if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
16950764Smarkm		LIBELF_SET_ERROR(RESOURCE, errno);
17050764Smarkm		return (NULL);
17150764Smarkm	}
17250764Smarkm
173233294Sstas	s->s_elf = e;
17450764Smarkm	s->s_ndx = ndx;
175
176	STAILQ_INIT(&s->s_data);
177	STAILQ_INIT(&s->s_rawdata);
178
179	STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
180
181	return (s);
182}
183
184Elf_Scn *
185_libelf_release_scn(Elf_Scn *s)
186{
187	Elf *e;
188	struct _Libelf_Data *d, *td;
189
190	assert(s != NULL);
191
192	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
193		STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next);
194		d = _libelf_release_data(d);
195	}
196
197	STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
198		assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0);
199		STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next);
200		d = _libelf_release_data(d);
201	}
202
203	e = s->s_elf;
204
205	assert(e != NULL);
206
207	STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
208
209	free(s);
210
211	return (NULL);
212}
213