Path: blob/main/contrib/elftoolchain/libelf/elf_data.c
39478 views
/*-1* Copyright (c) 2006,2008,2011 Joseph Koshy2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <assert.h>27#include <errno.h>28#include <libelf.h>29#include <stdint.h>30#include <stdlib.h>3132#include "_libelf.h"3334ELFTC_VCSID("$Id: elf_data.c 3732 2019-04-22 11:08:38Z jkoshy $");3536Elf_Data *37elf_getdata(Elf_Scn *s, Elf_Data *ed)38{39Elf *e;40unsigned int sh_type;41int elfclass, elftype;42size_t count, fsz, msz;43struct _Libelf_Data *d;44uint64_t sh_align, sh_offset, sh_size, raw_size;45_libelf_translator_function *xlate;4647d = (struct _Libelf_Data *) ed;4849if (s == NULL || (e = s->s_elf) == NULL ||50(d != NULL && s != d->d_scn)) {51LIBELF_SET_ERROR(ARGUMENT, 0);52return (NULL);53}5455assert(e->e_kind == ELF_K_ELF);5657if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)58return (&d->d_data);5960if (d != NULL)61return (STAILQ_NEXT(d, d_next) ?62&STAILQ_NEXT(d, d_next)->d_data : NULL);6364if (e->e_rawfile == NULL) {65/*66* In the ELF_C_WRITE case, there is no source that67* can provide data for the section.68*/69LIBELF_SET_ERROR(ARGUMENT, 0);70return (NULL);71}7273elfclass = e->e_class;7475assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);7677if (elfclass == ELFCLASS32) {78sh_type = s->s_shdr.s_shdr32.sh_type;79sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;80sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;81sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;82} else {83sh_type = s->s_shdr.s_shdr64.sh_type;84sh_offset = s->s_shdr.s_shdr64.sh_offset;85sh_size = s->s_shdr.s_shdr64.sh_size;86sh_align = s->s_shdr.s_shdr64.sh_addralign;87}8889if (sh_type == SHT_NULL) {90LIBELF_SET_ERROR(SECTION, 0);91return (NULL);92}9394raw_size = (uint64_t) e->e_rawsize;95if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||96elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&97(sh_offset > raw_size || sh_size > raw_size - sh_offset))) {98LIBELF_SET_ERROR(SECTION, 0);99return (NULL);100}101102if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)103(elftype, (size_t) 1, e->e_version)) == 0) {104LIBELF_SET_ERROR(UNIMPL, 0);105return (NULL);106}107108if (sh_size % fsz) {109LIBELF_SET_ERROR(SECTION, 0);110return (NULL);111}112113if (sh_size / fsz > SIZE_MAX) {114LIBELF_SET_ERROR(RANGE, 0);115return (NULL);116}117118count = (size_t) (sh_size / fsz);119120if ((msz = _libelf_msize(elftype, elfclass, e->e_version)) == 0)121return (NULL);122123if (count > 0 && msz > SIZE_MAX / count) {124LIBELF_SET_ERROR(RANGE, 0);125return (NULL);126}127128assert(msz > 0);129assert(count <= SIZE_MAX);130assert(msz * count <= SIZE_MAX);131132if ((d = _libelf_allocate_data(s)) == NULL)133return (NULL);134135d->d_data.d_buf = NULL;136d->d_data.d_off = 0;137d->d_data.d_align = sh_align;138d->d_data.d_size = msz * count;139d->d_data.d_type = elftype;140d->d_data.d_version = e->e_version;141142if (sh_type == SHT_NOBITS || sh_size == 0) {143STAILQ_INSERT_TAIL(&s->s_data, d, d_next);144return (&d->d_data);145}146147if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {148(void) _libelf_release_data(d);149LIBELF_SET_ERROR(RESOURCE, 0);150return (NULL);151}152153d->d_flags |= LIBELF_F_DATA_MALLOCED;154155xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass,156_libelf_elfmachine(e));157if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,158e->e_rawfile + sh_offset, count,159e->e_byteorder != LIBELF_PRIVATE(byteorder))) {160_libelf_release_data(d);161LIBELF_SET_ERROR(DATA, 0);162return (NULL);163}164165STAILQ_INSERT_TAIL(&s->s_data, d, d_next);166167return (&d->d_data);168}169170Elf_Data *171elf_newdata(Elf_Scn *s)172{173Elf *e;174struct _Libelf_Data *d;175176if (s == NULL || (e = s->s_elf) == NULL) {177LIBELF_SET_ERROR(ARGUMENT, 0);178return (NULL);179}180181assert(e->e_kind == ELF_K_ELF);182183/*184* elf_newdata() has to append a data descriptor, so185* bring in existing section data if not already present.186*/187if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))188if (elf_getdata(s, NULL) == NULL)189return (NULL);190191if ((d = _libelf_allocate_data(s)) == NULL)192return (NULL);193194STAILQ_INSERT_TAIL(&s->s_data, d, d_next);195196d->d_data.d_align = 1;197d->d_data.d_buf = NULL;198d->d_data.d_off = (uint64_t) ~0;199d->d_data.d_size = 0;200d->d_data.d_type = ELF_T_BYTE;201d->d_data.d_version = LIBELF_PRIVATE(version);202203(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);204205return (&d->d_data);206}207208/*209* Retrieve a data descriptor for raw (untranslated) data for section210* `s'.211*/212213Elf_Data *214elf_rawdata(Elf_Scn *s, Elf_Data *ed)215{216Elf *e;217int elf_class;218uint32_t sh_type;219struct _Libelf_Data *d;220uint64_t sh_align, sh_offset, sh_size, raw_size;221222if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {223LIBELF_SET_ERROR(ARGUMENT, 0);224return (NULL);225}226227assert(e->e_kind == ELF_K_ELF);228229d = (struct _Libelf_Data *) ed;230231if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)232return (&d->d_data);233234if (d != NULL)235return (&STAILQ_NEXT(d, d_next)->d_data);236237elf_class = e->e_class;238239assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);240241if (elf_class == ELFCLASS32) {242sh_type = s->s_shdr.s_shdr32.sh_type;243sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;244sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;245sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;246} else {247sh_type = s->s_shdr.s_shdr64.sh_type;248sh_offset = s->s_shdr.s_shdr64.sh_offset;249sh_size = s->s_shdr.s_shdr64.sh_size;250sh_align = s->s_shdr.s_shdr64.sh_addralign;251}252253if (sh_type == SHT_NULL) {254LIBELF_SET_ERROR(SECTION, 0);255return (NULL);256}257258raw_size = (uint64_t) e->e_rawsize;259if (sh_type != SHT_NOBITS &&260(sh_offset > raw_size || sh_size > raw_size - sh_offset)) {261LIBELF_SET_ERROR(SECTION, 0);262return (NULL);263}264265if ((d = _libelf_allocate_data(s)) == NULL)266return (NULL);267268d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :269e->e_rawfile + sh_offset;270d->d_data.d_off = 0;271d->d_data.d_align = sh_align;272d->d_data.d_size = sh_size;273d->d_data.d_type = ELF_T_BYTE;274d->d_data.d_version = e->e_version;275276STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);277278return (&d->d_data);279}280281282