• 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 #include <unistd.h>
39 
40 #include <system.h>
41 #include "libelfP.h"
42 #include "common.h"
43 
44 
45 int
elf_getshdrstrndx(Elf * elf,size_t * dst)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 		  ssize_t r;
137 
138 		  if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
139 						  sizeof (Elf32_Shdr), offset))
140 				!= sizeof (Elf32_Shdr)))
141 		    {
142 		      /* We must be able to read this ELF section header.  */
143 		      if (r < 0)
144 			__libelf_seterrno (ELF_E_INVALID_FILE);
145 		      else
146 			__libelf_seterrno (ELF_E_INVALID_ELF);
147 		      result = -1;
148 		      goto out;
149 		    }
150 
151 		  if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
152 		    CONVERT (shdr_mem.sh_link);
153 		  num = shdr_mem.sh_link;
154 		}
155 	    }
156 	  else
157 	    {
158 	      if (unlikely (elf->state.elf64.scns.cnt == 0))
159 		{
160 		  /* Cannot use SHN_XINDEX without section headers.  */
161 		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
162 		  result = -1;
163 		  goto out;
164 		}
165 
166 	      if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
167 		{
168 		  num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
169 		  goto success;
170 		}
171 
172 	      size_t offset = elf->state.elf64.ehdr->e_shoff;
173 
174 	      if (elf->map_address != NULL
175 		  && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
176 		  && (ALLOW_UNALIGNED
177 		      || (((size_t) ((char *) elf->map_address
178 			   + elf->start_offset + offset))
179 			  & (__alignof__ (Elf64_Shdr) - 1)) == 0))
180 		{
181 		  /* First see whether the information in the ELF header is
182 		     valid and it does not ask for too much.  */
183 		  if (unlikely (elf->maximum_size - offset
184 				< sizeof (Elf64_Shdr)))
185 		    {
186 		      /* Something is wrong.  */
187 		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
188 		      result = -1;
189 		      goto out;
190 		    }
191 
192 		  /* We can directly access the memory.  */
193 		  num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
194 					 + offset))->sh_link;
195 		}
196 	      else
197 		{
198 		  /* We avoid reading in all the section headers.  Just read
199 		     the first one.  */
200 		  Elf64_Shdr shdr_mem;
201 		  ssize_t r;
202 
203 		  if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
204 						  sizeof (Elf64_Shdr), offset))
205 				!= sizeof (Elf64_Shdr)))
206 		    {
207 		      /* We must be able to read this ELF section header.  */
208 		      if (r < 0)
209 			__libelf_seterrno (ELF_E_INVALID_FILE);
210 		      else
211 			__libelf_seterrno (ELF_E_INVALID_ELF);
212 		      result = -1;
213 		      goto out;
214 		    }
215 
216 		  if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
217 		    CONVERT (shdr_mem.sh_link);
218 		  num = shdr_mem.sh_link;
219 		}
220 	    }
221 	}
222 
223       /* Store the result.  */
224     success:
225       *dst = num;
226     }
227 
228  out:
229   rwlock_unlock (elf->lock);
230 
231   return result;
232 }
233 INTDEF(elf_getshdrstrndx)
234 /* Alias for the deprecated name.  */
235 strong_alias (elf_getshdrstrndx, elf_getshstrndx)
236