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