packaging: update homepage url
[platform/upstream/elfutils.git] / libelf / elf_getshdrstrndx.c
1 /* Return section index of section header string table.
2    Copyright (C) 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
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 <gelf.h>
37 #include <stddef.h>
38 #include <unistd.h>
39
40 #include <system.h>
41 #include "libelfP.h"
42 #include "common.h"
43
44
45 int
46 elf_getshdrstrndx (Elf *elf, size_t *dst)
47 {
48   int result = 0;
49
50   if (elf == NULL)
51     return -1;
52
53   if (unlikely (elf->kind != ELF_K_ELF))
54     {
55       __libelf_seterrno (ELF_E_INVALID_HANDLE);
56       return -1;
57     }
58
59   rwlock_rdlock (elf->lock);
60
61   /* We rely here on the fact that the `elf' element is a common prefix
62      of `elf32' and `elf64'.  */
63   assert (offsetof (struct Elf, state.elf.ehdr)
64           == offsetof (struct Elf, state.elf32.ehdr));
65   assert (sizeof (elf->state.elf.ehdr)
66           == sizeof (elf->state.elf32.ehdr));
67   assert (offsetof (struct Elf, state.elf.ehdr)
68           == offsetof (struct Elf, state.elf64.ehdr));
69   assert (sizeof (elf->state.elf.ehdr)
70           == sizeof (elf->state.elf64.ehdr));
71
72   if (unlikely (elf->state.elf.ehdr == NULL))
73     {
74       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
75       result = -1;
76     }
77   else
78     {
79       Elf32_Word num;
80
81       num = (elf->class == ELFCLASS32
82              ? elf->state.elf32.ehdr->e_shstrndx
83              : elf->state.elf64.ehdr->e_shstrndx);
84
85       /* Determine whether the index is too big to fit in the ELF
86          header.  */
87       if (unlikely (num == SHN_XINDEX))
88         {
89           /* Yes.  Search the zeroth section header.  */
90           if (elf->class == ELFCLASS32)
91             {
92               size_t offset;
93               if (unlikely (elf->state.elf32.scns.cnt == 0))
94                 {
95                   /* Cannot use SHN_XINDEX without section headers.  */
96                   __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
97                   result = -1;
98                   goto out;
99                 }
100
101               if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
102                 {
103                   num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
104                   goto success;
105                 }
106
107               offset = elf->state.elf32.ehdr->e_shoff;
108
109               if (elf->map_address != NULL
110                   && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
111                   && (ALLOW_UNALIGNED
112                       || (((size_t) ((char *) elf->map_address
113                            + elf->start_offset + offset))
114                           & (__alignof__ (Elf32_Shdr) - 1)) == 0))
115                 {
116                   /* First see whether the information in the ELF header is
117                      valid and it does not ask for too much.  */
118                   if (unlikely (elf->maximum_size - offset
119                                 < sizeof (Elf32_Shdr)))
120                     {
121                       /* Something is wrong.  */
122                       __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
123                       result = -1;
124                       goto out;
125                     }
126
127                   /* We can directly access the memory.  */
128                   num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
129                                          + offset))->sh_link;
130                 }
131               else
132                 {
133                   /* We avoid reading in all the section headers.  Just read
134                      the first one.  */
135                   Elf32_Shdr shdr_mem;
136
137                   if (unlikely (pread_retry (elf->fildes, &shdr_mem,
138                                              sizeof (Elf32_Shdr), offset)
139                                 != sizeof (Elf32_Shdr)))
140                     {
141                       /* We must be able to read this ELF section header.  */
142                       __libelf_seterrno (ELF_E_INVALID_FILE);
143                       result = -1;
144                       goto out;
145                     }
146
147                   if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
148                     CONVERT (shdr_mem.sh_link);
149                   num = shdr_mem.sh_link;
150                 }
151             }
152           else
153             {
154               if (unlikely (elf->state.elf64.scns.cnt == 0))
155                 {
156                   /* Cannot use SHN_XINDEX without section headers.  */
157                   __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
158                   result = -1;
159                   goto out;
160                 }
161
162               if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
163                 {
164                   num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
165                   goto success;
166                 }
167
168               size_t offset = elf->state.elf64.ehdr->e_shoff;
169
170               if (elf->map_address != NULL
171                   && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
172                   && (ALLOW_UNALIGNED
173                       || (((size_t) ((char *) elf->map_address
174                            + elf->start_offset + offset))
175                           & (__alignof__ (Elf64_Shdr) - 1)) == 0))
176                 {
177                   /* First see whether the information in the ELF header is
178                      valid and it does not ask for too much.  */
179                   if (unlikely (elf->maximum_size - offset
180                                 < sizeof (Elf64_Shdr)))
181                     {
182                       /* Something is wrong.  */
183                       __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
184                       result = -1;
185                       goto out;
186                     }
187
188                   /* We can directly access the memory.  */
189                   num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
190                                          + offset))->sh_link;
191                 }
192               else
193                 {
194                   /* We avoid reading in all the section headers.  Just read
195                      the first one.  */
196                   Elf64_Shdr shdr_mem;
197
198                   if (unlikely (pread_retry (elf->fildes, &shdr_mem,
199                                              sizeof (Elf64_Shdr), offset)
200                                 != sizeof (Elf64_Shdr)))
201                     {
202                       /* We must be able to read this ELF section header.  */
203                       __libelf_seterrno (ELF_E_INVALID_FILE);
204                       result = -1;
205                       goto out;
206                     }
207
208                   if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
209                     CONVERT (shdr_mem.sh_link);
210                   num = shdr_mem.sh_link;
211                 }
212             }
213         }
214
215       /* Store the result.  */
216     success:
217       *dst = num;
218     }
219
220  out:
221   rwlock_unlock (elf->lock);
222
223   return result;
224 }
225 INTDEF(elf_getshdrstrndx)
226 /* Alias for the deprecated name.  */
227 strong_alias (elf_getshdrstrndx, elf_getshstrndx)