• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Get ELF program header table.
2    Copyright (C) 1998-2010, 2014, 2015 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
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 <errno.h>
35 #include <stdbool.h>
36 #include <stdlib.h>
37 #include <assert.h>
38 
39 #include "libelfP.h"
40 #include "common.h"
41 
42 #ifndef LIBELFBITS
43 # define LIBELFBITS 32
44 #endif
45 
ElfW2(LIBELFBITS,Phdr)46 ElfW2(LIBELFBITS,Phdr) *
47 __elfw2(LIBELFBITS,getphdr_wrlock) (Elf *elf)
48 {
49   ElfW2(LIBELFBITS,Phdr) *result;
50 
51   /* If the program header entry has already been filled in the code
52      below must already have been run.  So the class is set, too.  No
53      need to waste any more time here.  */
54   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
55   if (likely (result != NULL))
56     return result;
57 
58   if (elf->class == 0)
59     elf->class = ELFW(ELFCLASS,LIBELFBITS);
60   else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
61     {
62       __libelf_seterrno (ELF_E_INVALID_CLASS);
63       result = NULL;
64       goto out;
65     }
66 
67   if (likely (result == NULL))
68     {
69       /* Read the section header table.  */
70       ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
71 
72       /* If no program header exists return NULL.  */
73       size_t phnum;
74       if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
75 	goto out;
76       if (phnum == 0 || ehdr->e_phoff == 0)
77 	{
78 	  __libelf_seterrno (ELF_E_NO_PHDR);
79 	  goto out;
80 	}
81 
82       /* Check this doesn't overflow.  */
83       size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
84 
85       if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))
86 	  || ehdr->e_phoff > elf->maximum_size
87 	  || elf->maximum_size - ehdr->e_phoff < size)
88 	{
89 	  __libelf_seterrno (ELF_E_INVALID_DATA);
90 	  goto out;
91 	}
92 
93       if (elf->map_address != NULL)
94 	{
95 	  /* First see whether the information in the ELF header is
96 	     valid and it does not ask for too much.  */
97 	  if (unlikely (ehdr->e_phoff >= elf->maximum_size)
98 	      || unlikely (elf->maximum_size - ehdr->e_phoff < size))
99 	    {
100 	      /* Something is wrong.  */
101 	      __libelf_seterrno (ELF_E_INVALID_PHDR);
102 	      goto out;
103 	    }
104 
105 	  /* All the data is already mapped.  Use it.  */
106 	  void *file_phdr = ((char *) elf->map_address
107 			     + elf->start_offset + ehdr->e_phoff);
108 	  if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
109 	      && (ALLOW_UNALIGNED
110 		  || ((uintptr_t) file_phdr
111 		      & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
112 	    /* Simply use the mapped data.  */
113 	    elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
114 	  else
115 	    {
116 	      ElfW2(LIBELFBITS,Phdr) *notcvt;
117 	      ElfW2(LIBELFBITS,Phdr) *phdr;
118 
119 	      /* Allocate memory for the program headers.  We know the number
120 		 of entries from the ELF header.  */
121 	      phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
122 		(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
123 	      if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
124 		{
125 		  __libelf_seterrno (ELF_E_NOMEM);
126 		  goto out;
127 		}
128 	      elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
129 		ELF_F_MALLOCED | ELF_F_DIRTY;
130 
131 	      /* Now copy the data and at the same time convert the
132 		 byte order.  */
133 
134 	      if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
135 		{
136 		  assert (! ALLOW_UNALIGNED);
137 		  memcpy (phdr, file_phdr, size);
138 		}
139 	      else
140 		{
141 		  bool copy = ! (ALLOW_UNALIGNED
142 				 || ((uintptr_t) file_phdr
143 				     & (__alignof__ (ElfW2(LIBELFBITS,Phdr))
144 					- 1)) == 0);
145 		  if (! copy)
146 		    notcvt = file_phdr;
147 		  else
148 		    {
149 		      notcvt = (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
150 		      if (unlikely (notcvt == NULL))
151 			{
152 			  __libelf_seterrno (ELF_E_NOMEM);
153 			  goto out;
154 			}
155 		      memcpy (notcvt, file_phdr, size);
156 		    }
157 
158 		  for (size_t cnt = 0; cnt < phnum; ++cnt)
159 		    {
160 		      CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
161 		      CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
162 		      CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
163 		      CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
164 		      CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
165 		      CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
166 		      CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
167 		      CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
168 		    }
169 
170 		  if (copy)
171 		    free (notcvt);
172 		}
173 	    }
174 	}
175       else if (likely (elf->fildes != -1))
176 	{
177 	  /* Allocate memory for the program headers.  We know the number
178 	     of entries from the ELF header.  */
179 	  elf->state.ELFW(elf,LIBELFBITS).phdr =
180 	    (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
181 	  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
182 	    {
183 	      __libelf_seterrno (ELF_E_NOMEM);
184 	      goto out;
185 	    }
186 	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
187 
188 	  /* Read the header.  */
189 	  ssize_t n = pread_retry (elf->fildes,
190 				   elf->state.ELFW(elf,LIBELFBITS).phdr, size,
191 				   elf->start_offset + ehdr->e_phoff);
192 	  if (unlikely ((size_t) n != size))
193 	    {
194 	      /* Severe problems.  We cannot read the data.  */
195 	      __libelf_seterrno (ELF_E_READ_ERROR);
196 	      free (elf->state.ELFW(elf,LIBELFBITS).phdr);
197 	      elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
198 	      goto out;
199 	    }
200 
201 	  /* If the byte order of the file is not the same as the one
202 	     of the host convert the data now.  */
203 	  if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
204 	    {
205 	      ElfW2(LIBELFBITS,Phdr) *phdr
206 		= elf->state.ELFW(elf,LIBELFBITS).phdr;
207 
208 	      for (size_t cnt = 0; cnt < phnum; ++cnt)
209 		{
210 		  CONVERT (phdr[cnt].p_type);
211 		  CONVERT (phdr[cnt].p_offset);
212 		  CONVERT (phdr[cnt].p_vaddr);
213 		  CONVERT (phdr[cnt].p_paddr);
214 		  CONVERT (phdr[cnt].p_filesz);
215 		  CONVERT (phdr[cnt].p_memsz);
216 		  CONVERT (phdr[cnt].p_flags);
217 		  CONVERT (phdr[cnt].p_align);
218 		}
219 	    }
220 	}
221       else
222 	{
223 	  /* The file descriptor was already enabled and not all data was
224 	     read.  */
225 	  __libelf_seterrno (ELF_E_FD_DISABLED);
226 	  goto out;
227 	}
228 
229       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
230     }
231 
232  out:
233   return result;
234 }
235 
ElfW2(LIBELFBITS,Phdr)236 ElfW2(LIBELFBITS,Phdr) *
237 elfw2(LIBELFBITS,getphdr) (Elf *elf)
238 {
239   ElfW2(LIBELFBITS,Phdr) *result;
240 
241   if (elf == NULL)
242     return NULL;
243 
244   if (unlikely (elf->kind != ELF_K_ELF))
245     {
246       __libelf_seterrno (ELF_E_INVALID_HANDLE);
247       return NULL;
248     }
249 
250   /* If the program header entry has already been filled in the code
251    * in getphdr_wrlock must already have been run.  So the class is
252    * set, too.  No need to waste any more time here.  */
253   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
254   if (likely (result != NULL))
255     return result;
256 
257   rwlock_wrlock (elf->lock);
258   result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
259   rwlock_unlock (elf->lock);
260 
261   return result;
262 }
263 INTDEF(elfw2(LIBELFBITS,getphdr))
264