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