• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Return section header.
2    Copyright (C) 1998, 1999, 2000, 2001, 2002 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 <assert.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,Shdr) *
34 elfw2(LIBELFBITS,getshdr) (scn)
35      Elf_Scn *scn;
36 {
ElfW2(LIBELFBITS,Shdr)37   ElfW2(LIBELFBITS,Shdr) *result;
38 
39   if (scn == NULL)
40     return NULL;
41 
42   if (unlikely (scn->elf->state.elf.ehdr == NULL))
43     {
44       __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
45       return NULL;
46     }
47 
48   if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
49     {
50       __libelf_seterrno (ELF_E_INVALID_CLASS);
51       return NULL;
52     }
53 
54   result = scn->shdr.ELFW(e,LIBELFBITS);
55   if (result == NULL)
56     {
57       /* Read the section header table.  */
58       Elf *elf = scn->elf;
59       ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
60       size_t shnum;
61       ElfW2(LIBELFBITS,Shdr) *shdr;
62       size_t size;
63       size_t cnt;
64 
65       rwlock_wrlock (elf->lock);
66 
67       /* Try again, maybe the data is there now.  */
68       result = scn->shdr.ELFW(e,LIBELFBITS);
69       if (result != NULL)
70 	goto out;
71 
72       if (INTUSE (elf_getshnum) (elf, &shnum) != 0)
73 	goto out;
74       size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
75 
76       /* Allocate memory for the program headers.  We know the number
77 	 of entries from the ELF header.  */
78       shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
79 	(ElfW2(LIBELFBITS,Shdr) *) malloc (size);
80       if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
81 	{
82 	  __libelf_seterrno (ELF_E_NOMEM);
83 	  goto out;
84 	}
85       elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
86 
87       if (elf->map_address != NULL)
88 	{
89 	  ElfW2(LIBELFBITS,Shdr) *notcvt;
90 
91 	  /* All the data is already mapped.  If we could use it
92 	     directly this would already have happened.  */
93 	  assert (ehdr->e_ident[EI_DATA] != MY_ELFDATA
94 		  || (! ALLOW_UNALIGNED
95 		      && (ehdr->e_shoff
96 			  & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
97 
98 	  /* Now copy the data and at the same time convert the byte
99 	     order.  */
100 	  if (ALLOW_UNALIGNED
101 	      || (ehdr->e_shoff
102 		  & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) == 0)
103 	    notcvt = (ElfW2(LIBELFBITS,Shdr) *)
104 	      ((char *) elf->map_address
105 	       + elf->start_offset + ehdr->e_shoff);
106 	  else
107 	    {
108 	      notcvt = (ElfW2(LIBELFBITS,Shdr) *) alloca (size);
109 	      memcpy (notcvt, ((char *) elf->map_address
110 			       + elf->start_offset + ehdr->e_shoff),
111 		      size);
112 	    }
113 
114 	  for (cnt = 0; cnt < shnum; ++cnt)
115 	    {
116 	      CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
117 	      CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
118 	      CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
119 	      CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
120 	      CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
121 	      CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
122 	      CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
123 	      CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
124 	      CONVERT_TO (shdr[cnt].sh_addralign, notcvt[cnt].sh_addralign);
125 	      CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
126 	    }
127 	}
128       else if (elf->fildes != -1)
129 	{
130 	  /* Read the header.  */
131 	  if ((size_t) pread (elf->fildes,
132 			      elf->state.ELFW(elf,LIBELFBITS).shdr, size,
133 			      elf->start_offset + ehdr->e_shoff) != size)
134 	    {
135 	      /* Severe problems.  We cannot read the data.  */
136 	      __libelf_seterrno (ELF_E_READ_ERROR);
137 	      goto free_and_out;
138 	    }
139 
140 	  /* If the byte order of the file is not the same as the one
141 	     of the host convert the data now.  */
142 	  if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
143 	    for (cnt = 0; cnt < shnum; ++cnt)
144 	      {
145 		CONVERT (shdr[cnt].sh_name);
146 		CONVERT (shdr[cnt].sh_type);
147 		CONVERT (shdr[cnt].sh_flags);
148 		CONVERT (shdr[cnt].sh_addr);
149 		CONVERT (shdr[cnt].sh_offset);
150 		CONVERT (shdr[cnt].sh_size);
151 		CONVERT (shdr[cnt].sh_link);
152 		CONVERT (shdr[cnt].sh_info);
153 		CONVERT (shdr[cnt].sh_addralign);
154 		CONVERT (shdr[cnt].sh_entsize);
155 	      }
156 	}
157       else
158 	{
159 	  /* The file descriptor was already enabled and not all data was
160 	     read.  Undo the allocation.  */
161 	  __libelf_seterrno (ELF_E_FD_DISABLED);
162 
163 	free_and_out:
164 	  free (shdr);
165 	  elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
166 	  elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
167 
168 	  goto out;
169 	}
170 
171       /* Set the pointers in the `scn's.  */
172       for (cnt = 0; cnt < shnum; ++cnt)
173 	elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
174 	  = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
175 
176       result = scn->shdr.ELFW(e,LIBELFBITS);
177       assert (result != NULL);
178 
179     out:
180       rwlock_unlock (elf->lock);
181     }
182 
183   return result;
184 }
185 INTDEF(elfw2(LIBELFBITS,getshdr))
186