1164190Sjkoshy/*- 2164190Sjkoshy * Copyright (c) 2006 Joseph Koshy 3164190Sjkoshy * All rights reserved. 4164190Sjkoshy * 5164190Sjkoshy * Redistribution and use in source and binary forms, with or without 6164190Sjkoshy * modification, are permitted provided that the following conditions 7164190Sjkoshy * are met: 8164190Sjkoshy * 1. Redistributions of source code must retain the above copyright 9164190Sjkoshy * notice, this list of conditions and the following disclaimer. 10164190Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11164190Sjkoshy * notice, this list of conditions and the following disclaimer in the 12164190Sjkoshy * documentation and/or other materials provided with the distribution. 13164190Sjkoshy * 14164190Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15164190Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16164190Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17164190Sjkoshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18164190Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19164190Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20164190Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21164190Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22164190Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23164190Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24164190Sjkoshy * SUCH DAMAGE. 25164190Sjkoshy */ 26164190Sjkoshy 27164190Sjkoshy#include <sys/cdefs.h> 28164190Sjkoshy__FBSDID("$FreeBSD: releng/10.2/lib/libelf/gelf_phdr.c 210325 2010-07-21 08:58:52Z kaiw $"); 29164190Sjkoshy 30164190Sjkoshy#include <sys/limits.h> 31164190Sjkoshy 32164190Sjkoshy#include <gelf.h> 33164190Sjkoshy#include <libelf.h> 34164190Sjkoshy 35164190Sjkoshy#include "_libelf.h" 36164190Sjkoshy 37164190SjkoshyElf32_Phdr * 38164190Sjkoshyelf32_getphdr(Elf *e) 39164190Sjkoshy{ 40164190Sjkoshy return (_libelf_getphdr(e, ELFCLASS32)); 41164190Sjkoshy} 42164190Sjkoshy 43164190SjkoshyElf64_Phdr * 44164190Sjkoshyelf64_getphdr(Elf *e) 45164190Sjkoshy{ 46164190Sjkoshy return (_libelf_getphdr(e, ELFCLASS64)); 47164190Sjkoshy} 48164190Sjkoshy 49164190SjkoshyGElf_Phdr * 50164190Sjkoshygelf_getphdr(Elf *e, int index, GElf_Phdr *d) 51164190Sjkoshy{ 52164190Sjkoshy int ec; 53164190Sjkoshy Elf32_Ehdr *eh32; 54164190Sjkoshy Elf64_Ehdr *eh64; 55164190Sjkoshy Elf32_Phdr *ep32; 56164190Sjkoshy Elf64_Phdr *ep64; 57164190Sjkoshy 58164190Sjkoshy if (d == NULL || e == NULL || 59164190Sjkoshy ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || 60164190Sjkoshy (e->e_kind != ELF_K_ELF) || index < 0) { 61164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 62164190Sjkoshy return (NULL); 63164190Sjkoshy } 64164190Sjkoshy 65164190Sjkoshy if (ec == ELFCLASS32) { 66164190Sjkoshy if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL || 67164190Sjkoshy ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL)) 68164190Sjkoshy return (NULL); 69164190Sjkoshy 70164190Sjkoshy if (index >= eh32->e_phnum) { 71164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 72164190Sjkoshy return (NULL); 73164190Sjkoshy } 74164190Sjkoshy 75164190Sjkoshy ep32 += index; 76164190Sjkoshy 77164190Sjkoshy d->p_type = ep32->p_type; 78164190Sjkoshy d->p_offset = ep32->p_offset; 79164190Sjkoshy d->p_vaddr = (Elf64_Addr) ep32->p_vaddr; 80164190Sjkoshy d->p_paddr = (Elf64_Addr) ep32->p_paddr; 81164190Sjkoshy d->p_filesz = (Elf64_Xword) ep32->p_filesz; 82164190Sjkoshy d->p_memsz = (Elf64_Xword) ep32->p_memsz; 83164190Sjkoshy d->p_flags = ep32->p_flags; 84164190Sjkoshy d->p_align = (Elf64_Xword) ep32->p_align; 85164190Sjkoshy 86164190Sjkoshy } else { 87164190Sjkoshy if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL || 88164190Sjkoshy (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL) 89164190Sjkoshy return (NULL); 90164190Sjkoshy 91164190Sjkoshy if (index >= eh64->e_phnum) { 92164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 93164190Sjkoshy return (NULL); 94164190Sjkoshy } 95164190Sjkoshy 96164190Sjkoshy ep64 += index; 97164190Sjkoshy 98164190Sjkoshy *d = *ep64; 99164190Sjkoshy } 100164190Sjkoshy 101164190Sjkoshy return (d); 102164190Sjkoshy} 103164190Sjkoshy 104164190SjkoshyElf32_Phdr * 105164190Sjkoshyelf32_newphdr(Elf *e, size_t count) 106164190Sjkoshy{ 107164190Sjkoshy return (_libelf_newphdr(e, ELFCLASS32, count)); 108164190Sjkoshy} 109164190Sjkoshy 110164190SjkoshyElf64_Phdr * 111164190Sjkoshyelf64_newphdr(Elf *e, size_t count) 112164190Sjkoshy{ 113164190Sjkoshy return (_libelf_newphdr(e, ELFCLASS64, count)); 114164190Sjkoshy} 115164190Sjkoshy 116164190Sjkoshyvoid * 117164190Sjkoshygelf_newphdr(Elf *e, size_t count) 118164190Sjkoshy{ 119164190Sjkoshy if (e == NULL) { 120164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 121164190Sjkoshy return (NULL); 122164190Sjkoshy } 123164190Sjkoshy return (_libelf_newphdr(e, e->e_class, count)); 124164190Sjkoshy} 125164190Sjkoshy 126164190Sjkoshyint 127164190Sjkoshygelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s) 128164190Sjkoshy{ 129164190Sjkoshy int ec, phnum; 130164190Sjkoshy void *ehdr; 131164190Sjkoshy Elf32_Phdr *ph32; 132164190Sjkoshy Elf64_Phdr *ph64; 133164190Sjkoshy 134164190Sjkoshy if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF || 135164190Sjkoshy ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { 136164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 137164190Sjkoshy return (0); 138164190Sjkoshy } 139164190Sjkoshy 140164190Sjkoshy if (e->e_cmd == ELF_C_READ) { 141164190Sjkoshy LIBELF_SET_ERROR(MODE, 0); 142164190Sjkoshy return (0); 143164190Sjkoshy } 144164190Sjkoshy 145164190Sjkoshy if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) 146164190Sjkoshy return (0); 147164190Sjkoshy 148164190Sjkoshy if (ec == ELFCLASS32) 149164190Sjkoshy phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; 150164190Sjkoshy else 151164190Sjkoshy phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; 152164190Sjkoshy 153164190Sjkoshy if (ndx < 0 || ndx > phnum) { 154164190Sjkoshy LIBELF_SET_ERROR(ARGUMENT, 0); 155164190Sjkoshy return (0); 156164190Sjkoshy } 157164190Sjkoshy 158210325Skaiw (void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); 159210325Skaiw 160164190Sjkoshy if (ec == ELFCLASS64) { 161164190Sjkoshy ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx; 162164190Sjkoshy *ph64 = *s; 163164190Sjkoshy return (1); 164164190Sjkoshy } 165164190Sjkoshy 166164190Sjkoshy ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx; 167164190Sjkoshy 168164190Sjkoshy ph32->p_type = s->p_type; 169164190Sjkoshy ph32->p_flags = s->p_flags; 170164190Sjkoshy LIBELF_COPY_U32(ph32, s, p_offset); 171164190Sjkoshy LIBELF_COPY_U32(ph32, s, p_vaddr); 172164190Sjkoshy LIBELF_COPY_U32(ph32, s, p_paddr); 173164190Sjkoshy LIBELF_COPY_U32(ph32, s, p_filesz); 174164190Sjkoshy LIBELF_COPY_U32(ph32, s, p_memsz); 175164190Sjkoshy LIBELF_COPY_U32(ph32, s, p_align); 176164190Sjkoshy 177164190Sjkoshy return (1); 178164190Sjkoshy} 179