1 /* Return section index of section header string table.
2 Copyright (C) 2002 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 2.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <assert.h>
23 #include <gelf.h>
24 #include <stddef.h>
25 #include <unistd.h>
26
27 #include "libelfP.h"
28 #include "common.h"
29
30
31 int
elf_getshstrndx(elf,dst)32 elf_getshstrndx (elf, dst)
33 Elf *elf;
34 size_t *dst;
35 {
36 int result = 0;
37
38 if (elf == NULL)
39 return -1;
40
41 if (unlikely (elf->kind != ELF_K_ELF))
42 {
43 __libelf_seterrno (ELF_E_INVALID_HANDLE);
44 return -1;
45 }
46
47 rwlock_rdlock (elf->lock);
48
49 /* We rely here on the fact that the `elf' element is a common prefix
50 of `elf32' and `elf64'. */
51 assert (offsetof (struct Elf, state.elf.ehdr)
52 == offsetof (struct Elf, state.elf32.ehdr));
53 assert (sizeof (elf->state.elf.ehdr)
54 == sizeof (elf->state.elf32.ehdr));
55 assert (offsetof (struct Elf, state.elf.ehdr)
56 == offsetof (struct Elf, state.elf64.ehdr));
57 assert (sizeof (elf->state.elf.ehdr)
58 == sizeof (elf->state.elf64.ehdr));
59
60 if (unlikely (elf->state.elf.ehdr == NULL))
61 {
62 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
63 result = -1;
64 }
65 else
66 {
67 Elf32_Word num;
68
69 num = (elf->class == ELFCLASS32
70 ? elf->state.elf32.ehdr->e_shstrndx
71 : elf->state.elf64.ehdr->e_shstrndx);
72
73 /* Determine whether the index is too big to fit in the ELF
74 header. */
75 if (unlikely (num == SHN_XINDEX))
76 {
77 /* Yes. Search the zeroth section header. */
78 if (elf->class == ELFCLASS32)
79 {
80 size_t offset;
81
82 if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
83 {
84 num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
85 goto success;
86 }
87
88 offset = elf->state.elf32.ehdr->e_shoff;
89
90 if (elf->map_address != NULL
91 && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
92 && (ALLOW_UNALIGNED
93 || (((size_t) ((char *) elf->map_address + offset))
94 & (__alignof__ (Elf32_Shdr) - 1)) == 0))
95 /* We can directly access the memory. */
96 num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link;
97 else
98 {
99 /* We avoid reading in all the section headers. Just read
100 the first one. */
101 Elf32_Shdr shdr_mem;
102
103 if (pread (elf->fildes, &shdr_mem, sizeof (Elf32_Shdr),
104 offset) != sizeof (Elf32_Shdr))
105 {
106 /* We must be able to read this ELF section header. */
107 __libelf_seterrno (ELF_E_INVALID_FILE);
108 result = -1;
109 goto out;
110 }
111
112 if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
113 CONVERT (shdr_mem.sh_link);
114 num = shdr_mem.sh_link;
115 }
116 }
117 else
118 {
119 size_t offset;
120
121 if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
122 {
123 num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
124 goto success;
125 }
126
127 offset = elf->state.elf64.ehdr->e_shoff;
128
129 if (elf->map_address != NULL
130 && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
131 && (ALLOW_UNALIGNED
132 || (((size_t) ((char *) elf->map_address + offset))
133 & (__alignof__ (Elf64_Shdr) - 1)) == 0))
134 /* We can directly access the memory. */
135 num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link;
136 else
137 {
138 /* We avoid reading in all the section headers. Just read
139 the first one. */
140 Elf64_Shdr shdr_mem;
141
142 if (pread (elf->fildes, &shdr_mem, sizeof (Elf64_Shdr),
143 offset) != sizeof (Elf64_Shdr))
144 {
145 /* We must be able to read this ELF section header. */
146 __libelf_seterrno (ELF_E_INVALID_FILE);
147 result = -1;
148 goto out;
149 }
150
151 if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
152 CONVERT (shdr_mem.sh_link);
153 num = shdr_mem.sh_link;
154 }
155 }
156 }
157
158 /* Store the result. */
159 success:
160 *dst = num;
161 }
162
163 out:
164 rwlock_unlock (elf->lock);
165
166 return result;
167 }
168 INTDEF(elf_getshstrndx)
169