1 /* Return the next data element from the section after possibly converting it.
2 Copyright (C) 1998-2005, 2006, 2007 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
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/>. */
42 #include "elf-knowledge.h"
45 #define TYPEIDX(Sh_Type) \
46 (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \
48 : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \
49 ? SHT_NUM + Sh_Type - SHT_GNU_HASH \
52 /* Associate section types with libelf types. */
53 static const Elf_Type shtype_map
[EV_NUM
- 1][TYPEIDX (SHT_HISUNW
) + 1] =
57 [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
,
68 [SHT_NOTE
] = ELF_T_NHDR
,
69 [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
,
80 /* Associate libelf types with their internal alignment requirements. */
81 const uint_fast8_t __libelf_type_aligns
[EV_NUM
- 1][ELFCLASSNUM
- 1][ELF_T_NUM
] =
83 # define TYPE_ALIGNS(Bits) \
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)), \
99 [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
103 [ELFCLASS32
- 1] = TYPE_ALIGNS (32),
104 [ELFCLASS64
- 1] = TYPE_ALIGNS (64),
111 /* Convert the data in the current section. */
113 convert_data (Elf_Scn
*scn
, int version
__attribute__ ((unused
)), int eclass
,
114 int data
, size_t size
, Elf_Type type
)
116 const size_t align
= __libelf_type_align (eclass
, type
);
118 if (data
== MY_ELFDATA
)
120 if (((((size_t) (char *) scn
->rawdata_base
)) & (align
- 1)) == 0)
121 /* No need to copy, we can use the raw data. */
122 scn
->data_base
= scn
->rawdata_base
;
125 scn
->data_base
= (char *) malloc (size
);
126 if (scn
->data_base
== NULL
)
128 __libelf_seterrno (ELF_E_NOMEM
);
132 /* The copy will be appropriately aligned for direct access. */
133 memcpy (scn
->data_base
, scn
->rawdata_base
, size
);
140 scn
->data_base
= (char *) malloc (size
);
141 if (scn
->data_base
== NULL
)
143 __libelf_seterrno (ELF_E_NOMEM
);
147 /* Get the conversion function. */
149 fp
= __elf_xfctstom
[version
- 1][__libelf_version
- 1][eclass
- 1][type
];
151 fp
= __elf_xfctstom
[0][0][eclass
- 1][type
];
154 fp (scn
->data_base
, scn
->rawdata_base
, size
, 0);
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
;
164 scn
->data_list
.data
.s
= scn
;
168 /* Store the information for the raw data in the `rawdata' element. */
171 __libelf_set_rawdata_wrlock (Elf_Scn
*scn
)
179 if (elf
->class == ELFCLASS32
)
182 = scn
->shdr
.e32
?: __elf32_getshdr_wrlock (scn
);
185 /* Something went terribly wrong. */
188 offset
= shdr
->sh_offset
;
189 size
= shdr
->sh_size
;
190 type
= shdr
->sh_type
;
191 align
= shdr
->sh_addralign
;
196 = scn
->shdr
.e64
?: __elf64_getshdr_wrlock (scn
);
199 /* Something went terribly wrong. */
202 offset
= shdr
->sh_offset
;
203 size
= shdr
->sh_size
;
204 type
= shdr
->sh_type
;
205 align
= shdr
->sh_addralign
;
208 /* If the section has no data (for whatever reason), leave the `d_buf'
210 if (size
!= 0 && type
!= SHT_NOBITS
)
212 /* First a test whether the section is valid at all. */
215 if (type
== SHT_HASH
)
218 GElf_Ehdr
*ehdr
= __gelf_getehdr_rdlock (elf
, &ehdr_mem
);
219 entsize
= SH_ENTSIZE_HASH (ehdr
);
223 Elf_Type t
= shtype_map
[LIBELF_EV_IDX
][TYPEIDX (type
)];
224 if (t
== ELF_T_VDEF
|| t
== ELF_T_NHDR
225 || (t
== ELF_T_GNUHASH
&& elf
->class == ELFCLASS64
))
228 entsize
= __libelf_type_sizes
[LIBELF_EV_IDX
][elf
->class - 1][t
];
231 /* We assume it is an array of bytes if it is none of the structured
232 sections we know of. */
236 if (unlikely (size
% entsize
!= 0))
238 __libelf_seterrno (ELF_E_INVALID_DATA
);
242 /* We can use the mapped or loaded data if available. */
243 if (elf
->map_address
!= NULL
)
245 /* First see whether the information in the section header is
246 valid and it does not ask for too much. */
247 if (unlikely (offset
+ size
> elf
->maximum_size
))
249 /* Something is wrong. */
250 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER
);
254 scn
->rawdata_base
= scn
->rawdata
.d
.d_buf
255 = (char *) elf
->map_address
+ elf
->start_offset
+ offset
;
257 else if (likely (elf
->fildes
!= -1))
259 /* We have to read the data from the file. Allocate the needed
261 scn
->rawdata_base
= scn
->rawdata
.d
.d_buf
262 = (char *) malloc (size
);
263 if (scn
->rawdata
.d
.d_buf
== NULL
)
265 __libelf_seterrno (ELF_E_NOMEM
);
269 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
))
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
);
282 /* The file descriptor is already closed, we cannot get the data
284 __libelf_seterrno (ELF_E_FD_DISABLED
);
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
)
295 GElf_Ehdr
*ehdr
= __gelf_getehdr_rdlock (elf
, &ehdr_mem
);
296 scn
->rawdata
.d
.d_type
297 = (SH_ENTSIZE_HASH (ehdr
) == 4 ? ELF_T_WORD
: ELF_T_XWORD
);
300 scn
->rawdata
.d
.d_type
= shtype_map
[LIBELF_EV_IDX
][TYPEIDX (type
)];
301 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
];
309 scn
->rawdata
.d
.d_version
=
310 elf
->state
.elf64
.ehdr
->e_ident
[EI_VERSION
];
312 scn
->rawdata
.s
= scn
;
316 /* We actually read data from the file. At least we tried. */
317 scn
->flags
|= ELF_F_FILEDATA
;
324 __libelf_set_rawdata (Elf_Scn
*scn
)
331 rwlock_wrlock (scn
->elf
->lock
);
332 result
= __libelf_set_rawdata_wrlock (scn
);
333 rwlock_unlock (scn
->elf
->lock
);
340 __elf_getdata_rdlock (scn
, data
)
344 Elf_Data
*result
= NULL
;
351 if (unlikely (scn
->elf
->kind
!= ELF_K_ELF
))
353 __libelf_seterrno (ELF_E_INVALID_HANDLE
);
357 /* We will need this multiple times later on. */
360 /* 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. */
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
372 if (scn
->data_list_rear
== NULL
373 /* The section the reference data is for must match the section
375 || unlikely (((Elf_Data_Scn
*) data
)->s
!= scn
))
377 __libelf_seterrno (ELF_E_DATA_MISMATCH
);
381 /* We start searching with the first entry. */
382 runp
= &scn
->data_list
;
386 /* If `data' does not match any known record punt. */
389 __libelf_seterrno (ELF_E_DATA_MISMATCH
);
393 if (&runp
->data
.d
== data
)
394 /* Found the entry. */
400 /* Return the data for the next data record. */
401 result
= runp
->next
? &runp
->next
->data
.d
: NULL
;
405 /* If the data for this section was not yet initialized do it now. */
406 if (scn
->data_read
== 0)
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. */
412 rwlock_unlock (elf
->lock
);
413 rwlock_wrlock (elf
->lock
);
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. */
419 if (scn
->data_read
== 0 && __libelf_set_rawdata_wrlock (scn
) != 0)
420 /* Something went wrong. The error value is already set. */
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
)
429 if (scn
->rawdata
.d
.d_buf
!= NULL
&& scn
->rawdata
.d
.d_size
> 0)
433 rwlock_unlock (elf
->lock
);
434 rwlock_wrlock (elf
->lock
);
435 if (scn
->data_list_rear
!= NULL
)
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
);
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
;
456 scn
->data_list_rear
= &scn
->data_list
;
459 /* If no data is present we cannot return any. */
460 if (scn
->data_list_rear
!= NULL
)
462 /* Return the first data element in the list. */
463 result
= &scn
->data_list
.data
.d
;
470 elf_getdata (scn
, data
)
479 rwlock_rdlock (scn
->elf
->lock
);
480 result
= __elf_getdata_rdlock (scn
, data
);
481 rwlock_unlock (scn
->elf
->lock
);