1 /*- 2 * Copyright (c) 2006,2008,2011 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 #include <assert.h> 28 #include <errno.h> 29 #include <libelf.h> 30 #include <stdint.h> 31 #include <stdlib.h> 32 33 #include "_libelf.h" 34 35 ELFTC_VCSID("$Id: elf_data.c 3009 2014-03-23 01:49:59Z jkoshy $"); 36 37 Elf_Data * 38 elf_getdata(Elf_Scn *s, Elf_Data *ed) 39 { 40 Elf *e; 41 unsigned int sh_type; 42 int elfclass, elftype; 43 size_t count, fsz, msz; 44 struct _Libelf_Data *d; 45 uint64_t sh_align, sh_offset, sh_size; 46 int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s, 47 size_t _c, int _swap); 48 49 d = (struct _Libelf_Data *) ed; 50 51 if (s == NULL || (e = s->s_elf) == NULL || 52 (d != NULL && s != d->d_scn)) { 53 LIBELF_SET_ERROR(ARGUMENT, 0); 54 return (NULL); 55 } 56 57 assert(e->e_kind == ELF_K_ELF); 58 59 if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL) 60 return (&d->d_data); 61 62 if (d != NULL) 63 return (&STAILQ_NEXT(d, d_next)->d_data); 64 65 if (e->e_rawfile == NULL) { 66 /* 67 * In the ELF_C_WRITE case, there is no source that 68 * can provide data for the section. 69 */ 70 LIBELF_SET_ERROR(ARGUMENT, 0); 71 return (NULL); 72 } 73 74 elfclass = e->e_class; 75 76 assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 77 78 if (elfclass == ELFCLASS32) { 79 sh_type = s->s_shdr.s_shdr32.sh_type; 80 sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; 81 sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; 82 sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; 83 } else { 84 sh_type = s->s_shdr.s_shdr64.sh_type; 85 sh_offset = s->s_shdr.s_shdr64.sh_offset; 86 sh_size = s->s_shdr.s_shdr64.sh_size; 87 sh_align = s->s_shdr.s_shdr64.sh_addralign; 88 } 89 90 if (sh_type == SHT_NULL) { 91 LIBELF_SET_ERROR(SECTION, 0); 92 return (NULL); 93 } 94 95 if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST || 96 elftype > ELF_T_LAST || (sh_type != SHT_NOBITS && 97 sh_offset + sh_size > (uint64_t) e->e_rawsize)) { 98 LIBELF_SET_ERROR(SECTION, 0); 99 return (NULL); 100 } 101 102 if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize) 103 (elftype, (size_t) 1, e->e_version)) == 0) { 104 LIBELF_SET_ERROR(UNIMPL, 0); 105 return (NULL); 106 } 107 108 if (sh_size % fsz) { 109 LIBELF_SET_ERROR(SECTION, 0); 110 return (NULL); 111 } 112 113 if (sh_size / fsz > SIZE_MAX) { 114 LIBELF_SET_ERROR(RANGE, 0); 115 return (NULL); 116 } 117 118 count = (size_t) (sh_size / fsz); 119 120 msz = _libelf_msize(elftype, elfclass, e->e_version); 121 122 if (count > 0 && msz > SIZE_MAX / count) { 123 LIBELF_SET_ERROR(RANGE, 0); 124 return (NULL); 125 } 126 127 assert(msz > 0); 128 assert(count <= SIZE_MAX); 129 assert(msz * count <= SIZE_MAX); 130 131 if ((d = _libelf_allocate_data(s)) == NULL) 132 return (NULL); 133 134 d->d_data.d_buf = NULL; 135 d->d_data.d_off = 0; 136 d->d_data.d_align = sh_align; 137 d->d_data.d_size = msz * count; 138 d->d_data.d_type = elftype; 139 d->d_data.d_version = e->e_version; 140 141 if (sh_type == SHT_NOBITS || sh_size == 0) { 142 STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 143 return (&d->d_data); 144 } 145 146 if ((d->d_data.d_buf = malloc(msz * count)) == NULL) { 147 (void) _libelf_release_data(d); 148 LIBELF_SET_ERROR(RESOURCE, 0); 149 return (NULL); 150 } 151 152 d->d_flags |= LIBELF_F_DATA_MALLOCED; 153 154 xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass); 155 if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size, 156 e->e_rawfile + sh_offset, count, 157 e->e_byteorder != LIBELF_PRIVATE(byteorder))) { 158 _libelf_release_data(d); 159 LIBELF_SET_ERROR(DATA, 0); 160 return (NULL); 161 } 162 163 STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 164 165 return (&d->d_data); 166 } 167 168 Elf_Data * 169 elf_newdata(Elf_Scn *s) 170 { 171 Elf *e; 172 struct _Libelf_Data *d; 173 174 if (s == NULL || (e = s->s_elf) == NULL) { 175 LIBELF_SET_ERROR(ARGUMENT, 0); 176 return (NULL); 177 } 178 179 assert(e->e_kind == ELF_K_ELF); 180 181 /* 182 * elf_newdata() has to append a data descriptor, so 183 * bring in existing section data if not already present. 184 */ 185 if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) 186 if (elf_getdata(s, NULL) == NULL) 187 return (NULL); 188 189 if ((d = _libelf_allocate_data(s)) == NULL) 190 return (NULL); 191 192 STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 193 194 d->d_data.d_align = 1; 195 d->d_data.d_buf = NULL; 196 d->d_data.d_off = (uint64_t) ~0; 197 d->d_data.d_size = 0; 198 d->d_data.d_type = ELF_T_BYTE; 199 d->d_data.d_version = LIBELF_PRIVATE(version); 200 201 (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); 202 203 return (&d->d_data); 204 } 205 206 /* 207 * Retrieve a data descriptor for raw (untranslated) data for section 208 * `s'. 209 */ 210 211 Elf_Data * 212 elf_rawdata(Elf_Scn *s, Elf_Data *ed) 213 { 214 Elf *e; 215 int elf_class; 216 uint32_t sh_type; 217 struct _Libelf_Data *d; 218 uint64_t sh_align, sh_offset, sh_size; 219 220 if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) { 221 LIBELF_SET_ERROR(ARGUMENT, 0); 222 return (NULL); 223 } 224 225 assert(e->e_kind == ELF_K_ELF); 226 227 d = (struct _Libelf_Data *) ed; 228 229 if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL) 230 return (&d->d_data); 231 232 if (d != NULL) 233 return (&STAILQ_NEXT(d, d_next)->d_data); 234 235 elf_class = e->e_class; 236 237 assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64); 238 239 if (elf_class == ELFCLASS32) { 240 sh_type = s->s_shdr.s_shdr32.sh_type; 241 sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; 242 sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; 243 sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; 244 } else { 245 sh_type = s->s_shdr.s_shdr64.sh_type; 246 sh_offset = s->s_shdr.s_shdr64.sh_offset; 247 sh_size = s->s_shdr.s_shdr64.sh_size; 248 sh_align = s->s_shdr.s_shdr64.sh_addralign; 249 } 250 251 if (sh_type == SHT_NULL) { 252 LIBELF_SET_ERROR(SECTION, 0); 253 return (NULL); 254 } 255 256 if ((d = _libelf_allocate_data(s)) == NULL) 257 return (NULL); 258 259 d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL : 260 e->e_rawfile + sh_offset; 261 d->d_data.d_off = 0; 262 d->d_data.d_align = sh_align; 263 d->d_data.d_size = sh_size; 264 d->d_data.d_type = ELF_T_BYTE; 265 d->d_data.d_version = e->e_version; 266 267 STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next); 268 269 return (&d->d_data); 270 } 271