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