1*2de3b87aSKai Wang /*- 2*2de3b87aSKai Wang * Copyright (c) 2006,2008,2011 Joseph Koshy 3*2de3b87aSKai Wang * All rights reserved. 4*2de3b87aSKai Wang * 5*2de3b87aSKai Wang * Redistribution and use in source and binary forms, with or without 6*2de3b87aSKai Wang * modification, are permitted provided that the following conditions 7*2de3b87aSKai Wang * are met: 8*2de3b87aSKai Wang * 1. Redistributions of source code must retain the above copyright 9*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer. 10*2de3b87aSKai Wang * 2. Redistributions in binary form must reproduce the above copyright 11*2de3b87aSKai Wang * notice, this list of conditions and the following disclaimer in the 12*2de3b87aSKai Wang * documentation and/or other materials provided with the distribution. 13*2de3b87aSKai Wang * 14*2de3b87aSKai Wang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*2de3b87aSKai Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*2de3b87aSKai Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*2de3b87aSKai Wang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*2de3b87aSKai Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*2de3b87aSKai Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*2de3b87aSKai Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*2de3b87aSKai Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*2de3b87aSKai Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*2de3b87aSKai Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*2de3b87aSKai Wang * SUCH DAMAGE. 25*2de3b87aSKai Wang */ 26*2de3b87aSKai Wang 27*2de3b87aSKai Wang #include <assert.h> 28*2de3b87aSKai Wang #include <errno.h> 29*2de3b87aSKai Wang #include <libelf.h> 30*2de3b87aSKai Wang #include <stdlib.h> 31*2de3b87aSKai Wang 32*2de3b87aSKai Wang #include "_libelf.h" 33*2de3b87aSKai Wang 34*2de3b87aSKai Wang ELFTC_VCSID("$Id: elf_data.c 2921 2013-03-04 16:19:22Z jkoshy $"); 35*2de3b87aSKai Wang 36*2de3b87aSKai Wang Elf_Data * 37*2de3b87aSKai Wang elf_getdata(Elf_Scn *s, Elf_Data *ed) 38*2de3b87aSKai Wang { 39*2de3b87aSKai Wang Elf *e; 40*2de3b87aSKai Wang unsigned int sh_type; 41*2de3b87aSKai Wang int elfclass, elftype; 42*2de3b87aSKai Wang size_t fsz, msz, count; 43*2de3b87aSKai Wang struct _Libelf_Data *d; 44*2de3b87aSKai Wang uint64_t sh_align, sh_offset, sh_size; 45*2de3b87aSKai Wang int (*xlate)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); 46*2de3b87aSKai Wang 47*2de3b87aSKai Wang d = (struct _Libelf_Data *) ed; 48*2de3b87aSKai Wang 49*2de3b87aSKai Wang if (s == NULL || (e = s->s_elf) == NULL || 50*2de3b87aSKai Wang (d != NULL && s != d->d_scn)) { 51*2de3b87aSKai Wang LIBELF_SET_ERROR(ARGUMENT, 0); 52*2de3b87aSKai Wang return (NULL); 53*2de3b87aSKai Wang } 54*2de3b87aSKai Wang 55*2de3b87aSKai Wang assert(e->e_kind == ELF_K_ELF); 56*2de3b87aSKai Wang 57*2de3b87aSKai Wang if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL) 58*2de3b87aSKai Wang return (&d->d_data); 59*2de3b87aSKai Wang 60*2de3b87aSKai Wang if (d != NULL) 61*2de3b87aSKai Wang return (&STAILQ_NEXT(d, d_next)->d_data); 62*2de3b87aSKai Wang 63*2de3b87aSKai Wang if (e->e_rawfile == NULL) { 64*2de3b87aSKai Wang /* 65*2de3b87aSKai Wang * In the ELF_C_WRITE case, there is no source that 66*2de3b87aSKai Wang * can provide data for the section. 67*2de3b87aSKai Wang */ 68*2de3b87aSKai Wang LIBELF_SET_ERROR(ARGUMENT, 0); 69*2de3b87aSKai Wang return (NULL); 70*2de3b87aSKai Wang } 71*2de3b87aSKai Wang 72*2de3b87aSKai Wang elfclass = e->e_class; 73*2de3b87aSKai Wang 74*2de3b87aSKai Wang assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); 75*2de3b87aSKai Wang 76*2de3b87aSKai Wang if (elfclass == ELFCLASS32) { 77*2de3b87aSKai Wang sh_type = s->s_shdr.s_shdr32.sh_type; 78*2de3b87aSKai Wang sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; 79*2de3b87aSKai Wang sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; 80*2de3b87aSKai Wang sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; 81*2de3b87aSKai Wang } else { 82*2de3b87aSKai Wang sh_type = s->s_shdr.s_shdr64.sh_type; 83*2de3b87aSKai Wang sh_offset = s->s_shdr.s_shdr64.sh_offset; 84*2de3b87aSKai Wang sh_size = s->s_shdr.s_shdr64.sh_size; 85*2de3b87aSKai Wang sh_align = s->s_shdr.s_shdr64.sh_addralign; 86*2de3b87aSKai Wang } 87*2de3b87aSKai Wang 88*2de3b87aSKai Wang if (sh_type == SHT_NULL) { 89*2de3b87aSKai Wang LIBELF_SET_ERROR(SECTION, 0); 90*2de3b87aSKai Wang return (NULL); 91*2de3b87aSKai Wang } 92*2de3b87aSKai Wang 93*2de3b87aSKai Wang if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST || 94*2de3b87aSKai Wang elftype > ELF_T_LAST || (sh_type != SHT_NOBITS && 95*2de3b87aSKai Wang sh_offset + sh_size > (uint64_t) e->e_rawsize)) { 96*2de3b87aSKai Wang LIBELF_SET_ERROR(SECTION, 0); 97*2de3b87aSKai Wang return (NULL); 98*2de3b87aSKai Wang } 99*2de3b87aSKai Wang 100*2de3b87aSKai Wang if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize) 101*2de3b87aSKai Wang (elftype, (size_t) 1, e->e_version)) == 0) { 102*2de3b87aSKai Wang LIBELF_SET_ERROR(UNIMPL, 0); 103*2de3b87aSKai Wang return (NULL); 104*2de3b87aSKai Wang } 105*2de3b87aSKai Wang 106*2de3b87aSKai Wang if (sh_size % fsz) { 107*2de3b87aSKai Wang LIBELF_SET_ERROR(SECTION, 0); 108*2de3b87aSKai Wang return (NULL); 109*2de3b87aSKai Wang } 110*2de3b87aSKai Wang 111*2de3b87aSKai Wang count = sh_size / fsz; 112*2de3b87aSKai Wang 113*2de3b87aSKai Wang msz = _libelf_msize(elftype, elfclass, e->e_version); 114*2de3b87aSKai Wang 115*2de3b87aSKai Wang assert(msz > 0); 116*2de3b87aSKai Wang 117*2de3b87aSKai Wang if ((d = _libelf_allocate_data(s)) == NULL) 118*2de3b87aSKai Wang return (NULL); 119*2de3b87aSKai Wang 120*2de3b87aSKai Wang d->d_data.d_buf = NULL; 121*2de3b87aSKai Wang d->d_data.d_off = 0; 122*2de3b87aSKai Wang d->d_data.d_align = sh_align; 123*2de3b87aSKai Wang d->d_data.d_size = msz * count; 124*2de3b87aSKai Wang d->d_data.d_type = elftype; 125*2de3b87aSKai Wang d->d_data.d_version = e->e_version; 126*2de3b87aSKai Wang 127*2de3b87aSKai Wang if (sh_type == SHT_NOBITS || sh_size == 0) { 128*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 129*2de3b87aSKai Wang return (&d->d_data); 130*2de3b87aSKai Wang } 131*2de3b87aSKai Wang 132*2de3b87aSKai Wang if ((d->d_data.d_buf = malloc(msz*count)) == NULL) { 133*2de3b87aSKai Wang (void) _libelf_release_data(d); 134*2de3b87aSKai Wang LIBELF_SET_ERROR(RESOURCE, 0); 135*2de3b87aSKai Wang return (NULL); 136*2de3b87aSKai Wang } 137*2de3b87aSKai Wang 138*2de3b87aSKai Wang d->d_flags |= LIBELF_F_DATA_MALLOCED; 139*2de3b87aSKai Wang 140*2de3b87aSKai Wang xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass); 141*2de3b87aSKai Wang if (!(*xlate)(d->d_data.d_buf, d->d_data.d_size, 142*2de3b87aSKai Wang e->e_rawfile + sh_offset, count, 143*2de3b87aSKai Wang e->e_byteorder != LIBELF_PRIVATE(byteorder))) { 144*2de3b87aSKai Wang _libelf_release_data(d); 145*2de3b87aSKai Wang LIBELF_SET_ERROR(DATA, 0); 146*2de3b87aSKai Wang return (NULL); 147*2de3b87aSKai Wang } 148*2de3b87aSKai Wang 149*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 150*2de3b87aSKai Wang 151*2de3b87aSKai Wang return (&d->d_data); 152*2de3b87aSKai Wang } 153*2de3b87aSKai Wang 154*2de3b87aSKai Wang Elf_Data * 155*2de3b87aSKai Wang elf_newdata(Elf_Scn *s) 156*2de3b87aSKai Wang { 157*2de3b87aSKai Wang Elf *e; 158*2de3b87aSKai Wang struct _Libelf_Data *d; 159*2de3b87aSKai Wang 160*2de3b87aSKai Wang if (s == NULL || (e = s->s_elf) == NULL) { 161*2de3b87aSKai Wang LIBELF_SET_ERROR(ARGUMENT, 0); 162*2de3b87aSKai Wang return (NULL); 163*2de3b87aSKai Wang } 164*2de3b87aSKai Wang 165*2de3b87aSKai Wang assert(e->e_kind == ELF_K_ELF); 166*2de3b87aSKai Wang 167*2de3b87aSKai Wang /* 168*2de3b87aSKai Wang * elf_newdata() has to append a data descriptor, so 169*2de3b87aSKai Wang * bring in existing section data if not already present. 170*2de3b87aSKai Wang */ 171*2de3b87aSKai Wang if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) 172*2de3b87aSKai Wang if (elf_getdata(s, NULL) == NULL) 173*2de3b87aSKai Wang return (NULL); 174*2de3b87aSKai Wang 175*2de3b87aSKai Wang if ((d = _libelf_allocate_data(s)) == NULL) 176*2de3b87aSKai Wang return (NULL); 177*2de3b87aSKai Wang 178*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&s->s_data, d, d_next); 179*2de3b87aSKai Wang 180*2de3b87aSKai Wang d->d_data.d_align = 1; 181*2de3b87aSKai Wang d->d_data.d_buf = NULL; 182*2de3b87aSKai Wang d->d_data.d_off = (uint64_t) ~0; 183*2de3b87aSKai Wang d->d_data.d_size = 0; 184*2de3b87aSKai Wang d->d_data.d_type = ELF_T_BYTE; 185*2de3b87aSKai Wang d->d_data.d_version = LIBELF_PRIVATE(version); 186*2de3b87aSKai Wang 187*2de3b87aSKai Wang (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); 188*2de3b87aSKai Wang 189*2de3b87aSKai Wang return (&d->d_data); 190*2de3b87aSKai Wang } 191*2de3b87aSKai Wang 192*2de3b87aSKai Wang /* 193*2de3b87aSKai Wang * Retrieve a data descriptor for raw (untranslated) data for section 194*2de3b87aSKai Wang * `s'. 195*2de3b87aSKai Wang */ 196*2de3b87aSKai Wang 197*2de3b87aSKai Wang Elf_Data * 198*2de3b87aSKai Wang elf_rawdata(Elf_Scn *s, Elf_Data *ed) 199*2de3b87aSKai Wang { 200*2de3b87aSKai Wang Elf *e; 201*2de3b87aSKai Wang int elf_class; 202*2de3b87aSKai Wang uint32_t sh_type; 203*2de3b87aSKai Wang struct _Libelf_Data *d; 204*2de3b87aSKai Wang uint64_t sh_align, sh_offset, sh_size; 205*2de3b87aSKai Wang 206*2de3b87aSKai Wang if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) { 207*2de3b87aSKai Wang LIBELF_SET_ERROR(ARGUMENT, 0); 208*2de3b87aSKai Wang return (NULL); 209*2de3b87aSKai Wang } 210*2de3b87aSKai Wang 211*2de3b87aSKai Wang assert(e->e_kind == ELF_K_ELF); 212*2de3b87aSKai Wang 213*2de3b87aSKai Wang d = (struct _Libelf_Data *) ed; 214*2de3b87aSKai Wang 215*2de3b87aSKai Wang if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL) 216*2de3b87aSKai Wang return (&d->d_data); 217*2de3b87aSKai Wang 218*2de3b87aSKai Wang if (d != NULL) 219*2de3b87aSKai Wang return (&STAILQ_NEXT(d, d_next)->d_data); 220*2de3b87aSKai Wang 221*2de3b87aSKai Wang elf_class = e->e_class; 222*2de3b87aSKai Wang 223*2de3b87aSKai Wang assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64); 224*2de3b87aSKai Wang 225*2de3b87aSKai Wang if (elf_class == ELFCLASS32) { 226*2de3b87aSKai Wang sh_type = s->s_shdr.s_shdr32.sh_type; 227*2de3b87aSKai Wang sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; 228*2de3b87aSKai Wang sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; 229*2de3b87aSKai Wang sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; 230*2de3b87aSKai Wang } else { 231*2de3b87aSKai Wang sh_type = s->s_shdr.s_shdr64.sh_type; 232*2de3b87aSKai Wang sh_offset = s->s_shdr.s_shdr64.sh_offset; 233*2de3b87aSKai Wang sh_size = s->s_shdr.s_shdr64.sh_size; 234*2de3b87aSKai Wang sh_align = s->s_shdr.s_shdr64.sh_addralign; 235*2de3b87aSKai Wang } 236*2de3b87aSKai Wang 237*2de3b87aSKai Wang if (sh_type == SHT_NULL) { 238*2de3b87aSKai Wang LIBELF_SET_ERROR(SECTION, 0); 239*2de3b87aSKai Wang return (NULL); 240*2de3b87aSKai Wang } 241*2de3b87aSKai Wang 242*2de3b87aSKai Wang if ((d = _libelf_allocate_data(s)) == NULL) 243*2de3b87aSKai Wang return (NULL); 244*2de3b87aSKai Wang 245*2de3b87aSKai Wang d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL : 246*2de3b87aSKai Wang e->e_rawfile + sh_offset; 247*2de3b87aSKai Wang d->d_data.d_off = 0; 248*2de3b87aSKai Wang d->d_data.d_align = sh_align; 249*2de3b87aSKai Wang d->d_data.d_size = sh_size; 250*2de3b87aSKai Wang d->d_data.d_type = ELF_T_BYTE; 251*2de3b87aSKai Wang d->d_data.d_version = e->e_version; 252*2de3b87aSKai Wang 253*2de3b87aSKai Wang STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next); 254*2de3b87aSKai Wang 255*2de3b87aSKai Wang return (&d->d_data); 256*2de3b87aSKai Wang } 257