• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Return the next data element from the section after possibly converting it.
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 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 <stddef.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #include "libelfP.h"
27 #include "common.h"
28 #include "elf-knowledge.h"
29 
30 
31 #if _STRING_ARCH_unaligned
32 # define ALLOW_ALIGNED	1
33 #else
34 # define ALLOW_ALIGNED	0
35 #endif
36 
37 
38 #define TYPEIDX(Sh_Type) \
39   (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM				      \
40    ? Sh_Type								      \
41    : (Sh_Type >= SHT_GNU_LIBLIST && Sh_Type <= SHT_HISUNW		      \
42       ? SHT_NUM + Sh_Type - SHT_GNU_LIBLIST				      \
43       : 0))
44 
45 static const struct
46 {
47   Elf_Type type;
48   size_t size;
49 #if ALLOW_ALIGNED
50 # define AL(val)
51 #else
52   size_t align;
53 # define AL(val), val
54 #endif
55 } shtype_map[EV_NUM - 1][ELFCLASSNUM - 1][TYPEIDX (SHT_HISUNW) + 1] =
56 {
57   [EV_CURRENT - 1] =
58   {
59     [ELFCLASS32 - 1] =
60     {
61       /* Associate section types with libelf types, their sizes and
62 	 alignment.  SHT_GNU_verdef is special since the section does
63 	 not contain entries of only one size.  */
64 #define DEFINE(Bits) \
65       [SHT_SYMTAB] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym))		      \
66 		       AL (__alignof__ (ElfW2(Bits,Sym))) },		      \
67       [SHT_RELA] = { ELF_T_RELA, sizeof (ElfW2(Bits,Rela))		      \
68 		       AL (__alignof__ (ElfW2(Bits,Rela))) },		      \
69       [SHT_HASH] = { ELF_T_WORD, sizeof (ElfW2(Bits,Word))		      \
70 		       AL (__alignof__ (ElfW2(Bits,Word))) },		      \
71       [SHT_DYNAMIC] = { ELF_T_DYN, sizeof (ElfW2(Bits,Dyn))		      \
72 		       AL (__alignof__ (ElfW2(Bits,Dyn))) },		      \
73       [SHT_REL] = { ELF_T_REL, sizeof (ElfW2(Bits,Rel))			      \
74 		       AL (__alignof__ (ElfW2(Bits,Rel))) },		      \
75       [SHT_DYNSYM] = { ELF_T_SYM, sizeof (ElfW2(Bits,Sym))		      \
76 		       AL (__alignof__ (ElfW2(Bits,Sym))) },		      \
77       [SHT_INIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr))	      \
78 			   AL (__alignof__ (ElfW2(Bits,Addr))) },	      \
79       [SHT_FINI_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr))	      \
80 			   AL (__alignof__ (ElfW2(Bits,Addr))) },	      \
81       [SHT_PREINIT_ARRAY] = { ELF_T_ADDR, sizeof (ElfW2(Bits,Addr))	      \
82 			      AL (__alignof__ (ElfW2(Bits,Addr))) },	      \
83       [SHT_GROUP] = { ELF_T_WORD, sizeof (Elf32_Word)			      \
84 		      AL (__alignof__ (Elf32_Word)) },			      \
85       [SHT_SYMTAB_SHNDX] = { ELF_T_WORD, sizeof (Elf32_Word)		      \
86 			     AL (__alignof__ (Elf32_Word)) },		      \
87       [TYPEIDX (SHT_GNU_verdef)] = { ELF_T_VDEF, 1 AL (1) },		      \
88       [TYPEIDX (SHT_GNU_verneed)] = { ELF_T_VNEED,			      \
89 				      sizeof (ElfW2(Bits,Verneed))	      \
90 				      AL (__alignof__ (ElfW2(Bits,Verneed)))},\
91       [TYPEIDX (SHT_GNU_versym)] = { ELF_T_HALF, sizeof (ElfW2(Bits,Versym))  \
92 				     AL (__alignof__ (ElfW2(Bits,Versym))) }, \
93       [TYPEIDX (SHT_SUNW_syminfo)] = { ELF_T_SYMINFO,			      \
94 				       sizeof (ElfW2(Bits,Syminfo))	      \
95 				       AL(__alignof__ (ElfW2(Bits,Syminfo)))},\
96       [TYPEIDX (SHT_SUNW_move)] = { ELF_T_MOVE, sizeof (ElfW2(Bits,Move))     \
97 				    AL (__alignof__ (ElfW2(Bits,Move))) },    \
98       [TYPEIDX (SHT_GNU_LIBLIST)] = { ELF_T_LIB, sizeof (ElfW2(Bits,Lib))     \
99 				    AL (__alignof__ (ElfW2(Bits,Lib))) }
100       DEFINE (32)
101     },
102     [ELFCLASS64 - 1] =
103     {
104       DEFINE (64)
105     }
106   }
107 };
108 
109 
110 /* Convert the data in the current section.  */
111 static void
convert_data(Elf_Scn * scn,int version,int eclass,int data,size_t size,size_t type)112 convert_data (Elf_Scn *scn, int version, int eclass, int data,
113 	      size_t size, size_t type)
114 {
115 #if ALLOW_ALIGNED
116   /* No need to compute the alignment requirement of the host.  */
117   const size_t align = 1;
118 #else
119 # if EV_NUM != 2
120   size_t align = shtype_map[__libelf_version - 1][eclass - 1][type].align;
121 # else
122   size_t align = shtype_map[0][eclass - 1][type].align;
123 # endif
124 #endif
125 
126   if (data == MY_ELFDATA)
127     {
128       if (ALLOW_ALIGNED
129 	  || (((size_t) ((char *) scn->rawdata_base)) & (align - 1)) == 0)
130 	/* No need to copy, we can use the raw data.  */
131 	scn->data_base = scn->rawdata_base;
132       else
133 	{
134 	  scn->data_base = (char *) malloc (size);
135 	  if (scn->data_base == NULL)
136 	    {
137 	      __libelf_seterrno (ELF_E_NOMEM);
138 	      return;
139 	    }
140 
141 	  /* The copy will be appropriately aligned for direct access.  */
142 	  memcpy (scn->data_base, scn->rawdata_base, size);
143 	}
144     }
145   else
146     {
147       xfct_t fp;
148 
149       scn->data_base = (char *) malloc (size);
150       if (scn->data_base == NULL)
151 	{
152 	  __libelf_seterrno (ELF_E_NOMEM);
153 	  return;
154 	}
155 
156       /* Get the conversion function.  */
157 #if EV_NUM != 2
158       fp = __elf_xfctstom[version - 1][__libelf_version - 1][eclass - 1][type];
159 #else
160       fp = __elf_xfctstom[0][0][eclass - 1][type];
161 #endif
162 
163       fp (scn->data_base, scn->rawdata_base, size, 0);
164     }
165 
166   scn->data_list.data.d.d_buf = scn->data_base;
167   scn->data_list.data.d.d_size = size;
168   scn->data_list.data.d.d_type = type;
169   scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
170   scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
171   scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
172 
173   scn->data_list.data.s = scn;
174 }
175 
176 
177 /* Store the information for the raw data in the `rawdata' element.  */
178 int
179 internal_function_def
__libelf_set_rawdata(Elf_Scn * scn)180 __libelf_set_rawdata (Elf_Scn *scn)
181 {
182   size_t offset;
183   size_t size;
184   size_t align;
185   int type;
186   Elf *elf = scn->elf;
187 
188   if (elf->class == ELFCLASS32)
189     {
190       Elf32_Shdr *shdr = scn->shdr.e32 ?: INTUSE(elf32_getshdr) (scn);
191 
192       if (shdr == NULL)
193 	/* Something went terribly wrong.  */
194 	return 1;
195 
196       offset = shdr->sh_offset;
197       size = shdr->sh_size;
198       type = shdr->sh_type;
199       align = shdr->sh_addralign;
200     }
201   else
202     {
203       Elf64_Shdr *shdr = scn->shdr.e64 ?: INTUSE(elf64_getshdr) (scn);
204 
205       if (shdr == NULL)
206 	/* Something went terribly wrong.  */
207 	return 1;
208 
209       offset = shdr->sh_offset;
210       size = shdr->sh_size;
211       type = shdr->sh_type;
212       align = shdr->sh_addralign;
213     }
214 
215   /* If the section has no data (for whatever reason), leave the `d_buf'
216      pointer NULL.  */
217   if (size != 0 && type != SHT_NOBITS)
218     {
219       /* First a test whether the section is valid at all.  */
220       size_t entsize;
221 
222       if (type == SHT_HASH)
223 	{
224 	  GElf_Ehdr ehdr_mem;
225 
226 	  entsize = SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem));
227 	}
228       else
229 	{
230 #if EV_NUM != 2
231 	  entsize = shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].size;
232 #else
233 	  entsize = shtype_map[0][elf->class - 1][TYPEIDX (type)].size;
234 #endif
235 	}
236 
237       /* We assume it is an array of bytes if it is none of the structured
238 	 sections we know of.  */
239       if (entsize == 0)
240 	entsize = 1;
241 
242       if (size % entsize != 0)
243 	{
244 	  __libelf_seterrno (ELF_E_INVALID_DATA);
245 	  return 1;
246 	}
247 
248       /* We can use the mapped or loaded data if available.  */
249       if (elf->map_address != NULL)
250 	{
251 	  /* First see whether the information in the section header is
252 	     valid and it does not ask for too much.  */
253 	  if (offset + size > elf->maximum_size)
254 	    {
255 	      /* Something is wrong.  */
256 	      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
257 	      return 1;
258 	    }
259 
260 	  scn->rawdata_base = scn->rawdata.d.d_buf
261 	    = (char *) elf->map_address + elf->start_offset + offset;
262 	}
263       else if (elf->fildes != -1)
264 	{
265 	  /* We have to read the data from the file.  Allocate the needed
266 	     memory.  */
267 	  scn->rawdata_base = scn->rawdata.d.d_buf
268 	    = (char *) malloc (size);
269 	  if (scn->rawdata.d.d_buf == NULL)
270 	    {
271 	      __libelf_seterrno (ELF_E_NOMEM);
272 	      return 1;
273 	    }
274 
275 	  if ((size_t) pread (elf->fildes, scn->rawdata.d.d_buf, size,
276 			      elf->start_offset + offset) != size)
277 	    {
278 	      /* Cannot read the data.  */
279 	      free (scn->rawdata.d.d_buf);
280 	      scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
281 	      __libelf_seterrno (ELF_E_READ_ERROR);
282 	      return 1;
283 	    }
284 	}
285       else
286 	{
287 	  /* The file descriptor is already closed, we cannot get the data
288 	     anymore.  */
289 	  __libelf_seterrno (ELF_E_FD_DISABLED);
290 	  return 1;
291 	}
292     }
293 
294   scn->rawdata.d.d_size = size;
295   /* Some broken ELF ABI for 64-bit machines use the wrong hash table
296      entry size.  See elf-knowledge.h for more information.  */
297   if (type == SHT_HASH && elf->class == ELFCLASS64)
298     {
299       GElf_Ehdr ehdr_mem;
300 
301       scn->rawdata.d.d_type = (SH_ENTSIZE_HASH (gelf_getehdr (elf, &ehdr_mem))
302 			       == 4 ? ELF_T_WORD : ELF_T_XWORD);
303     }
304   else
305     {
306 #if EV_NUM != 2
307       scn->rawdata.d.d_type =
308 	shtype_map[__libelf_version - 1][elf->class - 1][TYPEIDX (type)].type;
309 #else
310       scn->rawdata.d.d_type =
311 	shtype_map[0][elf->class - 1][TYPEIDX (type)].type;
312 #endif
313     }
314   scn->rawdata.d.d_off = 0;
315   scn->rawdata.d.d_align = align;
316   if (elf->class == ELFCLASS32
317       || (offsetof (struct Elf, state.elf32.ehdr)
318 	  == offsetof (struct Elf, state.elf64.ehdr)))
319     scn->rawdata.d.d_version =
320       elf->state.elf32.ehdr->e_ident[EI_VERSION];
321   else
322     scn->rawdata.d.d_version =
323       elf->state.elf64.ehdr->e_ident[EI_VERSION];
324 
325   scn->rawdata.s = scn;
326 
327   scn->data_read = 1;
328 
329   /* We actually read data from the file.  At least we tried.  */
330   scn->flags |= ELF_F_FILEDATA;
331 
332   return 0;
333 }
334 
335 
336 Elf_Data *
elf_getdata(scn,data)337 elf_getdata (scn, data)
338      Elf_Scn *scn;
339      Elf_Data *data;
340 {
341   Elf_Data *result = NULL;
342   Elf *elf;
343 
344   if (scn == NULL)
345     return NULL;
346 
347   if (unlikely (scn->elf->kind != ELF_K_ELF))
348     {
349       __libelf_seterrno (ELF_E_INVALID_HANDLE);
350       return NULL;
351     }
352 
353   /* We will need this multiple times later on.  */
354   elf = scn->elf;
355 
356   rwlock_rdlock (elf->lock);
357 
358   /* If `data' is not NULL this means we are not addressing the initial
359      data in the file.  But this also means this data is already read
360      (since otherwise it is not possible to have a valid `data' pointer)
361      and all the data structures are initialized as well.  In this case
362      we can simply walk the list of data records.  */
363   if (data != NULL)
364     {
365       Elf_Data_List *runp;
366 
367       /* It is not possible that if DATA is not NULL the first entry is
368 	 returned.  But this also means that there must be a first data
369 	 entry.  */
370       if (scn->data_list_rear == NULL
371 	  /* The section the reference data is for must match the section
372 	     parameter.  */
373 	  || unlikely (((Elf_Data_Scn *) data)->s != scn))
374 	{
375 	  __libelf_seterrno (ELF_E_DATA_MISMATCH);
376 	  goto out;
377 	}
378 
379       /* We start searching with the first entry.  */
380       runp = &scn->data_list;
381 
382       while (1)
383 	{
384 	  /* If `data' does not match any known record punt.  */
385 	  if (runp == NULL)
386 	    {
387 	      __libelf_seterrno (ELF_E_DATA_MISMATCH);
388 	      goto out;
389 	    }
390 
391 	  if (&runp->data.d == data)
392 	    /* Found the entry.  */
393 	    break;
394 
395 	  runp = runp->next;
396 	}
397 
398       /* Return the data for the next data record.  */
399       result = runp->next ? &runp->next->data.d : NULL;
400       goto out;
401     }
402 
403   /* If the data for this section was not yet initialized do it now.  */
404   if (scn->data_read == 0)
405     {
406       /* We cannot acquire a write lock while we are holding a read
407          lock.  Therefore give up the read lock and then get the write
408          lock.  But this means that the data could meanwhile be
409          modified, therefore start the tests again.  */
410       rwlock_unlock (elf->lock);
411       rwlock_wrlock (elf->lock);
412 
413       /* Read the data from the file.  There is always a file (or
414 	 memory region) associated with this descriptor since
415 	 otherwise the `data_read' flag would be set.  */
416       if (scn->data_read == 0 && __libelf_set_rawdata (scn) != 0)
417 	/* Something went wrong.  The error value is already set.  */
418 	goto out;
419     }
420 
421   /* At this point we know the raw data is available.  But it might be
422      empty in case the section has size zero (for whatever reason).
423      Now create the converted data in case this is necessary.  */
424   if (scn->data_list_rear == NULL)
425     {
426       if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
427 	/* Convert according to the version and the type.   */
428 	convert_data (scn, __libelf_version, elf->class,
429 		      (elf->class == ELFCLASS32
430 		       || (offsetof (struct Elf, state.elf32.ehdr)
431 			   == offsetof (struct Elf, state.elf64.ehdr))
432 		       ? elf->state.elf32.ehdr->e_ident[EI_DATA]
433 		       : elf->state.elf64.ehdr->e_ident[EI_DATA]),
434 			  scn->rawdata.d.d_size,
435 		      scn->rawdata.d.d_type);
436       else
437 	/* This is an empty or NOBITS section.  There is no buffer but
438 	   the size information etc is important.  */
439 	scn->data_list.data.d = scn->rawdata.d;
440 
441       scn->data_list_rear = &scn->data_list;
442     }
443 
444   /* If no data is present we cannot return any.  */
445   if (scn->data_list_rear != NULL)
446     /* Return the first data element in the list.  */
447     result = &scn->data_list.data.d;
448 
449  out:
450   rwlock_unlock (elf->lock);
451 
452   return result;
453 }
454 INTDEF(elf_getdata)
455