1
/* Return the next data element from the section after possibly converting it.
2
Copyright (C) 1998-2005, 2006 Red Hat, Inc.
3
This file is part of Red Hat elfutils.
4
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6
Red Hat elfutils is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by the
8
Free Software Foundation; version 2 of the License.
10
Red Hat elfutils is distributed in the hope that it will be useful, but
11
WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
General Public License for more details.
15
You should have received a copy of the GNU General Public License along
16
with Red Hat elfutils; if not, write to the Free Software Foundation,
17
Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19
In addition, as a special exception, Red Hat, Inc. gives You the
20
additional right to link the code of Red Hat elfutils with code licensed
21
under any Open Source Initiative certified open source license
22
(http://www.opensource.org/licenses/index.php) which requires the
23
distribution of source code with any binary distribution and to
24
distribute linked combinations of the two. Non-GPL Code permitted under
25
this exception must only link to the code of Red Hat elfutils through
26
those well defined interfaces identified in the file named EXCEPTION
27
found in the source code files (the "Approved Interfaces"). The files
28
of Non-GPL Code may instantiate templates or use macros or inline
29
functions from the Approved Interfaces without causing the resulting
30
work to be covered by the GNU General Public License. Only Red Hat,
31
Inc. may make changes or additions to the list of Approved Interfaces.
32
Red Hat's grant of this exception is conditioned upon your not adding
33
any new exceptions. If you wish to add a new Approved Interface or
34
exception, please contact Red Hat. You must obey the GNU General Public
35
License in all respects for all of the Red Hat elfutils code and other
36
code used in conjunction with Red Hat elfutils except the Non-GPL Code
37
covered by this exception. If you modify this file, you may extend this
38
exception to your version of the file, but you are not obligated to do
39
so. If you do not wish to provide this exception without modification,
40
you must delete this exception statement from your version and license
41
this file solely under the GPL without exception.
43
Red Hat elfutils is an included package of the Open Invention Network.
44
An included package of the Open Invention Network is a package for which
45
Open Invention Network licensees cross-license their patents. No patent
46
license is granted, either expressly or impliedly, by designation as an
47
included package. Should you wish to participate in the Open Invention
48
Network licensing program, please visit www.openinventionnetwork.com
49
<http://www.openinventionnetwork.com>. */
63
#include "elf-knowledge.h"
66
#if _STRING_ARCH_unaligned
67
# define ALLOW_ALIGNED 1
69
# define ALLOW_ALIGNED 0
73
#define TYPEIDX(Sh_Type) \
74
(Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \
76
: (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \
77
? SHT_NUM + Sh_Type - SHT_GNU_HASH \
90
} shtype_map[EV_NUM - 1][ELFCLASSNUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
96
/* Associate section types with libelf types, their sizes and
97
alignment. SHT_GNU_verdef is special since the section does
98
not contain entries of only one size. */
99
#define DEFINE(Bits) \
100
[SHT_SYMTAB] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym)) \
101
AL (__alignof__ (ElfW2(Bits,Sym))) }, \
102
[SHT_RELA] = { ELF_T_RELA, sizeof (ElfW2(Bits,Rela)) \
103
AL (__alignof__ (ElfW2(Bits,Rela))) }, \
104
[SHT_HASH] = { ELF_T_WORD, sizeof (ElfW2(Bits,Word)) \
105
AL (__alignof__ (ElfW2(Bits,Word))) }, \
106
[SHT_DYNAMIC] = { ELF_T_DYN, sizeof (ElfW2(Bits,Dyn)) \
107
AL (__alignof__ (ElfW2(Bits,Dyn))) }, \
108
[SHT_REL] = { ELF_T_REL, sizeof (ElfW2(Bits,Rel)) \
109
AL (__alignof__ (ElfW2(Bits,Rel))) }, \
110
[SHT_DYNSYM] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym)) \
111
AL (__alignof__ (ElfW2(Bits,Sym))) }, \
112
[SHT_INIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \
113
AL (__alignof__ (ElfW2(Bits,Addr))) }, \
114
[SHT_FINI_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \
115
AL (__alignof__ (ElfW2(Bits,Addr))) }, \
116
[SHT_PREINIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr)) \
117
AL (__alignof__ (ElfW2(Bits,Addr))) }, \
118
[SHT_GROUP] = { ELF_T_WORD, sizeof (Elf32_Word) \
119
AL (__alignof__ (Elf32_Word)) }, \
120
[SHT_SYMTAB_SHNDX] = { ELF_T_WORD, sizeof (Elf32_Word) \
121
AL (__alignof__ (Elf32_Word)) }, \
122
[TYPEIDX (SHT_GNU_verdef)] = { ELF_T_VDEF, 1 AL (1) }, \
123
[TYPEIDX (SHT_GNU_verneed)] = { ELF_T_VNEED, \
124
sizeof (ElfW2(Bits,Verneed)) \
125
AL (__alignof__ (ElfW2(Bits,Verneed)))},\
126
[TYPEIDX (SHT_GNU_versym)] = { ELF_T_HALF, sizeof (ElfW2(Bits,Versym)) \
127
AL (__alignof__ (ElfW2(Bits,Versym))) }, \
128
[TYPEIDX (SHT_SUNW_syminfo)] = { ELF_T_SYMINFO, \
129
sizeof (ElfW2(Bits,Syminfo)) \
130
AL(__alignof__ (ElfW2(Bits,Syminfo)))},\
131
[TYPEIDX (SHT_SUNW_move)] = { ELF_T_MOVE, sizeof (ElfW2(Bits,Move)) \
132
AL (__alignof__ (ElfW2(Bits,Move))) }, \
133
[TYPEIDX (SHT_GNU_LIBLIST)] = { ELF_T_LIB, sizeof (ElfW2(Bits,Lib)) \
134
AL (__alignof__ (ElfW2(Bits,Lib))) }
136
[TYPEIDX (SHT_GNU_HASH)] = { ELF_T_WORD, sizeof (Elf32_Word)
137
AL (__alignof__ (Elf32_Word)) }
142
[TYPEIDX (SHT_GNU_HASH)] = { ELF_T_GNUHASH, 1
143
AL (__alignof__ (Elf64_Xword)) }
149
/* Convert the data in the current section. */
151
convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
152
int data, size_t size, size_t type)
155
/* No need to compute the alignment requirement of the host. */
156
const size_t align = 1;
159
size_t align = shtype_map[version - 1][eclass - 1][type].align;
161
size_t align = shtype_map[0][eclass - 1][type].align;
165
if (data == MY_ELFDATA)
168
|| (((size_t) ((char *) scn->rawdata_base)) & (align - 1)) == 0)
169
/* No need to copy, we can use the raw data. */
170
scn->data_base = scn->rawdata_base;
173
scn->data_base = (char *) malloc (size);
174
if (scn->data_base == NULL)
176
__libelf_seterrno (ELF_E_NOMEM);
180
/* The copy will be appropriately aligned for direct access. */
181
memcpy (scn->data_base, scn->rawdata_base, size);
188
scn->data_base = (char *) malloc (size);
189
if (scn->data_base == NULL)
191
__libelf_seterrno (ELF_E_NOMEM);
195
/* Get the conversion function. */
197
fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type];
199
fp = __elf_xfctstom[0][0][eclass - 1][type];
202
fp (scn->data_base, scn->rawdata_base, size, 0);
205
scn->data_list.data.d.d_buf = scn->data_base;
206
scn->data_list.data.d.d_size = size;
207
scn->data_list.data.d.d_type = type;
208
scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
209
scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
210
scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
212
scn->data_list.data.s = scn;
216
/* Store the information for the raw data in the `rawdata' element. */
219
__libelf_set_rawdata (Elf_Scn *scn)
227
if (elf->class == ELFCLASS32)
229
Elf32_Shdr *shdr = scn->shdr.e32 ?: INTUSE(elf32_getshdr) (scn);
232
/* Something went terribly wrong. */
235
offset = shdr->sh_offset;
236
size = shdr->sh_size;
237
type = shdr->sh_type;
238
align = shdr->sh_addralign;
242
Elf64_Shdr *shdr = scn->shdr.e64 ?: INTUSE(elf64_getshdr) (scn);
245
/* Something went terribly wrong. */
248
offset = shdr->sh_offset;
249
size = shdr->sh_size;
250
type = shdr->sh_type;
251
align = shdr->sh_addralign;
254
/* If the section has no data (for whatever reason), leave the `d_buf'
256
if (size != 0 && type != SHT_NOBITS)
258
/* First a test whether the section is valid at all. */
261
if (type == SHT_HASH)
265
entsize = SH_ENTSIZE_HASH (INTUSE(gelf_getehdr) (elf, &ehdr_mem));
270
entsize = shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].size;
272
entsize = shtype_map[0][elf->class - 1][TYPEIDX (type)].size;
276
/* We assume it is an array of bytes if it is none of the structured
277
sections we know of. */
281
if (unlikely (size % entsize != 0))
283
__libelf_seterrno (ELF_E_INVALID_DATA);
287
/* We can use the mapped or loaded data if available. */
288
if (elf->map_address != NULL)
290
/* First see whether the information in the section header is
291
valid and it does not ask for too much. */
292
if (unlikely (offset + size > elf->maximum_size))
294
/* Something is wrong. */
295
__libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
299
scn->rawdata_base = scn->rawdata.d.d_buf
300
= (char *) elf->map_address + elf->start_offset + offset;
302
else if (likely (elf->fildes != -1))
304
/* We have to read the data from the file. Allocate the needed
306
scn->rawdata_base = scn->rawdata.d.d_buf
307
= (char *) malloc (size);
308
if (scn->rawdata.d.d_buf == NULL)
310
__libelf_seterrno (ELF_E_NOMEM);
314
ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
315
elf->start_offset + offset);
316
if (unlikely ((size_t) n != size))
318
/* Cannot read the data. */
319
free (scn->rawdata.d.d_buf);
320
scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
321
__libelf_seterrno (ELF_E_READ_ERROR);
327
/* The file descriptor is already closed, we cannot get the data
329
__libelf_seterrno (ELF_E_FD_DISABLED);
334
scn->rawdata.d.d_size = size;
335
/* Some broken ELF ABI for 64-bit machines use the wrong hash table
336
entry size. See elf-knowledge.h for more information. */
337
if (type == SHT_HASH && elf->class == ELFCLASS64)
341
scn->rawdata.d.d_type
342
= (SH_ENTSIZE_HASH (INTUSE(gelf_getehdr) (elf, &ehdr_mem)) == 4
343
? ELF_T_WORD : ELF_T_XWORD);
348
scn->rawdata.d.d_type =
349
shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].type;
351
scn->rawdata.d.d_type =
352
shtype_map[0][elf->class - 1][TYPEIDX (type)].type;
355
scn->rawdata.d.d_off = 0;
356
scn->rawdata.d.d_align = align;
357
if (elf->class == ELFCLASS32
358
|| (offsetof (struct Elf, state.elf32.ehdr)
359
== offsetof (struct Elf, state.elf64.ehdr)))
360
scn->rawdata.d.d_version =
361
elf->state.elf32.ehdr->e_ident[EI_VERSION];
363
scn->rawdata.d.d_version =
364
elf->state.elf64.ehdr->e_ident[EI_VERSION];
366
scn->rawdata.s = scn;
370
/* We actually read data from the file. At least we tried. */
371
scn->flags |= ELF_F_FILEDATA;
378
elf_getdata (scn, data)
382
Elf_Data *result = NULL;
388
if (unlikely (scn->elf->kind != ELF_K_ELF))
390
__libelf_seterrno (ELF_E_INVALID_HANDLE);
394
/* We will need this multiple times later on. */
397
rwlock_rdlock (elf->lock);
399
/* If `data' is not NULL this means we are not addressing the initial
400
data in the file. But this also means this data is already read
401
(since otherwise it is not possible to have a valid `data' pointer)
402
and all the data structures are initialized as well. In this case
403
we can simply walk the list of data records. */
408
/* It is not possible that if DATA is not NULL the first entry is
409
returned. But this also means that there must be a first data
411
if (scn->data_list_rear == NULL
412
/* The section the reference data is for must match the section
414
|| unlikely (((Elf_Data_Scn *) data)->s != scn))
416
__libelf_seterrno (ELF_E_DATA_MISMATCH);
420
/* We start searching with the first entry. */
421
runp = &scn->data_list;
425
/* If `data' does not match any known record punt. */
428
__libelf_seterrno (ELF_E_DATA_MISMATCH);
432
if (&runp->data.d == data)
433
/* Found the entry. */
439
/* Return the data for the next data record. */
440
result = runp->next ? &runp->next->data.d : NULL;
444
/* If the data for this section was not yet initialized do it now. */
445
if (scn->data_read == 0)
447
/* We cannot acquire a write lock while we are holding a read
448
lock. Therefore give up the read lock and then get the write
449
lock. But this means that the data could meanwhile be
450
modified, therefore start the tests again. */
451
rwlock_unlock (elf->lock);
452
rwlock_wrlock (elf->lock);
454
/* Read the data from the file. There is always a file (or
455
memory region) associated with this descriptor since
456
otherwise the `data_read' flag would be set. */
457
if (scn->data_read == 0 && __libelf_set_rawdata (scn) != 0)
458
/* Something went wrong. The error value is already set. */
462
/* At this point we know the raw data is available. But it might be
463
empty in case the section has size zero (for whatever reason).
464
Now create the converted data in case this is necessary. */
465
if (scn->data_list_rear == NULL)
467
if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
468
/* Convert according to the version and the type. */
469
convert_data (scn, __libelf_version, elf->class,
470
(elf->class == ELFCLASS32
471
|| (offsetof (struct Elf, state.elf32.ehdr)
472
== offsetof (struct Elf, state.elf64.ehdr))
473
? elf->state.elf32.ehdr->e_ident[EI_DATA]
474
: elf->state.elf64.ehdr->e_ident[EI_DATA]),
475
scn->rawdata.d.d_size, scn->rawdata.d.d_type);
477
/* This is an empty or NOBITS section. There is no buffer but
478
the size information etc is important. */
479
scn->data_list.data.d = scn->rawdata.d;
481
scn->data_list_rear = &scn->data_list;
484
/* If no data is present we cannot return any. */
485
if (scn->data_list_rear != NULL)
486
/* Return the first data element in the list. */
487
result = &scn->data_list.data.d;
490
rwlock_unlock (elf->lock);