libelf_allocate.c revision 259065
1179055Sjfv/*-
2171384Sjfv * Copyright (c) 2006 Joseph Koshy
3221041Sjfv * All rights reserved.
4179055Sjfv *
5179055Sjfv * Redistribution and use in source and binary forms, with or without
6179055Sjfv * modification, are permitted provided that the following conditions
7179055Sjfv * are met:
8179055Sjfv * 1. Redistributions of source code must retain the above copyright
9179055Sjfv *    notice, this list of conditions and the following disclaimer.
10179055Sjfv * 2. Redistributions in binary form must reproduce the above copyright
11179055Sjfv *    notice, this list of conditions and the following disclaimer in the
12179055Sjfv *    documentation and/or other materials provided with the distribution.
13179055Sjfv *
14179055Sjfv * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15179055Sjfv * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16179055Sjfv * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17179055Sjfv * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18179055Sjfv * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19179055Sjfv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20179055Sjfv * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21179055Sjfv * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22179055Sjfv * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23179055Sjfv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24179055Sjfv * SUCH DAMAGE.
25179055Sjfv */
26179055Sjfv
27179055Sjfv/*
28179055Sjfv * Internal APIs
29179055Sjfv */
30179055Sjfv
31171384Sjfv#include <sys/cdefs.h>
32179055Sjfv__FBSDID("$FreeBSD: releng/10.0/lib/libelf/libelf_allocate.c 166863 2007-02-21 08:14:22Z dumbbell $");
33179055Sjfv
34171384Sjfv#include <sys/errno.h>
35185352Sjfv
36171384Sjfv#include <assert.h>
37171384Sjfv#include <libelf.h>
38171384Sjfv#include <stdlib.h>
39171384Sjfv#include <string.h>
40171384Sjfv
41171384Sjfv#include "_libelf.h"
42194875Sjfv
43194875SjfvElf *
44194875Sjfv_libelf_allocate_elf(void)
45171384Sjfv{
46171384Sjfv	Elf *e;
47171384Sjfv
48171384Sjfv	if ((e = malloc(sizeof(*e))) == NULL) {
49171384Sjfv		LIBELF_SET_ERROR(RESOURCE, errno);
50171384Sjfv		return NULL;
51171384Sjfv	}
52171384Sjfv
53171384Sjfv	e->e_activations = 1;
54171384Sjfv	e->e_arhdr	 = NULL;
55171384Sjfv	e->e_byteorder   = ELFDATANONE;
56171384Sjfv	e->e_class       = ELFCLASSNONE;
57171384Sjfv	e->e_cmd         = ELF_C_NULL;
58171384Sjfv	e->e_fd          = -1;
59171384Sjfv	e->e_flags	 = 0;
60171384Sjfv	e->e_kind        = ELF_K_NONE;
61171384Sjfv	e->e_parent      = NULL;
62171384Sjfv	e->e_rawfile     = NULL;
63171384Sjfv	e->e_rawsize     = 0;
64171384Sjfv	e->e_version     = LIBELF_PRIVATE(version);
65171384Sjfv
66171384Sjfv	(void) memset(&e->e_u, 0, sizeof(e->e_u));
67171384Sjfv
68171384Sjfv	return (e);
69171384Sjfv}
70190873Sjfv
71171384Sjfvvoid
72171384Sjfv_libelf_init_elf(Elf *e, Elf_Kind kind)
73171384Sjfv{
74171384Sjfv	assert(e != NULL);
75171384Sjfv	assert(e->e_kind == ELF_K_NONE);
76171384Sjfv
77171384Sjfv	e->e_kind = kind;
78171384Sjfv
79171384Sjfv	switch (kind) {
80171384Sjfv	case ELF_K_ELF:
81171384Sjfv		STAILQ_INIT(&e->e_u.e_elf.e_scn);
82171384Sjfv		break;
83171384Sjfv	default:
84171384Sjfv		break;
85171384Sjfv	}
86171384Sjfv}
87171384Sjfv
88179055Sjfv#define	FREE(P)		do {				\
89194875Sjfv		if (P)					\
90194875Sjfv			free(P);			\
91171384Sjfv	} while (0)
92194875Sjfv
93194875Sjfv
94190873SjfvElf *
95190873Sjfv_libelf_release_elf(Elf *e)
96171384Sjfv{
97171384Sjfv	switch (e->e_kind) {
98171384Sjfv	case ELF_K_AR:
99171384Sjfv		FREE(e->e_u.e_ar.e_symtab);
100171384Sjfv		break;
101172043Sjfv
102171384Sjfv	case ELF_K_ELF:
103171384Sjfv		switch (e->e_class) {
104172043Sjfv		case ELFCLASS32:
105172043Sjfv			FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
106171384Sjfv			FREE(e->e_u.e_elf.e_phdr.e_phdr32);
107190873Sjfv			break;
108172043Sjfv		case ELFCLASS64:
109171384Sjfv			FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
110171384Sjfv			FREE(e->e_u.e_elf.e_phdr.e_phdr64);
111171384Sjfv			break;
112171384Sjfv		}
113172043Sjfv
114172043Sjfv		assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
115171384Sjfv
116172043Sjfv		if (e->e_arhdr) {
117171384Sjfv			FREE(e->e_arhdr->ar_name);
118172043Sjfv			FREE(e->e_arhdr->ar_rawname);
119172043Sjfv			free(e->e_arhdr);
120172043Sjfv		}
121171384Sjfv
122190873Sjfv		break;
123172043Sjfv
124171384Sjfv	default:
125171384Sjfv		break;
126171384Sjfv	}
127172043Sjfv
128172043Sjfv	free(e);
129172043Sjfv
130171384Sjfv	return (NULL);
131171384Sjfv}
132171384Sjfv
133171384SjfvElf_Data *
134185352Sjfv_libelf_allocate_data(Elf_Scn *s)
135171384Sjfv{
136171384Sjfv	Elf_Data *d;
137200239Sjfv
138200239Sjfv	if ((d = calloc((size_t) 1, sizeof(Elf_Data))) == NULL) {
139200239Sjfv		LIBELF_SET_ERROR(RESOURCE, 0);
140171384Sjfv		return (NULL);
141200239Sjfv	}
142171384Sjfv
143171384Sjfv	d->d_scn = s;
144171384Sjfv
145171384Sjfv	return (d);
146171384Sjfv}
147171384Sjfv
148171384SjfvElf_Data *
149171384Sjfv_libelf_release_data(Elf_Data *d)
150171384Sjfv{
151171384Sjfv
152172043Sjfv	if (d->d_flags & LIBELF_F_MALLOCED)
153200239Sjfv		free(d->d_buf);
154172043Sjfv
155172043Sjfv	free(d);
156171384Sjfv
157171384Sjfv	return (NULL);
158171384Sjfv}
159171384Sjfv
160171384SjfvElf_Scn *
161171384Sjfv_libelf_allocate_scn(Elf *e, size_t ndx)
162171384Sjfv{
163171384Sjfv	Elf_Scn *s;
164171384Sjfv
165171384Sjfv	if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
166171384Sjfv		LIBELF_SET_ERROR(RESOURCE, errno);
167171384Sjfv		return (NULL);
168171384Sjfv	}
169171384Sjfv
170171384Sjfv	s->s_elf = e;
171171384Sjfv	s->s_ndx = ndx;
172171384Sjfv
173190873Sjfv	STAILQ_INIT(&s->s_data);
174190873Sjfv	STAILQ_INIT(&s->s_rawdata);
175185352Sjfv
176185352Sjfv	STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
177171384Sjfv
178171384Sjfv	return (s);
179205720Sjfv}
180194875Sjfv
181194875SjfvElf_Scn *
182215911Sjfv_libelf_release_scn(Elf_Scn *s)
183215911Sjfv{
184215911Sjfv	Elf *e;
185171384Sjfv	Elf_Data *d, *td;
186205904Sjfv
187205904Sjfv	assert(s != NULL);
188205904Sjfv
189205904Sjfv	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
190205904Sjfv		STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next);
191205904Sjfv		d = _libelf_release_data(d);
192205904Sjfv	}
193172043Sjfv
194190873Sjfv	STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
195190873Sjfv		assert((d->d_flags & LIBELF_F_MALLOCED) == 0);
196190873Sjfv		STAILQ_REMOVE(&s->s_rawdata, d, _Elf_Data, d_next);
197190873Sjfv		d = _libelf_release_data(d);
198172043Sjfv	}
199172043Sjfv
200172043Sjfv	e = s->s_elf;
201172043Sjfv
202172043Sjfv	assert(e != NULL);
203171384Sjfv
204171384Sjfv	STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
205171384Sjfv
206185352Sjfv	free(s);
207185352Sjfv
208185352Sjfv	return (NULL);
209185352Sjfv}
210171384Sjfv