Line data Source code
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[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
54 : {
55 : [EV_CURRENT - 1] =
56 : {
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,
76 : }
77 : };
78 :
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] =
82 : {
83 : # define TYPE_ALIGNS(Bits) \
84 : { \
85 : [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \
86 : [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)), \
87 : [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \
88 : [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)), \
89 : [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)), \
90 : [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)), \
91 : [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)), \
92 : [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \
93 : [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)), \
94 : [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)), \
95 : [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \
96 : [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \
97 : [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \
98 : [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \
99 : [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \
100 : [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \
101 : [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \
102 : [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \
103 : [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \
104 : [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \
105 : [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \
106 : [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
107 : [ELF_T_GNUHASH] = __alignof__ (Elf32_Word), \
108 : [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)), \
109 : [ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)), \
110 : }
111 : [EV_CURRENT - 1] =
112 : {
113 : [ELFCLASS32 - 1] = TYPE_ALIGNS (32),
114 : [ELFCLASS64 - 1] = TYPE_ALIGNS (64),
115 : }
116 : # undef TYPE_ALIGNS
117 : };
118 : #endif
119 :
120 :
121 : Elf_Type
122 : internal_function
123 68749 : __libelf_data_type (Elf *elf, int sh_type)
124 : {
125 : /* Some broken ELF ABI for 64-bit machines use the wrong hash table
126 : entry size. See elf-knowledge.h for more information. */
127 68749 : if (sh_type == SHT_HASH && elf->class == ELFCLASS64)
128 : {
129 : GElf_Ehdr ehdr_mem;
130 51 : GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
131 51 : return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
132 : }
133 : else
134 68698 : return shtype_map[LIBELF_EV_IDX][TYPEIDX (sh_type)];
135 : }
136 :
137 : /* Convert the data in the current section. */
138 : static void
139 67286 : convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
140 : int data, size_t size, Elf_Type type)
141 : {
142 67286 : const size_t align = __libelf_type_align (eclass, type);
143 :
144 67286 : if (data == MY_ELFDATA)
145 : {
146 : if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
147 : /* No need to copy, we can use the raw data. */
148 64422 : scn->data_base = scn->rawdata_base;
149 : else
150 : {
151 : scn->data_base = (char *) 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 2864 : scn->data_base = (char *) malloc (size);
167 2864 : if (scn->data_base == NULL)
168 : {
169 0 : __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 (ALLOW_UNALIGNED ||
177 : ((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
178 2864 : rawdata_source = scn->rawdata_base;
179 : else
180 : {
181 : rawdata_source = (char *) malloc (size);
182 : if (rawdata_source == NULL)
183 : {
184 : __libelf_seterrno (ELF_E_NOMEM);
185 : return;
186 : }
187 :
188 : /* The copy will be appropriately aligned for direct access. */
189 : memcpy (rawdata_source, scn->rawdata_base, size);
190 : }
191 :
192 : /* Get the conversion function. */
193 : #if EV_NUM != 2
194 : fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type];
195 : #else
196 2864 : fp = __elf_xfctstom[0][0][eclass - 1][type];
197 : #endif
198 :
199 2864 : fp (scn->data_base, rawdata_source, size, 0);
200 :
201 2864 : if (rawdata_source != scn->rawdata_base)
202 0 : free (rawdata_source);
203 : }
204 :
205 67286 : scn->data_list.data.d.d_buf = scn->data_base;
206 67286 : scn->data_list.data.d.d_size = size;
207 67286 : scn->data_list.data.d.d_type = type;
208 67286 : scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
209 67286 : scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
210 67286 : scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
211 :
212 67286 : scn->data_list.data.s = scn;
213 : }
214 :
215 :
216 : /* Store the information for the raw data in the `rawdata' element. */
217 : int
218 : internal_function
219 68581 : __libelf_set_rawdata_wrlock (Elf_Scn *scn)
220 : {
221 : Elf64_Off offset;
222 : Elf64_Xword size;
223 : Elf64_Xword align;
224 : Elf64_Xword flags;
225 : int type;
226 68581 : Elf *elf = scn->elf;
227 :
228 68581 : if (elf->class == ELFCLASS32)
229 : {
230 26062 : Elf32_Shdr *shdr
231 26062 : = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
232 :
233 26062 : if (shdr == NULL)
234 : /* Something went terribly wrong. */
235 : return 1;
236 :
237 26062 : offset = shdr->sh_offset;
238 26062 : size = shdr->sh_size;
239 26062 : type = shdr->sh_type;
240 26062 : align = shdr->sh_addralign;
241 26062 : flags = shdr->sh_flags;
242 : }
243 : else
244 : {
245 42519 : Elf64_Shdr *shdr
246 42519 : = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
247 :
248 42519 : if (shdr == NULL)
249 : /* Something went terribly wrong. */
250 : return 1;
251 :
252 42519 : offset = shdr->sh_offset;
253 42519 : size = shdr->sh_size;
254 42519 : type = shdr->sh_type;
255 42519 : align = shdr->sh_addralign;
256 42519 : flags = shdr->sh_flags;
257 : }
258 :
259 : /* If the section has no data (for whatever reason), leave the `d_buf'
260 : pointer NULL. */
261 68581 : if (size != 0 && type != SHT_NOBITS)
262 : {
263 : /* First a test whether the section is valid at all. */
264 : size_t entsize;
265 :
266 : /* Compressed data has a header, but then compressed data. */
267 67904 : if ((flags & SHF_COMPRESSED) != 0)
268 : entsize = 1;
269 67586 : else if (type == SHT_HASH)
270 : {
271 : GElf_Ehdr ehdr_mem;
272 98 : GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
273 98 : entsize = SH_ENTSIZE_HASH (ehdr);
274 : }
275 : else
276 : {
277 67488 : Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)];
278 67488 : if (t == ELF_T_VDEF || t == ELF_T_NHDR
279 66868 : || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
280 : entsize = 1;
281 : else
282 66796 : entsize = __libelf_type_sizes[LIBELF_EV_IDX][elf->class - 1][t];
283 : }
284 :
285 : /* We assume it is an array of bytes if it is none of the structured
286 : sections we know of. */
287 67904 : if (entsize == 0)
288 0 : entsize = 1;
289 :
290 67904 : if (unlikely (size % entsize != 0))
291 : {
292 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
293 0 : return 1;
294 : }
295 :
296 : /* We can use the mapped or loaded data if available. */
297 67904 : if (elf->map_address != NULL)
298 : {
299 : /* First see whether the information in the section header is
300 : valid and it does not ask for too much. Check for unsigned
301 : overflow. */
302 63429 : if (unlikely (offset > elf->maximum_size
303 : || elf->maximum_size - offset < size))
304 : {
305 : /* Something is wrong. */
306 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
307 0 : return 1;
308 : }
309 :
310 63429 : scn->rawdata_base = scn->rawdata.d.d_buf
311 63429 : = (char *) elf->map_address + elf->start_offset + offset;
312 : }
313 4475 : else if (likely (elf->fildes != -1))
314 : {
315 : /* First see whether the information in the section header is
316 : valid and it does not ask for too much. Check for unsigned
317 : overflow. */
318 4475 : if (unlikely (offset > elf->maximum_size
319 : || elf->maximum_size - offset < size))
320 : {
321 : /* Something is wrong. */
322 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
323 0 : return 1;
324 : }
325 :
326 : /* We have to read the data from the file. Allocate the needed
327 : memory. */
328 4475 : scn->rawdata_base = scn->rawdata.d.d_buf
329 4475 : = (char *) malloc (size);
330 4475 : if (scn->rawdata.d.d_buf == NULL)
331 : {
332 0 : __libelf_seterrno (ELF_E_NOMEM);
333 0 : return 1;
334 : }
335 :
336 4475 : ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
337 4475 : elf->start_offset + offset);
338 4475 : if (unlikely ((size_t) n != size))
339 : {
340 : /* Cannot read the data. */
341 0 : free (scn->rawdata.d.d_buf);
342 0 : scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
343 0 : __libelf_seterrno (ELF_E_READ_ERROR);
344 0 : return 1;
345 : }
346 : }
347 : else
348 : {
349 : /* The file descriptor is already closed, we cannot get the data
350 : anymore. */
351 0 : __libelf_seterrno (ELF_E_FD_DISABLED);
352 0 : return 1;
353 : }
354 : }
355 :
356 68581 : scn->rawdata.d.d_size = size;
357 :
358 : /* Compressed data always has type ELF_T_CHDR regardless of the
359 : section type. */
360 68581 : if ((flags & SHF_COMPRESSED) != 0)
361 318 : scn->rawdata.d.d_type = ELF_T_CHDR;
362 : else
363 68263 : scn->rawdata.d.d_type = __libelf_data_type (elf, type);
364 68581 : scn->rawdata.d.d_off = 0;
365 :
366 : /* Make sure the alignment makes sense. d_align should be aligned both
367 : in the section (trivially true since d_off is zero) and in the file.
368 : Unfortunately we cannot be too strict because there are ELF files
369 : out there that fail this requirement. We will try to fix those up
370 : in elf_update when writing out the image. But for very large
371 : alignment values this can bloat the image considerably. So here
372 : just check and clamp the alignment value to not be bigger than the
373 : actual offset of the data in the file. Given that there is always
374 : at least an ehdr this will only trigger for alignment values > 64
375 : which should be uncommon. */
376 68581 : align = align ?: 1;
377 68581 : if (type != SHT_NOBITS && align > offset)
378 0 : align = offset;
379 68581 : scn->rawdata.d.d_align = align;
380 : if (elf->class == ELFCLASS32
381 : || (offsetof (struct Elf, state.elf32.ehdr)
382 : == offsetof (struct Elf, state.elf64.ehdr)))
383 68581 : scn->rawdata.d.d_version =
384 68581 : elf->state.elf32.ehdr->e_ident[EI_VERSION];
385 : else
386 : scn->rawdata.d.d_version =
387 : elf->state.elf64.ehdr->e_ident[EI_VERSION];
388 :
389 68581 : scn->rawdata.s = scn;
390 :
391 68581 : scn->data_read = 1;
392 :
393 : /* We actually read data from the file. At least we tried. */
394 68581 : scn->flags |= ELF_F_FILEDATA;
395 :
396 68581 : return 0;
397 : }
398 :
399 : int
400 : internal_function
401 826 : __libelf_set_rawdata (Elf_Scn *scn)
402 : {
403 : int result;
404 :
405 826 : if (scn == NULL)
406 : return 1;
407 :
408 : rwlock_wrlock (scn->elf->lock);
409 826 : result = __libelf_set_rawdata_wrlock (scn);
410 : rwlock_unlock (scn->elf->lock);
411 :
412 826 : return result;
413 : }
414 :
415 : void
416 : internal_function
417 67963 : __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
418 : {
419 67963 : if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
420 67286 : {
421 67286 : Elf *elf = scn->elf;
422 :
423 : /* Upgrade the lock to a write lock if necessary and check
424 : nobody else already did the work. */
425 67286 : if (!wrlocked)
426 : {
427 : rwlock_unlock (elf->lock);
428 : rwlock_wrlock (elf->lock);
429 1181 : if (scn->data_list_rear != NULL)
430 : return;
431 : }
432 :
433 : /* Convert according to the version and the type. */
434 134572 : convert_data (scn, __libelf_version, elf->class,
435 : (elf->class == ELFCLASS32
436 : || (offsetof (struct Elf, state.elf32.ehdr)
437 : == offsetof (struct Elf, state.elf64.ehdr))
438 67286 : ? elf->state.elf32.ehdr->e_ident[EI_DATA]
439 : : elf->state.elf64.ehdr->e_ident[EI_DATA]),
440 : scn->rawdata.d.d_size, scn->rawdata.d.d_type);
441 : }
442 : else
443 : {
444 : /* This is an empty or NOBITS section. There is no buffer but
445 : the size information etc is important. */
446 677 : scn->data_list.data.d = scn->rawdata.d;
447 677 : scn->data_list.data.s = scn;
448 : }
449 :
450 67963 : scn->data_list_rear = &scn->data_list;
451 : }
452 :
453 : Elf_Data *
454 : internal_function
455 114840 : __elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
456 : {
457 114840 : Elf_Data *result = NULL;
458 : Elf *elf;
459 114840 : int locked = 0;
460 :
461 114840 : if (scn == NULL)
462 : return NULL;
463 :
464 114840 : if (unlikely (scn->elf->kind != ELF_K_ELF))
465 : {
466 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
467 0 : return NULL;
468 : }
469 :
470 : /* We will need this multiple times later on. */
471 114840 : elf = scn->elf;
472 :
473 : /* If `data' is not NULL this means we are not addressing the initial
474 : data in the file. But this also means this data is already read
475 : (since otherwise it is not possible to have a valid `data' pointer)
476 : and all the data structures are initialized as well. In this case
477 : we can simply walk the list of data records. */
478 114840 : if (data != NULL)
479 : {
480 : Elf_Data_List *runp;
481 :
482 : /* It is not possible that if DATA is not NULL the first entry is
483 : returned. But this also means that there must be a first data
484 : entry. */
485 447 : if (scn->data_list_rear == NULL
486 : /* The section the reference data is for must match the section
487 : parameter. */
488 447 : || unlikely (((Elf_Data_Scn *) data)->s != scn))
489 : {
490 0 : __libelf_seterrno (ELF_E_DATA_MISMATCH);
491 0 : goto out;
492 : }
493 :
494 : /* We start searching with the first entry. */
495 447 : runp = &scn->data_list;
496 :
497 : while (1)
498 : {
499 : /* If `data' does not match any known record punt. */
500 471 : if (runp == NULL)
501 : {
502 0 : __libelf_seterrno (ELF_E_DATA_MISMATCH);
503 0 : goto out;
504 : }
505 :
506 459 : if (&runp->data.d == data)
507 : /* Found the entry. */
508 : break;
509 :
510 12 : runp = runp->next;
511 : }
512 :
513 : /* Return the data for the next data record. */
514 447 : result = runp->next ? &runp->next->data.d : NULL;
515 : goto out;
516 : }
517 :
518 : /* If the data for this section was not yet initialized do it now. */
519 114393 : if (scn->data_read == 0)
520 : {
521 : /* We cannot acquire a write lock while we are holding a read
522 : lock. Therefore give up the read lock and then get the write
523 : lock. But this means that the data could meanwhile be
524 : modified, therefore start the tests again. */
525 : rwlock_unlock (elf->lock);
526 : rwlock_wrlock (elf->lock);
527 66764 : locked = 1;
528 :
529 : /* Read the data from the file. There is always a file (or
530 : memory region) associated with this descriptor since
531 : otherwise the `data_read' flag would be set. */
532 66764 : if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
533 : /* Something went wrong. The error value is already set. */
534 : goto out;
535 : }
536 :
537 : /* At this point we know the raw data is available. But it might be
538 : empty in case the section has size zero (for whatever reason).
539 : Now create the converted data in case this is necessary. */
540 114393 : if (scn->data_list_rear == NULL)
541 67951 : __libelf_set_data_list_rdlock (scn, locked);
542 :
543 : /* Return the first data element in the list. */
544 114393 : result = &scn->data_list.data.d;
545 :
546 : out:
547 : return result;
548 : }
549 :
550 : Elf_Data *
551 114929 : elf_getdata (Elf_Scn *scn, Elf_Data *data)
552 : {
553 : Elf_Data *result;
554 :
555 114929 : if (scn == NULL)
556 : return NULL;
557 :
558 : rwlock_rdlock (scn->elf->lock);
559 114827 : result = __elf_getdata_rdlock (scn, data);
560 : rwlock_unlock (scn->elf->lock);
561 :
562 114827 : return result;
563 : }
564 : INTDEF(elf_getdata)
|