Home | History | Annotate | Download | only in libelf
      1 /* Return the next data element from the section after possibly converting it.
      2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      4 
      5    This program is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation, version 2.
      8 
      9    This program is distributed in the hope that it will be useful,
     10    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12    GNU General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License
     15    along with this program; if not, write to the Free Software Foundation,
     16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
     17 
     18 #ifdef HAVE_CONFIG_H
     19 # include <config.h>
     20 #endif
     21 
     22 #include <stddef.h>
     23 #include <string.h>
     24 #include <unistd.h>
     25 
     26 #include "libelfP.h"
     27 #include "common.h"
     28 #include "elf-knowledge.h"
     29 
     30 
     31 #if _STRING_ARCH_unaligned
     32 # define ALLOW_ALIGNED	1
     33 #else
     34 # define ALLOW_ALIGNED	0
     35 #endif
     36 
     37 
     38 #define TYPEIDX(Sh_Type) \
     39   (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM				      \
     40    ? Sh_Type								      \
     41    : (Sh_Type >= SHT_GNU_LIBLIST && Sh_Type <= SHT_HISUNW		      \
     42       ? SHT_NUM + Sh_Type - SHT_GNU_LIBLIST				      \
     43       : 0))
     44 
     45 static const struct
     46 {
     47   Elf_Type type;
     48   size_t size;
     49 #if ALLOW_ALIGNED
     50 # define AL(val)
     51 #else
     52   size_t align;
     53 # define AL(val), val
     54 #endif
     55 } shtype_map[EV_NUM - 1][ELFCLASSNUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
     56 {
     57   [EV_CURRENT - 1] =
     58   {
     59     [ELFCLASS32 - 1] =
     60     {
     61       /* Associate section types with libelf types, their sizes and
     62 	 alignment.  SHT_GNU_verdef is special since the section does
     63 	 not contain entries of only one size.  */
     64 #define DEFINE(Bits) \
     65       [SHT_SYMTAB] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym))		      \
     66 		       AL (__alignof__ (ElfW2(Bits,Sym))) },		      \
     67       [SHT_RELA] = { ELF_T_RELA, sizeof (ElfW2(Bits,Rela))		      \
     68 		       AL (__alignof__ (ElfW2(Bits,Rela))) },		      \
     69       [SHT_HASH] = { ELF_T_WORD, sizeof (ElfW2(Bits,Word))		      \
     70 		       AL (__alignof__ (ElfW2(Bits,Word))) },		      \
     71       [SHT_DYNAMIC] = { ELF_T_DYN, sizeof (ElfW2(Bits,Dyn))		      \
     72 		       AL (__alignof__ (ElfW2(Bits,Dyn))) },		      \
     73       [SHT_REL] = { ELF_T_REL, sizeof (ElfW2(Bits,Rel))			      \
     74 		       AL (__alignof__ (ElfW2(Bits,Rel))) },		      \
     75       [SHT_DYNSYM] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym))		      \
     76 		       AL (__alignof__ (ElfW2(Bits,Sym))) },		      \
     77       [SHT_INIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr))	      \
     78 			   AL (__alignof__ (ElfW2(Bits,Addr))) },	      \
     79       [SHT_FINI_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr))	      \
     80 			   AL (__alignof__ (ElfW2(Bits,Addr))) },	      \
     81       [SHT_PREINIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr))	      \
     82 			      AL (__alignof__ (ElfW2(Bits,Addr))) },	      \
     83       [SHT_GROUP] = { ELF_T_WORD, sizeof (Elf32_Word)			      \
     84 		      AL (__alignof__ (Elf32_Word)) },			      \
     85       [SHT_SYMTAB_SHNDX] = { ELF_T_WORD, sizeof (Elf32_Word)		      \
     86 			     AL (__alignof__ (Elf32_Word)) },		      \
     87       [TYPEIDX (SHT_GNU_verdef)] = { ELF_T_VDEF, 1 AL (1) },		      \
     88       [TYPEIDX (SHT_GNU_verneed)] = { ELF_T_VNEED,			      \
     89 				      sizeof (ElfW2(Bits,Verneed))	      \
     90 				      AL (__alignof__ (ElfW2(Bits,Verneed)))},\
     91       [TYPEIDX (SHT_GNU_versym)] = { ELF_T_HALF, sizeof (ElfW2(Bits,Versym))  \
     92 				     AL (__alignof__ (ElfW2(Bits,Versym))) }, \
     93       [TYPEIDX (SHT_SUNW_syminfo)] = { ELF_T_SYMINFO,			      \
     94 				       sizeof (ElfW2(Bits,Syminfo))	      \
     95 				       AL(__alignof__ (ElfW2(Bits,Syminfo)))},\
     96       [TYPEIDX (SHT_SUNW_move)] = { ELF_T_MOVE, sizeof (ElfW2(Bits,Move))     \
     97 				    AL (__alignof__ (ElfW2(Bits,Move))) },    \
     98       [TYPEIDX (SHT_GNU_LIBLIST)] = { ELF_T_LIB, sizeof (ElfW2(Bits,Lib))     \
     99 				    AL (__alignof__ (ElfW2(Bits,Lib))) }
    100       DEFINE (32)
    101     },
    102     [ELFCLASS64 - 1] =
    103     {
    104       DEFINE (64)
    105     }
    106   }
    107 };
    108 
    109 
    110 /* Convert the data in the current section.  */
    111 static void
    112 convert_data (Elf_Scn *scn, int version, int eclass, int data,
    113 	      size_t size, size_t type)
    114 {
    115 #if ALLOW_ALIGNED
    116   /* No need to compute the alignment requirement of the host.  */
    117   const size_t align = 1;
    118 #else
    119 # if EV_NUM != 2
    120   size_t align = shtype_map[__libelf_version - 1][eclass - 1][type].align;
    121 # else
    122   size_t align = shtype_map[0][eclass - 1][type].align;
    123 # endif
    124 #endif
    125 
    126   if (data == MY_ELFDATA)
    127     {
    128       if (ALLOW_ALIGNED
    129 	  || (((size_t) ((char *) scn->rawdata_base)) & (align - 1)) == 0)
    130 	/* No need to copy, we can use the raw data.  */
    131 	scn->data_base = scn->rawdata_base;
    132       else
    133 	{
    134 	  scn->data_base = (char *) malloc (size);
    135 	  if (scn->data_base == NULL)
    136 	    {
    137 	      __libelf_seterrno (ELF_E_NOMEM);
    138 	      return;
    139 	    }
    140 
    141 	  /* The copy will be appropriately aligned for direct access.  */
    142 	  memcpy (scn->data_base, scn->rawdata_base, size);
    143 	}
    144     }
    145   else
    146     {
    147       xfct_t fp;
    148 
    149       scn->data_base = (char *) malloc (size);
    150       if (scn->data_base == NULL)
    151 	{
    152 	  __libelf_seterrno (ELF_E_NOMEM);
    153 	  return;
    154 	}
    155 
    156       /* Get the conversion function.  */
    157 #if EV_NUM != 2
    158       fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type];
    159 #else
    160       fp = __elf_xfctstom[0][0][eclass - 1][type];
    161 #endif
    162 
    163       fp (scn->data_base, scn->rawdata_base, size, 0);
    164     }
    165 
    166   scn->data_list.data.d.d_buf = scn->data_base;
    167   scn->data_list.data.d.d_size = size;
    168   scn->data_list.data.d.d_type = type;
    169   scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
    170   scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
    171   scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
    172 
    173   scn->data_list.data.s = scn;
    174 }
    175 
    176 
    177 /* Store the information for the raw data in the `rawdata' element.  */
    178 int
    179 internal_function_def
    180 __libelf_set_rawdata (Elf_Scn *scn)
    181 {
    182   size_t offset;
    183   size_t size;
    184   size_t align;
    185   int type;
    186   Elf *elf = scn->elf;
    187 
    188   if (elf->class == ELFCLASS32)
    189     {
    190       Elf32_Shdr *shdr = scn->shdr.e32 ?: INTUSE(elf32_getshdr) (scn);
    191 
    192       if (shdr == NULL)
    193 	/* Something went terribly wrong.  */
    194 	return 1;
    195 
    196       offset = shdr->sh_offset;
    197       size = shdr->sh_size;
    198       type = shdr->sh_type;
    199       align = shdr->sh_addralign;
    200     }
    201   else
    202     {
    203       Elf64_Shdr *shdr = scn->shdr.e64 ?: INTUSE(elf64_getshdr) (scn);
    204 
    205       if (shdr == NULL)
    206 	/* Something went terribly wrong.  */
    207 	return 1;
    208 
    209       offset = shdr->sh_offset;
    210       size = shdr->sh_size;
    211       type = shdr->sh_type;
    212       align = shdr->sh_addralign;
    213     }
    214 
    215   /* If the section has no data (for whatever reason), leave the `d_buf'
    216      pointer NULL.  */
    217   if (size != 0 && type != SHT_NOBITS)
    218     {
    219       /* First a test whether the section is valid at all.  */
    220       size_t entsize;
    221 
    222       if (type == SHT_HASH)
    223 	{
    224 	  GElf_Ehdr ehdr_mem;
    225 
    226 	  entsize = SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem));
    227 	}
    228       else
    229 	{
    230 #if EV_NUM != 2
    231 	  entsize = shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].size;
    232 #else
    233 	  entsize = shtype_map[0][elf->class - 1][TYPEIDX (type)].size;
    234 #endif
    235 	}
    236 
    237       /* We assume it is an array of bytes if it is none of the structured
    238 	 sections we know of.  */
    239       if (entsize == 0)
    240 	entsize = 1;
    241 
    242       if (size % entsize != 0)
    243 	{
    244 	  __libelf_seterrno (ELF_E_INVALID_DATA);
    245 	  return 1;
    246 	}
    247 
    248       /* We can use the mapped or loaded data if available.  */
    249       if (elf->map_address != NULL)
    250 	{
    251 	  /* First see whether the information in the section header is
    252 	     valid and it does not ask for too much.  */
    253 	  if (offset + size > elf->maximum_size)
    254 	    {
    255 	      /* Something is wrong.  */
    256 	      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
    257 	      return 1;
    258 	    }
    259 
    260 	  scn->rawdata_base = scn->rawdata.d.d_buf
    261 	    = (char *) elf->map_address + elf->start_offset + offset;
    262 	}
    263       else if (elf->fildes != -1)
    264 	{
    265 	  /* We have to read the data from the file.  Allocate the needed
    266 	     memory.  */
    267 	  scn->rawdata_base = scn->rawdata.d.d_buf
    268 	    = (char *) malloc (size);
    269 	  if (scn->rawdata.d.d_buf == NULL)
    270 	    {
    271 	      __libelf_seterrno (ELF_E_NOMEM);
    272 	      return 1;
    273 	    }
    274 
    275 	  if ((size_t) pread (elf->fildes, scn->rawdata.d.d_buf, size,
    276 			      elf->start_offset + offset) != size)
    277 	    {
    278 	      /* Cannot read the data.  */
    279 	      free (scn->rawdata.d.d_buf);
    280 	      scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
    281 	      __libelf_seterrno (ELF_E_READ_ERROR);
    282 	      return 1;
    283 	    }
    284 	}
    285       else
    286 	{
    287 	  /* The file descriptor is already closed, we cannot get the data
    288 	     anymore.  */
    289 	  __libelf_seterrno (ELF_E_FD_DISABLED);
    290 	  return 1;
    291 	}
    292     }
    293 
    294   scn->rawdata.d.d_size = size;
    295   /* Some broken ELF ABI for 64-bit machines use the wrong hash table
    296      entry size.  See elf-knowledge.h for more information.  */
    297   if (type == SHT_HASH && elf->class == ELFCLASS64)
    298     {
    299       GElf_Ehdr ehdr_mem;
    300 
    301       scn->rawdata.d.d_type = (SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem))
    302 			       == 4 ? ELF_T_WORD : ELF_T_XWORD);
    303     }
    304   else
    305     {
    306 #if EV_NUM != 2
    307       scn->rawdata.d.d_type =
    308 	shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].type;
    309 #else
    310       scn->rawdata.d.d_type =
    311 	shtype_map[0][elf->class - 1][TYPEIDX (type)].type;
    312 #endif
    313     }
    314   scn->rawdata.d.d_off = 0;
    315   scn->rawdata.d.d_align = align;
    316   if (elf->class == ELFCLASS32
    317       || (offsetof (struct Elf, state.elf32.ehdr)
    318 	  == offsetof (struct Elf, state.elf64.ehdr)))
    319     scn->rawdata.d.d_version =
    320       elf->state.elf32.ehdr->e_ident[EI_VERSION];
    321   else
    322     scn->rawdata.d.d_version =
    323       elf->state.elf64.ehdr->e_ident[EI_VERSION];
    324 
    325   scn->rawdata.s = scn;
    326 
    327   scn->data_read = 1;
    328 
    329   /* We actually read data from the file.  At least we tried.  */
    330   scn->flags |= ELF_F_FILEDATA;
    331 
    332   return 0;
    333 }
    334 
    335 
    336 Elf_Data *
    337 elf_getdata (scn, data)
    338      Elf_Scn *scn;
    339      Elf_Data *data;
    340 {
    341   Elf_Data *result = NULL;
    342   Elf *elf;
    343 
    344   if (scn == NULL)
    345     return NULL;
    346 
    347   if (unlikely (scn->elf->kind != ELF_K_ELF))
    348     {
    349       __libelf_seterrno (ELF_E_INVALID_HANDLE);
    350       return NULL;
    351     }
    352 
    353   /* We will need this multiple times later on.  */
    354   elf = scn->elf;
    355 
    356   rwlock_rdlock (elf->lock);
    357 
    358   /* If `data' is not NULL this means we are not addressing the initial
    359      data in the file.  But this also means this data is already read
    360      (since otherwise it is not possible to have a valid `data' pointer)
    361      and all the data structures are initialized as well.  In this case
    362      we can simply walk the list of data records.  */
    363   if (data != NULL)
    364     {
    365       Elf_Data_List *runp;
    366 
    367       /* It is not possible that if DATA is not NULL the first entry is
    368 	 returned.  But this also means that there must be a first data
    369 	 entry.  */
    370       if (scn->data_list_rear == NULL
    371 	  /* The section the reference data is for must match the section
    372 	     parameter.  */
    373 	  || unlikely (((Elf_Data_Scn *) data)->s != scn))
    374 	{
    375 	  __libelf_seterrno (ELF_E_DATA_MISMATCH);
    376 	  goto out;
    377 	}
    378 
    379       /* We start searching with the first entry.  */
    380       runp = &scn->data_list;
    381 
    382       while (1)
    383 	{
    384 	  /* If `data' does not match any known record punt.  */
    385 	  if (runp == NULL)
    386 	    {
    387 	      __libelf_seterrno (ELF_E_DATA_MISMATCH);
    388 	      goto out;
    389 	    }
    390 
    391 	  if (&runp->data.d == data)
    392 	    /* Found the entry.  */
    393 	    break;
    394 
    395 	  runp = runp->next;
    396 	}
    397 
    398       /* Return the data for the next data record.  */
    399       result = runp->next ? &runp->next->data.d : NULL;
    400       goto out;
    401     }
    402 
    403   /* If the data for this section was not yet initialized do it now.  */
    404   if (scn->data_read == 0)
    405     {
    406       /* We cannot acquire a write lock while we are holding a read
    407          lock.  Therefore give up the read lock and then get the write
    408          lock.  But this means that the data could meanwhile be
    409          modified, therefore start the tests again.  */
    410       rwlock_unlock (elf->lock);
    411       rwlock_wrlock (elf->lock);
    412 
    413       /* Read the data from the file.  There is always a file (or
    414 	 memory region) associated with this descriptor since
    415 	 otherwise the `data_read' flag would be set.  */
    416       if (scn->data_read == 0 && __libelf_set_rawdata (scn) != 0)
    417 	/* Something went wrong.  The error value is already set.  */
    418 	goto out;
    419     }
    420 
    421   /* At this point we know the raw data is available.  But it might be
    422      empty in case the section has size zero (for whatever reason).
    423      Now create the converted data in case this is necessary.  */
    424   if (scn->data_list_rear == NULL)
    425     {
    426       if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
    427 	/* Convert according to the version and the type.   */
    428 	convert_data (scn, __libelf_version, elf->class,
    429 		      (elf->class == ELFCLASS32
    430 		       || (offsetof (struct Elf, state.elf32.ehdr)
    431 			   == offsetof (struct Elf, state.elf64.ehdr))
    432 		       ? elf->state.elf32.ehdr->e_ident[EI_DATA]
    433 		       : elf->state.elf64.ehdr->e_ident[EI_DATA]),
    434 			  scn->rawdata.d.d_size,
    435 		      scn->rawdata.d.d_type);
    436       else
    437 	/* This is an empty or NOBITS section.  There is no buffer but
    438 	   the size information etc is important.  */
    439 	scn->data_list.data.d = scn->rawdata.d;
    440 
    441       scn->data_list_rear = &scn->data_list;
    442     }
    443 
    444   /* If no data is present we cannot return any.  */
    445   if (scn->data_list_rear != NULL)
    446     /* Return the first data element in the list.  */
    447     result = &scn->data_list.data.d;
    448 
    449  out:
    450   rwlock_unlock (elf->lock);
    451 
    452   return result;
    453 }
    454 INTDEF(elf_getdata)
    455