• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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