add some utils
[libelf-compat.git] / src / elf_getshdrstrndx.c
blob13824ff8a4bf5086a8958640c2a47819313cdb5a
1 /* Return section index of section header string table.
2 Copyright (C) 2002, 2005, 2009 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
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
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
19 or both in parallel, as here.
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.
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/>. */
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
34 #include <assert.h>
35 #include <errno.h>
36 #include <stddef.h>
37 #include <unistd.h>
39 #include "gelf.h"
40 #include "system.h"
41 #include "libelfP.h"
42 #include "common.h"
45 int
46 elf_getshdrstrndx (elf, dst)
47 Elf *elf;
48 size_t *dst;
50 int result = 0;
52 if (elf == NULL)
53 return -1;
55 if (unlikely (elf->kind != ELF_K_ELF))
57 __libelf_seterrno (ELF_E_INVALID_HANDLE);
58 return -1;
61 rwlock_rdlock (elf->lock);
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));
74 if (unlikely (elf->state.elf.ehdr == NULL))
76 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
77 result = -1;
79 else
81 Elf32_Word num;
83 num = (elf->class == ELFCLASS32
84 ? elf->state.elf32.ehdr->e_shstrndx
85 : elf->state.elf64.ehdr->e_shstrndx);
87 /* Determine whether the index is too big to fit in the ELF
88 header. */
89 if (unlikely (num == SHN_XINDEX))
91 /* Yes. Search the zeroth section header. */
92 if (elf->class == ELFCLASS32)
94 size_t offset;
96 if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
98 num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
99 goto success;
102 offset = elf->state.elf32.ehdr->e_shoff;
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
113 /* We avoid reading in all the section headers. Just read
114 the first one. */
115 Elf32_Shdr shdr_mem;
117 if (unlikely (pread_retry (elf->fildes, &shdr_mem,
118 sizeof (Elf32_Shdr), offset)
119 != sizeof (Elf32_Shdr)))
121 /* We must be able to read this ELF section header. */
122 __libelf_seterrno (ELF_E_INVALID_FILE);
123 result = -1;
124 goto out;
127 if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
128 CONVERT (shdr_mem.sh_link);
129 num = shdr_mem.sh_link;
132 else
134 if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
136 num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
137 goto success;
140 size_t offset = elf->state.elf64.ehdr->e_shoff;
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
151 /* We avoid reading in all the section headers. Just read
152 the first one. */
153 Elf64_Shdr shdr_mem;
155 if (unlikely (pread_retry (elf->fildes, &shdr_mem,
156 sizeof (Elf64_Shdr), offset)
157 != sizeof (Elf64_Shdr)))
159 /* We must be able to read this ELF section header. */
160 __libelf_seterrno (ELF_E_INVALID_FILE);
161 result = -1;
162 goto out;
165 if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
166 CONVERT (shdr_mem.sh_link);
167 num = shdr_mem.sh_link;
172 /* Store the result. */
173 success:
174 *dst = num;
177 out:
178 rwlock_unlock (elf->lock);
180 return result;
182 INTDEF(elf_getshdrstrndx)
183 /* Alias for the deprecated name. */
184 strong_alias (elf_getshdrstrndx, elf_getshstrndx)