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