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