1 /* Return the next data element from the section after possibly converting it.
2 Copyright (C) 1998-2005, 2006, 2007, 2015, 2016 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
8
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
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
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.
25
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/>. */
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #include <errno.h>
35 #include <stddef.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include "libelfP.h"
40 #include <system.h>
41 #include "common.h"
42 #include "elf-knowledge.h"
43
44
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))
51
52 /* Associate section types with libelf types. */
53 static const Elf_Type shtype_map[TYPEIDX (SHT_HISUNW) + 1] =
54 {
55 [SHT_SYMTAB] = ELF_T_SYM,
56 [SHT_RELA] = ELF_T_RELA,
57 [SHT_HASH] = ELF_T_WORD,
58 [SHT_DYNAMIC] = ELF_T_DYN,
59 [SHT_REL] = ELF_T_REL,
60 [SHT_DYNSYM] = ELF_T_SYM,
61 [SHT_INIT_ARRAY] = ELF_T_ADDR,
62 [SHT_FINI_ARRAY] = ELF_T_ADDR,
63 [SHT_PREINIT_ARRAY] = ELF_T_ADDR,
64 [SHT_GROUP] = ELF_T_WORD,
65 [SHT_SYMTAB_SHNDX] = ELF_T_WORD,
66 [SHT_NOTE] = ELF_T_NHDR, /* Need alignment to guess ELF_T_NHDR8. */
67 [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF,
68 [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED,
69 [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF,
70 [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO,
71 [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE,
72 [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB,
73 [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH,
74 };
75
76 /* Associate libelf types with their internal alignment requirements. */
77 const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
78 {
79 # define TYPE_ALIGNS(Bits) \
80 { \
81 [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \
82 [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)), \
83 [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \
84 [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)), \
85 [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)), \
86 [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)), \
87 [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)), \
88 [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \
89 [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)), \
90 [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)), \
91 [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \
92 [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \
93 [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \
94 [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \
95 [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \
96 [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \
97 [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \
98 [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \
99 [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \
100 [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \
101 [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \
102 [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
103 [ELF_T_GNUHASH] = __alignof__ (Elf32_Word), \
104 [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)), \
105 [ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)), \
106 [ELF_T_NHDR8] = 8 /* Special case for GNU Property note. */ \
107 }
108 [ELFCLASS32 - 1] = TYPE_ALIGNS (32),
109 [ELFCLASS64 - 1] = TYPE_ALIGNS (64),
110 # undef TYPE_ALIGNS
111 };
112
113
114 Elf_Type
115 internal_function
__libelf_data_type(GElf_Ehdr * ehdr,int sh_type,GElf_Xword align)116 __libelf_data_type (GElf_Ehdr *ehdr, int sh_type, GElf_Xword align)
117 {
118 /* Some broken ELF ABI for 64-bit machines use the wrong hash table
119 entry size. See elf-knowledge.h for more information. */
120 if (sh_type == SHT_HASH && ehdr->e_ident[EI_CLASS] == ELFCLASS64)
121 {
122 return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
123 }
124 else
125 {
126 Elf_Type t = shtype_map[TYPEIDX (sh_type)];
127 /* Special case for GNU Property notes. */
128 if (t == ELF_T_NHDR && align == 8)
129 t = ELF_T_NHDR8;
130 return t;
131 }
132 }
133
134 /* Convert the data in the current section. */
135 static void
convert_data(Elf_Scn * scn,int eclass,int data,size_t size,Elf_Type type)136 convert_data (Elf_Scn *scn, int eclass,
137 int data, size_t size, Elf_Type type)
138 {
139 const size_t align = __libelf_type_align (eclass, type);
140
141 /* Do we need to convert the data and/or adjust for alignment? */
142 if (data == MY_ELFDATA || type == ELF_T_BYTE)
143 {
144 if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
145 /* No need to copy, we can use the raw data. */
146 scn->data_base = scn->rawdata_base;
147 else
148 {
149 scn->data_base = malloc (size);
150 if (scn->data_base == NULL)
151 {
152 __libelf_seterrno (ELF_E_NOMEM);
153 return;
154 }
155
156 /* The copy will be appropriately aligned for direct access. */
157 memcpy (scn->data_base, scn->rawdata_base, size);
158 }
159 }
160 else
161 {
162 xfct_t fp;
163
164 scn->data_base = malloc (size);
165 if (scn->data_base == NULL)
166 {
167 __libelf_seterrno (ELF_E_NOMEM);
168 return;
169 }
170
171 /* Make sure the source is correctly aligned for the conversion
172 function to directly access the data elements. */
173 char *rawdata_source;
174 if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
175 rawdata_source = scn->rawdata_base;
176 else
177 {
178 rawdata_source = malloc (size);
179 if (rawdata_source == NULL)
180 {
181 __libelf_seterrno (ELF_E_NOMEM);
182 return;
183 }
184
185 /* The copy will be appropriately aligned for direct access. */
186 memcpy (rawdata_source, scn->rawdata_base, size);
187 }
188
189 /* Get the conversion function. */
190 fp = __elf_xfctstom[eclass - 1][type];
191
192 fp (scn->data_base, rawdata_source, size, 0);
193
194 if (rawdata_source != scn->rawdata_base)
195 free (rawdata_source);
196 }
197
198 scn->data_list.data.d.d_buf = scn->data_base;
199 scn->data_list.data.d.d_size = size;
200 scn->data_list.data.d.d_type = type;
201 scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
202 scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
203 scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
204
205 scn->data_list.data.s = scn;
206 }
207
208
209 /* Store the information for the raw data in the `rawdata' element. */
210 int
211 internal_function
__libelf_set_rawdata_wrlock(Elf_Scn * scn)212 __libelf_set_rawdata_wrlock (Elf_Scn *scn)
213 {
214 Elf64_Off offset;
215 Elf64_Xword size;
216 Elf64_Xword align;
217 Elf64_Xword flags;
218 int type;
219 Elf *elf = scn->elf;
220
221 if (elf->class == ELFCLASS32)
222 {
223 Elf32_Shdr *shdr
224 = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
225
226 if (shdr == NULL)
227 /* Something went terribly wrong. */
228 return 1;
229
230 offset = shdr->sh_offset;
231 size = shdr->sh_size;
232 type = shdr->sh_type;
233 align = shdr->sh_addralign;
234 flags = shdr->sh_flags;
235 }
236 else
237 {
238 Elf64_Shdr *shdr
239 = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
240
241 if (shdr == NULL)
242 /* Something went terribly wrong. */
243 return 1;
244
245 offset = shdr->sh_offset;
246 size = shdr->sh_size;
247 type = shdr->sh_type;
248 align = shdr->sh_addralign;
249 flags = shdr->sh_flags;
250 }
251
252 /* If the section has no data (for whatever reason), leave the `d_buf'
253 pointer NULL. */
254 if (size != 0 && type != SHT_NOBITS)
255 {
256 /* First a test whether the section is valid at all. */
257 size_t entsize;
258
259 /* Compressed data has a header, but then compressed data.
260 Make sure to set the alignment of the header explicitly,
261 don't trust the file alignment for the section, it is
262 often wrong. */
263 if ((flags & SHF_COMPRESSED) != 0)
264 {
265 entsize = 1;
266 align = __libelf_type_align (elf->class, ELF_T_CHDR);
267 }
268 else if (type == SHT_HASH)
269 {
270 GElf_Ehdr ehdr_mem;
271 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
272 if (unlikely (ehdr == NULL))
273 return 1;
274 entsize = SH_ENTSIZE_HASH (ehdr);
275 }
276 else
277 {
278 Elf_Type t = shtype_map[TYPEIDX (type)];
279 if (t == ELF_T_NHDR && align == 8)
280 t = ELF_T_NHDR8;
281 if (t == ELF_T_VDEF || t == ELF_T_NHDR || t == ELF_T_NHDR8
282 || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
283 entsize = 1;
284 else
285 entsize = __libelf_type_sizes[elf->class - 1][t];
286 }
287
288 /* We assume it is an array of bytes if it is none of the structured
289 sections we know of. */
290 if (entsize == 0)
291 entsize = 1;
292
293 if (unlikely (size % entsize != 0))
294 {
295 __libelf_seterrno (ELF_E_INVALID_DATA);
296 return 1;
297 }
298
299 /* We can use the mapped or loaded data if available. */
300 if (elf->map_address != NULL)
301 {
302 /* First see whether the information in the section header is
303 valid and it does not ask for too much. Check for unsigned
304 overflow. */
305 if (unlikely (offset > elf->maximum_size
306 || elf->maximum_size - offset < size))
307 {
308 /* Something is wrong. */
309 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
310 return 1;
311 }
312
313 scn->rawdata_base = scn->rawdata.d.d_buf
314 = (char *) elf->map_address + elf->start_offset + offset;
315 }
316 else if (likely (elf->fildes != -1))
317 {
318 /* First see whether the information in the section header is
319 valid and it does not ask for too much. Check for unsigned
320 overflow. */
321 if (unlikely (offset > elf->maximum_size
322 || elf->maximum_size - offset < size))
323 {
324 /* Something is wrong. */
325 __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
326 return 1;
327 }
328
329 /* We have to read the data from the file. Allocate the needed
330 memory. */
331 scn->rawdata_base = scn->rawdata.d.d_buf = malloc (size);
332 if (scn->rawdata.d.d_buf == NULL)
333 {
334 __libelf_seterrno (ELF_E_NOMEM);
335 return 1;
336 }
337
338 ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
339 elf->start_offset + offset);
340 if (unlikely ((size_t) n != size))
341 {
342 /* Cannot read the data. */
343 free (scn->rawdata.d.d_buf);
344 scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
345 __libelf_seterrno (ELF_E_READ_ERROR);
346 return 1;
347 }
348 }
349 else
350 {
351 /* The file descriptor is already closed, we cannot get the data
352 anymore. */
353 __libelf_seterrno (ELF_E_FD_DISABLED);
354 return 1;
355 }
356 }
357
358 scn->rawdata.d.d_size = size;
359
360 /* Compressed data always has type ELF_T_CHDR regardless of the
361 section type. */
362 if ((flags & SHF_COMPRESSED) != 0)
363 scn->rawdata.d.d_type = ELF_T_CHDR;
364 else
365 {
366 GElf_Ehdr ehdr_mem;
367 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
368 if (unlikely (ehdr == NULL))
369 return 1;
370 scn->rawdata.d.d_type = __libelf_data_type (ehdr, type, align);
371 }
372 scn->rawdata.d.d_off = 0;
373
374 /* Make sure the alignment makes sense. d_align should be aligned both
375 in the section (trivially true since d_off is zero) and in the file.
376 Unfortunately we cannot be too strict because there are ELF files
377 out there that fail this requirement. We will try to fix those up
378 in elf_update when writing out the image. But for very large
379 alignment values this can bloat the image considerably. So here
380 just check and clamp the alignment value to not be bigger than the
381 actual offset of the data in the file. Given that there is always
382 at least an ehdr this will only trigger for alignment values > 64
383 which should be uncommon. */
384 align = align ?: 1;
385 if (type != SHT_NOBITS && align > offset)
386 {
387 /* Align the offset to the next power of two. Uses algorithm from
388 https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
389 align = offset - 1;
390 align |= align >> 1;
391 align |= align >> 2;
392 align |= align >> 4;
393 align |= align >> 8;
394 align |= align >> 16;
395 align |= align >> 32;
396 align++;
397 }
398 scn->rawdata.d.d_align = align;
399 if (elf->class == ELFCLASS32
400 || (offsetof (struct Elf, state.elf32.ehdr)
401 == offsetof (struct Elf, state.elf64.ehdr)))
402 scn->rawdata.d.d_version =
403 elf->state.elf32.ehdr->e_ident[EI_VERSION];
404 else
405 scn->rawdata.d.d_version =
406 elf->state.elf64.ehdr->e_ident[EI_VERSION];
407
408 scn->rawdata.s = scn;
409
410 scn->data_read = 1;
411
412 /* We actually read data from the file. At least we tried. */
413 scn->flags |= ELF_F_FILEDATA;
414
415 return 0;
416 }
417
418 int
419 internal_function
__libelf_set_rawdata(Elf_Scn * scn)420 __libelf_set_rawdata (Elf_Scn *scn)
421 {
422 int result;
423
424 if (scn == NULL)
425 return 1;
426
427 rwlock_wrlock (scn->elf->lock);
428 result = __libelf_set_rawdata_wrlock (scn);
429 rwlock_unlock (scn->elf->lock);
430
431 return result;
432 }
433
434 void
435 internal_function
__libelf_set_data_list_rdlock(Elf_Scn * scn,int wrlocked)436 __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
437 {
438 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
439 {
440 Elf *elf = scn->elf;
441
442 /* Upgrade the lock to a write lock if necessary and check
443 nobody else already did the work. */
444 if (!wrlocked)
445 {
446 rwlock_unlock (elf->lock);
447 rwlock_wrlock (elf->lock);
448 if (scn->data_list_rear != NULL)
449 return;
450 }
451
452 /* Convert according to the version and the type. */
453 convert_data (scn, elf->class,
454 (elf->class == ELFCLASS32
455 || (offsetof (struct Elf, state.elf32.ehdr)
456 == offsetof (struct Elf, state.elf64.ehdr))
457 ? elf->state.elf32.ehdr->e_ident[EI_DATA]
458 : elf->state.elf64.ehdr->e_ident[EI_DATA]),
459 scn->rawdata.d.d_size, scn->rawdata.d.d_type);
460 }
461 else
462 {
463 /* This is an empty or NOBITS section. There is no buffer but
464 the size information etc is important. */
465 scn->data_list.data.d = scn->rawdata.d;
466 scn->data_list.data.s = scn;
467 }
468
469 scn->data_list_rear = &scn->data_list;
470 }
471
472 Elf_Data *
473 internal_function
__elf_getdata_rdlock(Elf_Scn * scn,Elf_Data * data)474 __elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
475 {
476 Elf_Data *result = NULL;
477 Elf *elf;
478 int locked = 0;
479
480 if (scn == NULL)
481 return NULL;
482
483 if (unlikely (scn->elf->kind != ELF_K_ELF))
484 {
485 __libelf_seterrno (ELF_E_INVALID_HANDLE);
486 return NULL;
487 }
488
489 /* We will need this multiple times later on. */
490 elf = scn->elf;
491
492 /* If `data' is not NULL this means we are not addressing the initial
493 data in the file. But this also means this data is already read
494 (since otherwise it is not possible to have a valid `data' pointer)
495 and all the data structures are initialized as well. In this case
496 we can simply walk the list of data records. */
497 if (data != NULL)
498 {
499 Elf_Data_List *runp;
500
501 /* It is not possible that if DATA is not NULL the first entry is
502 returned. But this also means that there must be a first data
503 entry. */
504 if (scn->data_list_rear == NULL
505 /* The section the reference data is for must match the section
506 parameter. */
507 || unlikely (((Elf_Data_Scn *) data)->s != scn))
508 {
509 __libelf_seterrno (ELF_E_DATA_MISMATCH);
510 goto out;
511 }
512
513 /* We start searching with the first entry. */
514 runp = &scn->data_list;
515
516 while (1)
517 {
518 /* If `data' does not match any known record punt. */
519 if (runp == NULL)
520 {
521 __libelf_seterrno (ELF_E_DATA_MISMATCH);
522 goto out;
523 }
524
525 if (&runp->data.d == data)
526 /* Found the entry. */
527 break;
528
529 runp = runp->next;
530 }
531
532 /* Return the data for the next data record. */
533 result = runp->next ? &runp->next->data.d : NULL;
534 goto out;
535 }
536
537 /* If the data for this section was not yet initialized do it now. */
538 if (scn->data_read == 0)
539 {
540 /* We cannot acquire a write lock while we are holding a read
541 lock. Therefore give up the read lock and then get the write
542 lock. But this means that the data could meanwhile be
543 modified, therefore start the tests again. */
544 rwlock_unlock (elf->lock);
545 rwlock_wrlock (elf->lock);
546 locked = 1;
547
548 /* Read the data from the file. There is always a file (or
549 memory region) associated with this descriptor since
550 otherwise the `data_read' flag would be set. */
551 if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
552 /* Something went wrong. The error value is already set. */
553 goto out;
554 }
555
556 /* At this point we know the raw data is available. But it might be
557 empty in case the section has size zero (for whatever reason).
558 Now create the converted data in case this is necessary. */
559 if (scn->data_list_rear == NULL)
560 __libelf_set_data_list_rdlock (scn, locked);
561
562 /* Return the first data element in the list. */
563 result = &scn->data_list.data.d;
564
565 out:
566 return result;
567 }
568
569 Elf_Data *
elf_getdata(Elf_Scn * scn,Elf_Data * data)570 elf_getdata (Elf_Scn *scn, Elf_Data *data)
571 {
572 Elf_Data *result;
573
574 if (scn == NULL)
575 return NULL;
576
577 rwlock_rdlock (scn->elf->lock);
578 result = __elf_getdata_rdlock (scn, data);
579 rwlock_unlock (scn->elf->lock);
580
581 return result;
582 }
583 INTDEF(elf_getdata)
584