/src/libbpf/elfutils/libelf/elf32_getphdr.c
Line | Count | Source (jump to first uncovered line) |
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 | | __elfw2(LIBELFBITS,getphdr_wrlock) (Elf *elf) |
48 | 0 | { |
49 | 0 | 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 | 0 | result = elf->state.ELFW(elf,LIBELFBITS).phdr; |
55 | 0 | if (likely (result != NULL)) |
56 | 0 | return result; |
57 | | |
58 | 0 | if (elf->class == 0) |
59 | 0 | elf->class = ELFW(ELFCLASS,LIBELFBITS); |
60 | 0 | else if (elf->class != ELFW(ELFCLASS,LIBELFBITS)) |
61 | 0 | { |
62 | 0 | __libelf_seterrno (ELF_E_INVALID_CLASS); |
63 | 0 | result = NULL; |
64 | 0 | goto out; |
65 | 0 | } |
66 | | |
67 | 0 | if (likely (result == NULL)) |
68 | 0 | { |
69 | | /* Read the section header table. */ |
70 | 0 | ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr; |
71 | | |
72 | | /* If no program header exists return NULL. */ |
73 | 0 | size_t phnum; |
74 | 0 | if (__elf_getphdrnum_rdlock (elf, &phnum) != 0) |
75 | 0 | goto out; |
76 | 0 | if (phnum == 0 || ehdr->e_phoff == 0) |
77 | 0 | { |
78 | 0 | __libelf_seterrno (ELF_E_NO_PHDR); |
79 | 0 | goto out; |
80 | 0 | } |
81 | | |
82 | | /* Check this doesn't overflow. */ |
83 | 0 | size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr)); |
84 | |
|
85 | 0 | if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr)) |
86 | 0 | || ehdr->e_phoff > elf->maximum_size |
87 | 0 | || elf->maximum_size - ehdr->e_phoff < size) |
88 | 0 | { |
89 | 0 | __libelf_seterrno (ELF_E_INVALID_DATA); |
90 | 0 | goto out; |
91 | 0 | } |
92 | | |
93 | 0 | if (elf->map_address != NULL) |
94 | 0 | { |
95 | | /* First see whether the information in the ELF header is |
96 | | valid and it does not ask for too much. */ |
97 | 0 | if (unlikely (ehdr->e_phoff >= elf->maximum_size) |
98 | 0 | || unlikely (elf->maximum_size - ehdr->e_phoff < size)) |
99 | 0 | { |
100 | | /* Something is wrong. */ |
101 | 0 | __libelf_seterrno (ELF_E_INVALID_PHDR); |
102 | 0 | goto out; |
103 | 0 | } |
104 | | |
105 | | /* All the data is already mapped. Use it. */ |
106 | 0 | void *file_phdr = ((char *) elf->map_address |
107 | 0 | + elf->start_offset + ehdr->e_phoff); |
108 | 0 | if (ehdr->e_ident[EI_DATA] == MY_ELFDATA |
109 | 0 | && (ALLOW_UNALIGNED |
110 | 0 | || ((uintptr_t) file_phdr |
111 | 0 | & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)) |
112 | | /* Simply use the mapped data. */ |
113 | 0 | elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr; |
114 | 0 | else |
115 | 0 | { |
116 | 0 | ElfW2(LIBELFBITS,Phdr) *notcvt; |
117 | 0 | ElfW2(LIBELFBITS,Phdr) *phdr; |
118 | | |
119 | | /* Allocate memory for the program headers. We know the number |
120 | | of entries from the ELF header. */ |
121 | 0 | phdr = elf->state.ELFW(elf,LIBELFBITS).phdr = |
122 | 0 | (ElfW2(LIBELFBITS,Phdr) *) malloc (size); |
123 | 0 | if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) |
124 | 0 | { |
125 | 0 | __libelf_seterrno (ELF_E_NOMEM); |
126 | 0 | goto out; |
127 | 0 | } |
128 | 0 | elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= |
129 | 0 | ELF_F_MALLOCED | ELF_F_DIRTY; |
130 | | |
131 | | /* Now copy the data and at the same time convert the |
132 | | byte order. */ |
133 | |
|
134 | 0 | if (ehdr->e_ident[EI_DATA] == MY_ELFDATA) |
135 | 0 | { |
136 | 0 | assert (! ALLOW_UNALIGNED); |
137 | 0 | memcpy (phdr, file_phdr, size); |
138 | 0 | } |
139 | 0 | else |
140 | 0 | { |
141 | 0 | bool copy = ! (ALLOW_UNALIGNED |
142 | 0 | || ((uintptr_t) file_phdr |
143 | 0 | & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) |
144 | 0 | - 1)) == 0); |
145 | 0 | if (! copy) |
146 | 0 | notcvt = file_phdr; |
147 | 0 | else |
148 | 0 | { |
149 | 0 | notcvt = (ElfW2(LIBELFBITS,Phdr) *) malloc (size); |
150 | 0 | if (unlikely (notcvt == NULL)) |
151 | 0 | { |
152 | 0 | __libelf_seterrno (ELF_E_NOMEM); |
153 | 0 | goto out; |
154 | 0 | } |
155 | 0 | memcpy (notcvt, file_phdr, size); |
156 | 0 | } |
157 | | |
158 | 0 | for (size_t cnt = 0; cnt < phnum; ++cnt) |
159 | 0 | { |
160 | 0 | CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type); |
161 | 0 | CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset); |
162 | 0 | CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr); |
163 | 0 | CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr); |
164 | 0 | CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz); |
165 | 0 | CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz); |
166 | 0 | CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags); |
167 | 0 | CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align); |
168 | 0 | } |
169 | |
|
170 | 0 | if (copy) |
171 | 0 | free (notcvt); |
172 | 0 | } |
173 | 0 | } |
174 | 0 | } |
175 | 0 | else if (likely (elf->fildes != -1)) |
176 | 0 | { |
177 | | /* Allocate memory for the program headers. We know the number |
178 | | of entries from the ELF header. */ |
179 | 0 | elf->state.ELFW(elf,LIBELFBITS).phdr = |
180 | 0 | (ElfW2(LIBELFBITS,Phdr) *) malloc (size); |
181 | 0 | if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL) |
182 | 0 | { |
183 | 0 | __libelf_seterrno (ELF_E_NOMEM); |
184 | 0 | goto out; |
185 | 0 | } |
186 | 0 | elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED; |
187 | | |
188 | | /* Read the header. */ |
189 | 0 | ssize_t n = pread_retry (elf->fildes, |
190 | 0 | elf->state.ELFW(elf,LIBELFBITS).phdr, size, |
191 | 0 | elf->start_offset + ehdr->e_phoff); |
192 | 0 | if (unlikely ((size_t) n != size)) |
193 | 0 | { |
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 | 0 | } |
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 | 0 | if (ehdr->e_ident[EI_DATA] != MY_ELFDATA) |
204 | 0 | { |
205 | 0 | ElfW2(LIBELFBITS,Phdr) *phdr |
206 | 0 | = elf->state.ELFW(elf,LIBELFBITS).phdr; |
207 | |
|
208 | 0 | for (size_t cnt = 0; cnt < phnum; ++cnt) |
209 | 0 | { |
210 | 0 | CONVERT (phdr[cnt].p_type); |
211 | 0 | CONVERT (phdr[cnt].p_offset); |
212 | 0 | CONVERT (phdr[cnt].p_vaddr); |
213 | 0 | CONVERT (phdr[cnt].p_paddr); |
214 | 0 | CONVERT (phdr[cnt].p_filesz); |
215 | 0 | CONVERT (phdr[cnt].p_memsz); |
216 | 0 | CONVERT (phdr[cnt].p_flags); |
217 | 0 | CONVERT (phdr[cnt].p_align); |
218 | 0 | } |
219 | 0 | } |
220 | 0 | } |
221 | 0 | else |
222 | 0 | { |
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 | 0 | } |
228 | | |
229 | 0 | result = elf->state.ELFW(elf,LIBELFBITS).phdr; |
230 | 0 | } |
231 | | |
232 | 0 | out: |
233 | 0 | return result; |
234 | 0 | } Unexecuted instantiation: __elf32_getphdr_wrlock Unexecuted instantiation: __elf64_getphdr_wrlock |
235 | | |
236 | | ElfW2(LIBELFBITS,Phdr) * |
237 | | elfw2(LIBELFBITS,getphdr) (Elf *elf) |
238 | 0 | { |
239 | 0 | ElfW2(LIBELFBITS,Phdr) *result; |
240 | |
|
241 | 0 | if (elf == NULL) |
242 | 0 | return NULL; |
243 | | |
244 | 0 | if (unlikely (elf->kind != ELF_K_ELF)) |
245 | 0 | { |
246 | 0 | __libelf_seterrno (ELF_E_INVALID_HANDLE); |
247 | 0 | return NULL; |
248 | 0 | } |
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 | 0 | result = elf->state.ELFW(elf,LIBELFBITS).phdr; |
254 | 0 | if (likely (result != NULL)) |
255 | 0 | return result; |
256 | | |
257 | 0 | rwlock_wrlock (elf->lock); |
258 | 0 | result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf); |
259 | 0 | rwlock_unlock (elf->lock); |
260 | |
|
261 | 0 | return result; |
262 | 0 | } Unexecuted instantiation: elf32_getphdr Unexecuted instantiation: elf64_getphdr |
263 | | INTDEF(elfw2(LIBELFBITS,getphdr)) |