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