• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
39 #include "libelfP.h"
40 #include "common.h"
41 
42 
43 int
elf_getshdrstrndx(Elf * elf,size_t * dst)44 elf_getshdrstrndx (Elf *elf, size_t *dst)
45 {
46   int result = 0;
47 
48   if (elf == NULL)
49     return -1;
50 
51   if (unlikely (elf->kind != ELF_K_ELF))
52     {
53       __libelf_seterrno (ELF_E_INVALID_HANDLE);
54       return -1;
55     }
56 
57   rwlock_rdlock (elf->lock);
58 
59   /* We rely here on the fact that the `elf' element is a common prefix
60      of `elf32' and `elf64'.  */
61   assert (offsetof (struct Elf, state.elf.ehdr)
62 	  == offsetof (struct Elf, state.elf32.ehdr));
63   assert (sizeof (elf->state.elf.ehdr)
64 	  == sizeof (elf->state.elf32.ehdr));
65   assert (offsetof (struct Elf, state.elf.ehdr)
66 	  == offsetof (struct Elf, state.elf64.ehdr));
67   assert (sizeof (elf->state.elf.ehdr)
68 	  == sizeof (elf->state.elf64.ehdr));
69 
70   if (unlikely (elf->state.elf.ehdr == NULL))
71     {
72       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
73       result = -1;
74     }
75   else
76     {
77       Elf32_Word num;
78 
79       num = (elf->class == ELFCLASS32
80 	     ? elf->state.elf32.ehdr->e_shstrndx
81 	     : elf->state.elf64.ehdr->e_shstrndx);
82 
83       /* Determine whether the index is too big to fit in the ELF
84 	 header.  */
85       if (unlikely (num == SHN_XINDEX))
86 	{
87 	  /* Yes.  Search the zeroth section header.  */
88 	  if (elf->class == ELFCLASS32)
89 	    {
90 	      size_t offset;
91 	      if (unlikely (elf->state.elf32.scns.cnt == 0))
92 		{
93 		  /* Cannot use SHN_XINDEX without section headers.  */
94 		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
95 		  result = -1;
96 		  goto out;
97 		}
98 
99 	      if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
100 		{
101 		  num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
102 		  goto success;
103 		}
104 
105 	      offset = elf->state.elf32.ehdr->e_shoff;
106 
107 	      if (elf->map_address != NULL
108 		  && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
109 		  && (ALLOW_UNALIGNED
110 		      || (((size_t) ((char *) elf->map_address
111 			   + elf->start_offset + offset))
112 			  & (__alignof__ (Elf32_Shdr) - 1)) == 0))
113 		{
114 		  /* First see whether the information in the ELF header is
115 		     valid and it does not ask for too much.  */
116 		  if (unlikely (elf->maximum_size - offset
117 				< sizeof (Elf32_Shdr)))
118 		    {
119 		      /* Something is wrong.  */
120 		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
121 		      result = -1;
122 		      goto out;
123 		    }
124 
125 		  /* We can directly access the memory.  */
126 		  num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
127 					 + offset))->sh_link;
128 		}
129 	      else
130 		{
131 		  /* We avoid reading in all the section headers.  Just read
132 		     the first one.  */
133 		  Elf32_Shdr shdr_mem;
134 		  ssize_t r;
135 
136 		  if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
137 						  sizeof (Elf32_Shdr), offset))
138 				!= sizeof (Elf32_Shdr)))
139 		    {
140 		      /* We must be able to read this ELF section header.  */
141 		      if (r < 0)
142 			__libelf_seterrno (ELF_E_INVALID_FILE);
143 		      else
144 			__libelf_seterrno (ELF_E_INVALID_ELF);
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 		  ssize_t r;
200 
201 		  if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
202 						  sizeof (Elf64_Shdr), offset))
203 				!= sizeof (Elf64_Shdr)))
204 		    {
205 		      /* We must be able to read this ELF section header.  */
206 		      if (r < 0)
207 			__libelf_seterrno (ELF_E_INVALID_FILE);
208 		      else
209 			__libelf_seterrno (ELF_E_INVALID_ELF);
210 		      result = -1;
211 		      goto out;
212 		    }
213 
214 		  if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
215 		    CONVERT (shdr_mem.sh_link);
216 		  num = shdr_mem.sh_link;
217 		}
218 	    }
219 	}
220 
221       /* Store the result.  */
222     success:
223       *dst = num;
224     }
225 
226  out:
227   rwlock_unlock (elf->lock);
228 
229   return result;
230 }
231 INTDEF(elf_getshdrstrndx)
232 /* Alias for the deprecated name.  */
233 strong_alias (elf_getshdrstrndx, elf_getshstrndx)
234