• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Get ELF program header table.
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
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 <stdlib.h>
23 #include <unistd.h>
24 
25 #include "libelfP.h"
26 #include "common.h"
27 
28 #ifndef LIBELFBITS
29 # define LIBELFBITS 32
30 #endif
31 
32 
33 ElfW2(LIBELFBITS,Phdr) *
34 elfw2(LIBELFBITS,getphdr) (elf)
35      Elf *elf;
36 {
ElfW2(LIBELFBITS,Phdr)37   ElfW2(LIBELFBITS,Phdr) *result;
38 
39   if (elf == NULL)
40     return NULL;
41 
42   if (unlikely (elf->kind != ELF_K_ELF))
43     {
44       __libelf_seterrno (ELF_E_INVALID_HANDLE);
45       return NULL;
46     }
47 
48   /* If the program header entry has already been filled in the code
49      below must already have been run.  So the class is set, too.  No
50      need to waste any more time here.  */
51   result = elf->state.ELFW(elf,LIBELFBITS).phdr;
52   if (likely (result != NULL))
53     return result;
54 
55   rwlock_wrlock (elf->lock);
56 
57   if (elf->class == 0)
58     elf->class = ELFW(ELFCLASS,LIBELFBITS);
59   else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
60     {
61       __libelf_seterrno (ELF_E_INVALID_CLASS);
62       result = NULL;
63       goto out;
64     }
65 
66   if (likely (result == NULL))
67     {
68       /* Read the section header table.  */
69       ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
70       size_t phnum;
71       size_t size;
72 
73       /* If no program header exists return NULL.  */
74       phnum = ehdr->e_phnum;
75       if (phnum == 0)
76 	{
77 	  __libelf_seterrno (ELF_E_NO_PHDR);
78 	  goto out;
79 	}
80 
81       size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
82 
83       if (elf->map_address != NULL)
84 	{
85 	  /* All the data is already mapped.  Use it.  */
86 	  if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
87 	      && (ALLOW_UNALIGNED
88 		  || (ehdr->e_phoff
89 		      & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
90 	    /* Simply use the mapped data.  */
91 	    elf->state.ELFW(elf,LIBELFBITS).phdr = (ElfW2(LIBELFBITS,Phdr) *)
92 	      ((char *) elf->map_address + elf->start_offset + ehdr->e_phoff);
93 	  else
94 	    {
95 	      size_t cnt;
96 	      ElfW2(LIBELFBITS,Phdr) *notcvt;
97 	      ElfW2(LIBELFBITS,Phdr) *phdr;
98 
99 	      /* Allocate memory for the program headers.  We know the number
100 		 of entries from the ELF header.  */
101 	      phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
102 		(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
103 	      if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
104 		{
105 		  __libelf_seterrno (ELF_E_NOMEM);
106 		  goto out;
107 		}
108 	      elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
109 		ELF_F_MALLOCED | ELF_F_DIRTY;
110 
111 	      /* Now copy the data and at the same time convert the
112 		 byte order.  */
113 	      if (ALLOW_UNALIGNED
114 		  || (ehdr->e_phoff
115 		      & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0)
116 		notcvt = (ElfW2(LIBELFBITS,Phdr) *)
117 		  ((char *) elf->map_address
118 		   + elf->start_offset + ehdr->e_phoff);
119 	      else
120 		{
121 		  notcvt = (ElfW2(LIBELFBITS,Phdr) *) alloca (size);
122 		  memcpy (notcvt, ((char *) elf->map_address +
123 				   elf->start_offset + ehdr->e_phoff),
124 			  size);
125 		}
126 
127 	      for (cnt = 0; cnt < phnum; ++cnt)
128 		{
129 		  CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
130 		  CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
131 		  CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
132 		  CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
133 		  CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
134 		  CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
135 		  CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
136 		  CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
137 		}
138 	    }
139 	}
140       else if (likely (elf->fildes != -1))
141 	{
142 	  /* Allocate memory for the program headers.  We know the number
143 	     of entries from the ELF header.  */
144 	  elf->state.ELFW(elf,LIBELFBITS).phdr =
145 	    (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
146 	  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
147 	    {
148 	      __libelf_seterrno (ELF_E_NOMEM);
149 	      goto out;
150 	    }
151 	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
152 
153 	  /* Read the header.  */
154 	  if ((size_t) pread (elf->fildes,
155 			      elf->state.ELFW(elf,LIBELFBITS).phdr, size,
156 			      (elf->start_offset + ehdr->e_phoff)) != size)
157 	    {
158 	      /* Severe problems.  We cannot read the data.  */
159 	      __libelf_seterrno (ELF_E_READ_ERROR);
160 	      free (elf->state.ELFW(elf,LIBELFBITS).phdr);
161 	      elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
162 	      goto out;
163 	    }
164 
165 	  /* If the byte order of the file is not the same as the one
166 	     of the host convert the data now.  */
167 	  if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
168 	    {
169 	      ElfW2(LIBELFBITS,Phdr) *phdr;
170 	      size_t cnt;
171 
172 	      phdr = elf->state.ELFW(elf,LIBELFBITS).phdr;
173 	      for (cnt = 0; cnt < phnum; ++cnt)
174 		{
175 		  CONVERT (phdr[cnt].p_type);
176 		  CONVERT (phdr[cnt].p_offset);
177 		  CONVERT (phdr[cnt].p_vaddr);
178 		  CONVERT (phdr[cnt].p_paddr);
179 		  CONVERT (phdr[cnt].p_filesz);
180 		  CONVERT (phdr[cnt].p_memsz);
181 		  CONVERT (phdr[cnt].p_flags);
182 		  CONVERT (phdr[cnt].p_align);
183 		}
184 	    }
185 	}
186       else
187 	{
188 	  /* The file descriptor was already enabled and not all data was
189 	     read.  */
190 	  __libelf_seterrno (ELF_E_FD_DISABLED);
191 	  goto out;
192 	}
193 
194       result = elf->state.ELFW(elf,LIBELFBITS).phdr;
195     }
196 
197  out:
198   rwlock_unlock (elf->lock);
199 
200   return result;
201 }
202 INTDEF(elfw2(LIBELFBITS,getphdr))
203