1260684Skaiw/*- 2260684Skaiw * Copyright (c) 2006,2008 Joseph Koshy 3260684Skaiw * All rights reserved. 4260684Skaiw * 5260684Skaiw * Redistribution and use in source and binary forms, with or without 6260684Skaiw * modification, are permitted provided that the following conditions 7260684Skaiw * are met: 8260684Skaiw * 1. Redistributions of source code must retain the above copyright 9260684Skaiw * notice, this list of conditions and the following disclaimer. 10260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 11260684Skaiw * notice, this list of conditions and the following disclaimer in the 12260684Skaiw * documentation and/or other materials provided with the distribution. 13260684Skaiw * 14260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15260684Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16260684Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17260684Skaiw * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18260684Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19260684Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20260684Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21260684Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22260684Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23260684Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24260684Skaiw * SUCH DAMAGE. 25260684Skaiw */ 26260684Skaiw 27260684Skaiw#include <assert.h> 28260684Skaiw#include <gelf.h> 29260684Skaiw#include <libelf.h> 30260684Skaiw#include <stdlib.h> 31260684Skaiw 32260684Skaiw#include "_libelf.h" 33260684Skaiw 34280932SemasteELFTC_VCSID("$Id: libelf_ehdr.c 3174 2015-03-27 17:13:41Z emaste $"); 35260684Skaiw 36260684Skaiw/* 37260684Skaiw * Retrieve counts for sections, phdrs and the section string table index 38260684Skaiw * from section header #0 of the ELF object. 39260684Skaiw */ 40260684Skaiwstatic int 41260684Skaiw_libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum, 42260684Skaiw uint16_t strndx) 43260684Skaiw{ 44260684Skaiw Elf_Scn *scn; 45260684Skaiw size_t fsz; 46276371Semaste int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s, 47276371Semaste size_t _c, int _swap); 48260684Skaiw uint32_t shtype; 49260684Skaiw 50260684Skaiw assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); 51260684Skaiw 52260684Skaiw fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1); 53260684Skaiw assert(fsz > 0); 54260684Skaiw 55260684Skaiw if (e->e_rawsize < shoff + fsz) { /* raw file too small */ 56260684Skaiw LIBELF_SET_ERROR(HEADER, 0); 57260684Skaiw return (0); 58260684Skaiw } 59260684Skaiw 60260684Skaiw if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL) 61260684Skaiw return (0); 62260684Skaiw 63260684Skaiw xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); 64276371Semaste (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr), 65276371Semaste (unsigned char *) e->e_rawfile + shoff, (size_t) 1, 66260684Skaiw e->e_byteorder != LIBELF_PRIVATE(byteorder)); 67260684Skaiw 68260684Skaiw#define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \ 69260684Skaiw scn->s_shdr.s_shdr64.M) 70260684Skaiw 71260684Skaiw if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) { 72260684Skaiw LIBELF_SET_ERROR(SECTION, 0); 73260684Skaiw return (0); 74260684Skaiw } 75260684Skaiw 76276371Semaste e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size); 77260684Skaiw e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum : 78260684Skaiw GET_SHDR_MEMBER(sh_info); 79260684Skaiw e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx : 80260684Skaiw GET_SHDR_MEMBER(sh_link); 81260684Skaiw#undef GET_SHDR_MEMBER 82260684Skaiw 83260684Skaiw return (1); 84260684Skaiw} 85260684Skaiw 86260684Skaiw#define EHDR_INIT(E,SZ) do { \ 87260684Skaiw Elf##SZ##_Ehdr *eh = (E); \ 88260684Skaiw eh->e_ident[EI_MAG0] = ELFMAG0; \ 89260684Skaiw eh->e_ident[EI_MAG1] = ELFMAG1; \ 90260684Skaiw eh->e_ident[EI_MAG2] = ELFMAG2; \ 91260684Skaiw eh->e_ident[EI_MAG3] = ELFMAG3; \ 92260684Skaiw eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \ 93260684Skaiw eh->e_ident[EI_DATA] = ELFDATANONE; \ 94276371Semaste eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version) & 0xFFU; \ 95260684Skaiw eh->e_machine = EM_NONE; \ 96260684Skaiw eh->e_type = ELF_K_NONE; \ 97260684Skaiw eh->e_version = LIBELF_PRIVATE(version); \ 98260684Skaiw } while (0) 99260684Skaiw 100260684Skaiwvoid * 101260684Skaiw_libelf_ehdr(Elf *e, int ec, int allocate) 102260684Skaiw{ 103260684Skaiw void *ehdr; 104260684Skaiw size_t fsz, msz; 105260684Skaiw uint16_t phnum, shnum, strndx; 106260684Skaiw uint64_t shoff; 107276371Semaste int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s, 108276371Semaste size_t _c, int _swap); 109260684Skaiw 110260684Skaiw assert(ec == ELFCLASS32 || ec == ELFCLASS64); 111260684Skaiw 112260684Skaiw if (e == NULL || e->e_kind != ELF_K_ELF) { 113260684Skaiw LIBELF_SET_ERROR(ARGUMENT, 0); 114260684Skaiw return (NULL); 115260684Skaiw } 116260684Skaiw 117260684Skaiw if (e->e_class != ELFCLASSNONE && e->e_class != ec) { 118260684Skaiw LIBELF_SET_ERROR(CLASS, 0); 119260684Skaiw return (NULL); 120260684Skaiw } 121260684Skaiw 122260684Skaiw if (e->e_version != EV_CURRENT) { 123260684Skaiw LIBELF_SET_ERROR(VERSION, 0); 124260684Skaiw return (NULL); 125260684Skaiw } 126260684Skaiw 127260684Skaiw if (e->e_class == ELFCLASSNONE) 128260684Skaiw e->e_class = ec; 129260684Skaiw 130260684Skaiw if (ec == ELFCLASS32) 131260684Skaiw ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32; 132260684Skaiw else 133260684Skaiw ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64; 134260684Skaiw 135260684Skaiw if (ehdr != NULL) /* already have a translated ehdr */ 136260684Skaiw return (ehdr); 137260684Skaiw 138260684Skaiw fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); 139260684Skaiw assert(fsz > 0); 140260684Skaiw 141260684Skaiw if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) { 142260684Skaiw LIBELF_SET_ERROR(HEADER, 0); 143260684Skaiw return (NULL); 144260684Skaiw } 145260684Skaiw 146260684Skaiw msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT); 147260684Skaiw 148260684Skaiw assert(msz > 0); 149260684Skaiw 150260684Skaiw if ((ehdr = calloc((size_t) 1, msz)) == NULL) { 151260684Skaiw LIBELF_SET_ERROR(RESOURCE, 0); 152260684Skaiw return (NULL); 153260684Skaiw } 154260684Skaiw 155260684Skaiw if (ec == ELFCLASS32) { 156260684Skaiw e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr; 157260684Skaiw EHDR_INIT(ehdr,32); 158260684Skaiw } else { 159260684Skaiw e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr; 160260684Skaiw EHDR_INIT(ehdr,64); 161260684Skaiw } 162260684Skaiw 163260684Skaiw if (allocate) 164260684Skaiw e->e_flags |= ELF_F_DIRTY; 165260684Skaiw 166260684Skaiw if (e->e_cmd == ELF_C_WRITE) 167260684Skaiw return (ehdr); 168260684Skaiw 169260684Skaiw xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec); 170276371Semaste (*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1, 171260684Skaiw e->e_byteorder != LIBELF_PRIVATE(byteorder)); 172260684Skaiw 173260684Skaiw /* 174260684Skaiw * If extended numbering is being used, read the correct 175260684Skaiw * number of sections and program header entries. 176260684Skaiw */ 177260684Skaiw if (ec == ELFCLASS32) { 178260684Skaiw phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; 179260684Skaiw shnum = ((Elf32_Ehdr *) ehdr)->e_shnum; 180260684Skaiw shoff = ((Elf32_Ehdr *) ehdr)->e_shoff; 181260684Skaiw strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx; 182260684Skaiw } else { 183260684Skaiw phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; 184260684Skaiw shnum = ((Elf64_Ehdr *) ehdr)->e_shnum; 185260684Skaiw shoff = ((Elf64_Ehdr *) ehdr)->e_shoff; 186260684Skaiw strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx; 187260684Skaiw } 188260684Skaiw 189260684Skaiw if (shnum >= SHN_LORESERVE || 190260684Skaiw (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM || 191260684Skaiw strndx == SHN_XINDEX))) { 192260684Skaiw LIBELF_SET_ERROR(HEADER, 0); 193260684Skaiw return (NULL); 194260684Skaiw } 195260684Skaiw 196260684Skaiw if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */ 197260684Skaiw e->e_u.e_elf.e_nphdr = phnum; 198260684Skaiw e->e_u.e_elf.e_nscn = shnum; 199260684Skaiw e->e_u.e_elf.e_strndx = strndx; 200260684Skaiw } else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0) 201260684Skaiw return (NULL); 202260684Skaiw 203260684Skaiw return (ehdr); 204260684Skaiw} 205