blob: a47c9f7afd5b0d66f0e8ec4836f8e8a06104857d [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Get ELF program header table.
Roland McGrath6fd3cd12010-01-07 19:41:04 -08002 Copyright (C) 1998-2010 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008
Mark Wielaardde2ed972012-06-05 17:15:16 +02009 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
12
13 or
14
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
18
19 or both in parallel, as here.
20
21 elfutils is distributed in the hope that it will be useful, but
Ulrich Drepper361df7d2006-04-04 21:38:57 +000022 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000025
Mark Wielaardde2ed972012-06-05 17:15:16 +020026 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000029
30#ifdef HAVE_CONFIG_H
31# include <config.h>
32#endif
33
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000034#include <errno.h>
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000035#include <stdbool.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000036#include <stdlib.h>
37#include <unistd.h>
Roland McGrathc373d852006-10-10 00:25:21 +000038#include <assert.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000039
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000040#include <system.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000041#include "libelfP.h"
42#include "common.h"
43
44#ifndef LIBELFBITS
45# define LIBELFBITS 32
46#endif
47
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000048ElfW2(LIBELFBITS,Phdr) *
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000049__elfw2(LIBELFBITS,getphdr_wrlock) (elf)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000050 Elf *elf;
51{
52 ElfW2(LIBELFBITS,Phdr) *result;
53
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000054 /* If the program header entry has already been filled in the code
55 below must already have been run. So the class is set, too. No
56 need to waste any more time here. */
57 result = elf->state.ELFW(elf,LIBELFBITS).phdr;
58 if (likely (result != NULL))
59 return result;
60
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000061 if (elf->class == 0)
62 elf->class = ELFW(ELFCLASS,LIBELFBITS);
63 else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
64 {
65 __libelf_seterrno (ELF_E_INVALID_CLASS);
66 result = NULL;
67 goto out;
68 }
69
70 if (likely (result == NULL))
71 {
72 /* Read the section header table. */
73 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
74
75 /* If no program header exists return NULL. */
Roland McGrath6fd3cd12010-01-07 19:41:04 -080076 size_t phnum;
77 if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
78 goto out;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000079 if (phnum == 0)
80 {
81 __libelf_seterrno (ELF_E_NO_PHDR);
82 goto out;
83 }
84
85 size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
86
Roland McGrath9d81c7d2010-04-14 11:37:06 -070087 if (ehdr->e_phoff > elf->maximum_size
Roland McGrath957072c2010-04-14 11:24:15 -070088 || elf->maximum_size - ehdr->e_phoff < size)
89 {
90 __libelf_seterrno (ELF_E_INVALID_DATA);
91 goto out;
92 }
93
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000094 if (elf->map_address != NULL)
95 {
96 /* All the data is already mapped. Use it. */
Roland McGrathc373d852006-10-10 00:25:21 +000097 void *file_phdr = ((char *) elf->map_address
98 + elf->start_offset + ehdr->e_phoff);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000099 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
100 && (ALLOW_UNALIGNED
Roland McGrathc373d852006-10-10 00:25:21 +0000101 || ((uintptr_t) file_phdr
102 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000103 /* Simply use the mapped data. */
Roland McGrathc373d852006-10-10 00:25:21 +0000104 elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000105 else
106 {
107 ElfW2(LIBELFBITS,Phdr) *notcvt;
108 ElfW2(LIBELFBITS,Phdr) *phdr;
109
110 /* Allocate memory for the program headers. We know the number
111 of entries from the ELF header. */
112 phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
113 (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
114 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
115 {
116 __libelf_seterrno (ELF_E_NOMEM);
117 goto out;
118 }
119 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
120 ELF_F_MALLOCED | ELF_F_DIRTY;
121
122 /* Now copy the data and at the same time convert the
123 byte order. */
Roland McGrathc373d852006-10-10 00:25:21 +0000124
125 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
126 {
127 assert (! ALLOW_UNALIGNED);
128 memcpy (phdr, file_phdr, size);
129 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000130 else
131 {
Roland McGrathc373d852006-10-10 00:25:21 +0000132 if (ALLOW_UNALIGNED
133 || ((uintptr_t) file_phdr
134 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)
135 notcvt = file_phdr;
136 else
137 {
138 notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size);
139 memcpy (notcvt, file_phdr, size);
140 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000141
Roland McGrathc373d852006-10-10 00:25:21 +0000142 for (size_t cnt = 0; cnt < phnum; ++cnt)
143 {
144 CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
145 CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
146 CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
147 CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
148 CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
149 CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
150 CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
151 CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
152 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000153 }
154 }
155 }
156 else if (likely (elf->fildes != -1))
157 {
158 /* Allocate memory for the program headers. We know the number
159 of entries from the ELF header. */
160 elf->state.ELFW(elf,LIBELFBITS).phdr =
161 (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
162 if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
163 {
164 __libelf_seterrno (ELF_E_NOMEM);
165 goto out;
166 }
167 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
168
169 /* Read the header. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000170 ssize_t n = pread_retry (elf->fildes,
171 elf->state.ELFW(elf,LIBELFBITS).phdr, size,
172 elf->start_offset + ehdr->e_phoff);
173 if (unlikely ((size_t) n != size))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000174 {
175 /* Severe problems. We cannot read the data. */
176 __libelf_seterrno (ELF_E_READ_ERROR);
177 free (elf->state.ELFW(elf,LIBELFBITS).phdr);
178 elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
179 goto out;
180 }
181
182 /* If the byte order of the file is not the same as the one
183 of the host convert the data now. */
184 if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
185 {
186 ElfW2(LIBELFBITS,Phdr) *phdr
187 = elf->state.ELFW(elf,LIBELFBITS).phdr;
188
189 for (size_t cnt = 0; cnt < phnum; ++cnt)
190 {
191 CONVERT (phdr[cnt].p_type);
192 CONVERT (phdr[cnt].p_offset);
193 CONVERT (phdr[cnt].p_vaddr);
194 CONVERT (phdr[cnt].p_paddr);
195 CONVERT (phdr[cnt].p_filesz);
196 CONVERT (phdr[cnt].p_memsz);
197 CONVERT (phdr[cnt].p_flags);
198 CONVERT (phdr[cnt].p_align);
199 }
200 }
201 }
202 else
203 {
204 /* The file descriptor was already enabled and not all data was
205 read. */
206 __libelf_seterrno (ELF_E_FD_DISABLED);
207 goto out;
208 }
209
210 result = elf->state.ELFW(elf,LIBELFBITS).phdr;
211 }
212
213 out:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000214 return result;
215}
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000216
217ElfW2(LIBELFBITS,Phdr) *
218elfw2(LIBELFBITS,getphdr) (elf)
219 Elf *elf;
220{
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000221 ElfW2(LIBELFBITS,Phdr) *result;
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000222
Roland McGrath122f3882008-08-26 07:20:29 +0000223 if (elf == NULL)
224 return NULL;
225
226 if (unlikely (elf->kind != ELF_K_ELF))
227 {
228 __libelf_seterrno (ELF_E_INVALID_HANDLE);
229 return NULL;
230 }
231
232 /* If the program header entry has already been filled in the code
233 * in getphdr_wrlock must already have been run. So the class is
234 * set, too. No need to waste any more time here. */
235 result = elf->state.ELFW(elf,LIBELFBITS).phdr;
236 if (likely (result != NULL))
237 return result;
238
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000239 rwlock_wrlock (elf->lock);
240 result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
241 rwlock_unlock (elf->lock);
242
243 return result;
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000244}
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000245INTDEF(elfw2(LIBELFBITS,getphdr))