elf_scn.c revision 277558
18097Sjkh/*- 28097Sjkh * Copyright (c) 2006 Joseph Koshy 38097Sjkh * All rights reserved. 48097Sjkh * 58097Sjkh * Redistribution and use in source and binary forms, with or without 68097Sjkh * modification, are permitted provided that the following conditions 720064Sjkh * are met: 88097Sjkh * 1. Redistributions of source code must retain the above copyright 98097Sjkh * notice, this list of conditions and the following disclaimer. 108097Sjkh * 2. Redistributions in binary form must reproduce the above copyright 118097Sjkh * notice, this list of conditions and the following disclaimer in the 128097Sjkh * documentation and/or other materials provided with the distribution. 138097Sjkh * 148097Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 158097Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168881Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 178881Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 188097Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 198097Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 208097Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 218097Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 228097Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 238097Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 248097Sjkh * SUCH DAMAGE. 258097Sjkh */ 268097Sjkh 278097Sjkh#include <sys/cdefs.h> 288097Sjkh__FBSDID("$FreeBSD: stable/10/lib/libelf/elf_scn.c 277558 2015-01-23 04:07:07Z emaste $"); 298097Sjkh 308097Sjkh#include <assert.h> 318097Sjkh#include <errno.h> 328097Sjkh#include <gelf.h> 338097Sjkh#include <libelf.h> 348097Sjkh#include <stdint.h> 358097Sjkh#include <stdlib.h> 368097Sjkh 378097Sjkh#include "_libelf.h" 3818650Sjkh 3912661Speter/* 408347Sjkh * Load an ELF section table and create a list of Elf_Scn structures. 418347Sjkh */ 428751Sjkhint 438347Sjkh_libelf_load_scn(Elf *e, void *ehdr) 448641Sjkh{ 4512661Speter int ec, swapbytes; 4612661Speter size_t fsz, i, shnum; 4712661Speter uint64_t shoff; 4812661Speter char *src; 4910882Speter Elf32_Ehdr *eh32; 508347Sjkh Elf64_Ehdr *eh64; 5112661Speter Elf_Scn *scn; 528097Sjkh int (*xlator)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); 5312661Speter 5418711Sjkh assert(e != NULL); 5518643Sjkh assert(ehdr != NULL); 5618711Sjkh assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0); 578281Sjkh 5812661Speter#define CHECK_EHDR(E,EH) do { \ 598549Sjkh if (shoff > e->e_rawsize || \ 6015451Sjkh fsz != (EH)->e_shentsize || \ 6115451Sjkh shnum > SIZE_MAX / fsz || \ 6217362Sjkh fsz * shnum > e->e_rawsize - shoff) { \ 6317368Sjkh LIBELF_SET_ERROR(HEADER, 0); \ 648702Sjkh return (0); \ 658702Sjkh } \ 6612661Speter } while (0) 678702Sjkh 6817362Sjkh ec = e->e_class; 698702Sjkh fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); 708702Sjkh assert(fsz > 0); 7112661Speter 7217362Sjkh shnum = e->e_u.e_elf.e_nscn; 7317027Sjkh 7417362Sjkh if (ec == ELFCLASS32) { 7517027Sjkh eh32 = (Elf32_Ehdr *) ehdr; 7617027Sjkh shoff = (uint64_t) eh32->e_shoff; 7717027Sjkh CHECK_EHDR(e, eh32); 788702Sjkh } else { 798702Sjkh eh64 = (Elf64_Ehdr *) ehdr; 808702Sjkh shoff = eh64->e_shoff; 818702Sjkh CHECK_EHDR(e, eh64); 828702Sjkh } 838702Sjkh 848702Sjkh xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); 858702Sjkh 868702Sjkh swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder); 878702Sjkh src = e->e_rawfile + shoff; 888702Sjkh 898702Sjkh /* 9014793Sjoerg * If the file is using extended numbering then section #0 919202Srgrimes * would have already been read in. 929202Srgrimes */ 9317368Sjkh 9417368Sjkh i = 0; 9517368Sjkh if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { 969202Srgrimes assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) == 979202Srgrimes STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next)); 9817027Sjkh 9917027Sjkh i = 1; 10017027Sjkh src += fsz; 10117027Sjkh } 10217027Sjkh 1039202Srgrimes for (; i < shnum; i++, src += fsz) { 10414793Sjoerg if ((scn = _libelf_allocate_scn(e, i)) == NULL) 1059202Srgrimes return (0); 10617368Sjkh 10717368Sjkh (*xlator)((char *) &scn->s_shdr, sizeof(scn->s_shdr), src, 10817368Sjkh (size_t) 1, swapbytes); 1099202Srgrimes 1109202Srgrimes if (ec == ELFCLASS32) { 11117027Sjkh scn->s_offset = scn->s_rawoff = 11217027Sjkh scn->s_shdr.s_shdr32.sh_offset; 11317027Sjkh scn->s_size = scn->s_shdr.s_shdr32.sh_size; 11417027Sjkh } else { 11517027Sjkh scn->s_offset = scn->s_rawoff = 1169202Srgrimes scn->s_shdr.s_shdr64.sh_offset; 11717362Sjkh scn->s_size = scn->s_shdr.s_shdr64.sh_size; 11817362Sjkh } 11917368Sjkh } 12017368Sjkh 12117368Sjkh e->e_flags |= LIBELF_F_SHDRS_LOADED; 12217362Sjkh 12317362Sjkh return (1); 12417362Sjkh} 12517362Sjkh 12617362Sjkh 12717362SjkhElf_Scn * 12817362Sjkhelf_getscn(Elf *e, size_t index) 12917362Sjkh{ 1308702Sjkh int ec; 1318702Sjkh void *ehdr; 1328702Sjkh Elf_Scn *s; 1338702Sjkh 1348702Sjkh if (e == NULL || e->e_kind != ELF_K_ELF || 1358702Sjkh ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { 1368705Sjkh LIBELF_SET_ERROR(ARGUMENT, 0); 1378702Sjkh return (NULL); 13813421Sjkh } 13913421Sjkh 1408702Sjkh if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) 1418702Sjkh return (NULL); 1428702Sjkh 1438702Sjkh if (e->e_cmd != ELF_C_WRITE && 1448702Sjkh (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && 1458702Sjkh _libelf_load_scn(e, ehdr) == 0) 1468702Sjkh return (NULL); 14712661Speter 1488702Sjkh STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) 14912661Speter if (s->s_ndx == index) 15012661Speter return (s); 1518702Sjkh 1528702Sjkh LIBELF_SET_ERROR(ARGUMENT, 0); 1538702Sjkh return (NULL); 1548702Sjkh} 1558702Sjkh 1568702Sjkhsize_t 1578702Sjkhelf_ndxscn(Elf_Scn *s) 15817027Sjkh{ 15912661Speter if (s == NULL) { 16017027Sjkh LIBELF_SET_ERROR(ARGUMENT, 0); 16117027Sjkh return (SHN_UNDEF); 16217362Sjkh } 16317027Sjkh return (s->s_ndx); 16417368Sjkh} 16512661Speter 16612661SpeterElf_Scn * 16712661Speterelf_newscn(Elf *e) 1688702Sjkh{ 16917368Sjkh int ec; 17012661Speter void *ehdr; 17112661Speter Elf_Scn *scn; 17212661Speter 1738702Sjkh if (e == NULL || e->e_kind != ELF_K_ELF) { 17417368Sjkh LIBELF_SET_ERROR(ARGUMENT, 0); 17512661Speter return (NULL); 17612661Speter } 17712661Speter 17812661Speter if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { 17912661Speter LIBELF_SET_ERROR(CLASS, 0); 18017368Sjkh return (NULL); 18117362Sjkh } 18217362Sjkh 18317362Sjkh if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) 18417362Sjkh return (NULL); 18517362Sjkh 18617362Sjkh /* 18712661Speter * The application may be asking for a new section descriptor 1888702Sjkh * on an ELF object opened with ELF_C_RDWR or ELF_C_READ. We 1898702Sjkh * need to bring in the existing section information before 19012661Speter * appending a new one to the list. 1918636Sjkh * 1928589Sjkh * Per the ELF(3) API, an application is allowed to open a 1938636Sjkh * file using ELF_C_READ, mess with its internal structure and 1948589Sjkh * use elf_update(...,ELF_C_NULL) to compute its new layout. 1958636Sjkh */ 19615242Sjkh if (e->e_cmd != ELF_C_WRITE && 1978636Sjkh (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && 19812661Speter _libelf_load_scn(e, ehdr) == 0) 19915439Sjkh return (NULL); 20015439Sjkh 20115242Sjkh if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { 2028677Sjkh assert(e->e_u.e_elf.e_nscn == 0); 20312661Speter if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) == 20412661Speter NULL) 20512661Speter return (NULL); 2068677Sjkh e->e_u.e_elf.e_nscn++; 2078677Sjkh } 20817404Sjkh 20912661Speter assert(e->e_u.e_elf.e_nscn > 0); 21012661Speter 21112661Speter if ((scn = _libelf_allocate_scn(e, e->e_u.e_elf.e_nscn)) == NULL) 21212661Speter return (NULL); 21318830Sjkh 21415451Sjkh e->e_u.e_elf.e_nscn++; 2158556Sjkh 21615419Sjkh (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); 2179202Srgrimes 21815242Sjkh return (scn); 2199202Srgrimes} 22015445Sjkh 22115445SjkhElf_Scn * 22210882Speterelf_nextscn(Elf *e, Elf_Scn *s) 22312661Speter{ 22412661Speter if (e == NULL || (e->e_kind != ELF_K_ELF) || 22512661Speter (s && s->s_elf != e)) { 22615242Sjkh LIBELF_SET_ERROR(ARGUMENT, 0); 2279202Srgrimes return (NULL); 22810882Speter } 22912661Speter 23012661Speter return (s == NULL ? elf_getscn(e, (size_t) 1) : 23115242Sjkh STAILQ_NEXT(s, s_next)); 23212661Speter} 23312661Speter