1/*- 2 * Copyright (c) 2006 Joseph Koshy 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27/* 28 * Internal APIs 29 */ 30 31#include <errno.h> 32 33#include <assert.h> 34#include "libelf.h" 35#include <stdlib.h> 36#include <string.h> 37 38#include "_libelf.h" 39 40Elf * 41_libelf_allocate_elf(void) 42{ 43 Elf *e; 44 45 if ((e = malloc(sizeof(*e))) == NULL) { 46 LIBELF_SET_ERROR(RESOURCE, errno); 47 return NULL; 48 } 49 50 e->e_activations = 1; 51 e->e_arhdr = NULL; 52 e->e_byteorder = ELFDATANONE; 53 e->e_class = ELFCLASSNONE; 54 e->e_cmd = ELF_C_NULL; 55 e->e_fd = -1; 56 e->e_flags = 0; 57 e->e_kind = ELF_K_NONE; 58 e->e_parent = NULL; 59 e->e_rawfile = NULL; 60 e->e_rawsize = 0; 61 e->e_version = LIBELF_PRIVATE(version); 62 63 (void) memset(&e->e_u, 0, sizeof(e->e_u)); 64 65 return (e); 66} 67 68void 69_libelf_init_elf(Elf *e, Elf_Kind kind) 70{ 71 assert(e != NULL); 72 assert(e->e_kind == ELF_K_NONE); 73 74 e->e_kind = kind; 75 76 switch (kind) { 77 case ELF_K_ELF: 78 STAILQ_INIT(&e->e_u.e_elf.e_scn); 79 break; 80 default: 81 break; 82 } 83} 84 85#define FREE(P) do { \ 86 if (P) \ 87 free(P); \ 88 } while (0) 89 90 91Elf * 92_libelf_release_elf(Elf *e) 93{ 94 switch (e->e_kind) { 95 case ELF_K_AR: 96 FREE(e->e_u.e_ar.e_symtab); 97 break; 98 99 case ELF_K_ELF: 100 switch (e->e_class) { 101 case ELFCLASS32: 102 FREE(e->e_u.e_elf.e_ehdr.e_ehdr32); 103 FREE(e->e_u.e_elf.e_phdr.e_phdr32); 104 break; 105 case ELFCLASS64: 106 FREE(e->e_u.e_elf.e_ehdr.e_ehdr64); 107 FREE(e->e_u.e_elf.e_phdr.e_phdr64); 108 break; 109 } 110 111 assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); 112 113 if (e->e_arhdr) { 114 FREE(e->e_arhdr->ar_name); 115 FREE(e->e_arhdr->ar_rawname); 116 free(e->e_arhdr); 117 } 118 119 break; 120 121 default: 122 break; 123 } 124 125 free(e); 126 127 return (NULL); 128} 129 130Elf_Data * 131_libelf_allocate_data(Elf_Scn *s) 132{ 133 Elf_Data *d; 134 135 if ((d = calloc((size_t) 1, sizeof(Elf_Data))) == NULL) { 136 LIBELF_SET_ERROR(RESOURCE, 0); 137 return (NULL); 138 } 139 140 d->d_scn = s; 141 142 return (d); 143} 144 145Elf_Data * 146_libelf_release_data(Elf_Data *d) 147{ 148 149 if (d->d_flags & LIBELF_F_MALLOCED) 150 free(d->d_buf); 151 152 free(d); 153 154 return (NULL); 155} 156 157Elf_Scn * 158_libelf_allocate_scn(Elf *e, size_t ndx) 159{ 160 Elf_Scn *s; 161 162 if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) { 163 LIBELF_SET_ERROR(RESOURCE, errno); 164 return (NULL); 165 } 166 167 s->s_elf = e; 168 s->s_ndx = ndx; 169 170 STAILQ_INIT(&s->s_data); 171 STAILQ_INIT(&s->s_rawdata); 172 173 STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next); 174 175 return (s); 176} 177 178Elf_Scn * 179_libelf_release_scn(Elf_Scn *s) 180{ 181 Elf *e; 182 Elf_Data *d, *td; 183 184 assert(s != NULL); 185 186 STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { 187 STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next); 188 d = _libelf_release_data(d); 189 } 190 191 STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) { 192 assert((d->d_flags & LIBELF_F_MALLOCED) == 0); 193 STAILQ_REMOVE(&s->s_rawdata, d, _Elf_Data, d_next); 194 d = _libelf_release_data(d); 195 } 196 197 e = s->s_elf; 198 199 assert(e != NULL); 200 201 STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next); 202 203 free(s); 204 205 return (NULL); 206} 207