Imported Upstream version 0.155
[platform/upstream/elfutils.git] / libelf / elf32_getphdr.c
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 __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           /* All the data is already mapped.  Use it.  */
97           void *file_phdr = ((char *) elf->map_address
98                              + elf->start_offset + ehdr->e_phoff);
99           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             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               phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
113                 (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
114               if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
115                 {
116                   __libelf_seterrno (ELF_E_NOMEM);
117                   goto out;
118                 }
119               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               if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
126                 {
127                   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                   for (size_t cnt = 0; cnt < phnum; ++cnt)
143                     {
144                       CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
145                       CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
146                       CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
147                       CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
148                       CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
149                       CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
150                       CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
151                       CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
152                     }
153                 }
154             }
155         }
156       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           elf->state.ELFW(elf,LIBELFBITS).phdr =
161             (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
162           if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
163             {
164               __libelf_seterrno (ELF_E_NOMEM);
165               goto out;
166             }
167           elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
168
169           /* Read the header.  */
170           ssize_t n = pread_retry (elf->fildes,
171                                    elf->state.ELFW(elf,LIBELFBITS).phdr, size,
172                                    elf->start_offset + ehdr->e_phoff);
173           if (unlikely ((size_t) n != size))
174             {
175               /* Severe problems.  We cannot read the data.  */
176               __libelf_seterrno (ELF_E_READ_ERROR);
177               free (elf->state.ELFW(elf,LIBELFBITS).phdr);
178               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           if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
185             {
186               ElfW2(LIBELFBITS,Phdr) *phdr
187                 = elf->state.ELFW(elf,LIBELFBITS).phdr;
188
189               for (size_t cnt = 0; cnt < phnum; ++cnt)
190                 {
191                   CONVERT (phdr[cnt].p_type);
192                   CONVERT (phdr[cnt].p_offset);
193                   CONVERT (phdr[cnt].p_vaddr);
194                   CONVERT (phdr[cnt].p_paddr);
195                   CONVERT (phdr[cnt].p_filesz);
196                   CONVERT (phdr[cnt].p_memsz);
197                   CONVERT (phdr[cnt].p_flags);
198                   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           __libelf_seterrno (ELF_E_FD_DISABLED);
207           goto out;
208         }
209
210       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
211     }
212
213  out:
214   return result;
215 }
216
217 ElfW2(LIBELFBITS,Phdr) *
218 elfw2(LIBELFBITS,getphdr) (elf)
219      Elf *elf;
220 {
221   ElfW2(LIBELFBITS,Phdr) *result;
222
223   if (elf == NULL)
224     return NULL;
225
226   if (unlikely (elf->kind != ELF_K_ELF))
227     {
228       __libelf_seterrno (ELF_E_INVALID_HANDLE);
229       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   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
236   if (likely (result != NULL))
237     return result;
238
239   rwlock_wrlock (elf->lock);
240   result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
241   rwlock_unlock (elf->lock);
242
243   return result;
244 }
245 INTDEF(elfw2(LIBELFBITS,getphdr))