blob: a765f4e3644c38ed8e6115c1978f749764d3e85d [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return section index of section header string table.
Ulrich Drepper6abe27b2005-08-29 06:25:06 +00002 Copyright (C) 2002, 2005 Red Hat, Inc.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00003 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>
Ulrich Drepper6abe27b2005-08-29 06:25:06 +000023#include <errno.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000024#include <gelf.h>
25#include <stddef.h>
26#include <unistd.h>
27
Ulrich Drepper6abe27b2005-08-29 06:25:06 +000028#include <system.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000029#include "libelfP.h"
30#include "common.h"
31
32
33int
34elf_getshstrndx (elf, dst)
35 Elf *elf;
36 size_t *dst;
37{
38 int result = 0;
39
40 if (elf == NULL)
41 return -1;
42
43 if (unlikely (elf->kind != ELF_K_ELF))
44 {
45 __libelf_seterrno (ELF_E_INVALID_HANDLE);
46 return -1;
47 }
48
49 rwlock_rdlock (elf->lock);
50
51 /* We rely here on the fact that the `elf' element is a common prefix
52 of `elf32' and `elf64'. */
53 assert (offsetof (struct Elf, state.elf.ehdr)
54 == offsetof (struct Elf, state.elf32.ehdr));
55 assert (sizeof (elf->state.elf.ehdr)
56 == sizeof (elf->state.elf32.ehdr));
57 assert (offsetof (struct Elf, state.elf.ehdr)
58 == offsetof (struct Elf, state.elf64.ehdr));
59 assert (sizeof (elf->state.elf.ehdr)
60 == sizeof (elf->state.elf64.ehdr));
61
62 if (unlikely (elf->state.elf.ehdr == NULL))
63 {
64 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
65 result = -1;
66 }
67 else
68 {
69 Elf32_Word num;
70
71 num = (elf->class == ELFCLASS32
72 ? elf->state.elf32.ehdr->e_shstrndx
73 : elf->state.elf64.ehdr->e_shstrndx);
74
75 /* Determine whether the index is too big to fit in the ELF
76 header. */
77 if (unlikely (num == SHN_XINDEX))
78 {
79 /* Yes. Search the zeroth section header. */
80 if (elf->class == ELFCLASS32)
81 {
82 size_t offset;
83
84 if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
85 {
86 num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
87 goto success;
88 }
89
90 offset = elf->state.elf32.ehdr->e_shoff;
91
92 if (elf->map_address != NULL
93 && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
94 && (ALLOW_UNALIGNED
95 || (((size_t) ((char *) elf->map_address + offset))
96 & (__alignof__ (Elf32_Shdr) - 1)) == 0))
97 /* We can directly access the memory. */
98 num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link;
99 else
100 {
101 /* We avoid reading in all the section headers. Just read
102 the first one. */
103 Elf32_Shdr shdr_mem;
104
Ulrich Drepper6abe27b2005-08-29 06:25:06 +0000105 if (unlikely (pread_retry (elf->fildes, &shdr_mem,
106 sizeof (Elf32_Shdr), offset)
107 != sizeof (Elf32_Shdr)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000108 {
109 /* We must be able to read this ELF section header. */
110 __libelf_seterrno (ELF_E_INVALID_FILE);
111 result = -1;
112 goto out;
113 }
114
115 if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
116 CONVERT (shdr_mem.sh_link);
117 num = shdr_mem.sh_link;
118 }
119 }
120 else
121 {
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000122 if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
123 {
124 num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
125 goto success;
126 }
127
Ulrich Drepper6abe27b2005-08-29 06:25:06 +0000128 size_t offset = elf->state.elf64.ehdr->e_shoff;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000129
130 if (elf->map_address != NULL
131 && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
132 && (ALLOW_UNALIGNED
133 || (((size_t) ((char *) elf->map_address + offset))
134 & (__alignof__ (Elf64_Shdr) - 1)) == 0))
135 /* We can directly access the memory. */
136 num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link;
137 else
138 {
139 /* We avoid reading in all the section headers. Just read
140 the first one. */
141 Elf64_Shdr shdr_mem;
142
Ulrich Drepper6abe27b2005-08-29 06:25:06 +0000143 if (unlikely (pread_retry (elf->fildes, &shdr_mem,
144 sizeof (Elf64_Shdr), offset)
145 != sizeof (Elf64_Shdr)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000146 {
147 /* We must be able to read this ELF section header. */
148 __libelf_seterrno (ELF_E_INVALID_FILE);
149 result = -1;
150 goto out;
151 }
152
153 if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
154 CONVERT (shdr_mem.sh_link);
155 num = shdr_mem.sh_link;
156 }
157 }
158 }
159
160 /* Store the result. */
161 success:
162 *dst = num;
163 }
164
165 out:
166 rwlock_unlock (elf->lock);
167
168 return result;
169}
170INTDEF(elf_getshstrndx)