libelf_allocate.c revision 256281
1227569Sphilip/*-
2227569Sphilip * Copyright (c) 2006 Joseph Koshy
3227569Sphilip * All rights reserved.
4227569Sphilip *
5227569Sphilip * Redistribution and use in source and binary forms, with or without
6227569Sphilip * modification, are permitted provided that the following conditions
7227569Sphilip * are met:
8227569Sphilip * 1. Redistributions of source code must retain the above copyright
9227569Sphilip *    notice, this list of conditions and the following disclaimer.
10227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright
11227569Sphilip *    notice, this list of conditions and the following disclaimer in the
12227569Sphilip *    documentation and/or other materials provided with the distribution.
13227569Sphilip *
14227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17227569Sphilip * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24227569Sphilip * SUCH DAMAGE.
25228078Sphilip */
26228078Sphilip
27228078Sphilip/*
28228078Sphilip * Internal APIs
29227569Sphilip */
30227569Sphilip
31227569Sphilip#include <sys/cdefs.h>
32227569Sphilip__FBSDID("$FreeBSD: stable/10/lib/libelf/libelf_allocate.c 166863 2007-02-21 08:14:22Z dumbbell $");
33227569Sphilip
34227569Sphilip#include <sys/errno.h>
35227569Sphilip
36227569Sphilip#include <assert.h>
37227569Sphilip#include <libelf.h>
38227569Sphilip#include <stdlib.h>
39227569Sphilip#include <string.h>
40227569Sphilip
41227569Sphilip#include "_libelf.h"
42227569Sphilip
43227569SphilipElf *
44227569Sphilip_libelf_allocate_elf(void)
45227569Sphilip{
46227569Sphilip	Elf *e;
47227569Sphilip
48227569Sphilip	if ((e = malloc(sizeof(*e))) == NULL) {
49227569Sphilip		LIBELF_SET_ERROR(RESOURCE, errno);
50227569Sphilip		return NULL;
51227569Sphilip	}
52227569Sphilip
53227569Sphilip	e->e_activations = 1;
54227569Sphilip	e->e_arhdr	 = NULL;
55227569Sphilip	e->e_byteorder   = ELFDATANONE;
56227569Sphilip	e->e_class       = ELFCLASSNONE;
57227569Sphilip	e->e_cmd         = ELF_C_NULL;
58227569Sphilip	e->e_fd          = -1;
59227569Sphilip	e->e_flags	 = 0;
60227569Sphilip	e->e_kind        = ELF_K_NONE;
61227569Sphilip	e->e_parent      = NULL;
62227569Sphilip	e->e_rawfile     = NULL;
63227569Sphilip	e->e_rawsize     = 0;
64227569Sphilip	e->e_version     = LIBELF_PRIVATE(version);
65227569Sphilip
66227569Sphilip	(void) memset(&e->e_u, 0, sizeof(e->e_u));
67227569Sphilip
68227569Sphilip	return (e);
69227569Sphilip}
70227569Sphilip
71227569Sphilipvoid
72227569Sphilip_libelf_init_elf(Elf *e, Elf_Kind kind)
73227569Sphilip{
74227569Sphilip	assert(e != NULL);
75227569Sphilip	assert(e->e_kind == ELF_K_NONE);
76227569Sphilip
77227569Sphilip	e->e_kind = kind;
78227569Sphilip
79227569Sphilip	switch (kind) {
80227569Sphilip	case ELF_K_ELF:
81227569Sphilip		STAILQ_INIT(&e->e_u.e_elf.e_scn);
82227569Sphilip		break;
83227569Sphilip	default:
84227569Sphilip		break;
85227569Sphilip	}
86227569Sphilip}
87227569Sphilip
88227569Sphilip#define	FREE(P)		do {				\
89227569Sphilip		if (P)					\
90227569Sphilip			free(P);			\
91227569Sphilip	} while (0)
92227569Sphilip
93227569Sphilip
94227569SphilipElf *
95227569Sphilip_libelf_release_elf(Elf *e)
96227569Sphilip{
97227569Sphilip	switch (e->e_kind) {
98227569Sphilip	case ELF_K_AR:
99227569Sphilip		FREE(e->e_u.e_ar.e_symtab);
100227569Sphilip		break;
101227569Sphilip
102227569Sphilip	case ELF_K_ELF:
103227569Sphilip		switch (e->e_class) {
104227569Sphilip		case ELFCLASS32:
105227569Sphilip			FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
106227569Sphilip			FREE(e->e_u.e_elf.e_phdr.e_phdr32);
107227569Sphilip			break;
108227569Sphilip		case ELFCLASS64:
109227569Sphilip			FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
110227569Sphilip			FREE(e->e_u.e_elf.e_phdr.e_phdr64);
111227569Sphilip			break;
112227569Sphilip		}
113227569Sphilip
114227569Sphilip		assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
115227569Sphilip
116227569Sphilip		if (e->e_arhdr) {
117227569Sphilip			FREE(e->e_arhdr->ar_name);
118227569Sphilip			FREE(e->e_arhdr->ar_rawname);
119227569Sphilip			free(e->e_arhdr);
120227569Sphilip		}
121227569Sphilip
122227569Sphilip		break;
123227569Sphilip
124227569Sphilip	default:
125227569Sphilip		break;
126227569Sphilip	}
127227569Sphilip
128227569Sphilip	free(e);
129227569Sphilip
130227569Sphilip	return (NULL);
131227569Sphilip}
132227569Sphilip
133227569SphilipElf_Data *
134227569Sphilip_libelf_allocate_data(Elf_Scn *s)
135227569Sphilip{
136227569Sphilip	Elf_Data *d;
137227569Sphilip
138227569Sphilip	if ((d = calloc((size_t) 1, sizeof(Elf_Data))) == NULL) {
139227569Sphilip		LIBELF_SET_ERROR(RESOURCE, 0);
140227569Sphilip		return (NULL);
141227569Sphilip	}
142227569Sphilip
143227569Sphilip	d->d_scn = s;
144227569Sphilip
145227569Sphilip	return (d);
146227569Sphilip}
147227569Sphilip
148227569SphilipElf_Data *
149227569Sphilip_libelf_release_data(Elf_Data *d)
150227569Sphilip{
151227569Sphilip
152227569Sphilip	if (d->d_flags & LIBELF_F_MALLOCED)
153227569Sphilip		free(d->d_buf);
154227569Sphilip
155227569Sphilip	free(d);
156227569Sphilip
157227569Sphilip	return (NULL);
158227569Sphilip}
159227569Sphilip
160227569SphilipElf_Scn *
161227569Sphilip_libelf_allocate_scn(Elf *e, size_t ndx)
162227569Sphilip{
163227569Sphilip	Elf_Scn *s;
164227569Sphilip
165227569Sphilip	if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
166227569Sphilip		LIBELF_SET_ERROR(RESOURCE, errno);
167227569Sphilip		return (NULL);
168227569Sphilip	}
169227569Sphilip
170227569Sphilip	s->s_elf = e;
171227569Sphilip	s->s_ndx = ndx;
172227569Sphilip
173227569Sphilip	STAILQ_INIT(&s->s_data);
174227569Sphilip	STAILQ_INIT(&s->s_rawdata);
175227569Sphilip
176227569Sphilip	STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
177227569Sphilip
178227569Sphilip	return (s);
179227569Sphilip}
180227569Sphilip
181227569SphilipElf_Scn *
182227569Sphilip_libelf_release_scn(Elf_Scn *s)
183227569Sphilip{
184227569Sphilip	Elf *e;
185227569Sphilip	Elf_Data *d, *td;
186227569Sphilip
187227569Sphilip	assert(s != NULL);
188227569Sphilip
189227569Sphilip	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
190227569Sphilip		STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next);
191227569Sphilip		d = _libelf_release_data(d);
192227569Sphilip	}
193227569Sphilip
194227569Sphilip	STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
195227569Sphilip		assert((d->d_flags & LIBELF_F_MALLOCED) == 0);
196227569Sphilip		STAILQ_REMOVE(&s->s_rawdata, d, _Elf_Data, d_next);
197227569Sphilip		d = _libelf_release_data(d);
198227569Sphilip	}
199227569Sphilip
200227569Sphilip	e = s->s_elf;
201227569Sphilip
202227569Sphilip	assert(e != NULL);
203227569Sphilip
204227569Sphilip	STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
205227569Sphilip
206227569Sphilip	free(s);
207227569Sphilip
208227569Sphilip	return (NULL);
209227569Sphilip}
210227569Sphilip