Home | History | Annotate | Download | only in libelf
      1 /* Return section index of section header string table.
      2    Copyright (C) 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      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 <assert.h>
     35 #include <errno.h>
     36 #include <gelf.h>
     37 #include <stddef.h>
     38 #include <unistd.h>
     39 
     40 #include <system.h>
     41 #include "libelfP.h"
     42 #include "common.h"
     43 
     44 
     45 int
     46 elf_getshdrstrndx (Elf *elf, size_t *dst)
     47 {
     48   int result = 0;
     49 
     50   if (elf == NULL)
     51     return -1;
     52 
     53   if (unlikely (elf->kind != ELF_K_ELF))
     54     {
     55       __libelf_seterrno (ELF_E_INVALID_HANDLE);
     56       return -1;
     57     }
     58 
     59   rwlock_rdlock (elf->lock);
     60 
     61   /* We rely here on the fact that the `elf' element is a common prefix
     62      of `elf32' and `elf64'.  */
     63   assert (offsetof (struct Elf, state.elf.ehdr)
     64 	  == offsetof (struct Elf, state.elf32.ehdr));
     65   assert (sizeof (elf->state.elf.ehdr)
     66 	  == sizeof (elf->state.elf32.ehdr));
     67   assert (offsetof (struct Elf, state.elf.ehdr)
     68 	  == offsetof (struct Elf, state.elf64.ehdr));
     69   assert (sizeof (elf->state.elf.ehdr)
     70 	  == sizeof (elf->state.elf64.ehdr));
     71 
     72   if (unlikely (elf->state.elf.ehdr == NULL))
     73     {
     74       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
     75       result = -1;
     76     }
     77   else
     78     {
     79       Elf32_Word num;
     80 
     81       num = (elf->class == ELFCLASS32
     82 	     ? elf->state.elf32.ehdr->e_shstrndx
     83 	     : elf->state.elf64.ehdr->e_shstrndx);
     84 
     85       /* Determine whether the index is too big to fit in the ELF
     86 	 header.  */
     87       if (unlikely (num == SHN_XINDEX))
     88 	{
     89 	  /* Yes.  Search the zeroth section header.  */
     90 	  if (elf->class == ELFCLASS32)
     91 	    {
     92 	      size_t offset;
     93 	      if (unlikely (elf->state.elf32.scns.cnt == 0))
     94 		{
     95 		  /* Cannot use SHN_XINDEX without section headers.  */
     96 		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
     97 		  result = -1;
     98 		  goto out;
     99 		}
    100 
    101 	      if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
    102 		{
    103 		  num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
    104 		  goto success;
    105 		}
    106 
    107 	      offset = elf->state.elf32.ehdr->e_shoff;
    108 
    109 	      if (elf->map_address != NULL
    110 		  && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
    111 		  && (ALLOW_UNALIGNED
    112 		      || (((size_t) ((char *) elf->map_address
    113 			   + elf->start_offset + offset))
    114 			  & (__alignof__ (Elf32_Shdr) - 1)) == 0))
    115 		{
    116 		  /* First see whether the information in the ELF header is
    117 		     valid and it does not ask for too much.  */
    118 		  if (unlikely (elf->maximum_size - offset
    119 				< sizeof (Elf32_Shdr)))
    120 		    {
    121 		      /* Something is wrong.  */
    122 		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
    123 		      result = -1;
    124 		      goto out;
    125 		    }
    126 
    127 		  /* We can directly access the memory.  */
    128 		  num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
    129 					 + offset))->sh_link;
    130 		}
    131 	      else
    132 		{
    133 		  /* We avoid reading in all the section headers.  Just read
    134 		     the first one.  */
    135 		  Elf32_Shdr shdr_mem;
    136 
    137 		  if (unlikely (pread_retry (elf->fildes, &shdr_mem,
    138 					     sizeof (Elf32_Shdr), offset)
    139 				!= sizeof (Elf32_Shdr)))
    140 		    {
    141 		      /* We must be able to read this ELF section header.  */
    142 		      __libelf_seterrno (ELF_E_INVALID_FILE);
    143 		      result = -1;
    144 		      goto out;
    145 		    }
    146 
    147 		  if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
    148 		    CONVERT (shdr_mem.sh_link);
    149 		  num = shdr_mem.sh_link;
    150 		}
    151 	    }
    152 	  else
    153 	    {
    154 	      if (unlikely (elf->state.elf64.scns.cnt == 0))
    155 		{
    156 		  /* Cannot use SHN_XINDEX without section headers.  */
    157 		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
    158 		  result = -1;
    159 		  goto out;
    160 		}
    161 
    162 	      if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
    163 		{
    164 		  num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
    165 		  goto success;
    166 		}
    167 
    168 	      size_t offset = elf->state.elf64.ehdr->e_shoff;
    169 
    170 	      if (elf->map_address != NULL
    171 		  && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
    172 		  && (ALLOW_UNALIGNED
    173 		      || (((size_t) ((char *) elf->map_address
    174 			   + elf->start_offset + offset))
    175 			  & (__alignof__ (Elf64_Shdr) - 1)) == 0))
    176 		{
    177 		  /* First see whether the information in the ELF header is
    178 		     valid and it does not ask for too much.  */
    179 		  if (unlikely (elf->maximum_size - offset
    180 				< sizeof (Elf64_Shdr)))
    181 		    {
    182 		      /* Something is wrong.  */
    183 		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
    184 		      result = -1;
    185 		      goto out;
    186 		    }
    187 
    188 		  /* We can directly access the memory.  */
    189 		  num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
    190 					 + offset))->sh_link;
    191 		}
    192 	      else
    193 		{
    194 		  /* We avoid reading in all the section headers.  Just read
    195 		     the first one.  */
    196 		  Elf64_Shdr shdr_mem;
    197 
    198 		  if (unlikely (pread_retry (elf->fildes, &shdr_mem,
    199 					     sizeof (Elf64_Shdr), offset)
    200 				!= sizeof (Elf64_Shdr)))
    201 		    {
    202 		      /* We must be able to read this ELF section header.  */
    203 		      __libelf_seterrno (ELF_E_INVALID_FILE);
    204 		      result = -1;
    205 		      goto out;
    206 		    }
    207 
    208 		  if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
    209 		    CONVERT (shdr_mem.sh_link);
    210 		  num = shdr_mem.sh_link;
    211 		}
    212 	    }
    213 	}
    214 
    215       /* Store the result.  */
    216     success:
    217       *dst = num;
    218     }
    219 
    220  out:
    221   rwlock_unlock (elf->lock);
    222 
    223   return result;
    224 }
    225 INTDEF(elf_getshdrstrndx)
    226 /* Alias for the deprecated name.  */
    227 strong_alias (elf_getshdrstrndx, elf_getshstrndx)
    228