Branch data Line data Source code
1 : : /* Get ELF program header table.
2 : : Copyright (C) 1998-2010 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 : 5254 : __elfw2(LIBELFBITS,getphdr_wrlock) (elf)
50 : : Elf *elf;
51 : : {
52 : : ElfW2(LIBELFBITS,Phdr) *result;
53 : :
54 : : /* 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 : 5254 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
58 [ + - ]: 5254 : if (likely (result != NULL))
59 : : return result;
60 : :
61 [ - + ]: 5254 : if (elf->class == 0)
62 : 0 : elf->class = ELFW(ELFCLASS,LIBELFBITS);
63 [ - + ]: 5254 : else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
64 : : {
65 : 0 : __libelf_seterrno (ELF_E_INVALID_CLASS);
66 : 0 : result = NULL;
67 : 0 : goto out;
68 : : }
69 : :
70 [ + - ]: 5254 : if (likely (result == NULL))
71 : : {
72 : : /* Read the section header table. */
73 : 5254 : ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
74 : :
75 : : /* If no program header exists return NULL. */
76 : : size_t phnum;
77 [ + - ]: 5254 : if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
78 : : goto out;
79 [ - + ]: 5254 : if (phnum == 0)
80 : : {
81 : 0 : __libelf_seterrno (ELF_E_NO_PHDR);
82 : : goto out;
83 : : }
84 : :
85 : 5254 : size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
86 : :
87 [ + - ]: 5254 : if (ehdr->e_phoff > elf->maximum_size
88 [ - + ]: 5254 : || elf->maximum_size - ehdr->e_phoff < size)
89 : : {
90 : 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
91 : : goto out;
92 : : }
93 : :
94 [ + + ]: 5254 : if (elf->map_address != NULL)
95 : : {
96 : : /* All the data is already mapped. Use it. */
97 : 5231 : void *file_phdr = ((char *) elf->map_address
98 : 5231 : + elf->start_offset + ehdr->e_phoff);
99 [ + + ]: 5231 : if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
100 : : && (ALLOW_UNALIGNED
101 : : || ((uintptr_t) file_phdr
102 : : & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
103 : : /* Simply use the mapped data. */
104 : 5216 : elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
105 : : 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 : 15 : phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
113 : 15 : (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
114 [ - + ]: 15 : if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
115 : : {
116 : 0 : __libelf_seterrno (ELF_E_NOMEM);
117 : : goto out;
118 : : }
119 : 15 : 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. */
124 : :
125 [ + - ]: 15 : if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
126 : : {
127 : 0 : assert (! ALLOW_UNALIGNED);
128 : : memcpy (phdr, file_phdr, size);
129 : : }
130 : : else
131 : : {
132 : : 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 : : }
141 : :
142 [ + + ]: 106 : for (size_t cnt = 0; cnt < phnum; ++cnt)
143 : : {
144 : 182 : CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
145 : 182 : CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
146 : 182 : CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
147 : 182 : CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
148 : 182 : CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
149 : 182 : CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
150 : 182 : CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
151 : 182 : CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
152 : : }
153 : : }
154 : : }
155 : : }
156 [ + - ]: 23 : 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 : 23 : elf->state.ELFW(elf,LIBELFBITS).phdr =
161 : 23 : (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
162 [ - + ]: 23 : if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
163 : : {
164 : 0 : __libelf_seterrno (ELF_E_NOMEM);
165 : : goto out;
166 : : }
167 : 23 : elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
168 : :
169 : : /* Read the header. */
170 : 23 : ssize_t n = pread_retry (elf->fildes,
171 : : elf->state.ELFW(elf,LIBELFBITS).phdr, size,
172 : 23 : elf->start_offset + ehdr->e_phoff);
173 [ - + ]: 23 : if (unlikely ((size_t) n != size))
174 : : {
175 : : /* Severe problems. We cannot read the data. */
176 : 0 : __libelf_seterrno (ELF_E_READ_ERROR);
177 : 0 : free (elf->state.ELFW(elf,LIBELFBITS).phdr);
178 : 0 : 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 [ + + ]: 23 : if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
185 : : {
186 : 4 : ElfW2(LIBELFBITS,Phdr) *phdr
187 : : = elf->state.ELFW(elf,LIBELFBITS).phdr;
188 : :
189 [ + + ]: 22 : for (size_t cnt = 0; cnt < phnum; ++cnt)
190 : : {
191 : 36 : CONVERT (phdr[cnt].p_type);
192 : 36 : CONVERT (phdr[cnt].p_offset);
193 : 36 : CONVERT (phdr[cnt].p_vaddr);
194 : 36 : CONVERT (phdr[cnt].p_paddr);
195 : 36 : CONVERT (phdr[cnt].p_filesz);
196 : 36 : CONVERT (phdr[cnt].p_memsz);
197 : 36 : CONVERT (phdr[cnt].p_flags);
198 : 36 : 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 : 0 : __libelf_seterrno (ELF_E_FD_DISABLED);
207 : : goto out;
208 : : }
209 : :
210 : 5254 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
211 : : }
212 : :
213 : : out:
214 : 5254 : return result;
215 : : }
216 : :
217 : : ElfW2(LIBELFBITS,Phdr) *
218 : 5254 : elfw2(LIBELFBITS,getphdr) (elf)
219 : : Elf *elf;
220 : : {
221 : : ElfW2(LIBELFBITS,Phdr) *result;
222 : :
223 [ + - ]: 5254 : if (elf == NULL)
224 : : return NULL;
225 : :
226 [ - + ]: 5254 : if (unlikely (elf->kind != ELF_K_ELF))
227 : : {
228 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
229 : 0 : 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 : 5254 : result = elf->state.ELFW(elf,LIBELFBITS).phdr;
236 [ + - ]: 5254 : if (likely (result != NULL))
237 : : return result;
238 : :
239 : : rwlock_wrlock (elf->lock);
240 : 5254 : result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
241 : : rwlock_unlock (elf->lock);
242 : :
243 : 5254 : return result;
244 : : }
245 : : INTDEF(elfw2(LIBELFBITS,getphdr))
|