1 /* $NetBSD: gelf_phdr.c,v 1.3 2016/02/20 02:43:42 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2006,2008 Joseph Koshy 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <gelf.h> 30 #include <libelf.h> 31 #include <limits.h> 32 #include <stdint.h> 33 34 #include "_libelf.h" 35 36 __RCSID("$NetBSD: gelf_phdr.c,v 1.3 2016/02/20 02:43:42 christos Exp $"); 37 ELFTC_VCSID("Id: gelf_phdr.c 3177 2015-03-30 18:19:41Z emaste "); 38 39 Elf32_Phdr * 40 elf32_getphdr(Elf *e) 41 { 42 return (_libelf_getphdr(e, ELFCLASS32)); 43 } 44 45 Elf64_Phdr * 46 elf64_getphdr(Elf *e) 47 { 48 return (_libelf_getphdr(e, ELFCLASS64)); 49 } 50 51 GElf_Phdr * 52 gelf_getphdr(Elf *e, int index, GElf_Phdr *d) 53 { 54 int ec; 55 Elf32_Ehdr *eh32; 56 Elf64_Ehdr *eh64; 57 Elf32_Phdr *ep32; 58 Elf64_Phdr *ep64; 59 60 if (d == NULL || e == NULL || 61 ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || 62 (e->e_kind != ELF_K_ELF) || index < 0) { 63 LIBELF_SET_ERROR(ARGUMENT, 0); 64 return (NULL); 65 } 66 67 if (ec == ELFCLASS32) { 68 if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL || 69 ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL)) 70 return (NULL); 71 72 if (index >= eh32->e_phnum) { 73 LIBELF_SET_ERROR(ARGUMENT, 0); 74 return (NULL); 75 } 76 77 ep32 += index; 78 79 d->p_type = ep32->p_type; 80 d->p_offset = ep32->p_offset; 81 d->p_vaddr = (Elf64_Addr) ep32->p_vaddr; 82 d->p_paddr = (Elf64_Addr) ep32->p_paddr; 83 d->p_filesz = (Elf64_Xword) ep32->p_filesz; 84 d->p_memsz = (Elf64_Xword) ep32->p_memsz; 85 d->p_flags = ep32->p_flags; 86 d->p_align = (Elf64_Xword) ep32->p_align; 87 88 } else { 89 if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL || 90 (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL) 91 return (NULL); 92 93 if (index >= eh64->e_phnum) { 94 LIBELF_SET_ERROR(ARGUMENT, 0); 95 return (NULL); 96 } 97 98 ep64 += index; 99 100 *d = *ep64; 101 } 102 103 return (d); 104 } 105 106 Elf32_Phdr * 107 elf32_newphdr(Elf *e, size_t count) 108 { 109 return (_libelf_newphdr(e, ELFCLASS32, count)); 110 } 111 112 Elf64_Phdr * 113 elf64_newphdr(Elf *e, size_t count) 114 { 115 return (_libelf_newphdr(e, ELFCLASS64, count)); 116 } 117 118 void * 119 gelf_newphdr(Elf *e, size_t count) 120 { 121 if (e == NULL) { 122 LIBELF_SET_ERROR(ARGUMENT, 0); 123 return (NULL); 124 } 125 return (_libelf_newphdr(e, e->e_class, count)); 126 } 127 128 int 129 gelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s) 130 { 131 int ec, phnum; 132 void *ehdr; 133 Elf32_Phdr *ph32; 134 Elf64_Phdr *ph64; 135 136 if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF || 137 ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { 138 LIBELF_SET_ERROR(ARGUMENT, 0); 139 return (0); 140 } 141 142 if (e->e_cmd == ELF_C_READ) { 143 LIBELF_SET_ERROR(MODE, 0); 144 return (0); 145 } 146 147 if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) 148 return (0); 149 150 if (ec == ELFCLASS32) 151 phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; 152 else 153 phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; 154 155 if (ndx < 0 || ndx > phnum) { 156 LIBELF_SET_ERROR(ARGUMENT, 0); 157 return (0); 158 } 159 160 (void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); 161 162 if (ec == ELFCLASS64) { 163 ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx; 164 *ph64 = *s; 165 return (1); 166 } 167 168 ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx; 169 170 ph32->p_type = s->p_type; 171 ph32->p_flags = s->p_flags; 172 LIBELF_COPY_U32(ph32, s, p_offset); 173 LIBELF_COPY_U32(ph32, s, p_vaddr); 174 LIBELF_COPY_U32(ph32, s, p_paddr); 175 LIBELF_COPY_U32(ph32, s, p_filesz); 176 LIBELF_COPY_U32(ph32, s, p_memsz); 177 LIBELF_COPY_U32(ph32, s, p_align); 178 179 return (1); 180 } 181