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,v 1.2 2019/03/19 02:31:35 jsg Exp $"); 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, raw_size; 46 _libelf_translator_function *xlate; 47 48 d = (struct _Libelf_Data *) ed; 49 50 if (s == NULL || (e = s->s_elf) == NULL || 51 (d != NULL && s != d->d_scn)) { 52 LIBELF_SET_ERROR(ARGUMENT, 0); 53 return (NULL); 54 } 55 56 assert(e->e_kind == ELF_K_ELF); 57 58 if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL) 59 return (&d->d_data); 60 61 if (d != NULL) 62 return (STAILQ_NEXT(d, d_next) ? 63 &STAILQ_NEXT(d, d_next)->d_data : NULL); 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 raw_size = (uint64_t) e->e_rawsize; 96 if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST || 97 elftype > ELF_T_LAST || (sh_type != SHT_NOBITS && 98 (sh_offset > raw_size || sh_size > raw_size - sh_offset))) { 99 LIBELF_SET_ERROR(SECTION, 0); 100 return (NULL); 101 } 102 103 if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize) 104 (elftype, (size_t) 1, e->e_version)) == 0) { 105 LIBELF_SET_ERROR(UNIMPL, 0); 106 return (NULL); 107 } 108 109 if (sh_size % fsz) { 110 LIBELF_SET_ERROR(SECTION, 0); 111 return (NULL); 112 } 113 114 if (sh_size / fsz > SIZE_MAX) { 115 LIBELF_SET_ERROR(RANGE, 0); 116 return (NULL); 117 } 118 119 count = (size_t) (sh_size / fsz); 120 121 msz = _libelf_msize(elftype, elfclass, e->e_version); 122 123 if (count > 0 && msz > SIZE_MAX / count) { 124 LIBELF_SET_ERROR(RANGE, 0); 125 return (NULL); 126 } 127 128 assert(msz > 0); 129 assert(count <= SIZE_MAX); 130 assert(msz * count <= SIZE_MAX); 131 132 if ((d = _libelf_allocate_data(s)) == NULL) 133 return (NULL); 134 135 d->d_data.d_buf = NULL; 136 d->d_data.d_off = 0; 137 d->d_data.d_align = sh_align; 138 d->d_data.d_size = msz * count; 139 d->d_data.d_type = elftype; 140 d->d_data.d_version = e->e_version; 141 142 if (sh_type == SHT_NOBITS || sh_size == 0) { 143 STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 144 return (&d->d_data); 145 } 146 147 if ((d->d_data.d_buf = malloc(msz * count)) == NULL) { 148 (void) _libelf_release_data(d); 149 LIBELF_SET_ERROR(RESOURCE, 0); 150 return (NULL); 151 } 152 153 d->d_flags |= LIBELF_F_DATA_MALLOCED; 154 155 xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass, 156 _libelf_elfmachine(e)); 157 if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size, 158 e->e_rawfile + sh_offset, count, 159 e->e_byteorder != LIBELF_PRIVATE(byteorder))) { 160 _libelf_release_data(d); 161 LIBELF_SET_ERROR(DATA, 0); 162 return (NULL); 163 } 164 165 STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 166 167 return (&d->d_data); 168 } 169 170 Elf_Data * 171 elf_newdata(Elf_Scn *s) 172 { 173 Elf *e; 174 struct _Libelf_Data *d; 175 176 if (s == NULL || (e = s->s_elf) == NULL) { 177 LIBELF_SET_ERROR(ARGUMENT, 0); 178 return (NULL); 179 } 180 181 assert(e->e_kind == ELF_K_ELF); 182 183 /* 184 * elf_newdata() has to append a data descriptor, so 185 * bring in existing section data if not already present. 186 */ 187 if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) 188 if (elf_getdata(s, NULL) == NULL) 189 return (NULL); 190 191 if ((d = _libelf_allocate_data(s)) == NULL) 192 return (NULL); 193 194 STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 195 196 d->d_data.d_align = 1; 197 d->d_data.d_buf = NULL; 198 d->d_data.d_off = (uint64_t) ~0; 199 d->d_data.d_size = 0; 200 d->d_data.d_type = ELF_T_BYTE; 201 d->d_data.d_version = LIBELF_PRIVATE(version); 202 203 (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); 204 205 return (&d->d_data); 206 } 207 208 /* 209 * Retrieve a data descriptor for raw (untranslated) data for section 210 * `s'. 211 */ 212 213 Elf_Data * 214 elf_rawdata(Elf_Scn *s, Elf_Data *ed) 215 { 216 Elf *e; 217 int elf_class; 218 uint32_t sh_type; 219 struct _Libelf_Data *d; 220 uint64_t sh_align, sh_offset, sh_size, raw_size; 221 222 if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) { 223 LIBELF_SET_ERROR(ARGUMENT, 0); 224 return (NULL); 225 } 226 227 assert(e->e_kind == ELF_K_ELF); 228 229 d = (struct _Libelf_Data *) ed; 230 231 if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL) 232 return (&d->d_data); 233 234 if (d != NULL) 235 return (&STAILQ_NEXT(d, d_next)->d_data); 236 237 elf_class = e->e_class; 238 239 assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64); 240 241 if (elf_class == ELFCLASS32) { 242 sh_type = s->s_shdr.s_shdr32.sh_type; 243 sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; 244 sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; 245 sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; 246 } else { 247 sh_type = s->s_shdr.s_shdr64.sh_type; 248 sh_offset = s->s_shdr.s_shdr64.sh_offset; 249 sh_size = s->s_shdr.s_shdr64.sh_size; 250 sh_align = s->s_shdr.s_shdr64.sh_addralign; 251 } 252 253 if (sh_type == SHT_NULL) { 254 LIBELF_SET_ERROR(SECTION, 0); 255 return (NULL); 256 } 257 258 raw_size = (uint64_t) e->e_rawsize; 259 if (sh_type != SHT_NOBITS && 260 (sh_offset > raw_size || sh_size > raw_size - sh_offset)) { 261 LIBELF_SET_ERROR(SECTION, 0); 262 return (NULL); 263 } 264 265 if ((d = _libelf_allocate_data(s)) == NULL) 266 return (NULL); 267 268 d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL : 269 e->e_rawfile + sh_offset; 270 d->d_data.d_off = 0; 271 d->d_data.d_align = sh_align; 272 d->d_data.d_size = sh_size; 273 d->d_data.d_type = ELF_T_BYTE; 274 d->d_data.d_version = e->e_version; 275 276 STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next); 277 278 return (&d->d_data); 279 } 280