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 <sys/cdefs.h> 32__FBSDID("$FreeBSD$"); 33 34#include <sys/errno.h> 35 36#include <assert.h> 37#include <libelf.h> 38#include <stdlib.h> 39#include <string.h> 40 41#include "_libelf.h" 42 43Elf * 44_libelf_allocate_elf(void) 45{ 46 Elf *e; 47 48 if ((e = malloc(sizeof(*e))) == NULL) { 49 LIBELF_SET_ERROR(RESOURCE, errno); 50 return NULL; 51 } 52 53 e->e_activations = 1; 54 e->e_arhdr = NULL; 55 e->e_byteorder = ELFDATANONE; 56 e->e_class = ELFCLASSNONE; 57 e->e_cmd = ELF_C_NULL; 58 e->e_fd = -1; 59 e->e_flags = 0; 60 e->e_kind = ELF_K_NONE; 61 e->e_parent = NULL; 62 e->e_rawfile = NULL; 63 e->e_rawsize = 0; 64 e->e_version = LIBELF_PRIVATE(version); 65 66 (void) memset(&e->e_u, 0, sizeof(e->e_u)); 67 68 return (e); 69} 70 71void 72_libelf_init_elf(Elf *e, Elf_Kind kind) 73{ 74 assert(e != NULL); 75 assert(e->e_kind == ELF_K_NONE); 76 77 e->e_kind = kind; 78 79 switch (kind) { 80 case ELF_K_ELF: 81 STAILQ_INIT(&e->e_u.e_elf.e_scn); 82 break; 83 default: 84 break; 85 } 86} 87 88#define FREE(P) do { \ 89 if (P) \ 90 free(P); \ 91 } while (0) 92 93 94Elf * 95_libelf_release_elf(Elf *e) 96{ 97 switch (e->e_kind) { 98 case ELF_K_AR: 99 FREE(e->e_u.e_ar.e_symtab); 100 break; 101 102 case ELF_K_ELF: 103 switch (e->e_class) { 104 case ELFCLASS32: 105 FREE(e->e_u.e_elf.e_ehdr.e_ehdr32); 106 FREE(e->e_u.e_elf.e_phdr.e_phdr32); 107 break; 108 case ELFCLASS64: 109 FREE(e->e_u.e_elf.e_ehdr.e_ehdr64); 110 FREE(e->e_u.e_elf.e_phdr.e_phdr64); 111 break; 112 } 113 114 assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); 115 116 if (e->e_arhdr) { 117 FREE(e->e_arhdr->ar_name); 118 FREE(e->e_arhdr->ar_rawname); 119 free(e->e_arhdr); 120 } 121 122 break; 123 124 default: 125 break; 126 } 127 128 free(e); 129 130 return (NULL); 131} 132 133Elf_Data * 134_libelf_allocate_data(Elf_Scn *s) 135{ 136 Elf_Data *d; 137 138 if ((d = calloc((size_t) 1, sizeof(Elf_Data))) == NULL) { 139 LIBELF_SET_ERROR(RESOURCE, 0); 140 return (NULL); 141 } 142 143 d->d_scn = s; 144 145 return (d); 146} 147 148Elf_Data * 149_libelf_release_data(Elf_Data *d) 150{ 151 152 if (d->d_flags & LIBELF_F_MALLOCED) 153 free(d->d_buf); 154 155 free(d); 156 157 return (NULL); 158} 159 160Elf_Scn * 161_libelf_allocate_scn(Elf *e, size_t ndx) 162{ 163 Elf_Scn *s; 164 165 if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) { 166 LIBELF_SET_ERROR(RESOURCE, errno); 167 return (NULL); 168 } 169 170 s->s_elf = e; 171 s->s_ndx = ndx; 172 173 STAILQ_INIT(&s->s_data); 174 STAILQ_INIT(&s->s_rawdata); 175 176 STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next); 177 178 return (s); 179} 180 181Elf_Scn * 182_libelf_release_scn(Elf_Scn *s) 183{ 184 Elf *e; 185 Elf_Data *d, *td; 186 187 assert(s != NULL); 188 189 STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { 190 STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next); 191 d = _libelf_release_data(d); 192 } 193 194 STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) { 195 assert((d->d_flags & LIBELF_F_MALLOCED) == 0); 196 STAILQ_REMOVE(&s->s_rawdata, d, _Elf_Data, d_next); 197 d = _libelf_release_data(d); 198 } 199 200 e = s->s_elf; 201 202 assert(e != NULL); 203 204 STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next); 205 206 free(s); 207 208 return (NULL); 209} 210