• 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 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
__libelf_data_type(Elf * elf,int sh_type)123 __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   if (sh_type == SHT_HASH && elf->class == ELFCLASS64)
128     {
129       GElf_Ehdr ehdr_mem;
130       GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
131       return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
132     }
133   else
134     return shtype_map[LIBELF_EV_IDX][TYPEIDX (sh_type)];
135 }
136 
137 /* Convert the data in the current section.  */
138 static void
convert_data(Elf_Scn * scn,int version,int eclass,int data,size_t size,Elf_Type type)139 convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
140 	      int data, size_t size, Elf_Type type)
141 {
142   const size_t align = __libelf_type_align (eclass, type);
143 
144   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 	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       scn->data_base = (char *) 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 (ALLOW_UNALIGNED ||
177 	  ((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
178 	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       fp = __elf_xfctstom[0][0][eclass - 1][type];
197 #endif
198 
199       fp (scn->data_base, rawdata_source, size, 0);
200 
201       if (rawdata_source != scn->rawdata_base)
202 	free (rawdata_source);
203     }
204 
205   scn->data_list.data.d.d_buf = scn->data_base;
206   scn->data_list.data.d.d_size = size;
207   scn->data_list.data.d.d_type = type;
208   scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
209   scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
210   scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
211 
212   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
__libelf_set_rawdata_wrlock(Elf_Scn * scn)219 __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   Elf *elf = scn->elf;
227 
228   if (elf->class == ELFCLASS32)
229     {
230       Elf32_Shdr *shdr
231 	= scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
232 
233       if (shdr == NULL)
234 	/* Something went terribly wrong.  */
235 	return 1;
236 
237       offset = shdr->sh_offset;
238       size = shdr->sh_size;
239       type = shdr->sh_type;
240       align = shdr->sh_addralign;
241       flags = shdr->sh_flags;
242     }
243   else
244     {
245       Elf64_Shdr *shdr
246 	= scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
247 
248       if (shdr == NULL)
249 	/* Something went terribly wrong.  */
250 	return 1;
251 
252       offset = shdr->sh_offset;
253       size = shdr->sh_size;
254       type = shdr->sh_type;
255       align = shdr->sh_addralign;
256       flags = shdr->sh_flags;
257     }
258 
259   /* If the section has no data (for whatever reason), leave the `d_buf'
260      pointer NULL.  */
261   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       if ((flags & SHF_COMPRESSED) != 0)
268 	entsize = 1;
269       else if (type == SHT_HASH)
270 	{
271 	  GElf_Ehdr ehdr_mem;
272 	  GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
273 	  entsize = SH_ENTSIZE_HASH (ehdr);
274 	}
275       else
276 	{
277 	  Elf_Type t = shtype_map[LIBELF_EV_IDX][TYPEIDX (type)];
278 	  if (t == ELF_T_VDEF || t == ELF_T_NHDR
279 	      || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
280 	    entsize = 1;
281 	  else
282 	    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       if (entsize == 0)
288 	entsize = 1;
289 
290       if (unlikely (size % entsize != 0))
291 	{
292 	  __libelf_seterrno (ELF_E_INVALID_DATA);
293 	  return 1;
294 	}
295 
296       /* We can use the mapped or loaded data if available.  */
297       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 	  if (unlikely (offset > elf->maximum_size
303 	      || elf->maximum_size - offset < size))
304 	    {
305 	      /* Something is wrong.  */
306 	      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
307 	      return 1;
308 	    }
309 
310 	  scn->rawdata_base = scn->rawdata.d.d_buf
311 	    = (char *) elf->map_address + elf->start_offset + offset;
312 	}
313       else if (likely (elf->fildes != -1))
314 	{
315 	  /* We have to read the data from the file.  Allocate the needed
316 	     memory.  */
317 	  scn->rawdata_base = scn->rawdata.d.d_buf
318 	    = (char *) malloc (size);
319 	  if (scn->rawdata.d.d_buf == NULL)
320 	    {
321 	      __libelf_seterrno (ELF_E_NOMEM);
322 	      return 1;
323 	    }
324 
325 	  ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
326 				   elf->start_offset + offset);
327 	  if (unlikely ((size_t) n != size))
328 	    {
329 	      /* Cannot read the data.  */
330 	      free (scn->rawdata.d.d_buf);
331 	      scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
332 	      __libelf_seterrno (ELF_E_READ_ERROR);
333 	      return 1;
334 	    }
335 	}
336       else
337 	{
338 	  /* The file descriptor is already closed, we cannot get the data
339 	     anymore.  */
340 	  __libelf_seterrno (ELF_E_FD_DISABLED);
341 	  return 1;
342 	}
343     }
344 
345   scn->rawdata.d.d_size = size;
346 
347   /* Compressed data always has type ELF_T_CHDR regardless of the
348      section type.  */
349   if ((flags & SHF_COMPRESSED) != 0)
350     scn->rawdata.d.d_type = ELF_T_CHDR;
351   else
352     scn->rawdata.d.d_type = __libelf_data_type (elf, type);
353   scn->rawdata.d.d_off = 0;
354 
355   /* Make sure the alignment makes sense.  d_align should be aligned both
356      in the section (trivially true since d_off is zero) and in the file.
357      Unfortunately we cannot be too strict because there are ELF files
358      out there that fail this requirement.  We will try to fix those up
359      in elf_update when writing out the image.  But for very large
360      alignment values this can bloat the image considerably.  So here
361      just check and clamp the alignment value to not be bigger than the
362      actual offset of the data in the file.  Given that there is always
363      at least an ehdr this will only trigger for alignment values > 64
364      which should be uncommon.  */
365   align = align ?: 1;
366   if (align > offset)
367     align = offset;
368   scn->rawdata.d.d_align = align;
369   if (elf->class == ELFCLASS32
370       || (offsetof (struct Elf, state.elf32.ehdr)
371 	  == offsetof (struct Elf, state.elf64.ehdr)))
372     scn->rawdata.d.d_version =
373       elf->state.elf32.ehdr->e_ident[EI_VERSION];
374   else
375     scn->rawdata.d.d_version =
376       elf->state.elf64.ehdr->e_ident[EI_VERSION];
377 
378   scn->rawdata.s = scn;
379 
380   scn->data_read = 1;
381 
382   /* We actually read data from the file.  At least we tried.  */
383   scn->flags |= ELF_F_FILEDATA;
384 
385   return 0;
386 }
387 
388 int
389 internal_function
__libelf_set_rawdata(Elf_Scn * scn)390 __libelf_set_rawdata (Elf_Scn *scn)
391 {
392   int result;
393 
394   if (scn == NULL)
395     return 1;
396 
397   rwlock_wrlock (scn->elf->lock);
398   result = __libelf_set_rawdata_wrlock (scn);
399   rwlock_unlock (scn->elf->lock);
400 
401   return result;
402 }
403 
404 void
405 internal_function
__libelf_set_data_list_rdlock(Elf_Scn * scn,int wrlocked)406 __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
407 {
408   if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
409     {
410       Elf *elf = scn->elf;
411 
412       /* Upgrade the lock to a write lock if necessary and check
413 	 nobody else already did the work.  */
414       if (!wrlocked)
415 	{
416 	  rwlock_unlock (elf->lock);
417 	  rwlock_wrlock (elf->lock);
418 	  if (scn->data_list_rear != NULL)
419 	    return;
420 	}
421 
422       /* Convert according to the version and the type.   */
423       convert_data (scn, __libelf_version, elf->class,
424 		    (elf->class == ELFCLASS32
425 		     || (offsetof (struct Elf, state.elf32.ehdr)
426 			 == offsetof (struct Elf, state.elf64.ehdr))
427 		     ? elf->state.elf32.ehdr->e_ident[EI_DATA]
428 		     : elf->state.elf64.ehdr->e_ident[EI_DATA]),
429 		    scn->rawdata.d.d_size, scn->rawdata.d.d_type);
430     }
431   else
432     {
433       /* This is an empty or NOBITS section.  There is no buffer but
434 	 the size information etc is important.  */
435       scn->data_list.data.d = scn->rawdata.d;
436       scn->data_list.data.s = scn;
437     }
438 
439   scn->data_list_rear = &scn->data_list;
440 }
441 
442 Elf_Data *
443 internal_function
__elf_getdata_rdlock(Elf_Scn * scn,Elf_Data * data)444 __elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
445 {
446   Elf_Data *result = NULL;
447   Elf *elf;
448   int locked = 0;
449 
450   if (scn == NULL)
451     return NULL;
452 
453   if (unlikely (scn->elf->kind != ELF_K_ELF))
454     {
455       __libelf_seterrno (ELF_E_INVALID_HANDLE);
456       return NULL;
457     }
458 
459   /* We will need this multiple times later on.  */
460   elf = scn->elf;
461 
462   /* If `data' is not NULL this means we are not addressing the initial
463      data in the file.  But this also means this data is already read
464      (since otherwise it is not possible to have a valid `data' pointer)
465      and all the data structures are initialized as well.  In this case
466      we can simply walk the list of data records.  */
467   if (data != NULL)
468     {
469       Elf_Data_List *runp;
470 
471       /* It is not possible that if DATA is not NULL the first entry is
472 	 returned.  But this also means that there must be a first data
473 	 entry.  */
474       if (scn->data_list_rear == NULL
475 	  /* The section the reference data is for must match the section
476 	     parameter.  */
477 	  || unlikely (((Elf_Data_Scn *) data)->s != scn))
478 	{
479 	  __libelf_seterrno (ELF_E_DATA_MISMATCH);
480 	  goto out;
481 	}
482 
483       /* We start searching with the first entry.  */
484       runp = &scn->data_list;
485 
486       while (1)
487 	{
488 	  /* If `data' does not match any known record punt.  */
489 	  if (runp == NULL)
490 	    {
491 	      __libelf_seterrno (ELF_E_DATA_MISMATCH);
492 	      goto out;
493 	    }
494 
495 	  if (&runp->data.d == data)
496 	    /* Found the entry.  */
497 	    break;
498 
499 	  runp = runp->next;
500 	}
501 
502       /* Return the data for the next data record.  */
503       result = runp->next ? &runp->next->data.d : NULL;
504       goto out;
505     }
506 
507   /* If the data for this section was not yet initialized do it now.  */
508   if (scn->data_read == 0)
509     {
510       /* We cannot acquire a write lock while we are holding a read
511          lock.  Therefore give up the read lock and then get the write
512          lock.  But this means that the data could meanwhile be
513          modified, therefore start the tests again.  */
514       rwlock_unlock (elf->lock);
515       rwlock_wrlock (elf->lock);
516       locked = 1;
517 
518       /* Read the data from the file.  There is always a file (or
519 	 memory region) associated with this descriptor since
520 	 otherwise the `data_read' flag would be set.  */
521       if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
522 	/* Something went wrong.  The error value is already set.  */
523 	goto out;
524     }
525 
526   /* At this point we know the raw data is available.  But it might be
527      empty in case the section has size zero (for whatever reason).
528      Now create the converted data in case this is necessary.  */
529   if (scn->data_list_rear == NULL)
530     __libelf_set_data_list_rdlock (scn, locked);
531 
532   /* Return the first data element in the list.  */
533   result = &scn->data_list.data.d;
534 
535  out:
536   return result;
537 }
538 
539 Elf_Data *
elf_getdata(Elf_Scn * scn,Elf_Data * data)540 elf_getdata (Elf_Scn *scn, Elf_Data *data)
541 {
542   Elf_Data *result;
543 
544   if (scn == NULL)
545     return NULL;
546 
547   rwlock_rdlock (scn->elf->lock);
548   result = __elf_getdata_rdlock (scn, data);
549   rwlock_unlock (scn->elf->lock);
550 
551   return result;
552 }
553 INTDEF(elf_getdata)
554