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 = (char *) 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 = (char *) 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 = (char *) 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
332 = (char *) malloc (size);
333 if (scn->rawdata.d.d_buf == NULL)
334 {
335 __libelf_seterrno (ELF_E_NOMEM);
336 return 1;
337 }
338
339 ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
340 elf->start_offset + offset);
341 if (unlikely ((size_t) n != size))
342 {
343 /* Cannot read the data. */
344 free (scn->rawdata.d.d_buf);
345 scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
346 __libelf_seterrno (ELF_E_READ_ERROR);
347 return 1;
348 }
349 }
350 else
351 {
352 /* The file descriptor is already closed, we cannot get the data
353 anymore. */
354 __libelf_seterrno (ELF_E_FD_DISABLED);
355 return 1;
356 }
357 }
358
359 scn->rawdata.d.d_size = size;
360
361 /* Compressed data always has type ELF_T_CHDR regardless of the
362 section type. */
363 if ((flags & SHF_COMPRESSED) != 0)
364 scn->rawdata.d.d_type = ELF_T_CHDR;
365 else
366 {
367 GElf_Ehdr ehdr_mem;
368 GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
369 if (unlikely (ehdr == NULL))
370 return 1;
371 scn->rawdata.d.d_type = __libelf_data_type (ehdr, type, align);
372 }
373 scn->rawdata.d.d_off = 0;
374
375 /* Make sure the alignment makes sense. d_align should be aligned both
376 in the section (trivially true since d_off is zero) and in the file.
377 Unfortunately we cannot be too strict because there are ELF files
378 out there that fail this requirement. We will try to fix those up
379 in elf_update when writing out the image. But for very large
380 alignment values this can bloat the image considerably. So here
381 just check and clamp the alignment value to not be bigger than the
382 actual offset of the data in the file. Given that there is always
383 at least an ehdr this will only trigger for alignment values > 64
384 which should be uncommon. */
385 align = align ?: 1;
386 if (type != SHT_NOBITS && align > offset)
387 align = offset;
388 scn->rawdata.d.d_align = align;
389 if (elf->class == ELFCLASS32
390 || (offsetof (struct Elf, state.elf32.ehdr)
391 == offsetof (struct Elf, state.elf64.ehdr)))
392 scn->rawdata.d.d_version =
393 elf->state.elf32.ehdr->e_ident[EI_VERSION];
394 else
395 scn->rawdata.d.d_version =
396 elf->state.elf64.ehdr->e_ident[EI_VERSION];
397
398 scn->rawdata.s = scn;
399
400 scn->data_read = 1;
401
402 /* We actually read data from the file. At least we tried. */
403 scn->flags |= ELF_F_FILEDATA;
404
405 return 0;
406 }
407
408 int
409 internal_function
__libelf_set_rawdata(Elf_Scn * scn)410 __libelf_set_rawdata (Elf_Scn *scn)
411 {
412 int result;
413
414 if (scn == NULL)
415 return 1;
416
417 rwlock_wrlock (scn->elf->lock);
418 result = __libelf_set_rawdata_wrlock (scn);
419 rwlock_unlock (scn->elf->lock);
420
421 return result;
422 }
423
424 void
425 internal_function
__libelf_set_data_list_rdlock(Elf_Scn * scn,int wrlocked)426 __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
427 {
428 if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
429 {
430 Elf *elf = scn->elf;
431
432 /* Upgrade the lock to a write lock if necessary and check
433 nobody else already did the work. */
434 if (!wrlocked)
435 {
436 rwlock_unlock (elf->lock);
437 rwlock_wrlock (elf->lock);
438 if (scn->data_list_rear != NULL)
439 return;
440 }
441
442 /* Convert according to the version and the type. */
443 convert_data (scn, elf->class,
444 (elf->class == ELFCLASS32
445 || (offsetof (struct Elf, state.elf32.ehdr)
446 == offsetof (struct Elf, state.elf64.ehdr))
447 ? elf->state.elf32.ehdr->e_ident[EI_DATA]
448 : elf->state.elf64.ehdr->e_ident[EI_DATA]),
449 scn->rawdata.d.d_size, scn->rawdata.d.d_type);
450 }
451 else
452 {
453 /* This is an empty or NOBITS section. There is no buffer but
454 the size information etc is important. */
455 scn->data_list.data.d = scn->rawdata.d;
456 scn->data_list.data.s = scn;
457 }
458
459 scn->data_list_rear = &scn->data_list;
460 }
461
462 Elf_Data *
463 internal_function
__elf_getdata_rdlock(Elf_Scn * scn,Elf_Data * data)464 __elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
465 {
466 Elf_Data *result = NULL;
467 Elf *elf;
468 int locked = 0;
469
470 if (scn == NULL)
471 return NULL;
472
473 if (unlikely (scn->elf->kind != ELF_K_ELF))
474 {
475 __libelf_seterrno (ELF_E_INVALID_HANDLE);
476 return NULL;
477 }
478
479 /* We will need this multiple times later on. */
480 elf = scn->elf;
481
482 /* If `data' is not NULL this means we are not addressing the initial
483 data in the file. But this also means this data is already read
484 (since otherwise it is not possible to have a valid `data' pointer)
485 and all the data structures are initialized as well. In this case
486 we can simply walk the list of data records. */
487 if (data != NULL)
488 {
489 Elf_Data_List *runp;
490
491 /* It is not possible that if DATA is not NULL the first entry is
492 returned. But this also means that there must be a first data
493 entry. */
494 if (scn->data_list_rear == NULL
495 /* The section the reference data is for must match the section
496 parameter. */
497 || unlikely (((Elf_Data_Scn *) data)->s != scn))
498 {
499 __libelf_seterrno (ELF_E_DATA_MISMATCH);
500 goto out;
501 }
502
503 /* We start searching with the first entry. */
504 runp = &scn->data_list;
505
506 while (1)
507 {
508 /* If `data' does not match any known record punt. */
509 if (runp == NULL)
510 {
511 __libelf_seterrno (ELF_E_DATA_MISMATCH);
512 goto out;
513 }
514
515 if (&runp->data.d == data)
516 /* Found the entry. */
517 break;
518
519 runp = runp->next;
520 }
521
522 /* Return the data for the next data record. */
523 result = runp->next ? &runp->next->data.d : NULL;
524 goto out;
525 }
526
527 /* If the data for this section was not yet initialized do it now. */
528 if (scn->data_read == 0)
529 {
530 /* We cannot acquire a write lock while we are holding a read
531 lock. Therefore give up the read lock and then get the write
532 lock. But this means that the data could meanwhile be
533 modified, therefore start the tests again. */
534 rwlock_unlock (elf->lock);
535 rwlock_wrlock (elf->lock);
536 locked = 1;
537
538 /* Read the data from the file. There is always a file (or
539 memory region) associated with this descriptor since
540 otherwise the `data_read' flag would be set. */
541 if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
542 /* Something went wrong. The error value is already set. */
543 goto out;
544 }
545
546 /* At this point we know the raw data is available. But it might be
547 empty in case the section has size zero (for whatever reason).
548 Now create the converted data in case this is necessary. */
549 if (scn->data_list_rear == NULL)
550 __libelf_set_data_list_rdlock (scn, locked);
551
552 /* Return the first data element in the list. */
553 result = &scn->data_list.data.d;
554
555 out:
556 return result;
557 }
558
559 Elf_Data *
elf_getdata(Elf_Scn * scn,Elf_Data * data)560 elf_getdata (Elf_Scn *scn, Elf_Data *data)
561 {
562 Elf_Data *result;
563
564 if (scn == NULL)
565 return NULL;
566
567 rwlock_rdlock (scn->elf->lock);
568 result = __elf_getdata_rdlock (scn, data);
569 rwlock_unlock (scn->elf->lock);
570
571 return result;
572 }
573 INTDEF(elf_getdata)
574