• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Get ELF program header table.
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 Red Hat, Inc.
3    This file is part of Red Hat elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5 
6    Red Hat elfutils is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by the
8    Free Software Foundation; version 2 of the License.
9 
10    Red Hat elfutils is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License along
16    with Red Hat elfutils; if not, write to the Free Software Foundation,
17    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18 
19    In addition, as a special exception, Red Hat, Inc. gives You the
20    additional right to link the code of Red Hat elfutils with code licensed
21    under any Open Source Initiative certified open source license
22    (http://www.opensource.org/licenses/index.php) which requires the
23    distribution of source code with any binary distribution and to
24    distribute linked combinations of the two.  Non-GPL Code permitted under
25    this exception must only link to the code of Red Hat elfutils through
26    those well defined interfaces identified in the file named EXCEPTION
27    found in the source code files (the "Approved Interfaces").  The files
28    of Non-GPL Code may instantiate templates or use macros or inline
29    functions from the Approved Interfaces without causing the resulting
30    work to be covered by the GNU General Public License.  Only Red Hat,
31    Inc. may make changes or additions to the list of Approved Interfaces.
32    Red Hat's grant of this exception is conditioned upon your not adding
33    any new exceptions.  If you wish to add a new Approved Interface or
34    exception, please contact Red Hat.  You must obey the GNU General Public
35    License in all respects for all of the Red Hat elfutils code and other
36    code used in conjunction with Red Hat elfutils except the Non-GPL Code
37    covered by this exception.  If you modify this file, you may extend this
38    exception to your version of the file, but you are not obligated to do
39    so.  If you do not wish to provide this exception without modification,
40    you must delete this exception statement from your version and license
41    this file solely under the GPL without exception.
42 
43    Red Hat elfutils is an included package of the Open Invention Network.
44    An included package of the Open Invention Network is a package for which
45    Open Invention Network licensees cross-license their patents.  No patent
46    license is granted, either expressly or impliedly, by designation as an
47    included package.  Should you wish to participate in the Open Invention
48    Network licensing program, please visit www.openinventionnetwork.com
49    <http://www.openinventionnetwork.com>.  */
50 
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif
54 
55 #include <errno.h>
56 #include <stdbool.h>
57 #include <stdlib.h>
58 #include <unistd.h>
59 #include <assert.h>
60 
61 #include <system.h>
62 #include "libelfP.h"
63 #include "common.h"
64 
65 #ifndef LIBELFBITS
66 # define LIBELFBITS 32
67 #endif
68 
69 ElfW2(LIBELFBITS,Phdr) *
70 __elfw2(LIBELFBITS,getphdr_wrlock) (elf)
71      Elf *elf;
72 {
73   ElfW2(LIBELFBITS,Phdr) *result;
74 
75   /* If the program header entry has already been filled in the code
76      below must already have been run.  So the class is set, too.  No
77      need to waste any more time here.  */
78   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
79   if (likely (result != NULL))
80     return result;
81 
82   if (elf->class == 0)
83     elf->class = ELFW(ELFCLASS,LIBELFBITS);
84   else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
85     {
86       __libelf_seterrno (ELF_E_INVALID_CLASS);
87       result = NULL;
88       goto out;
89     }
90 
91   if (likely (result == NULL))
92     {
93       /* Read the section header table.  */
94       ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
95 
96       /* If no program header exists return NULL.  */
97       size_t phnum = ehdr->e_phnum;
98       if (phnum == 0)
99 	{
100 	  __libelf_seterrno (ELF_E_NO_PHDR);
101 	  goto out;
102 	}
103 
104       size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
105 
106       if (elf->map_address != NULL)
107 	{
108 	  /* All the data is already mapped.  Use it.  */
109 	  void *file_phdr = ((char *) elf->map_address
110 			     + elf->start_offset + ehdr->e_phoff);
111 	  if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
112 	      && (ALLOW_UNALIGNED
113 		  || ((uintptr_t) file_phdr
114 		      & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
115 	    /* Simply use the mapped data.  */
116 	    elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
117 	  else
118 	    {
119 	      ElfW2(LIBELFBITS,Phdr) *notcvt;
120 	      ElfW2(LIBELFBITS,Phdr) *phdr;
121 
122 	      /* Allocate memory for the program headers.  We know the number
123 		 of entries from the ELF header.  */
124 	      phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
125 		(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
126 	      if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
127 		{
128 		  __libelf_seterrno (ELF_E_NOMEM);
129 		  goto out;
130 		}
131 	      elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
132 		ELF_F_MALLOCED | ELF_F_DIRTY;
133 
134 	      /* Now copy the data and at the same time convert the
135 		 byte order.  */
136 
137 	      if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
138 		{
139 		  assert (! ALLOW_UNALIGNED);
140 		  memcpy (phdr, file_phdr, size);
141 		}
142 	      else
143 		{
144 		  if (ALLOW_UNALIGNED
145 		      || ((uintptr_t) file_phdr
146 			  & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)
147 		    notcvt = file_phdr;
148 		  else
149 		    {
150 		      notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size);
151 		      memcpy (notcvt, file_phdr, size);
152 		    }
153 
154 		  for (size_t cnt = 0; cnt < phnum; ++cnt)
155 		    {
156 		      CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
157 		      CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
158 		      CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
159 		      CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
160 		      CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
161 		      CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
162 		      CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
163 		      CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
164 		    }
165 		}
166 	    }
167 	}
168       else if (likely (elf->fildes != -1))
169 	{
170 	  /* Allocate memory for the program headers.  We know the number
171 	     of entries from the ELF header.  */
172 	  elf->state.ELFW(elf,LIBELFBITS).phdr =
173 	    (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
174 	  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
175 	    {
176 	      __libelf_seterrno (ELF_E_NOMEM);
177 	      goto out;
178 	    }
179 	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
180 
181 	  /* Read the header.  */
182 	  ssize_t n = pread_retry (elf->fildes,
183 				   elf->state.ELFW(elf,LIBELFBITS).phdr, size,
184 				   elf->start_offset + ehdr->e_phoff);
185 	  if (unlikely ((size_t) n != size))
186 	    {
187 	      /* Severe problems.  We cannot read the data.  */
188 	      __libelf_seterrno (ELF_E_READ_ERROR);
189 	      free (elf->state.ELFW(elf,LIBELFBITS).phdr);
190 	      elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
191 	      goto out;
192 	    }
193 
194 	  /* If the byte order of the file is not the same as the one
195 	     of the host convert the data now.  */
196 	  if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
197 	    {
198 	      ElfW2(LIBELFBITS,Phdr) *phdr
199 		= elf->state.ELFW(elf,LIBELFBITS).phdr;
200 
201 	      for (size_t cnt = 0; cnt < phnum; ++cnt)
202 		{
203 		  CONVERT (phdr[cnt].p_type);
204 		  CONVERT (phdr[cnt].p_offset);
205 		  CONVERT (phdr[cnt].p_vaddr);
206 		  CONVERT (phdr[cnt].p_paddr);
207 		  CONVERT (phdr[cnt].p_filesz);
208 		  CONVERT (phdr[cnt].p_memsz);
209 		  CONVERT (phdr[cnt].p_flags);
210 		  CONVERT (phdr[cnt].p_align);
211 		}
212 	    }
213 	}
214       else
215 	{
216 	  /* The file descriptor was already enabled and not all data was
217 	     read.  */
218 	  __libelf_seterrno (ELF_E_FD_DISABLED);
219 	  goto out;
220 	}
221 
222       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
223     }
224 
225  out:
226   return result;
227 }
228 
229 ElfW2(LIBELFBITS,Phdr) *
230 elfw2(LIBELFBITS,getphdr) (elf)
231      Elf *elf;
232 {
ElfW2(LIBELFBITS,Phdr)233   ElfW2(LIBELFBITS,Phdr) *result;
234 
235   if (elf == NULL)
236     return NULL;
237 
238   if (unlikely (elf->kind != ELF_K_ELF))
239     {
240       __libelf_seterrno (ELF_E_INVALID_HANDLE);
241       return NULL;
242     }
243 
244   /* If the program header entry has already been filled in the code
245    * in getphdr_wrlock must already have been run.  So the class is
246    * set, too.  No need to waste any more time here.  */
247   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
248   if (likely (result != NULL))
249     return result;
250 
251   rwlock_wrlock (elf->lock);
252   result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
253   rwlock_unlock (elf->lock);
254 
255   return result;
256 }
257 INTDEF(elfw2(LIBELFBITS,getphdr))
258