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 34367466SdimELFTC_VCSID("$Id: libelf_phdr.c 3732 2019-04-22 11:08:38Z jkoshy $"); 35260684Skaiw 36260684Skaiwvoid * 37260684Skaiw_libelf_getphdr(Elf *e, int ec) 38260684Skaiw{ 39260684Skaiw size_t phnum; 40260684Skaiw size_t fsz, msz; 41260684Skaiw uint64_t phoff; 42260684Skaiw Elf32_Ehdr *eh32; 43260684Skaiw Elf64_Ehdr *eh64; 44260684Skaiw void *ehdr, *phdr; 45367466Sdim _libelf_translator_function *xlator; 46260684Skaiw 47260684Skaiw assert(ec == ELFCLASS32 || ec == ELFCLASS64); 48260684Skaiw 49260684Skaiw if (e == NULL) { 50260684Skaiw LIBELF_SET_ERROR(ARGUMENT, 0); 51260684Skaiw return (NULL); 52260684Skaiw } 53260684Skaiw 54260684Skaiw if ((phdr = (ec == ELFCLASS32 ? 55260684Skaiw (void *) e->e_u.e_elf.e_phdr.e_phdr32 : 56260684Skaiw (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL) 57260684Skaiw return (phdr); 58260684Skaiw 59260684Skaiw /* 60260684Skaiw * Check the PHDR related fields in the EHDR for sanity. 61260684Skaiw */ 62260684Skaiw 63260684Skaiw if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) 64260684Skaiw return (NULL); 65260684Skaiw 66260684Skaiw phnum = e->e_u.e_elf.e_nphdr; 67260684Skaiw 68260684Skaiw if (ec == ELFCLASS32) { 69260684Skaiw eh32 = (Elf32_Ehdr *) ehdr; 70260684Skaiw phoff = (uint64_t) eh32->e_phoff; 71260684Skaiw } else { 72260684Skaiw eh64 = (Elf64_Ehdr *) ehdr; 73260684Skaiw phoff = (uint64_t) eh64->e_phoff; 74260684Skaiw } 75260684Skaiw 76260684Skaiw fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version); 77260684Skaiw 78260684Skaiw assert(fsz > 0); 79260684Skaiw 80367466Sdim if (phoff + fsz < phoff) { /* Numeric overflow. */ 81367466Sdim LIBELF_SET_ERROR(HEADER, 0); 82367466Sdim return (NULL); 83367466Sdim } 84367466Sdim 85260684Skaiw if ((uint64_t) e->e_rawsize < (phoff + fsz)) { 86260684Skaiw LIBELF_SET_ERROR(HEADER, 0); 87260684Skaiw return (NULL); 88260684Skaiw } 89260684Skaiw 90367466Sdim if ((msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT)) == 0) 91367466Sdim return (NULL); 92260684Skaiw 93260684Skaiw if ((phdr = calloc(phnum, msz)) == NULL) { 94260684Skaiw LIBELF_SET_ERROR(RESOURCE, 0); 95260684Skaiw return (NULL); 96260684Skaiw } 97260684Skaiw 98260684Skaiw if (ec == ELFCLASS32) 99260684Skaiw e->e_u.e_elf.e_phdr.e_phdr32 = phdr; 100260684Skaiw else 101260684Skaiw e->e_u.e_elf.e_phdr.e_phdr64 = phdr; 102260684Skaiw 103260684Skaiw 104367466Sdim xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec, 105367466Sdim _libelf_elfmachine(e)); 106260684Skaiw (*xlator)(phdr, phnum * msz, e->e_rawfile + phoff, phnum, 107260684Skaiw e->e_byteorder != LIBELF_PRIVATE(byteorder)); 108260684Skaiw 109260684Skaiw return (phdr); 110260684Skaiw} 111260684Skaiw 112260684Skaiwvoid * 113260684Skaiw_libelf_newphdr(Elf *e, int ec, size_t count) 114260684Skaiw{ 115260684Skaiw void *ehdr, *newphdr, *oldphdr; 116260684Skaiw size_t msz; 117260684Skaiw 118260684Skaiw if (e == NULL) { 119260684Skaiw LIBELF_SET_ERROR(ARGUMENT, 0); 120260684Skaiw return (NULL); 121260684Skaiw } 122260684Skaiw 123260684Skaiw if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) { 124260684Skaiw LIBELF_SET_ERROR(SEQUENCE, 0); 125260684Skaiw return (NULL); 126260684Skaiw } 127260684Skaiw 128260684Skaiw assert(e->e_class == ec); 129260684Skaiw assert(ec == ELFCLASS32 || ec == ELFCLASS64); 130260684Skaiw assert(e->e_version == EV_CURRENT); 131260684Skaiw 132367466Sdim if ((msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version)) == 0) 133367466Sdim return (NULL); 134260684Skaiw 135260684Skaiw newphdr = NULL; 136260684Skaiw if (count > 0 && (newphdr = calloc(count, msz)) == NULL) { 137260684Skaiw LIBELF_SET_ERROR(RESOURCE, 0); 138260684Skaiw return (NULL); 139260684Skaiw } 140260684Skaiw 141260684Skaiw if (ec == ELFCLASS32) { 142260684Skaiw if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL) 143260684Skaiw free(oldphdr); 144260684Skaiw e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr; 145260684Skaiw } else { 146260684Skaiw if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL) 147260684Skaiw free(oldphdr); 148260684Skaiw e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr; 149260684Skaiw } 150260684Skaiw 151260684Skaiw e->e_u.e_elf.e_nphdr = count; 152260684Skaiw 153260684Skaiw elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); 154260684Skaiw 155260684Skaiw return (newphdr); 156260684Skaiw} 157