Line data Source code
1 : /* Get ELF program header table.
2 : Copyright (C) 1998-2010, 2014, 2015 Red Hat, Inc.
3 : This file is part of elfutils.
4 : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5 :
6 : This file is free software; you can redistribute it and/or modify
7 : it under the terms of either
8 :
9 : * 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
22 : 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.
25 :
26 : 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/>. */
29 :
30 : #ifdef HAVE_CONFIG_H
31 : # include <config.h>
32 : #endif
33 :
34 : #include <errno.h>
35 : #include <stdbool.h>
36 : #include <stdlib.h>
37 : #include <unistd.h>
38 : #include <assert.h>
39 :
40 : #include <system.h>
41 : #include "libelfP.h"
42 : #include "common.h"
43 :
44 : #ifndef LIBELFBITS
45 : # define LIBELFBITS 32
46 : #endif
47 :
48 : ElfW2(LIBELFBITS,Phdr) *
49 6323 : __elfw2(LIBELFBITS,getphdr_wrlock) (Elf *elf)
50 : {
51 : ElfW2(LIBELFBITS,Phdr) *result;
52 :
53 : /* If the program header entry has already been filled in the code
54 : below must already have been run. So the class is set, too. No
55 : need to waste any more time here. */
56 6323 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
57 6323 : if (likely (result != NULL))
58 : return result;
59 :
60 6323 : if (elf->class == 0)
61 0 : elf->class = ELFW(ELFCLASS,LIBELFBITS);
62 6323 : else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
63 : {
64 0 : __libelf_seterrno (ELF_E_INVALID_CLASS);
65 0 : result = NULL;
66 0 : goto out;
67 : }
68 :
69 6323 : if (likely (result == NULL))
70 : {
71 : /* Read the section header table. */
72 6323 : ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
73 :
74 : /* If no program header exists return NULL. */
75 : size_t phnum;
76 6323 : if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
77 : goto out;
78 6323 : if (phnum == 0 || ehdr->e_phoff == 0)
79 : {
80 229 : __libelf_seterrno (ELF_E_NO_PHDR);
81 229 : goto out;
82 : }
83 :
84 : /* Check this doesn't overflow. */
85 6094 : size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
86 :
87 6094 : if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))
88 6094 : || ehdr->e_phoff > elf->maximum_size
89 6094 : || elf->maximum_size - ehdr->e_phoff < size)
90 : {
91 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
92 0 : goto out;
93 : }
94 :
95 6094 : if (elf->map_address != NULL)
96 : {
97 : /* First see whether the information in the ELF header is
98 : valid and it does not ask for too much. */
99 5833 : if (unlikely (ehdr->e_phoff >= elf->maximum_size)
100 : || unlikely (elf->maximum_size - ehdr->e_phoff < size))
101 : {
102 : /* Something is wrong. */
103 0 : __libelf_seterrno (ELF_E_INVALID_PHDR);
104 0 : goto out;
105 : }
106 :
107 : /* All the data is already mapped. Use it. */
108 5833 : void *file_phdr = ((char *) elf->map_address
109 5833 : + elf->start_offset + ehdr->e_phoff);
110 5833 : if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
111 : && (ALLOW_UNALIGNED
112 : || ((uintptr_t) file_phdr
113 : & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
114 : /* Simply use the mapped data. */
115 5642 : elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
116 : else
117 : {
118 : ElfW2(LIBELFBITS,Phdr) *notcvt;
119 : ElfW2(LIBELFBITS,Phdr) *phdr;
120 :
121 : /* Allocate memory for the program headers. We know the number
122 : of entries from the ELF header. */
123 191 : phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
124 191 : (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
125 191 : if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
126 : {
127 0 : __libelf_seterrno (ELF_E_NOMEM);
128 0 : goto out;
129 : }
130 191 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
131 : ELF_F_MALLOCED | ELF_F_DIRTY;
132 :
133 : /* Now copy the data and at the same time convert the
134 : byte order. */
135 :
136 191 : if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
137 : {
138 0 : assert (! ALLOW_UNALIGNED);
139 : memcpy (phdr, file_phdr, size);
140 : }
141 : else
142 : {
143 : bool copy = ! (ALLOW_UNALIGNED
144 : || ((uintptr_t) file_phdr
145 : & (__alignof__ (ElfW2(LIBELFBITS,Phdr))
146 : - 1)) == 0);
147 : if (! copy)
148 : notcvt = file_phdr;
149 : else
150 : {
151 : notcvt = (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
152 : if (unlikely (notcvt == NULL))
153 : {
154 : __libelf_seterrno (ELF_E_NOMEM);
155 : goto out;
156 : }
157 : memcpy (notcvt, file_phdr, size);
158 : }
159 :
160 1107 : for (size_t cnt = 0; cnt < phnum; ++cnt)
161 : {
162 2214 : CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
163 2214 : CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
164 2214 : CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
165 2214 : CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
166 2214 : CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
167 2214 : CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
168 2214 : CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
169 2214 : CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
170 : }
171 :
172 : if (copy)
173 : free (notcvt);
174 : }
175 : }
176 : }
177 261 : else if (likely (elf->fildes != -1))
178 : {
179 : /* Allocate memory for the program headers. We know the number
180 : of entries from the ELF header. */
181 261 : elf->state.ELFW(elf,LIBELFBITS).phdr =
182 261 : (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
183 261 : if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
184 : {
185 0 : __libelf_seterrno (ELF_E_NOMEM);
186 0 : goto out;
187 : }
188 261 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
189 :
190 : /* Read the header. */
191 261 : ssize_t n = pread_retry (elf->fildes,
192 : elf->state.ELFW(elf,LIBELFBITS).phdr, size,
193 261 : elf->start_offset + ehdr->e_phoff);
194 261 : if (unlikely ((size_t) n != size))
195 : {
196 : /* Severe problems. We cannot read the data. */
197 0 : __libelf_seterrno (ELF_E_READ_ERROR);
198 0 : free (elf->state.ELFW(elf,LIBELFBITS).phdr);
199 0 : elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
200 0 : goto out;
201 : }
202 :
203 : /* If the byte order of the file is not the same as the one
204 : of the host convert the data now. */
205 261 : if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
206 : {
207 91 : ElfW2(LIBELFBITS,Phdr) *phdr
208 : = elf->state.ELFW(elf,LIBELFBITS).phdr;
209 :
210 508 : for (size_t cnt = 0; cnt < phnum; ++cnt)
211 : {
212 834 : CONVERT (phdr[cnt].p_type);
213 834 : CONVERT (phdr[cnt].p_offset);
214 834 : CONVERT (phdr[cnt].p_vaddr);
215 834 : CONVERT (phdr[cnt].p_paddr);
216 834 : CONVERT (phdr[cnt].p_filesz);
217 834 : CONVERT (phdr[cnt].p_memsz);
218 834 : CONVERT (phdr[cnt].p_flags);
219 834 : CONVERT (phdr[cnt].p_align);
220 : }
221 : }
222 : }
223 : else
224 : {
225 : /* The file descriptor was already enabled and not all data was
226 : read. */
227 0 : __libelf_seterrno (ELF_E_FD_DISABLED);
228 0 : goto out;
229 : }
230 :
231 6094 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
232 : }
233 :
234 0 : out:
235 : return result;
236 : }
237 :
238 : ElfW2(LIBELFBITS,Phdr) *
239 6076 : elfw2(LIBELFBITS,getphdr) (Elf *elf)
240 : {
241 : ElfW2(LIBELFBITS,Phdr) *result;
242 :
243 6076 : if (elf == NULL)
244 : return NULL;
245 :
246 6076 : if (unlikely (elf->kind != ELF_K_ELF))
247 : {
248 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
249 0 : return NULL;
250 : }
251 :
252 : /* If the program header entry has already been filled in the code
253 : * in getphdr_wrlock must already have been run. So the class is
254 : * set, too. No need to waste any more time here. */
255 6076 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
256 6076 : if (likely (result != NULL))
257 : return result;
258 :
259 : rwlock_wrlock (elf->lock);
260 6076 : result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
261 : rwlock_unlock (elf->lock);
262 :
263 6076 : return result;
264 : }
265 : INTDEF(elfw2(LIBELFBITS,getphdr))
|