Home | History | Annotate | Download | only in libelf
      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 (at) 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 __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
    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
    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
    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
    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
    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 *
    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