1/* Get ELF program header table. 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper@redhat.com>, 1998. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, version 2. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <stdlib.h> 23#include <unistd.h> 24 25#include "libelfP.h" 26#include "common.h" 27 28#ifndef LIBELFBITS 29# define LIBELFBITS 32 30#endif 31 32 33ElfW2(LIBELFBITS,Phdr) * 34elfw2(LIBELFBITS,getphdr) (elf) 35 Elf *elf; 36{ 37 ElfW2(LIBELFBITS,Phdr) *result; 38 39 if (elf == NULL) 40 return NULL; 41 42 if (unlikely (elf->kind != ELF_K_ELF)) 43 { 44 __libelf_seterrno (ELF_E_INVALID_HANDLE); 45 return NULL; 46 } 47 48 /* If the program header entry has already been filled in the code 49 below must already have been run. So the class is set, too. No 50 need to waste any more time here. */ 51 result = elf->state.ELFW(elf,LIBELFBITS).phdr; 52 if (likely (result != NULL)) 53 return result; 54 55 rwlock_wrlock (elf->lock); 56 57 if (elf->class == 0) 58 elf->class = ELFW(ELFCLASS,LIBELFBITS); 59 else if (elf->class != ELFW(ELFCLASS,LIBELFBITS)) 60 { 61 __libelf_seterrno (ELF_E_INVALID_CLASS); 62 result = NULL; 63 goto out; 64 } 65 66 if (likely (result == NULL)) 67 { 68 /* Read the section header table. */ 69 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr; 70 size_t phnum; 71 size_t size; 72 73 /* If no program header exists return NULL. */ 74 phnum = ehdr->e_phnum; 75 if (phnum == 0) 76 { 77 __libelf_seterrno (ELF_E_NO_PHDR); 78 goto out; 79 } 80 81 size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr)); 82 83 if (elf->map_address != NULL) 84 { 85 /* All the data is already mapped. Use it. */ 86 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA 87 && (ALLOW_UNALIGNED 88 || (ehdr->e_phoff 89 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)) 90 /* Simply use the mapped data. */ 91 elf->state.ELFW(elf,LIBELFBITS).phdr = (ElfW2(LIBELFBITS,Phdr) *) 92 ((char *) elf->map_address + elf->start_offset + ehdr->e_phoff); 93 else 94 { 95 size_t cnt; 96 ElfW2(LIBELFBITS,Phdr) *notcvt; 97 ElfW2(LIBELFBITS,Phdr) *phdr; 98 99 /* Allocate memory for the program headers. We know the number 100 of entries from the ELF header. */ 101 phdr = elf->state.ELFW(elf,LIBELFBITS).phdr = 102 (ElfW2(LIBELFBITS,Phdr) *) malloc (size); 103 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) 104 { 105 __libelf_seterrno (ELF_E_NOMEM); 106 goto out; 107 } 108 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= 109 ELF_F_MALLOCED | ELF_F_DIRTY; 110 111 /* Now copy the data and at the same time convert the 112 byte order. */ 113 if (ALLOW_UNALIGNED 114 || (ehdr->e_phoff 115 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0) 116 notcvt = (ElfW2(LIBELFBITS,Phdr) *) 117 ((char *) elf->map_address 118 + elf->start_offset + ehdr->e_phoff); 119 else 120 { 121 notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size); 122 memcpy (notcvt, ((char *) elf->map_address + 123 elf->start_offset + ehdr->e_phoff), 124 size); 125 } 126 127 for (cnt = 0; cnt < phnum; ++cnt) 128 { 129 CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type); 130 CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset); 131 CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr); 132 CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr); 133 CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz); 134 CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz); 135 CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags); 136 CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align); 137 } 138 } 139 } 140 else if (likely (elf->fildes != -1)) 141 { 142 /* Allocate memory for the program headers. We know the number 143 of entries from the ELF header. */ 144 elf->state.ELFW(elf,LIBELFBITS).phdr = 145 (ElfW2(LIBELFBITS,Phdr) *) malloc (size); 146 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) 147 { 148 __libelf_seterrno (ELF_E_NOMEM); 149 goto out; 150 } 151 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED; 152 153 /* Read the header. */ 154 if ((size_t) pread (elf->fildes, 155 elf->state.ELFW(elf,LIBELFBITS).phdr, size, 156 (elf->start_offset + ehdr->e_phoff)) != size) 157 { 158 /* Severe problems. We cannot read the data. */ 159 __libelf_seterrno (ELF_E_READ_ERROR); 160 free (elf->state.ELFW(elf,LIBELFBITS).phdr); 161 elf->state.ELFW(elf,LIBELFBITS).phdr = NULL; 162 goto out; 163 } 164 165 /* If the byte order of the file is not the same as the one 166 of the host convert the data now. */ 167 if (ehdr->e_ident[EI_DATA] != MY_ELFDATA) 168 { 169 ElfW2(LIBELFBITS,Phdr) *phdr; 170 size_t cnt; 171 172 phdr = elf->state.ELFW(elf,LIBELFBITS).phdr; 173 for (cnt = 0; cnt < phnum; ++cnt) 174 { 175 CONVERT (phdr[cnt].p_type); 176 CONVERT (phdr[cnt].p_offset); 177 CONVERT (phdr[cnt].p_vaddr); 178 CONVERT (phdr[cnt].p_paddr); 179 CONVERT (phdr[cnt].p_filesz); 180 CONVERT (phdr[cnt].p_memsz); 181 CONVERT (phdr[cnt].p_flags); 182 CONVERT (phdr[cnt].p_align); 183 } 184 } 185 } 186 else 187 { 188 /* The file descriptor was already enabled and not all data was 189 read. */ 190 __libelf_seterrno (ELF_E_FD_DISABLED); 191 goto out; 192 } 193 194 result = elf->state.ELFW(elf,LIBELFBITS).phdr; 195 } 196 197 out: 198 rwlock_unlock (elf->lock); 199 200 return result; 201} 202INTDEF(elfw2(LIBELFBITS,getphdr)) 203