tests: Drop shared libraries from self_test_files_exe.
[platform/upstream/elfutils.git] / libelf / elf32_getshdr.c
1 /* Return section header.
2    Copyright (C) 1998-2002, 2005, 2007, 2009, 2012, 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 <assert.h>
35 #include <errno.h>
36 #include <stdbool.h>
37 #include <unistd.h>
38
39 #include <system.h>
40 #include "libelfP.h"
41 #include "common.h"
42
43 #ifndef LIBELFBITS
44 # define LIBELFBITS 32
45 #endif
46
47
48 static ElfW2(LIBELFBITS,Shdr) *
49 load_shdr_wrlock (Elf_Scn *scn)
50 {
51   ElfW2(LIBELFBITS,Shdr) *result;
52
53   /* Read the section header table.  */
54   Elf *elf = scn->elf;
55   ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
56
57   /* Try again, maybe the data is there now.  */
58   result = scn->shdr.ELFW(e,LIBELFBITS);
59   if (result != NULL)
60     goto out;
61
62   size_t shnum;
63   if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
64       || shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
65     goto out;
66   size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
67
68   /* Allocate memory for the section headers.  We know the number
69      of entries from the ELF header.  */
70   ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
71     (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
72   if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
73     {
74       __libelf_seterrno (ELF_E_NOMEM);
75       goto out;
76     }
77   elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
78
79   if (elf->map_address != NULL)
80     {
81       /* First see whether the information in the ELF header is
82          valid and it does not ask for too much.  */
83       if (unlikely (ehdr->e_shoff >= elf->maximum_size)
84           || unlikely (elf->maximum_size - ehdr->e_shoff < size))
85         {
86           /* Something is wrong.  */
87           __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
88           goto free_and_out;
89         }
90
91       ElfW2(LIBELFBITS,Shdr) *notcvt;
92
93       /* All the data is already mapped.  If we could use it
94          directly this would already have happened.  Unless
95          we allocated the memory ourselves and the ELF_F_MALLOCED
96          flag is set.  */
97       void *file_shdr = ((char *) elf->map_address
98                          + elf->start_offset + ehdr->e_shoff);
99
100       assert ((elf->flags & ELF_F_MALLOCED)
101               || ehdr->e_ident[EI_DATA] != MY_ELFDATA
102               || elf->cmd == ELF_C_READ_MMAP
103               || (! ALLOW_UNALIGNED
104                   && ((uintptr_t) file_shdr
105                       & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
106
107       /* Now copy the data and at the same time convert the byte order.  */
108       if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
109         {
110           assert ((elf->flags & ELF_F_MALLOCED)
111                   || elf->cmd == ELF_C_READ_MMAP
112                   || ! ALLOW_UNALIGNED);
113           memcpy (shdr, file_shdr, size);
114         }
115       else
116         {
117           bool copy = ! (ALLOW_UNALIGNED
118                          || ((uintptr_t) file_shdr
119                              & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1))
120                              == 0);
121           if (! copy)
122             notcvt = (ElfW2(LIBELFBITS,Shdr) *)
123               ((char *) elf->map_address
124                + elf->start_offset + ehdr->e_shoff);
125           else
126             {
127               notcvt = (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
128               if (unlikely (notcvt == NULL))
129                 {
130                   __libelf_seterrno (ELF_E_NOMEM);
131                   goto out;
132                 }
133               memcpy (notcvt, ((char *) elf->map_address
134                                + elf->start_offset + ehdr->e_shoff),
135                       size);
136             }
137
138           for (size_t cnt = 0; cnt < shnum; ++cnt)
139             {
140               CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
141               CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
142               CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
143               CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
144               CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
145               CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
146               CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
147               CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
148               CONVERT_TO (shdr[cnt].sh_addralign,
149                           notcvt[cnt].sh_addralign);
150               CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
151
152               /* If this is a section with an extended index add a
153                  reference in the section which uses the extended
154                  index.  */
155               if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
156                   && shdr[cnt].sh_link < shnum)
157                 elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
158                   = cnt;
159
160               /* Set the own shndx_index field in case it has not yet
161                  been set.  */
162               if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
163                 elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
164                   = -1;
165             }
166
167           if (copy)
168             free (notcvt);
169         }
170     }
171   else if (likely (elf->fildes != -1))
172     {
173       /* Read the header.  */
174       ssize_t n = pread_retry (elf->fildes,
175                                elf->state.ELFW(elf,LIBELFBITS).shdr, size,
176                                elf->start_offset + ehdr->e_shoff);
177       if (unlikely ((size_t) n != size))
178         {
179           /* Severe problems.  We cannot read the data.  */
180           __libelf_seterrno (ELF_E_READ_ERROR);
181           goto free_and_out;
182         }
183
184       /* If the byte order of the file is not the same as the one
185          of the host convert the data now.  */
186       if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
187         for (size_t cnt = 0; cnt < shnum; ++cnt)
188           {
189             CONVERT (shdr[cnt].sh_name);
190             CONVERT (shdr[cnt].sh_type);
191             CONVERT (shdr[cnt].sh_flags);
192             CONVERT (shdr[cnt].sh_addr);
193             CONVERT (shdr[cnt].sh_offset);
194             CONVERT (shdr[cnt].sh_size);
195             CONVERT (shdr[cnt].sh_link);
196             CONVERT (shdr[cnt].sh_info);
197             CONVERT (shdr[cnt].sh_addralign);
198             CONVERT (shdr[cnt].sh_entsize);
199           }
200     }
201   else
202     {
203       /* The file descriptor was already enabled and not all data was
204          read.  Undo the allocation.  */
205       __libelf_seterrno (ELF_E_FD_DISABLED);
206
207     free_and_out:
208       free (shdr);
209       elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
210       elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
211
212       goto out;
213     }
214
215   /* Set the pointers in the `scn's.  */
216   for (size_t cnt = 0; cnt < shnum; ++cnt)
217     elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
218       = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
219
220   result = scn->shdr.ELFW(e,LIBELFBITS);
221   assert (result != NULL);
222
223 out:
224   return result;
225 }
226
227 static bool
228 scn_valid (Elf_Scn *scn)
229 {
230   if (scn == NULL)
231     return false;
232
233   if (unlikely (scn->elf->state.elf.ehdr == NULL))
234     {
235       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
236       return false;
237     }
238
239   if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
240     {
241       __libelf_seterrno (ELF_E_INVALID_CLASS);
242       return false;
243     }
244
245   return true;
246 }
247
248 ElfW2(LIBELFBITS,Shdr) *
249 internal_function
250 __elfw2(LIBELFBITS,getshdr_rdlock) (Elf_Scn *scn)
251 {
252   ElfW2(LIBELFBITS,Shdr) *result;
253
254   if (!scn_valid (scn))
255     return NULL;
256
257   result = scn->shdr.ELFW(e,LIBELFBITS);
258   if (result == NULL)
259     {
260       rwlock_unlock (scn->elf->lock);
261       rwlock_wrlock (scn->elf->lock);
262       result = scn->shdr.ELFW(e,LIBELFBITS);
263       if (result == NULL)
264         result = load_shdr_wrlock (scn);
265     }
266
267   return result;
268 }
269
270 ElfW2(LIBELFBITS,Shdr) *
271 internal_function
272 __elfw2(LIBELFBITS,getshdr_wrlock) (Elf_Scn *scn)
273 {
274   ElfW2(LIBELFBITS,Shdr) *result;
275
276   if (!scn_valid (scn))
277     return NULL;
278
279   result = scn->shdr.ELFW(e,LIBELFBITS);
280   if (result == NULL)
281     result = load_shdr_wrlock (scn);
282
283   return result;
284 }
285
286 ElfW2(LIBELFBITS,Shdr) *
287 elfw2(LIBELFBITS,getshdr) (Elf_Scn *scn)
288 {
289   ElfW2(LIBELFBITS,Shdr) *result;
290
291   if (!scn_valid (scn))
292     return NULL;
293
294   rwlock_rdlock (scn->elf->lock);
295   result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
296   rwlock_unlock (scn->elf->lock);
297
298   return result;
299 }