Imported Upstream version 0.160
[platform/upstream/elfutils.git] / libelf / elf32_getphdr.c
1 /* Get ELF program header table.
2    Copyright (C) 1998-2010, 2014 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 __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   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
58   if (likely (result != NULL))
59     return result;
60
61   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.  */
76       size_t phnum;
77       if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
78         goto out;
79       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
87       if (ehdr->e_phoff > elf->maximum_size
88           || elf->maximum_size - ehdr->e_phoff < size)
89         {
90           __libelf_seterrno (ELF_E_INVALID_DATA);
91           goto out;
92         }
93
94       if (elf->map_address != NULL)
95         {
96           /* First see whether the information in the ELF header is
97              valid and it does not ask for too much.  */
98           if (unlikely (ehdr->e_phoff >= elf->maximum_size)
99               || unlikely (elf->maximum_size - ehdr->e_phoff < size))
100             {
101               /* Something is wrong.  */
102               __libelf_seterrno (ELF_E_INVALID_PHDR);
103               goto out;
104             }
105
106           /* All the data is already mapped.  Use it.  */
107           void *file_phdr = ((char *) elf->map_address
108                              + elf->start_offset + ehdr->e_phoff);
109           if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
110               && (ALLOW_UNALIGNED
111                   || ((uintptr_t) file_phdr
112                       & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
113             /* Simply use the mapped data.  */
114             elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
115           else
116             {
117               ElfW2(LIBELFBITS,Phdr) *notcvt;
118               ElfW2(LIBELFBITS,Phdr) *phdr;
119
120               /* Allocate memory for the program headers.  We know the number
121                  of entries from the ELF header.  */
122               phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
123                 (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
124               if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
125                 {
126                   __libelf_seterrno (ELF_E_NOMEM);
127                   goto out;
128                 }
129               elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
130                 ELF_F_MALLOCED | ELF_F_DIRTY;
131
132               /* Now copy the data and at the same time convert the
133                  byte order.  */
134
135               if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
136                 {
137                   assert (! ALLOW_UNALIGNED);
138                   memcpy (phdr, file_phdr, size);
139                 }
140               else
141                 {
142                   if (ALLOW_UNALIGNED
143                       || ((uintptr_t) file_phdr
144                           & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)
145                     notcvt = file_phdr;
146                   else
147                     {
148                       notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size);
149                       memcpy (notcvt, file_phdr, size);
150                     }
151
152                   for (size_t cnt = 0; cnt < phnum; ++cnt)
153                     {
154                       CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
155                       CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
156                       CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
157                       CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
158                       CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
159                       CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
160                       CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
161                       CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
162                     }
163                 }
164             }
165         }
166       else if (likely (elf->fildes != -1))
167         {
168           /* Allocate memory for the program headers.  We know the number
169              of entries from the ELF header.  */
170           elf->state.ELFW(elf,LIBELFBITS).phdr =
171             (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
172           if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
173             {
174               __libelf_seterrno (ELF_E_NOMEM);
175               goto out;
176             }
177           elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
178
179           /* Read the header.  */
180           ssize_t n = pread_retry (elf->fildes,
181                                    elf->state.ELFW(elf,LIBELFBITS).phdr, size,
182                                    elf->start_offset + ehdr->e_phoff);
183           if (unlikely ((size_t) n != size))
184             {
185               /* Severe problems.  We cannot read the data.  */
186               __libelf_seterrno (ELF_E_READ_ERROR);
187               free (elf->state.ELFW(elf,LIBELFBITS).phdr);
188               elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
189               goto out;
190             }
191
192           /* If the byte order of the file is not the same as the one
193              of the host convert the data now.  */
194           if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
195             {
196               ElfW2(LIBELFBITS,Phdr) *phdr
197                 = elf->state.ELFW(elf,LIBELFBITS).phdr;
198
199               for (size_t cnt = 0; cnt < phnum; ++cnt)
200                 {
201                   CONVERT (phdr[cnt].p_type);
202                   CONVERT (phdr[cnt].p_offset);
203                   CONVERT (phdr[cnt].p_vaddr);
204                   CONVERT (phdr[cnt].p_paddr);
205                   CONVERT (phdr[cnt].p_filesz);
206                   CONVERT (phdr[cnt].p_memsz);
207                   CONVERT (phdr[cnt].p_flags);
208                   CONVERT (phdr[cnt].p_align);
209                 }
210             }
211         }
212       else
213         {
214           /* The file descriptor was already enabled and not all data was
215              read.  */
216           __libelf_seterrno (ELF_E_FD_DISABLED);
217           goto out;
218         }
219
220       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
221     }
222
223  out:
224   return result;
225 }
226
227 ElfW2(LIBELFBITS,Phdr) *
228 elfw2(LIBELFBITS,getphdr) (elf)
229      Elf *elf;
230 {
231   ElfW2(LIBELFBITS,Phdr) *result;
232
233   if (elf == NULL)
234     return NULL;
235
236   if (unlikely (elf->kind != ELF_K_ELF))
237     {
238       __libelf_seterrno (ELF_E_INVALID_HANDLE);
239       return NULL;
240     }
241
242   /* If the program header entry has already been filled in the code
243    * in getphdr_wrlock must already have been run.  So the class is
244    * set, too.  No need to waste any more time here.  */
245   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
246   if (likely (result != NULL))
247     return result;
248
249   rwlock_wrlock (elf->lock);
250   result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
251   rwlock_unlock (elf->lock);
252
253   return result;
254 }
255 INTDEF(elfw2(LIBELFBITS,getphdr))