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 
45 int
elf_getshdrstrndx(elf,dst)46 elf_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 	      if (unlikely (elf->state.elf32.scns.cnt == 0))
96 		{
97 		  /* Cannot use SHN_XINDEX without section headers.  */
98 		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
99 		  result = -1;
100 		  goto out;
101 		}
102 
103 	      if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
104 		{
105 		  num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
106 		  goto success;
107 		}
108 
109 	      offset = elf->state.elf32.ehdr->e_shoff;
110 
111 	      if (elf->map_address != NULL
112 		  && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
113 		  && (ALLOW_UNALIGNED
114 		      || (((size_t) ((char *) elf->map_address
115 			   + elf->start_offset + offset))
116 			  & (__alignof__ (Elf32_Shdr) - 1)) == 0))
117 		{
118 		  /* First see whether the information in the ELF header is
119 		     valid and it does not ask for too much.  */
120 		  if (unlikely (elf->maximum_size - offset
121 				< sizeof (Elf32_Shdr)))
122 		    {
123 		      /* Something is wrong.  */
124 		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
125 		      result = -1;
126 		      goto out;
127 		    }
128 
129 		  /* We can directly access the memory.  */
130 		  num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
131 					 + offset))->sh_link;
132 		}
133 	      else
134 		{
135 		  /* We avoid reading in all the section headers.  Just read
136 		     the first one.  */
137 		  Elf32_Shdr shdr_mem;
138 
139 		  if (unlikely (pread_retry (elf->fildes, &shdr_mem,
140 					     sizeof (Elf32_Shdr), offset)
141 				!= sizeof (Elf32_Shdr)))
142 		    {
143 		      /* We must be able to read this ELF section header.  */
144 		      __libelf_seterrno (ELF_E_INVALID_FILE);
145 		      result = -1;
146 		      goto out;
147 		    }
148 
149 		  if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
150 		    CONVERT (shdr_mem.sh_link);
151 		  num = shdr_mem.sh_link;
152 		}
153 	    }
154 	  else
155 	    {
156 	      if (unlikely (elf->state.elf64.scns.cnt == 0))
157 		{
158 		  /* Cannot use SHN_XINDEX without section headers.  */
159 		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
160 		  result = -1;
161 		  goto out;
162 		}
163 
164 	      if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
165 		{
166 		  num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
167 		  goto success;
168 		}
169 
170 	      size_t offset = elf->state.elf64.ehdr->e_shoff;
171 
172 	      if (elf->map_address != NULL
173 		  && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
174 		  && (ALLOW_UNALIGNED
175 		      || (((size_t) ((char *) elf->map_address
176 			   + elf->start_offset + offset))
177 			  & (__alignof__ (Elf64_Shdr) - 1)) == 0))
178 		{
179 		  /* First see whether the information in the ELF header is
180 		     valid and it does not ask for too much.  */
181 		  if (unlikely (elf->maximum_size - offset
182 				< sizeof (Elf64_Shdr)))
183 		    {
184 		      /* Something is wrong.  */
185 		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
186 		      result = -1;
187 		      goto out;
188 		    }
189 
190 		  /* We can directly access the memory.  */
191 		  num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
192 					 + offset))->sh_link;
193 		}
194 	      else
195 		{
196 		  /* We avoid reading in all the section headers.  Just read
197 		     the first one.  */
198 		  Elf64_Shdr shdr_mem;
199 
200 		  if (unlikely (pread_retry (elf->fildes, &shdr_mem,
201 					     sizeof (Elf64_Shdr), offset)
202 				!= sizeof (Elf64_Shdr)))
203 		    {
204 		      /* We must be able to read this ELF section header.  */
205 		      __libelf_seterrno (ELF_E_INVALID_FILE);
206 		      result = -1;
207 		      goto out;
208 		    }
209 
210 		  if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
211 		    CONVERT (shdr_mem.sh_link);
212 		  num = shdr_mem.sh_link;
213 		}
214 	    }
215 	}
216 
217       /* Store the result.  */
218     success:
219       *dst = num;
220     }
221 
222  out:
223   rwlock_unlock (elf->lock);
224 
225   return result;
226 }
227 INTDEF(elf_getshdrstrndx)
228 /* Alias for the deprecated name.  */
229 strong_alias (elf_getshdrstrndx, elf_getshstrndx)
230