1 /* Get ELF program header table. 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 Red Hat, Inc. 3 This file is part of Red Hat elfutils. 4 Written by Ulrich Drepper <drepper@redhat.com>, 1998. 5 6 Red Hat elfutils is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by the 8 Free Software Foundation; version 2 of the License. 9 10 Red Hat elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with Red Hat elfutils; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 18 19 In addition, as a special exception, Red Hat, Inc. gives You the 20 additional right to link the code of Red Hat elfutils with code licensed 21 under any Open Source Initiative certified open source license 22 (http://www.opensource.org/licenses/index.php) which requires the 23 distribution of source code with any binary distribution and to 24 distribute linked combinations of the two. Non-GPL Code permitted under 25 this exception must only link to the code of Red Hat elfutils through 26 those well defined interfaces identified in the file named EXCEPTION 27 found in the source code files (the "Approved Interfaces"). The files 28 of Non-GPL Code may instantiate templates or use macros or inline 29 functions from the Approved Interfaces without causing the resulting 30 work to be covered by the GNU General Public License. Only Red Hat, 31 Inc. may make changes or additions to the list of Approved Interfaces. 32 Red Hat's grant of this exception is conditioned upon your not adding 33 any new exceptions. If you wish to add a new Approved Interface or 34 exception, please contact Red Hat. You must obey the GNU General Public 35 License in all respects for all of the Red Hat elfutils code and other 36 code used in conjunction with Red Hat elfutils except the Non-GPL Code 37 covered by this exception. If you modify this file, you may extend this 38 exception to your version of the file, but you are not obligated to do 39 so. If you do not wish to provide this exception without modification, 40 you must delete this exception statement from your version and license 41 this file solely under the GPL without exception. 42 43 Red Hat elfutils is an included package of the Open Invention Network. 44 An included package of the Open Invention Network is a package for which 45 Open Invention Network licensees cross-license their patents. No patent 46 license is granted, either expressly or impliedly, by designation as an 47 included package. Should you wish to participate in the Open Invention 48 Network licensing program, please visit www.openinventionnetwork.com 49 <http://www.openinventionnetwork.com>. */ 50 51 #ifdef HAVE_CONFIG_H 52 # include <config.h> 53 #endif 54 55 #include <errno.h> 56 #include <stdbool.h> 57 #include <stdlib.h> 58 #include <unistd.h> 59 #include <assert.h> 60 61 #include <system.h> 62 #include "libelfP.h" 63 #include "common.h" 64 65 #ifndef LIBELFBITS 66 # define LIBELFBITS 32 67 #endif 68 69 ElfW2(LIBELFBITS,Phdr) * 70 __elfw2(LIBELFBITS,getphdr_wrlock) (elf) 71 Elf *elf; 72 { 73 ElfW2(LIBELFBITS,Phdr) *result; 74 75 /* If the program header entry has already been filled in the code 76 below must already have been run. So the class is set, too. No 77 need to waste any more time here. */ 78 result = elf->state.ELFW(elf,LIBELFBITS).phdr; 79 if (likely (result != NULL)) 80 return result; 81 82 if (elf->class == 0) 83 elf->class = ELFW(ELFCLASS,LIBELFBITS); 84 else if (elf->class != ELFW(ELFCLASS,LIBELFBITS)) 85 { 86 __libelf_seterrno (ELF_E_INVALID_CLASS); 87 result = NULL; 88 goto out; 89 } 90 91 if (likely (result == NULL)) 92 { 93 /* Read the section header table. */ 94 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr; 95 96 /* If no program header exists return NULL. */ 97 size_t phnum = ehdr->e_phnum; 98 if (phnum == 0) 99 { 100 __libelf_seterrno (ELF_E_NO_PHDR); 101 goto out; 102 } 103 104 size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr)); 105 106 if (elf->map_address != NULL) 107 { 108 /* All the data is already mapped. Use it. */ 109 void *file_phdr = ((char *) elf->map_address 110 + elf->start_offset + ehdr->e_phoff); 111 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA 112 && (ALLOW_UNALIGNED 113 || ((uintptr_t) file_phdr 114 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)) 115 /* Simply use the mapped data. */ 116 elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr; 117 else 118 { 119 ElfW2(LIBELFBITS,Phdr) *notcvt; 120 ElfW2(LIBELFBITS,Phdr) *phdr; 121 122 /* Allocate memory for the program headers. We know the number 123 of entries from the ELF header. */ 124 phdr = elf->state.ELFW(elf,LIBELFBITS).phdr = 125 (ElfW2(LIBELFBITS,Phdr) *) malloc (size); 126 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) 127 { 128 __libelf_seterrno (ELF_E_NOMEM); 129 goto out; 130 } 131 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= 132 ELF_F_MALLOCED | ELF_F_DIRTY; 133 134 /* Now copy the data and at the same time convert the 135 byte order. */ 136 137 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA) 138 { 139 assert (! ALLOW_UNALIGNED); 140 memcpy (phdr, file_phdr, size); 141 } 142 else 143 { 144 if (ALLOW_UNALIGNED 145 || ((uintptr_t) file_phdr 146 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0) 147 notcvt = file_phdr; 148 else 149 { 150 notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size); 151 memcpy (notcvt, file_phdr, size); 152 } 153 154 for (size_t cnt = 0; cnt < phnum; ++cnt) 155 { 156 CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type); 157 CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset); 158 CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr); 159 CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr); 160 CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz); 161 CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz); 162 CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags); 163 CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align); 164 } 165 } 166 } 167 } 168 else if (likely (elf->fildes != -1)) 169 { 170 /* Allocate memory for the program headers. We know the number 171 of entries from the ELF header. */ 172 elf->state.ELFW(elf,LIBELFBITS).phdr = 173 (ElfW2(LIBELFBITS,Phdr) *) malloc (size); 174 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) 175 { 176 __libelf_seterrno (ELF_E_NOMEM); 177 goto out; 178 } 179 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED; 180 181 /* Read the header. */ 182 ssize_t n = pread_retry (elf->fildes, 183 elf->state.ELFW(elf,LIBELFBITS).phdr, size, 184 elf->start_offset + ehdr->e_phoff); 185 if (unlikely ((size_t) n != size)) 186 { 187 /* Severe problems. We cannot read the data. */ 188 __libelf_seterrno (ELF_E_READ_ERROR); 189 free (elf->state.ELFW(elf,LIBELFBITS).phdr); 190 elf->state.ELFW(elf,LIBELFBITS).phdr = NULL; 191 goto out; 192 } 193 194 /* If the byte order of the file is not the same as the one 195 of the host convert the data now. */ 196 if (ehdr->e_ident[EI_DATA] != MY_ELFDATA) 197 { 198 ElfW2(LIBELFBITS,Phdr) *phdr 199 = elf->state.ELFW(elf,LIBELFBITS).phdr; 200 201 for (size_t cnt = 0; cnt < phnum; ++cnt) 202 { 203 CONVERT (phdr[cnt].p_type); 204 CONVERT (phdr[cnt].p_offset); 205 CONVERT (phdr[cnt].p_vaddr); 206 CONVERT (phdr[cnt].p_paddr); 207 CONVERT (phdr[cnt].p_filesz); 208 CONVERT (phdr[cnt].p_memsz); 209 CONVERT (phdr[cnt].p_flags); 210 CONVERT (phdr[cnt].p_align); 211 } 212 } 213 } 214 else 215 { 216 /* The file descriptor was already enabled and not all data was 217 read. */ 218 __libelf_seterrno (ELF_E_FD_DISABLED); 219 goto out; 220 } 221 222 result = elf->state.ELFW(elf,LIBELFBITS).phdr; 223 } 224 225 out: 226 return result; 227 } 228 229 ElfW2(LIBELFBITS,Phdr) * 230 elfw2(LIBELFBITS,getphdr) (elf) 231 Elf *elf; 232 { ElfW2(LIBELFBITS,Phdr)233 ElfW2(LIBELFBITS,Phdr) *result; 234 235 if (elf == NULL) 236 return NULL; 237 238 if (unlikely (elf->kind != ELF_K_ELF)) 239 { 240 __libelf_seterrno (ELF_E_INVALID_HANDLE); 241 return NULL; 242 } 243 244 /* If the program header entry has already been filled in the code 245 * in getphdr_wrlock must already have been run. So the class is 246 * set, too. No need to waste any more time here. */ 247 result = elf->state.ELFW(elf,LIBELFBITS).phdr; 248 if (likely (result != NULL)) 249 return result; 250 251 rwlock_wrlock (elf->lock); 252 result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf); 253 rwlock_unlock (elf->lock); 254 255 return result; 256 } 257 INTDEF(elfw2(LIBELFBITS,getphdr)) 258