Home | History | Annotate | Download | only in libelf
      1 /* Return section index of section header string table.
      2    Copyright (C) 2002 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      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 <assert.h>
     23 #include <gelf.h>
     24 #include <stddef.h>
     25 #include <unistd.h>
     26 
     27 #include "libelfP.h"
     28 #include "common.h"
     29 
     30 
     31 int
     32 elf_getshstrndx (elf, dst)
     33      Elf *elf;
     34      size_t *dst;
     35 {
     36   int result = 0;
     37 
     38   if (elf == NULL)
     39     return -1;
     40 
     41   if (unlikely (elf->kind != ELF_K_ELF))
     42     {
     43       __libelf_seterrno (ELF_E_INVALID_HANDLE);
     44       return -1;
     45     }
     46 
     47   rwlock_rdlock (elf->lock);
     48 
     49   /* We rely here on the fact that the `elf' element is a common prefix
     50      of `elf32' and `elf64'.  */
     51   assert (offsetof (struct Elf, state.elf.ehdr)
     52 	  == offsetof (struct Elf, state.elf32.ehdr));
     53   assert (sizeof (elf->state.elf.ehdr)
     54 	  == sizeof (elf->state.elf32.ehdr));
     55   assert (offsetof (struct Elf, state.elf.ehdr)
     56 	  == offsetof (struct Elf, state.elf64.ehdr));
     57   assert (sizeof (elf->state.elf.ehdr)
     58 	  == sizeof (elf->state.elf64.ehdr));
     59 
     60   if (unlikely (elf->state.elf.ehdr == NULL))
     61     {
     62       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
     63       result = -1;
     64     }
     65   else
     66     {
     67       Elf32_Word num;
     68 
     69       num = (elf->class == ELFCLASS32
     70 	     ? elf->state.elf32.ehdr->e_shstrndx
     71 	     : elf->state.elf64.ehdr->e_shstrndx);
     72 
     73       /* Determine whether the index is too big to fit in the ELF
     74 	 header.  */
     75       if (unlikely (num == SHN_XINDEX))
     76 	{
     77 	  /* Yes.  Search the zeroth section header.  */
     78 	  if (elf->class == ELFCLASS32)
     79 	    {
     80 	      size_t offset;
     81 
     82 	      if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
     83 		{
     84 		  num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
     85 		  goto success;
     86 		}
     87 
     88 	      offset = elf->state.elf32.ehdr->e_shoff;
     89 
     90 	      if (elf->map_address != NULL
     91 		  && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
     92 		  && (ALLOW_UNALIGNED
     93 		      || (((size_t) ((char *) elf->map_address + offset))
     94 			  & (__alignof__ (Elf32_Shdr) - 1)) == 0))
     95 		/* We can directly access the memory.  */
     96 		num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link;
     97 	      else
     98 		{
     99 		  /* We avoid reading in all the section headers.  Just read
    100 		     the first one.  */
    101 		  Elf32_Shdr shdr_mem;
    102 
    103 		  if (pread (elf->fildes, &shdr_mem, sizeof (Elf32_Shdr),
    104 			     offset) != sizeof (Elf32_Shdr))
    105 		    {
    106 		      /* We must be able to read this ELF section header.  */
    107 		      __libelf_seterrno (ELF_E_INVALID_FILE);
    108 		      result = -1;
    109 		      goto out;
    110 		    }
    111 
    112 		  if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
    113 		    CONVERT (shdr_mem.sh_link);
    114 		  num = shdr_mem.sh_link;
    115 		}
    116 	    }
    117 	  else
    118 	    {
    119 	      size_t offset;
    120 
    121 	      if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
    122 		{
    123 		  num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
    124 		  goto success;
    125 		}
    126 
    127 	      offset = elf->state.elf64.ehdr->e_shoff;
    128 
    129 	      if (elf->map_address != NULL
    130 		  && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
    131 		  && (ALLOW_UNALIGNED
    132 		      || (((size_t) ((char *) elf->map_address + offset))
    133 			  & (__alignof__ (Elf64_Shdr) - 1)) == 0))
    134 		/* We can directly access the memory.  */
    135 		num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link;
    136 	      else
    137 		{
    138 		  /* We avoid reading in all the section headers.  Just read
    139 		     the first one.  */
    140 		  Elf64_Shdr shdr_mem;
    141 
    142 		  if (pread (elf->fildes, &shdr_mem, sizeof (Elf64_Shdr),
    143 			     offset) != sizeof (Elf64_Shdr))
    144 		    {
    145 		      /* We must be able to read this ELF section header.  */
    146 		      __libelf_seterrno (ELF_E_INVALID_FILE);
    147 		      result = -1;
    148 		      goto out;
    149 		    }
    150 
    151 		  if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
    152 		    CONVERT (shdr_mem.sh_link);
    153 		  num = shdr_mem.sh_link;
    154 		}
    155 	    }
    156 	}
    157 
    158       /* Store the result.  */
    159     success:
    160       *dst = num;
    161     }
    162 
    163  out:
    164   rwlock_unlock (elf->lock);
    165 
    166   return result;
    167 }
    168 INTDEF(elf_getshstrndx)
    169