• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Return section index of section header string table.
2    Copyright (C) 2002 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@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
elf_getshstrndx(elf,dst)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