add some utils
[libelf-compat.git] / src / elf_getdata.c
blobf60f4184b62e4d97fbf2a686e3580de72630e0f6
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/>. */
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
34 #include <errno.h>
35 #include <stddef.h>
36 #include <string.h>
37 #include <unistd.h>
39 #include "libelfP.h"
40 #include "system.h"
41 #include "common.h"
42 #include "elf-knowledge.h"
45 #define TYPEIDX(Sh_Type) \
46 (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \
47 ? Sh_Type \
48 : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \
49 ? SHT_NUM + Sh_Type - SHT_GNU_HASH \
50 : 0))
52 /* Associate section types with libelf types. */
53 static const Elf_Type shtype_map[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
55 [EV_CURRENT - 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,
79 #if !ALLOW_UNALIGNED
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) \
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)), \
99 [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
101 [EV_CURRENT - 1] =
103 [ELFCLASS32 - 1] = TYPE_ALIGNS (32),
104 [ELFCLASS64 - 1] = TYPE_ALIGNS (64),
106 # undef TYPE_ALIGNS
108 #endif
111 /* Convert the data in the current section. */
112 static void
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;
123 else
125 scn->data_base = (char *) malloc (size);
126 if (scn->data_base == NULL)
128 __libelf_seterrno (ELF_E_NOMEM);
129 return;
132 /* The copy will be appropriately aligned for direct access. */
133 memcpy (scn->data_base, scn->rawdata_base, size);
136 else
138 xfct_t fp;
140 scn->data_base = (char *) malloc (size);
141 if (scn->data_base == NULL)
143 __libelf_seterrno (ELF_E_NOMEM);
144 return;
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
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. */
170 internal_function
171 __libelf_set_rawdata_wrlock (Elf_Scn *scn)
173 size_t offset;
174 size_t size;
175 size_t align;
176 int type;
177 Elf *elf = scn->elf;
179 if (elf->class == ELFCLASS32)
181 Elf32_Shdr *shdr
182 = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
184 if (shdr == NULL)
185 /* Something went terribly wrong. */
186 return 1;
188 offset = shdr->sh_offset;
189 size = shdr->sh_size;
190 type = shdr->sh_type;
191 align = shdr->sh_addralign;
193 else
195 Elf64_Shdr *shdr
196 = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
198 if (shdr == NULL)
199 /* Something went terribly wrong. */
200 return 1;
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'
209 pointer NULL. */
210 if (size != 0 && type != SHT_NOBITS)
212 /* First a test whether the section is valid at all. */
213 size_t entsize;
215 if (type == SHT_HASH)
217 GElf_Ehdr ehdr_mem;
218 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
219 entsize = SH_ENTSIZE_HASH (ehdr);
221 else
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))
226 entsize = 1;
227 else
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. */
233 if (entsize == 0)
234 entsize = 1;
236 if (unlikely (size % entsize != 0))
238 __libelf_seterrno (ELF_E_INVALID_DATA);
239 return 1;
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);
251 return 1;
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
260 memory. */
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);
266 return 1;
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);
277 return 1;
280 else
282 /* The file descriptor is already closed, we cannot get the data
283 anymore. */
284 __libelf_seterrno (ELF_E_FD_DISABLED);
285 return 1;
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)
294 GElf_Ehdr ehdr_mem;
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);
299 else
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];
308 else
309 scn->rawdata.d.d_version =
310 elf->state.elf64.ehdr->e_ident[EI_VERSION];
312 scn->rawdata.s = scn;
314 scn->data_read = 1;
316 /* We actually read data from the file. At least we tried. */
317 scn->flags |= ELF_F_FILEDATA;
319 return 0;
323 internal_function
324 __libelf_set_rawdata (Elf_Scn *scn)
326 int result;
328 if (scn == NULL)
329 return 1;
331 rwlock_wrlock (scn->elf->lock);
332 result = __libelf_set_rawdata_wrlock (scn);
333 rwlock_unlock (scn->elf->lock);
335 return result;
338 Elf_Data *
339 internal_function
340 __elf_getdata_rdlock (scn, data)
341 Elf_Scn *scn;
342 Elf_Data *data;
344 Elf_Data *result = NULL;
345 Elf *elf;
346 int locked = 0;
348 if (scn == NULL)
349 return NULL;
351 if (unlikely (scn->elf->kind != ELF_K_ELF))
353 __libelf_seterrno (ELF_E_INVALID_HANDLE);
354 return NULL;
357 /* We will need this multiple times later on. */
358 elf = scn->elf;
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. */
365 if (data != NULL)
367 Elf_Data_List *runp;
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))
377 __libelf_seterrno (ELF_E_DATA_MISMATCH);
378 goto out;
381 /* We start searching with the first entry. */
382 runp = &scn->data_list;
384 while (1)
386 /* If `data' does not match any known record punt. */
387 if (runp == NULL)
389 __libelf_seterrno (ELF_E_DATA_MISMATCH);
390 goto out;
393 if (&runp->data.d == data)
394 /* Found the entry. */
395 break;
397 runp = runp->next;
400 /* Return the data for the next data record. */
401 result = runp->next ? &runp->next->data.d : NULL;
402 goto out;
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);
414 locked = 1;
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. */
421 goto out;
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)
431 if (!locked)
433 rwlock_unlock (elf->lock);
434 rwlock_wrlock (elf->lock);
435 if (scn->data_list_rear != NULL)
436 goto pass;
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);
448 else
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)
461 pass:
462 /* Return the first data element in the list. */
463 result = &scn->data_list.data.d;
465 out:
466 return result;
469 Elf_Data *
470 elf_getdata (scn, data)
471 Elf_Scn *scn;
472 Elf_Data *data;
474 Elf_Data *result;
476 if (scn == NULL)
477 return NULL;
479 rwlock_rdlock (scn->elf->lock);
480 result = __elf_getdata_rdlock (scn, data);
481 rwlock_unlock (scn->elf->lock);
483 return result;
485 INTDEF(elf_getdata)