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