blob: bc9f26ae57341b9f1cf5151f3f525c2f0a8f5938 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Return the next data element from the section after possibly converting it.
Ulrich Drepperc07fbb32007-03-30 19:14:59 +00002 Copyright (C) 1998-2005, 2006, 2007 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
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000034#include <errno.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000035#include <stddef.h>
36#include <string.h>
37#include <unistd.h>
38
39#include "libelfP.h"
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000040#include <system.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000041#include "common.h"
42#include "elf-knowledge.h"
43
44
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000045#define TYPEIDX(Sh_Type) \
46 (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \
47 ? Sh_Type \
Ulrich Drepper8ae58142006-07-12 05:22:32 +000048 : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \
49 ? SHT_NUM + Sh_Type - SHT_GNU_HASH \
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000050 : 0))
51
Ulrich Drepperc07fbb32007-03-30 19:14:59 +000052/* Associate section types with libelf types. */
53static const Elf_Type shtype_map[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000054 {
Ulrich Drepperc07fbb32007-03-30 19:14:59 +000055 [EV_CURRENT - 1] =
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000056 {
Ulrich Drepperc07fbb32007-03-30 19:14:59 +000057 [SHT_SYMTAB] = ELF_T_SYM,
58 [SHT_RELA] = ELF_T_RELA,
59 [SHT_HASH] = ELF_T_WORD,
60 [SHT_DYNAMIC] = ELF_T_DYN,
61 [SHT_REL] = ELF_T_REL,
62 [SHT_DYNSYM] = ELF_T_SYM,
63 [SHT_INIT_ARRAY] = ELF_T_ADDR,
64 [SHT_FINI_ARRAY] = ELF_T_ADDR,
65 [SHT_PREINIT_ARRAY] = ELF_T_ADDR,
66 [SHT_GROUP] = ELF_T_WORD,
67 [SHT_SYMTAB_SHNDX] = ELF_T_WORD,
Roland McGrathc76f0b02007-09-27 07:31:33 +000068 [SHT_NOTE] = ELF_T_NHDR,
Ulrich Drepperc07fbb32007-03-30 19:14:59 +000069 [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF,
70 [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED,
71 [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF,
72 [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO,
73 [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE,
74 [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB,
75 [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000076 }
Ulrich Drepperc07fbb32007-03-30 19:14:59 +000077 };
78
79#if !ALLOW_UNALIGNED
80/* Associate libelf types with their internal alignment requirements. */
81const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] =
82 {
83# define TYPE_ALIGNS(Bits) \
84 { \
85 [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \
86 [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \
87 [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \
88 [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \
89 [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \
90 [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \
91 [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \
92 [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \
93 [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \
94 [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \
95 [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \
96 [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \
97 [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \
98 [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \
Roland McGrathc76f0b02007-09-27 07:31:33 +000099 [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000100 }
101 [EV_CURRENT - 1] =
102 {
103 [ELFCLASS32 - 1] = TYPE_ALIGNS (32),
104 [ELFCLASS64 - 1] = TYPE_ALIGNS (64),
105 }
106# undef TYPE_ALIGNS
107 };
108#endif
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000109
110
111/* Convert the data in the current section. */
112static void
113convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000114 int data, size_t size, Elf_Type type)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000115{
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000116 const size_t align = __libelf_type_align (eclass, type);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000117
118 if (data == MY_ELFDATA)
119 {
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000120 if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000121 /* No need to copy, we can use the raw data. */
122 scn->data_base = scn->rawdata_base;
123 else
124 {
125 scn->data_base = (char *) malloc (size);
126 if (scn->data_base == NULL)
127 {
128 __libelf_seterrno (ELF_E_NOMEM);
129 return;
130 }
131
132 /* The copy will be appropriately aligned for direct access. */
133 memcpy (scn->data_base, scn->rawdata_base, size);
134 }
135 }
136 else
137 {
138 xfct_t fp;
139
140 scn->data_base = (char *) malloc (size);
141 if (scn->data_base == NULL)
142 {
143 __libelf_seterrno (ELF_E_NOMEM);
144 return;
145 }
146
147 /* Get the conversion function. */
148#if EV_NUM != 2
149 fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type];
150#else
151 fp = __elf_xfctstom[0][0][eclass - 1][type];
152#endif
153
154 fp (scn->data_base, scn->rawdata_base, size, 0);
155 }
156
157 scn->data_list.data.d.d_buf = scn->data_base;
158 scn->data_list.data.d.d_size = size;
159 scn->data_list.data.d.d_type = type;
160 scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
161 scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
162 scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
163
164 scn->data_list.data.s = scn;
165}
166
167
168/* Store the information for the raw data in the `rawdata' element. */
169int
Ulrich Drepper077c65f2006-07-12 19:54:51 +0000170internal_function
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000171__libelf_set_rawdata_wrlock (Elf_Scn *scn)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000172{
173 size_t offset;
174 size_t size;
175 size_t align;
176 int type;
177 Elf *elf = scn->elf;
178
179 if (elf->class == ELFCLASS32)
180 {
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000181 Elf32_Shdr *shdr
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000182 = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000183
184 if (shdr == NULL)
185 /* Something went terribly wrong. */
186 return 1;
187
188 offset = shdr->sh_offset;
189 size = shdr->sh_size;
190 type = shdr->sh_type;
191 align = shdr->sh_addralign;
192 }
193 else
194 {
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000195 Elf64_Shdr *shdr
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000196 = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000197
198 if (shdr == NULL)
199 /* Something went terribly wrong. */
200 return 1;
201
202 offset = shdr->sh_offset;
203 size = shdr->sh_size;
204 type = shdr->sh_type;
205 align = shdr->sh_addralign;
206 }
207
208 /* If the section has no data (for whatever reason), leave the `d_buf'
209 pointer NULL. */
210 if (size != 0 && type != SHT_NOBITS)
211 {
212 /* First a test whether the section is valid at all. */
213 size_t entsize;
214
215 if (type == SHT_HASH)
216 {
217 GElf_Ehdr ehdr_mem;
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000218 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000219 entsize = SH_ENTSIZE_HASH (ehdr);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000220 }
221 else
222 {
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000223 Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)];
Roland McGrathc76f0b02007-09-27 07:31:33 +0000224 if (t == ELF_T_VDEF || t == ELF_T_NHDR
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000225 || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
226 entsize = 1;
227 else
228 entsize = __libelf_type_sizes[LIBELF_EV_IDX][elf->class - 1][t];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000229 }
230
231 /* We assume it is an array of bytes if it is none of the structured
232 sections we know of. */
233 if (entsize == 0)
234 entsize = 1;
235
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000236 if (unlikely (size % entsize != 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000237 {
238 __libelf_seterrno (ELF_E_INVALID_DATA);
239 return 1;
240 }
241
242 /* We can use the mapped or loaded data if available. */
243 if (elf->map_address != NULL)
244 {
245 /* First see whether the information in the section header is
246 valid and it does not ask for too much. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000247 if (unlikely (offset + size > elf->maximum_size))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000248 {
249 /* Something is wrong. */
250 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
251 return 1;
252 }
253
254 scn->rawdata_base = scn->rawdata.d.d_buf
255 = (char *) elf->map_address + elf->start_offset + offset;
256 }
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000257 else if (likely (elf->fildes != -1))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000258 {
259 /* We have to read the data from the file. Allocate the needed
260 memory. */
261 scn->rawdata_base = scn->rawdata.d.d_buf
262 = (char *) malloc (size);
263 if (scn->rawdata.d.d_buf == NULL)
264 {
265 __libelf_seterrno (ELF_E_NOMEM);
266 return 1;
267 }
268
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000269 ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
270 elf->start_offset + offset);
271 if (unlikely ((size_t) n != size))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000272 {
273 /* Cannot read the data. */
274 free (scn->rawdata.d.d_buf);
275 scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
276 __libelf_seterrno (ELF_E_READ_ERROR);
277 return 1;
278 }
279 }
280 else
281 {
282 /* The file descriptor is already closed, we cannot get the data
283 anymore. */
284 __libelf_seterrno (ELF_E_FD_DISABLED);
285 return 1;
286 }
287 }
288
289 scn->rawdata.d.d_size = size;
290 /* Some broken ELF ABI for 64-bit machines use the wrong hash table
291 entry size. See elf-knowledge.h for more information. */
292 if (type == SHT_HASH && elf->class == ELFCLASS64)
293 {
294 GElf_Ehdr ehdr_mem;
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000295 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000296 scn->rawdata.d.d_type
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000297 = (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000298 }
299 else
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000300 scn->rawdata.d.d_type = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)];
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000301 scn->rawdata.d.d_off = 0;
302 scn->rawdata.d.d_align = align;
303 if (elf->class == ELFCLASS32
304 || (offsetof (struct Elf, state.elf32.ehdr)
305 == offsetof (struct Elf, state.elf64.ehdr)))
306 scn->rawdata.d.d_version =
307 elf->state.elf32.ehdr->e_ident[EI_VERSION];
308 else
309 scn->rawdata.d.d_version =
310 elf->state.elf64.ehdr->e_ident[EI_VERSION];
311
312 scn->rawdata.s = scn;
313
314 scn->data_read = 1;
315
316 /* We actually read data from the file. At least we tried. */
317 scn->flags |= ELF_F_FILEDATA;
318
319 return 0;
320}
321
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000322int
323internal_function
324__libelf_set_rawdata (Elf_Scn *scn)
325{
326 int result;
327
328 if (scn == NULL)
329 return 1;
330
331 rwlock_wrlock (scn->elf->lock);
332 result = __libelf_set_rawdata_wrlock (scn);
333 rwlock_unlock (scn->elf->lock);
334
335 return result;
336}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000337
338Elf_Data *
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000339internal_function
340__elf_getdata_rdlock (scn, data)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000341 Elf_Scn *scn;
342 Elf_Data *data;
343{
344 Elf_Data *result = NULL;
345 Elf *elf;
Ulrich Drepper02f66452008-12-04 05:58:16 +0000346 int locked = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000347
348 if (scn == NULL)
349 return NULL;
350
351 if (unlikely (scn->elf->kind != ELF_K_ELF))
352 {
353 __libelf_seterrno (ELF_E_INVALID_HANDLE);
354 return NULL;
355 }
356
357 /* We will need this multiple times later on. */
358 elf = scn->elf;
359
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000360 /* If `data' is not NULL this means we are not addressing the initial
361 data in the file. But this also means this data is already read
362 (since otherwise it is not possible to have a valid `data' pointer)
363 and all the data structures are initialized as well. In this case
364 we can simply walk the list of data records. */
365 if (data != NULL)
366 {
367 Elf_Data_List *runp;
368
369 /* It is not possible that if DATA is not NULL the first entry is
370 returned. But this also means that there must be a first data
371 entry. */
372 if (scn->data_list_rear == NULL
373 /* The section the reference data is for must match the section
374 parameter. */
375 || unlikely (((Elf_Data_Scn *) data)->s != scn))
376 {
377 __libelf_seterrno (ELF_E_DATA_MISMATCH);
378 goto out;
379 }
380
381 /* We start searching with the first entry. */
382 runp = &scn->data_list;
383
384 while (1)
385 {
386 /* If `data' does not match any known record punt. */
387 if (runp == NULL)
388 {
389 __libelf_seterrno (ELF_E_DATA_MISMATCH);
390 goto out;
391 }
392
393 if (&runp->data.d == data)
394 /* Found the entry. */
395 break;
396
397 runp = runp->next;
398 }
399
400 /* Return the data for the next data record. */
401 result = runp->next ? &runp->next->data.d : NULL;
402 goto out;
403 }
404
405 /* If the data for this section was not yet initialized do it now. */
406 if (scn->data_read == 0)
407 {
408 /* We cannot acquire a write lock while we are holding a read
409 lock. Therefore give up the read lock and then get the write
410 lock. But this means that the data could meanwhile be
411 modified, therefore start the tests again. */
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000412 rwlock_unlock (elf->lock);
413 rwlock_wrlock (elf->lock);
Ulrich Drepper02f66452008-12-04 05:58:16 +0000414 locked = 1;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000415
416 /* Read the data from the file. There is always a file (or
417 memory region) associated with this descriptor since
418 otherwise the `data_read' flag would be set. */
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000419 if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000420 /* Something went wrong. The error value is already set. */
421 goto out;
422 }
423
424 /* At this point we know the raw data is available. But it might be
425 empty in case the section has size zero (for whatever reason).
426 Now create the converted data in case this is necessary. */
427 if (scn->data_list_rear == NULL)
428 {
429 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
Ulrich Drepper02f66452008-12-04 05:58:16 +0000430 {
431 if (!locked)
432 {
433 rwlock_unlock (elf->lock);
434 rwlock_wrlock (elf->lock);
435 if (scn->data_list_rear != NULL)
436 goto pass;
437 }
438
439 /* Convert according to the version and the type. */
440 convert_data (scn, __libelf_version, elf->class,
441 (elf->class == ELFCLASS32
442 || (offsetof (struct Elf, state.elf32.ehdr)
443 == offsetof (struct Elf, state.elf64.ehdr))
444 ? elf->state.elf32.ehdr->e_ident[EI_DATA]
445 : elf->state.elf64.ehdr->e_ident[EI_DATA]),
446 scn->rawdata.d.d_size, scn->rawdata.d.d_type);
447 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000448 else
Petr Machatad7b12c62010-04-06 14:17:41 +0200449 {
450 /* This is an empty or NOBITS section. There is no buffer but
451 the size information etc is important. */
452 scn->data_list.data.d = scn->rawdata.d;
453 scn->data_list.data.s = scn;
454 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000455
456 scn->data_list_rear = &scn->data_list;
457 }
458
459 /* If no data is present we cannot return any. */
460 if (scn->data_list_rear != NULL)
Ulrich Drepper02f66452008-12-04 05:58:16 +0000461 pass:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000462 /* Return the first data element in the list. */
463 result = &scn->data_list.data.d;
464
465 out:
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000466 return result;
467}
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000468
469Elf_Data *
470elf_getdata (scn, data)
471 Elf_Scn *scn;
472 Elf_Data *data;
473{
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000474 Elf_Data *result;
475
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000476 if (scn == NULL)
477 return NULL;
478
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000479 rwlock_rdlock (scn->elf->lock);
480 result = __elf_getdata_rdlock (scn, data);
481 rwlock_unlock (scn->elf->lock);
482
483 return result;
Ulrich Drepperd56e2322008-08-16 03:09:13 +0000484}
Roland McGrathb4d6f0f2008-08-25 22:55:17 +0000485INTDEF(elf_getdata)