libelf_phdr.c revision 4484
111250Sradhika.jagtap@ARM.com/*- 211250Sradhika.jagtap@ARM.com * Copyright (c) 2006 Joseph Koshy 311250Sradhika.jagtap@ARM.com * All rights reserved. 411250Sradhika.jagtap@ARM.com * 511250Sradhika.jagtap@ARM.com * Redistribution and use in source and binary forms, with or without 611250Sradhika.jagtap@ARM.com * modification, are permitted provided that the following conditions 711250Sradhika.jagtap@ARM.com * are met: 811250Sradhika.jagtap@ARM.com * 1. Redistributions of source code must retain the above copyright 911250Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer. 1011250Sradhika.jagtap@ARM.com * 2. Redistributions in binary form must reproduce the above copyright 1111250Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer in the 1211250Sradhika.jagtap@ARM.com * documentation and/or other materials provided with the distribution. 1311250Sradhika.jagtap@ARM.com * 1411250Sradhika.jagtap@ARM.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1511250Sradhika.jagtap@ARM.com * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1611250Sradhika.jagtap@ARM.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1711250Sradhika.jagtap@ARM.com * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1811250Sradhika.jagtap@ARM.com * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1911250Sradhika.jagtap@ARM.com * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2011250Sradhika.jagtap@ARM.com * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2111250Sradhika.jagtap@ARM.com * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2211250Sradhika.jagtap@ARM.com * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2311250Sradhika.jagtap@ARM.com * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2411250Sradhika.jagtap@ARM.com * SUCH DAMAGE. 2511250Sradhika.jagtap@ARM.com * 2611250Sradhika.jagtap@ARM.com * $FreeBSD: src/lib/libelf/libelf_phdr.c,v 1.2 2006/12/25 02:22:22 jkoshy Exp $ 2711250Sradhika.jagtap@ARM.com */ 2811250Sradhika.jagtap@ARM.com 2911250Sradhika.jagtap@ARM.com#include <assert.h> 3011250Sradhika.jagtap@ARM.com#include <stdlib.h> 3111250Sradhika.jagtap@ARM.com 3211250Sradhika.jagtap@ARM.com#include "gelf.h" 3311250Sradhika.jagtap@ARM.com#include "libelf.h" 3411250Sradhika.jagtap@ARM.com#include "_libelf.h" 3511250Sradhika.jagtap@ARM.com 3611250Sradhika.jagtap@ARM.comvoid * 3711250Sradhika.jagtap@ARM.com_libelf_getphdr(Elf *e, int ec) 3811250Sradhika.jagtap@ARM.com{ 3911250Sradhika.jagtap@ARM.com size_t phnum, phentsize; 4011250Sradhika.jagtap@ARM.com size_t fsz, msz; 4111250Sradhika.jagtap@ARM.com uint64_t phoff; 4211250Sradhika.jagtap@ARM.com Elf32_Ehdr *eh32; 4311250Sradhika.jagtap@ARM.com Elf64_Ehdr *eh64; 4411250Sradhika.jagtap@ARM.com void *ehdr, *phdr; 4511250Sradhika.jagtap@ARM.com void (*xlator)(char *_d, char *_s, size_t _c, int _swap); 4611250Sradhika.jagtap@ARM.com 4711250Sradhika.jagtap@ARM.com assert(ec == ELFCLASS32 || ec == ELFCLASS64); 4811250Sradhika.jagtap@ARM.com 4911250Sradhika.jagtap@ARM.com if (e == NULL) { 5011250Sradhika.jagtap@ARM.com LIBELF_SET_ERROR(ARGUMENT, 0); 5111250Sradhika.jagtap@ARM.com return (NULL); 5211250Sradhika.jagtap@ARM.com } 5311250Sradhika.jagtap@ARM.com 5411250Sradhika.jagtap@ARM.com if ((phdr = (ec == ELFCLASS32 ? 5511250Sradhika.jagtap@ARM.com (void *) e->e_u.e_elf.e_phdr.e_phdr32 : 5611250Sradhika.jagtap@ARM.com (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL) 5711250Sradhika.jagtap@ARM.com return (phdr); 5811250Sradhika.jagtap@ARM.com 5911250Sradhika.jagtap@ARM.com /* 6011250Sradhika.jagtap@ARM.com * Check the PHDR related fields in the EHDR for sanity. 6111250Sradhika.jagtap@ARM.com */ 6211250Sradhika.jagtap@ARM.com 6311250Sradhika.jagtap@ARM.com if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) 6411250Sradhika.jagtap@ARM.com return (NULL); 6511250Sradhika.jagtap@ARM.com 6611250Sradhika.jagtap@ARM.com phnum = e->e_u.e_elf.e_nphdr; 6711250Sradhika.jagtap@ARM.com 6811250Sradhika.jagtap@ARM.com if (ec == ELFCLASS32) { 6911250Sradhika.jagtap@ARM.com eh32 = (Elf32_Ehdr *) ehdr; 7011250Sradhika.jagtap@ARM.com phentsize = eh32->e_phentsize; 7111250Sradhika.jagtap@ARM.com phoff = (uint64_t) eh32->e_phoff; 7211250Sradhika.jagtap@ARM.com } else { 7311250Sradhika.jagtap@ARM.com eh64 = (Elf64_Ehdr *) ehdr; 7411250Sradhika.jagtap@ARM.com phentsize = eh64->e_phentsize; 7511250Sradhika.jagtap@ARM.com phoff = (uint64_t) eh64->e_phoff; 7611250Sradhika.jagtap@ARM.com } 7711250Sradhika.jagtap@ARM.com 7811250Sradhika.jagtap@ARM.com fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version); 7911250Sradhika.jagtap@ARM.com 8011250Sradhika.jagtap@ARM.com assert(fsz > 0); 8111250Sradhika.jagtap@ARM.com 8211250Sradhika.jagtap@ARM.com if ((uint64_t) e->e_rawsize < (phoff + fsz)) { 8311250Sradhika.jagtap@ARM.com LIBELF_SET_ERROR(HEADER, 0); 8411250Sradhika.jagtap@ARM.com return (NULL); 8511250Sradhika.jagtap@ARM.com } 8611250Sradhika.jagtap@ARM.com 8711250Sradhika.jagtap@ARM.com msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT); 8811250Sradhika.jagtap@ARM.com 8911250Sradhika.jagtap@ARM.com assert(msz > 0); 9011250Sradhika.jagtap@ARM.com 9111250Sradhika.jagtap@ARM.com if ((phdr = calloc(phnum, msz)) == NULL) { 9211250Sradhika.jagtap@ARM.com LIBELF_SET_ERROR(RESOURCE, 0); 9311250Sradhika.jagtap@ARM.com return (NULL); 9411250Sradhika.jagtap@ARM.com } 9511250Sradhika.jagtap@ARM.com 9611250Sradhika.jagtap@ARM.com if (ec == ELFCLASS32) 9711250Sradhika.jagtap@ARM.com e->e_u.e_elf.e_phdr.e_phdr32 = phdr; 9811250Sradhika.jagtap@ARM.com else 9911250Sradhika.jagtap@ARM.com e->e_u.e_elf.e_phdr.e_phdr64 = phdr; 10011250Sradhika.jagtap@ARM.com 10111250Sradhika.jagtap@ARM.com 10211250Sradhika.jagtap@ARM.com xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec); 10311250Sradhika.jagtap@ARM.com (*xlator)(phdr, e->e_rawfile + phoff, phnum, 10411250Sradhika.jagtap@ARM.com e->e_byteorder != LIBELF_PRIVATE(byteorder)); 10511250Sradhika.jagtap@ARM.com 10611250Sradhika.jagtap@ARM.com return (phdr); 10711250Sradhika.jagtap@ARM.com} 10811250Sradhika.jagtap@ARM.com 10911250Sradhika.jagtap@ARM.comvoid * 11011250Sradhika.jagtap@ARM.com_libelf_newphdr(Elf *e, int ec, size_t count) 11111250Sradhika.jagtap@ARM.com{ 11211250Sradhika.jagtap@ARM.com void *ehdr, *newphdr, *oldphdr; 11311250Sradhika.jagtap@ARM.com size_t msz; 11411250Sradhika.jagtap@ARM.com 11511250Sradhika.jagtap@ARM.com if (e == NULL) { 11611250Sradhika.jagtap@ARM.com LIBELF_SET_ERROR(ARGUMENT, 0); 11711250Sradhika.jagtap@ARM.com return (NULL); 11811250Sradhika.jagtap@ARM.com } 11911250Sradhika.jagtap@ARM.com 12011250Sradhika.jagtap@ARM.com if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) { 12111250Sradhika.jagtap@ARM.com LIBELF_SET_ERROR(SEQUENCE, 0); 12211250Sradhika.jagtap@ARM.com return (NULL); 12311250Sradhika.jagtap@ARM.com } 12411250Sradhika.jagtap@ARM.com 12511250Sradhika.jagtap@ARM.com assert(e->e_class == ec); 12611250Sradhika.jagtap@ARM.com assert(ec == ELFCLASS32 || ec == ELFCLASS64); 12711250Sradhika.jagtap@ARM.com assert(e->e_version == EV_CURRENT); 12811250Sradhika.jagtap@ARM.com 12911250Sradhika.jagtap@ARM.com msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version); 13011250Sradhika.jagtap@ARM.com 13111250Sradhika.jagtap@ARM.com assert(msz > 0); 13211250Sradhika.jagtap@ARM.com 13311250Sradhika.jagtap@ARM.com newphdr = NULL; 13411250Sradhika.jagtap@ARM.com if (count > 0 && (newphdr = calloc(count, msz)) == NULL) { 13511250Sradhika.jagtap@ARM.com LIBELF_SET_ERROR(RESOURCE, 0); 13611250Sradhika.jagtap@ARM.com return (NULL); 13711250Sradhika.jagtap@ARM.com } 13811250Sradhika.jagtap@ARM.com 13911250Sradhika.jagtap@ARM.com if (ec == ELFCLASS32) { 14011250Sradhika.jagtap@ARM.com if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL) 14111250Sradhika.jagtap@ARM.com free(oldphdr); 14211250Sradhika.jagtap@ARM.com e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr; 14311250Sradhika.jagtap@ARM.com } else { 14411250Sradhika.jagtap@ARM.com if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL) 14511250Sradhika.jagtap@ARM.com free(oldphdr); 14611250Sradhika.jagtap@ARM.com e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr; 14711250Sradhika.jagtap@ARM.com } 14811250Sradhika.jagtap@ARM.com 14911250Sradhika.jagtap@ARM.com e->e_u.e_elf.e_nphdr = count; 15011250Sradhika.jagtap@ARM.com 15111250Sradhika.jagtap@ARM.com elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); 15211250Sradhika.jagtap@ARM.com 15311250Sradhika.jagtap@ARM.com return (newphdr); 15411250Sradhika.jagtap@ARM.com} 15511250Sradhika.jagtap@ARM.com