1164190Sjkoshy/*-
2164190Sjkoshy * Copyright (c) 2006 Joseph Koshy
3164190Sjkoshy * All rights reserved.
4164190Sjkoshy *
5164190Sjkoshy * Redistribution and use in source and binary forms, with or without
6164190Sjkoshy * modification, are permitted provided that the following conditions
7164190Sjkoshy * are met:
8164190Sjkoshy * 1. Redistributions of source code must retain the above copyright
9164190Sjkoshy *    notice, this list of conditions and the following disclaimer.
10164190Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright
11164190Sjkoshy *    notice, this list of conditions and the following disclaimer in the
12164190Sjkoshy *    documentation and/or other materials provided with the distribution.
13164190Sjkoshy *
14164190Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15164190Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16164190Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17164190Sjkoshy * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18164190Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19164190Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20164190Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21164190Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22164190Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23164190Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24164190Sjkoshy * SUCH DAMAGE.
25164190Sjkoshy */
26164190Sjkoshy
27164190Sjkoshy/*
28164190Sjkoshy * Internal APIs
29164190Sjkoshy */
30164190Sjkoshy
31164190Sjkoshy#include <sys/cdefs.h>
32164190Sjkoshy__FBSDID("$FreeBSD$");
33164190Sjkoshy
34164190Sjkoshy#include <sys/errno.h>
35164190Sjkoshy
36164190Sjkoshy#include <assert.h>
37164190Sjkoshy#include <libelf.h>
38164190Sjkoshy#include <stdlib.h>
39164190Sjkoshy#include <string.h>
40164190Sjkoshy
41164190Sjkoshy#include "_libelf.h"
42164190Sjkoshy
43164190SjkoshyElf *
44164190Sjkoshy_libelf_allocate_elf(void)
45164190Sjkoshy{
46164190Sjkoshy	Elf *e;
47164190Sjkoshy
48164190Sjkoshy	if ((e = malloc(sizeof(*e))) == NULL) {
49164190Sjkoshy		LIBELF_SET_ERROR(RESOURCE, errno);
50164190Sjkoshy		return NULL;
51164190Sjkoshy	}
52164190Sjkoshy
53164190Sjkoshy	e->e_activations = 1;
54164190Sjkoshy	e->e_arhdr	 = NULL;
55164190Sjkoshy	e->e_byteorder   = ELFDATANONE;
56164190Sjkoshy	e->e_class       = ELFCLASSNONE;
57164190Sjkoshy	e->e_cmd         = ELF_C_NULL;
58164190Sjkoshy	e->e_fd          = -1;
59164190Sjkoshy	e->e_flags	 = 0;
60164190Sjkoshy	e->e_kind        = ELF_K_NONE;
61164190Sjkoshy	e->e_parent      = NULL;
62164190Sjkoshy	e->e_rawfile     = NULL;
63164190Sjkoshy	e->e_rawsize     = 0;
64164190Sjkoshy	e->e_version     = LIBELF_PRIVATE(version);
65164190Sjkoshy
66164190Sjkoshy	(void) memset(&e->e_u, 0, sizeof(e->e_u));
67164190Sjkoshy
68164190Sjkoshy	return (e);
69164190Sjkoshy}
70164190Sjkoshy
71164190Sjkoshyvoid
72164190Sjkoshy_libelf_init_elf(Elf *e, Elf_Kind kind)
73164190Sjkoshy{
74164190Sjkoshy	assert(e != NULL);
75164190Sjkoshy	assert(e->e_kind == ELF_K_NONE);
76164190Sjkoshy
77164190Sjkoshy	e->e_kind = kind;
78164190Sjkoshy
79164190Sjkoshy	switch (kind) {
80164190Sjkoshy	case ELF_K_ELF:
81164190Sjkoshy		STAILQ_INIT(&e->e_u.e_elf.e_scn);
82164190Sjkoshy		break;
83164190Sjkoshy	default:
84164190Sjkoshy		break;
85164190Sjkoshy	}
86164190Sjkoshy}
87164190Sjkoshy
88164190Sjkoshy#define	FREE(P)		do {				\
89164190Sjkoshy		if (P)					\
90164190Sjkoshy			free(P);			\
91164190Sjkoshy	} while (0)
92164190Sjkoshy
93164190Sjkoshy
94164190SjkoshyElf *
95164190Sjkoshy_libelf_release_elf(Elf *e)
96164190Sjkoshy{
97164190Sjkoshy	switch (e->e_kind) {
98164190Sjkoshy	case ELF_K_AR:
99164190Sjkoshy		FREE(e->e_u.e_ar.e_symtab);
100164190Sjkoshy		break;
101164190Sjkoshy
102164190Sjkoshy	case ELF_K_ELF:
103164190Sjkoshy		switch (e->e_class) {
104164190Sjkoshy		case ELFCLASS32:
105164190Sjkoshy			FREE(e->e_u.e_elf.e_ehdr.e_ehdr32);
106164190Sjkoshy			FREE(e->e_u.e_elf.e_phdr.e_phdr32);
107164190Sjkoshy			break;
108164190Sjkoshy		case ELFCLASS64:
109164190Sjkoshy			FREE(e->e_u.e_elf.e_ehdr.e_ehdr64);
110164190Sjkoshy			FREE(e->e_u.e_elf.e_phdr.e_phdr64);
111164190Sjkoshy			break;
112164190Sjkoshy		}
113164190Sjkoshy
114164190Sjkoshy		assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));
115164190Sjkoshy
116164190Sjkoshy		if (e->e_arhdr) {
117164190Sjkoshy			FREE(e->e_arhdr->ar_name);
118164190Sjkoshy			FREE(e->e_arhdr->ar_rawname);
119164190Sjkoshy			free(e->e_arhdr);
120164190Sjkoshy		}
121164190Sjkoshy
122164190Sjkoshy		break;
123164190Sjkoshy
124164190Sjkoshy	default:
125164190Sjkoshy		break;
126164190Sjkoshy	}
127164190Sjkoshy
128164190Sjkoshy	free(e);
129164190Sjkoshy
130164190Sjkoshy	return (NULL);
131164190Sjkoshy}
132164190Sjkoshy
133164190SjkoshyElf_Data *
134164190Sjkoshy_libelf_allocate_data(Elf_Scn *s)
135164190Sjkoshy{
136164190Sjkoshy	Elf_Data *d;
137164190Sjkoshy
138164190Sjkoshy	if ((d = calloc((size_t) 1, sizeof(Elf_Data))) == NULL) {
139164190Sjkoshy		LIBELF_SET_ERROR(RESOURCE, 0);
140164190Sjkoshy		return (NULL);
141164190Sjkoshy	}
142164190Sjkoshy
143164190Sjkoshy	d->d_scn = s;
144164190Sjkoshy
145164190Sjkoshy	return (d);
146164190Sjkoshy}
147164190Sjkoshy
148164190SjkoshyElf_Data *
149164190Sjkoshy_libelf_release_data(Elf_Data *d)
150164190Sjkoshy{
151164190Sjkoshy
152164190Sjkoshy	if (d->d_flags & LIBELF_F_MALLOCED)
153164190Sjkoshy		free(d->d_buf);
154164190Sjkoshy
155164190Sjkoshy	free(d);
156164190Sjkoshy
157164190Sjkoshy	return (NULL);
158164190Sjkoshy}
159164190Sjkoshy
160164190SjkoshyElf_Scn *
161164190Sjkoshy_libelf_allocate_scn(Elf *e, size_t ndx)
162164190Sjkoshy{
163164190Sjkoshy	Elf_Scn *s;
164164190Sjkoshy
165164190Sjkoshy	if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) {
166164190Sjkoshy		LIBELF_SET_ERROR(RESOURCE, errno);
167164190Sjkoshy		return (NULL);
168164190Sjkoshy	}
169164190Sjkoshy
170164190Sjkoshy	s->s_elf = e;
171164190Sjkoshy	s->s_ndx = ndx;
172164190Sjkoshy
173164190Sjkoshy	STAILQ_INIT(&s->s_data);
174164190Sjkoshy	STAILQ_INIT(&s->s_rawdata);
175164190Sjkoshy
176164190Sjkoshy	STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next);
177164190Sjkoshy
178164190Sjkoshy	return (s);
179164190Sjkoshy}
180164190Sjkoshy
181164190SjkoshyElf_Scn *
182164190Sjkoshy_libelf_release_scn(Elf_Scn *s)
183164190Sjkoshy{
184164190Sjkoshy	Elf *e;
185164190Sjkoshy	Elf_Data *d, *td;
186164190Sjkoshy
187164190Sjkoshy	assert(s != NULL);
188164190Sjkoshy
189164190Sjkoshy	STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
190164190Sjkoshy		STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next);
191164190Sjkoshy		d = _libelf_release_data(d);
192164190Sjkoshy	}
193164190Sjkoshy
194166863Sdumbbell	STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) {
195164190Sjkoshy		assert((d->d_flags & LIBELF_F_MALLOCED) == 0);
196164190Sjkoshy		STAILQ_REMOVE(&s->s_rawdata, d, _Elf_Data, d_next);
197164190Sjkoshy		d = _libelf_release_data(d);
198164190Sjkoshy	}
199164190Sjkoshy
200164190Sjkoshy	e = s->s_elf;
201164190Sjkoshy
202164190Sjkoshy	assert(e != NULL);
203164190Sjkoshy
204164190Sjkoshy	STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next);
205164190Sjkoshy
206164190Sjkoshy	free(s);
207164190Sjkoshy
208164190Sjkoshy	return (NULL);
209164190Sjkoshy}
210