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.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
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
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
19 or both in parallel, as here.
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.
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/>. */
45 # define LIBELFBITS 32
48 ElfW2(LIBELFBITS,Phdr) *
49 __elfw2(LIBELFBITS,getphdr_wrlock) (elf)
52 ElfW2(LIBELFBITS,Phdr) *result;
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))
62 elf->class = ELFW(ELFCLASS,LIBELFBITS);
63 else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
65 __libelf_seterrno (ELF_E_INVALID_CLASS);
70 if (likely (result == NULL))
72 /* Read the section header table. */
73 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
75 /* If no program header exists return NULL. */
77 if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
81 __libelf_seterrno (ELF_E_NO_PHDR);
85 size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
87 if (ehdr->e_phoff > elf->maximum_size
88 || elf->maximum_size - ehdr->e_phoff < size)
90 __libelf_seterrno (ELF_E_INVALID_DATA);
94 if (elf->map_address != NULL)
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))
101 /* Something is wrong. */
102 __libelf_seterrno (ELF_E_INVALID_PHDR);
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
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;
117 ElfW2(LIBELFBITS,Phdr) *notcvt;
118 ElfW2(LIBELFBITS,Phdr) *phdr;
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)
126 __libelf_seterrno (ELF_E_NOMEM);
129 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
130 ELF_F_MALLOCED | ELF_F_DIRTY;
132 /* Now copy the data and at the same time convert the
135 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
137 assert (! ALLOW_UNALIGNED);
138 memcpy (phdr, file_phdr, size);
143 || ((uintptr_t) file_phdr
144 & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)
148 notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size);
149 memcpy (notcvt, file_phdr, size);
152 for (size_t cnt = 0; cnt < phnum; ++cnt)
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);
166 else if (likely (elf->fildes != -1))
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)
174 __libelf_seterrno (ELF_E_NOMEM);
177 elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
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))
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;
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)
196 ElfW2(LIBELFBITS,Phdr) *phdr
197 = elf->state.ELFW(elf,LIBELFBITS).phdr;
199 for (size_t cnt = 0; cnt < phnum; ++cnt)
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);
214 /* The file descriptor was already enabled and not all data was
216 __libelf_seterrno (ELF_E_FD_DISABLED);
220 result = elf->state.ELFW(elf,LIBELFBITS).phdr;
227 ElfW2(LIBELFBITS,Phdr) *
228 elfw2(LIBELFBITS,getphdr) (elf)
231 ElfW2(LIBELFBITS,Phdr) *result;
236 if (unlikely (elf->kind != ELF_K_ELF))
238 __libelf_seterrno (ELF_E_INVALID_HANDLE);
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))
249 rwlock_wrlock (elf->lock);
250 result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
251 rwlock_unlock (elf->lock);
255 INTDEF(elfw2(LIBELFBITS,getphdr))