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