blob: bd9340dd70710ab6fd69ca17a7eba9da9051383e [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return section header.
Mark Wielaard030f6262012-07-18 13:14:30 +02002 Copyright (C) 1998-2002, 2005, 2007, 2009, 2012 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>, 1998.
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>
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000036#include <stdbool.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000037#include <unistd.h>
38
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000039#include <system.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000040#include "libelfP.h"
41#include "common.h"
42
43#ifndef LIBELFBITS
44# define LIBELFBITS 32
45#endif
46
47
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000048static ElfW2(LIBELFBITS,Shdr) *
Ulrich Drepper02f66452008-12-04 05:58:16 +000049load_shdr_wrlock (Elf_Scn *scn)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000050{
51 ElfW2(LIBELFBITS,Shdr) *result;
52
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000053 /* Read the section header table. */
54 Elf *elf = scn->elf;
55 ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
56
57 /* Try again, maybe the data is there now. */
58 result = scn->shdr.ELFW(e,LIBELFBITS);
59 if (result != NULL)
60 goto out;
61
62 size_t shnum;
Ulrich Drepperf1894932009-06-13 15:55:42 -070063 if (__elf_getshdrnum_rdlock (elf, &shnum) != 0)
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000064 goto out;
65 size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
66
67 /* Allocate memory for the section headers. We know the number
68 of entries from the ELF header. */
69 ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
70 (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
71 if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
72 {
73 __libelf_seterrno (ELF_E_NOMEM);
74 goto out;
75 }
76 elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
77
78 if (elf->map_address != NULL)
79 {
80 ElfW2(LIBELFBITS,Shdr) *notcvt;
81
82 /* All the data is already mapped. If we could use it
Mark Wielaard030f6262012-07-18 13:14:30 +020083 directly this would already have happened. Unless
84 we allocated the memory ourselves and the ELF_F_MALLOCED
85 flag is set. */
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000086 void *file_shdr = ((char *) elf->map_address
87 + elf->start_offset + ehdr->e_shoff);
88
Mark Wielaard030f6262012-07-18 13:14:30 +020089 assert ((elf->flags & ELF_F_MALLOCED)
90 || ehdr->e_ident[EI_DATA] != MY_ELFDATA
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000091 || (! ALLOW_UNALIGNED
92 && ((uintptr_t) file_shdr
93 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
94
95 /* Now copy the data and at the same time convert the byte order. */
96 if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
97 {
Mark Wielaard030f6262012-07-18 13:14:30 +020098 assert ((elf->flags & ELF_F_MALLOCED) || ! ALLOW_UNALIGNED);
Roland McGrathb4d6f0f2008-08-25 22:55:17 +000099 memcpy (shdr, file_shdr, size);
100 }
101 else
102 {
103 if (ALLOW_UNALIGNED
104 || ((uintptr_t) file_shdr
105 & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) == 0)
106 notcvt = (ElfW2(LIBELFBITS,Shdr) *)
107 ((char *) elf->map_address
108 + elf->start_offset + ehdr->e_shoff);
109 else
110 {
111 notcvt = (ElfW2(LIBELFBITS,Shdr) *) alloca (size);
112 memcpy (notcvt, ((char *) elf->map_address
113 + elf->start_offset + ehdr->e_shoff),
114 size);
115 }
116
117 for (size_t cnt = 0; cnt < shnum; ++cnt)
118 {
119 CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
120 CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
121 CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
122 CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
123 CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
124 CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
125 CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
126 CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
127 CONVERT_TO (shdr[cnt].sh_addralign,
128 notcvt[cnt].sh_addralign);
129 CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
130
131 /* If this is a section with an extended index add a
132 reference in the section which uses the extended
133 index. */
134 if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
135 && shdr[cnt].sh_link < shnum)
136 elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
137 = cnt;
138
139 /* Set the own shndx_index field in case it has not yet
140 been set. */
141 if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
142 elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
143 = -1;
144 }
145 }
146 }
147 else if (likely (elf->fildes != -1))
148 {
149 /* Read the header. */
150 ssize_t n = pread_retry (elf->fildes,
151 elf->state.ELFW(elf,LIBELFBITS).shdr, size,
152 elf->start_offset + ehdr->e_shoff);
153 if (unlikely ((size_t) n != size))
154 {
155 /* Severe problems. We cannot read the data. */
156 __libelf_seterrno (ELF_E_READ_ERROR);
157 goto free_and_out;
158 }
159
160 /* If the byte order of the file is not the same as the one
161 of the host convert the data now. */
162 if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
163 for (size_t cnt = 0; cnt < shnum; ++cnt)
164 {
165 CONVERT (shdr[cnt].sh_name);
166 CONVERT (shdr[cnt].sh_type);
167 CONVERT (shdr[cnt].sh_flags);
168 CONVERT (shdr[cnt].sh_addr);
169 CONVERT (shdr[cnt].sh_offset);
170 CONVERT (shdr[cnt].sh_size);
171 CONVERT (shdr[cnt].sh_link);
172 CONVERT (shdr[cnt].sh_info);
173 CONVERT (shdr[cnt].sh_addralign);
174 CONVERT (shdr[cnt].sh_entsize);
175 }
176 }
177 else
178 {
179 /* The file descriptor was already enabled and not all data was
180 read. Undo the allocation. */
181 __libelf_seterrno (ELF_E_FD_DISABLED);
182
183 free_and_out:
184 free (shdr);
185 elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
186 elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
187
188 goto out;
189 }
190
191 /* Set the pointers in the `scn's. */
192 for (size_t cnt = 0; cnt < shnum; ++cnt)
193 elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
194 = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
195
196 result = scn->shdr.ELFW(e,LIBELFBITS);
197 assert (result != NULL);
198
199out:
200 return result;
201}
202
203static bool
204scn_valid (Elf_Scn *scn)
205{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000206 if (scn == NULL)
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000207 return false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000208
209 if (unlikely (scn->elf->state.elf.ehdr == NULL))
210 {
211 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000212 return false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000213 }
214
215 if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
216 {
217 __libelf_seterrno (ELF_E_INVALID_CLASS);
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000218 return false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000219 }
220
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000221 return true;
222}
223
224ElfW2(LIBELFBITS,Shdr) *
225__elfw2(LIBELFBITS,getshdr_rdlock) (scn)
226 Elf_Scn *scn;
227{
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000228 ElfW2(LIBELFBITS,Shdr) *result;
229
230 if (!scn_valid (scn))
231 return NULL;
232
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000233 result = scn->shdr.ELFW(e,LIBELFBITS);
234 if (result == NULL)
235 {
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000236 rwlock_unlock (scn->elf->lock);
237 rwlock_wrlock (scn->elf->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000238 result = scn->shdr.ELFW(e,LIBELFBITS);
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000239 if (result == NULL)
Ulrich Drepper02f66452008-12-04 05:58:16 +0000240 result = load_shdr_wrlock (scn);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000241 }
242
243 return result;
244}
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000245
246ElfW2(LIBELFBITS,Shdr) *
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000247__elfw2(LIBELFBITS,getshdr_wrlock) (scn)
248 Elf_Scn *scn;
249{
250 ElfW2(LIBELFBITS,Shdr) *result;
251
252 if (!scn_valid (scn))
253 return NULL;
254
255 result = scn->shdr.ELFW(e,LIBELFBITS);
256 if (result == NULL)
Ulrich Drepper02f66452008-12-04 05:58:16 +0000257 result = load_shdr_wrlock (scn);
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000258
259 return result;
260}
261
262ElfW2(LIBELFBITS,Shdr) *
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000263elfw2(LIBELFBITS,getshdr) (scn)
264 Elf_Scn *scn;
265{
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000266 ElfW2(LIBELFBITS,Shdr) *result;
267
268 if (!scn_valid (scn))
269 return NULL;
270
271 rwlock_rdlock (scn->elf->lock);
272 result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
273 rwlock_unlock (scn->elf->lock);
274
275 return result;
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000276}