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