Line data Source code
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 651380 : elf_getshdrstrndx (Elf *elf, size_t *dst)
47 : {
48 651380 : int result = 0;
49 :
50 651380 : if (elf == NULL)
51 : return -1;
52 :
53 651380 : if (unlikely (elf->kind != ELF_K_ELF))
54 : {
55 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
56 0 : 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 651380 : if (unlikely (elf->state.elf.ehdr == NULL))
73 : {
74 0 : __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
75 0 : result = -1;
76 : }
77 : else
78 : {
79 : Elf32_Word num;
80 :
81 1302760 : num = (elf->class == ELFCLASS32
82 10948 : ? elf->state.elf32.ehdr->e_shstrndx
83 662328 : : elf->state.elf64.ehdr->e_shstrndx);
84 :
85 : /* Determine whether the index is too big to fit in the ELF
86 : header. */
87 651380 : if (unlikely (num == SHN_XINDEX))
88 : {
89 : /* Yes. Search the zeroth section header. */
90 98 : if (elf->class == ELFCLASS32)
91 : {
92 : size_t offset;
93 53 : if (unlikely (elf->state.elf32.scns.cnt == 0))
94 : {
95 : /* Cannot use SHN_XINDEX without section headers. */
96 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
97 0 : result = -1;
98 0 : goto out;
99 : }
100 :
101 53 : if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
102 : {
103 17 : num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
104 17 : goto success;
105 : }
106 :
107 36 : offset = elf->state.elf32.ehdr->e_shoff;
108 :
109 36 : if (elf->map_address != NULL
110 24 : && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
111 24 : && (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 12 : if (unlikely (elf->maximum_size - offset
119 : < sizeof (Elf32_Shdr)))
120 : {
121 : /* Something is wrong. */
122 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
123 0 : result = -1;
124 0 : goto out;
125 : }
126 :
127 : /* We can directly access the memory. */
128 24 : num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
129 12 : + 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 : ssize_t r;
137 :
138 24 : if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
139 : sizeof (Elf32_Shdr), offset))
140 : != sizeof (Elf32_Shdr)))
141 : {
142 : /* We must be able to read this ELF section header. */
143 0 : if (r < 0)
144 0 : __libelf_seterrno (ELF_E_INVALID_FILE);
145 : else
146 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
147 0 : result = -1;
148 0 : goto out;
149 : }
150 :
151 24 : if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
152 32 : CONVERT (shdr_mem.sh_link);
153 24 : num = shdr_mem.sh_link;
154 : }
155 : }
156 : else
157 : {
158 45 : if (unlikely (elf->state.elf64.scns.cnt == 0))
159 : {
160 : /* Cannot use SHN_XINDEX without section headers. */
161 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
162 0 : result = -1;
163 0 : goto out;
164 : }
165 :
166 45 : if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
167 : {
168 14 : num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
169 14 : goto success;
170 : }
171 :
172 31 : size_t offset = elf->state.elf64.ehdr->e_shoff;
173 :
174 31 : if (elf->map_address != NULL
175 23 : && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
176 23 : && (ALLOW_UNALIGNED
177 : || (((size_t) ((char *) elf->map_address
178 : + elf->start_offset + offset))
179 : & (__alignof__ (Elf64_Shdr) - 1)) == 0))
180 : {
181 : /* First see whether the information in the ELF header is
182 : valid and it does not ask for too much. */
183 11 : if (unlikely (elf->maximum_size - offset
184 : < sizeof (Elf64_Shdr)))
185 : {
186 : /* Something is wrong. */
187 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
188 0 : result = -1;
189 0 : goto out;
190 : }
191 :
192 : /* We can directly access the memory. */
193 22 : num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
194 11 : + offset))->sh_link;
195 : }
196 : else
197 : {
198 : /* We avoid reading in all the section headers. Just read
199 : the first one. */
200 : Elf64_Shdr shdr_mem;
201 : ssize_t r;
202 :
203 20 : if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
204 : sizeof (Elf64_Shdr), offset))
205 : != sizeof (Elf64_Shdr)))
206 : {
207 : /* We must be able to read this ELF section header. */
208 0 : if (r < 0)
209 0 : __libelf_seterrno (ELF_E_INVALID_FILE);
210 : else
211 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
212 0 : result = -1;
213 0 : goto out;
214 : }
215 :
216 20 : if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
217 32 : CONVERT (shdr_mem.sh_link);
218 20 : num = shdr_mem.sh_link;
219 : }
220 : }
221 : }
222 :
223 : /* Store the result. */
224 1302662 : success:
225 651380 : *dst = num;
226 : }
227 :
228 : out:
229 : rwlock_unlock (elf->lock);
230 :
231 : return result;
232 : }
233 : INTDEF(elf_getshdrstrndx)
234 : /* Alias for the deprecated name. */
235 : strong_alias (elf_getshdrstrndx, elf_getshstrndx)
|