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