blob: 57ad80057f38dce85b4886c6742ea7e736c0f263 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return section index of section header string table.
Ulrich Drepperf1894932009-06-13 15:55:42 -07002 Copyright (C) 2002, 2005, 2009 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008
Mark Wielaardde2ed972012-06-05 17:15:16 +02009 * 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
Ulrich Drepper361df7d2006-04-04 21:38:57 +000022 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.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000025
Mark Wielaardde2ed972012-06-05 17:15:16 +020026 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/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000029
30#ifdef HAVE_CONFIG_H
31# include <config.h>
32#endif
33
34#include <assert.h>
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000035#include <errno.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000036#include <gelf.h>
37#include <stddef.h>
38#include <unistd.h>
39
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000040#include <system.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000041#include "libelfP.h"
42#include "common.h"
43
44
45int
Ulrich Drepperf1894932009-06-13 15:55:42 -070046elf_getshdrstrndx (elf, dst)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000047 Elf *elf;
48 size_t *dst;
49{
50 int result = 0;
51
52 if (elf == NULL)
53 return -1;
54
55 if (unlikely (elf->kind != ELF_K_ELF))
56 {
57 __libelf_seterrno (ELF_E_INVALID_HANDLE);
58 return -1;
59 }
60
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000061 rwlock_rdlock (elf->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000062
63 /* We rely here on the fact that the `elf' element is a common prefix
64 of `elf32' and `elf64'. */
65 assert (offsetof (struct Elf, state.elf.ehdr)
66 == offsetof (struct Elf, state.elf32.ehdr));
67 assert (sizeof (elf->state.elf.ehdr)
68 == sizeof (elf->state.elf32.ehdr));
69 assert (offsetof (struct Elf, state.elf.ehdr)
70 == offsetof (struct Elf, state.elf64.ehdr));
71 assert (sizeof (elf->state.elf.ehdr)
72 == sizeof (elf->state.elf64.ehdr));
73
74 if (unlikely (elf->state.elf.ehdr == NULL))
75 {
76 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
77 result = -1;
78 }
79 else
80 {
81 Elf32_Word num;
82
83 num = (elf->class == ELFCLASS32
84 ? elf->state.elf32.ehdr->e_shstrndx
85 : elf->state.elf64.ehdr->e_shstrndx);
86
87 /* Determine whether the index is too big to fit in the ELF
88 header. */
89 if (unlikely (num == SHN_XINDEX))
90 {
91 /* Yes. Search the zeroth section header. */
92 if (elf->class == ELFCLASS32)
93 {
94 size_t offset;
95
96 if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
97 {
98 num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
99 goto success;
100 }
101
102 offset = elf->state.elf32.ehdr->e_shoff;
103
104 if (elf->map_address != NULL
105 && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
106 && (ALLOW_UNALIGNED
107 || (((size_t) ((char *) elf->map_address + offset))
108 & (__alignof__ (Elf32_Shdr) - 1)) == 0))
109 /* We can directly access the memory. */
110 num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link;
111 else
112 {
113 /* We avoid reading in all the section headers. Just read
114 the first one. */
115 Elf32_Shdr shdr_mem;
116
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000117 if (unlikely (pread_retry (elf->fildes, &shdr_mem,
118 sizeof (Elf32_Shdr), offset)
119 != sizeof (Elf32_Shdr)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000120 {
121 /* We must be able to read this ELF section header. */
122 __libelf_seterrno (ELF_E_INVALID_FILE);
123 result = -1;
124 goto out;
125 }
126
127 if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
128 CONVERT (shdr_mem.sh_link);
129 num = shdr_mem.sh_link;
130 }
131 }
132 else
133 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000134 if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
135 {
136 num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
137 goto success;
138 }
139
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000140 size_t offset = elf->state.elf64.ehdr->e_shoff;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000141
142 if (elf->map_address != NULL
143 && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
144 && (ALLOW_UNALIGNED
145 || (((size_t) ((char *) elf->map_address + offset))
146 & (__alignof__ (Elf64_Shdr) - 1)) == 0))
147 /* We can directly access the memory. */
148 num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link;
149 else
150 {
151 /* We avoid reading in all the section headers. Just read
152 the first one. */
153 Elf64_Shdr shdr_mem;
154
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000155 if (unlikely (pread_retry (elf->fildes, &shdr_mem,
156 sizeof (Elf64_Shdr), offset)
157 != sizeof (Elf64_Shdr)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000158 {
159 /* We must be able to read this ELF section header. */
160 __libelf_seterrno (ELF_E_INVALID_FILE);
161 result = -1;
162 goto out;
163 }
164
165 if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
166 CONVERT (shdr_mem.sh_link);
167 num = shdr_mem.sh_link;
168 }
169 }
170 }
171
172 /* Store the result. */
173 success:
174 *dst = num;
175 }
176
177 out:
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000178 rwlock_unlock (elf->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000179
180 return result;
181}
Ulrich Drepperf1894932009-06-13 15:55:42 -0700182INTDEF(elf_getshdrstrndx)
183/* Alias for the deprecated name. */
184strong_alias (elf_getshdrstrndx, elf_getshstrndx)