blob: 25693687782a7cc3340ad498bba9259209a155d2 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Get ELF program header table.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 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
71 /* If no program header exists return NULL. */
72 size_t phnum = ehdr->e_phnum;
73 if (phnum == 0)
74 {
75 __libelf_seterrno (ELF_E_NO_PHDR);
76 goto out;
77 }
78
79 size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
80
81 if (elf->map_address != NULL)
82 {
83 /* All the data is already mapped. Use it. */
84 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
85 && (ALLOW_UNALIGNED
86 || (ehdr->e_phoff
87 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
88 /* Simply use the mapped data. */
89 elf->state.ELFW(elf,LIBELFBITS).phdr = (ElfW2(LIBELFBITS,Phdr) *)
90 ((char *) elf->map_address + elf->start_offset + ehdr->e_phoff);
91 else
92 {
93 ElfW2(LIBELFBITS,Phdr) *notcvt;
94 ElfW2(LIBELFBITS,Phdr) *phdr;
95
96 /* Allocate memory for the program headers. We know the number
97 of entries from the ELF header. */
98 phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
99 (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
100 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
101 {
102 __libelf_seterrno (ELF_E_NOMEM);
103 goto out;
104 }
105 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
106 ELF_F_MALLOCED | ELF_F_DIRTY;
107
108 /* Now copy the data and at the same time convert the
109 byte order. */
110 if (ALLOW_UNALIGNED
111 || (ehdr->e_phoff
112 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)
113 notcvt = (ElfW2(LIBELFBITS,Phdr) *)
114 ((char *) elf->map_address
115 + elf->start_offset + ehdr->e_phoff);
116 else
117 {
118 notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size);
119 memcpy (notcvt, ((char *) elf->map_address +
120 elf->start_offset + ehdr->e_phoff),
121 size);
122 }
123
124 for (size_t cnt = 0; cnt < phnum; ++cnt)
125 {
126 CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
127 CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
128 CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
129 CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
130 CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
131 CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
132 CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
133 CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
134 }
135 }
136 }
137 else if (likely (elf->fildes != -1))
138 {
139 /* Allocate memory for the program headers. We know the number
140 of entries from the ELF header. */
141 elf->state.ELFW(elf,LIBELFBITS).phdr =
142 (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
143 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
144 {
145 __libelf_seterrno (ELF_E_NOMEM);
146 goto out;
147 }
148 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
149
150 /* Read the header. */
151 if ((size_t) pread (elf->fildes,
152 elf->state.ELFW(elf,LIBELFBITS).phdr, size,
153 (elf->start_offset + ehdr->e_phoff)) != size)
154 {
155 /* Severe problems. We cannot read the data. */
156 __libelf_seterrno (ELF_E_READ_ERROR);
157 free (elf->state.ELFW(elf,LIBELFBITS).phdr);
158 elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
159 goto out;
160 }
161
162 /* If the byte order of the file is not the same as the one
163 of the host convert the data now. */
164 if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
165 {
166 ElfW2(LIBELFBITS,Phdr) *phdr
167 = elf->state.ELFW(elf,LIBELFBITS).phdr;
168
169 for (size_t cnt = 0; cnt < phnum; ++cnt)
170 {
171 CONVERT (phdr[cnt].p_type);
172 CONVERT (phdr[cnt].p_offset);
173 CONVERT (phdr[cnt].p_vaddr);
174 CONVERT (phdr[cnt].p_paddr);
175 CONVERT (phdr[cnt].p_filesz);
176 CONVERT (phdr[cnt].p_memsz);
177 CONVERT (phdr[cnt].p_flags);
178 CONVERT (phdr[cnt].p_align);
179 }
180 }
181 }
182 else
183 {
184 /* The file descriptor was already enabled and not all data was
185 read. */
186 __libelf_seterrno (ELF_E_FD_DISABLED);
187 goto out;
188 }
189
190 result = elf->state.ELFW(elf,LIBELFBITS).phdr;
191 }
192
193 out:
194 rwlock_unlock (elf->lock);
195
196 return result;
197}
198INTDEF(elfw2(LIBELFBITS,getphdr))