1*2de3b87aSKai Wang /*- 2*2de3b87aSKai Wang * Copyright (c) 2006,2008 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 <sys/cdefs.h> 28*2de3b87aSKai Wang 29*2de3b87aSKai Wang #include <assert.h> 30*2de3b87aSKai Wang #include <gelf.h> 31*2de3b87aSKai Wang #include <libelf.h> 32*2de3b87aSKai Wang #include <stdlib.h> 33*2de3b87aSKai Wang 34*2de3b87aSKai Wang #include "_libelf.h" 35*2de3b87aSKai Wang 36*2de3b87aSKai Wang ELFTC_VCSID("$Id: libelf_phdr.c 2931 2013-03-23 11:41:07Z jkoshy $"); 37*2de3b87aSKai Wang 38*2de3b87aSKai Wang void * 39*2de3b87aSKai Wang _libelf_getphdr(Elf *e, int ec) 40*2de3b87aSKai Wang { 41*2de3b87aSKai Wang size_t phnum; 42*2de3b87aSKai Wang size_t fsz, msz; 43*2de3b87aSKai Wang uint64_t phoff; 44*2de3b87aSKai Wang Elf32_Ehdr *eh32; 45*2de3b87aSKai Wang Elf64_Ehdr *eh64; 46*2de3b87aSKai Wang void *ehdr, *phdr; 47*2de3b87aSKai Wang int (*xlator)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); 48*2de3b87aSKai Wang 49*2de3b87aSKai Wang assert(ec == ELFCLASS32 || ec == ELFCLASS64); 50*2de3b87aSKai Wang 51*2de3b87aSKai Wang if (e == NULL) { 52*2de3b87aSKai Wang LIBELF_SET_ERROR(ARGUMENT, 0); 53*2de3b87aSKai Wang return (NULL); 54*2de3b87aSKai Wang } 55*2de3b87aSKai Wang 56*2de3b87aSKai Wang if ((phdr = (ec == ELFCLASS32 ? 57*2de3b87aSKai Wang (void *) e->e_u.e_elf.e_phdr.e_phdr32 : 58*2de3b87aSKai Wang (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL) 59*2de3b87aSKai Wang return (phdr); 60*2de3b87aSKai Wang 61*2de3b87aSKai Wang /* 62*2de3b87aSKai Wang * Check the PHDR related fields in the EHDR for sanity. 63*2de3b87aSKai Wang */ 64*2de3b87aSKai Wang 65*2de3b87aSKai Wang if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) 66*2de3b87aSKai Wang return (NULL); 67*2de3b87aSKai Wang 68*2de3b87aSKai Wang phnum = e->e_u.e_elf.e_nphdr; 69*2de3b87aSKai Wang 70*2de3b87aSKai Wang if (ec == ELFCLASS32) { 71*2de3b87aSKai Wang eh32 = (Elf32_Ehdr *) ehdr; 72*2de3b87aSKai Wang phoff = (uint64_t) eh32->e_phoff; 73*2de3b87aSKai Wang } else { 74*2de3b87aSKai Wang eh64 = (Elf64_Ehdr *) ehdr; 75*2de3b87aSKai Wang phoff = (uint64_t) eh64->e_phoff; 76*2de3b87aSKai Wang } 77*2de3b87aSKai Wang 78*2de3b87aSKai Wang fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version); 79*2de3b87aSKai Wang 80*2de3b87aSKai Wang assert(fsz > 0); 81*2de3b87aSKai Wang 82*2de3b87aSKai Wang if ((uint64_t) e->e_rawsize < (phoff + fsz)) { 83*2de3b87aSKai Wang LIBELF_SET_ERROR(HEADER, 0); 84*2de3b87aSKai Wang return (NULL); 85*2de3b87aSKai Wang } 86*2de3b87aSKai Wang 87*2de3b87aSKai Wang msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT); 88*2de3b87aSKai Wang 89*2de3b87aSKai Wang assert(msz > 0); 90*2de3b87aSKai Wang 91*2de3b87aSKai Wang if ((phdr = calloc(phnum, msz)) == NULL) { 92*2de3b87aSKai Wang LIBELF_SET_ERROR(RESOURCE, 0); 93*2de3b87aSKai Wang return (NULL); 94*2de3b87aSKai Wang } 95*2de3b87aSKai Wang 96*2de3b87aSKai Wang if (ec == ELFCLASS32) 97*2de3b87aSKai Wang e->e_u.e_elf.e_phdr.e_phdr32 = phdr; 98*2de3b87aSKai Wang else 99*2de3b87aSKai Wang e->e_u.e_elf.e_phdr.e_phdr64 = phdr; 100*2de3b87aSKai Wang 101*2de3b87aSKai Wang 102*2de3b87aSKai Wang xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec); 103*2de3b87aSKai Wang (*xlator)(phdr, phnum * msz, e->e_rawfile + phoff, phnum, 104*2de3b87aSKai Wang e->e_byteorder != LIBELF_PRIVATE(byteorder)); 105*2de3b87aSKai Wang 106*2de3b87aSKai Wang return (phdr); 107*2de3b87aSKai Wang } 108*2de3b87aSKai Wang 109*2de3b87aSKai Wang void * 110*2de3b87aSKai Wang _libelf_newphdr(Elf *e, int ec, size_t count) 111*2de3b87aSKai Wang { 112*2de3b87aSKai Wang void *ehdr, *newphdr, *oldphdr; 113*2de3b87aSKai Wang size_t msz; 114*2de3b87aSKai Wang 115*2de3b87aSKai Wang if (e == NULL) { 116*2de3b87aSKai Wang LIBELF_SET_ERROR(ARGUMENT, 0); 117*2de3b87aSKai Wang return (NULL); 118*2de3b87aSKai Wang } 119*2de3b87aSKai Wang 120*2de3b87aSKai Wang if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) { 121*2de3b87aSKai Wang LIBELF_SET_ERROR(SEQUENCE, 0); 122*2de3b87aSKai Wang return (NULL); 123*2de3b87aSKai Wang } 124*2de3b87aSKai Wang 125*2de3b87aSKai Wang assert(e->e_class == ec); 126*2de3b87aSKai Wang assert(ec == ELFCLASS32 || ec == ELFCLASS64); 127*2de3b87aSKai Wang assert(e->e_version == EV_CURRENT); 128*2de3b87aSKai Wang 129*2de3b87aSKai Wang msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version); 130*2de3b87aSKai Wang 131*2de3b87aSKai Wang assert(msz > 0); 132*2de3b87aSKai Wang 133*2de3b87aSKai Wang newphdr = NULL; 134*2de3b87aSKai Wang if (count > 0 && (newphdr = calloc(count, msz)) == NULL) { 135*2de3b87aSKai Wang LIBELF_SET_ERROR(RESOURCE, 0); 136*2de3b87aSKai Wang return (NULL); 137*2de3b87aSKai Wang } 138*2de3b87aSKai Wang 139*2de3b87aSKai Wang if (ec == ELFCLASS32) { 140*2de3b87aSKai Wang if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL) 141*2de3b87aSKai Wang free(oldphdr); 142*2de3b87aSKai Wang e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr; 143*2de3b87aSKai Wang } else { 144*2de3b87aSKai Wang if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL) 145*2de3b87aSKai Wang free(oldphdr); 146*2de3b87aSKai Wang e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr; 147*2de3b87aSKai Wang } 148*2de3b87aSKai Wang 149*2de3b87aSKai Wang e->e_u.e_elf.e_nphdr = count; 150*2de3b87aSKai Wang 151*2de3b87aSKai Wang elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); 152*2de3b87aSKai Wang 153*2de3b87aSKai Wang return (newphdr); 154*2de3b87aSKai Wang } 155