Home | History | Annotate | Download | only in libelf
      1 /* Read all of the file associated with the descriptor.
      2    Copyright (C) 1998-2009, 2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Contributed by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      5 
      6    This file is free software; you can redistribute it and/or modify
      7    it under the terms of either
      8 
      9      * the GNU Lesser General Public License as published by the Free
     10        Software Foundation; either version 3 of the License, or (at
     11        your option) any later version
     12 
     13    or
     14 
     15      * the GNU General Public License as published by the Free
     16        Software Foundation; either version 2 of the License, or (at
     17        your option) any later version
     18 
     19    or both in parallel, as here.
     20 
     21    elfutils is distributed in the hope that it will be useful, but
     22    WITHOUT ANY WARRANTY; without even the implied warranty of
     23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24    General Public License for more details.
     25 
     26    You should have received copies of the GNU General Public License and
     27    the GNU Lesser General Public License along with this program.  If
     28    not, see <http://www.gnu.org/licenses/>.  */
     29 
     30 #ifdef HAVE_CONFIG_H
     31 # include <config.h>
     32 #endif
     33 
     34 #include <errno.h>
     35 #include <unistd.h>
     36 #include <sys/stat.h>
     37 
     38 #include <system.h>
     39 #include "libelfP.h"
     40 #include "common.h"
     41 
     42 
     43 static void
     44 set_address (Elf *elf, size_t offset)
     45 {
     46   if (elf->kind == ELF_K_AR)
     47     {
     48       Elf *child = elf->state.ar.children;
     49 
     50       while (child != NULL)
     51 	{
     52 	  if (child->map_address == NULL)
     53 	    {
     54 	      child->map_address = elf->map_address;
     55 	      child->start_offset -= offset;
     56 	      if (child->kind == ELF_K_AR)
     57 		child->state.ar.offset -= offset;
     58 
     59 	      set_address (child, offset);
     60 	    }
     61 
     62 	  child = child->next;
     63 	}
     64     }
     65 }
     66 
     67 
     68 char *
     69 internal_function
     70 __libelf_readall (Elf *elf)
     71 {
     72   /* Get the file.  */
     73   rwlock_wrlock (elf->lock);
     74 
     75   if (elf->map_address == NULL && unlikely (elf->fildes == -1))
     76     {
     77       __libelf_seterrno (ELF_E_INVALID_HANDLE);
     78       rwlock_unlock (elf->lock);
     79       return NULL;
     80     }
     81 
     82   /* If the file is not mmap'ed and not previously loaded, do it now.  */
     83   if (elf->map_address == NULL)
     84     {
     85       char *mem = NULL;
     86 
     87       /* If this is an archive and we have derived descriptors get the
     88 	 locks for all of them.  */
     89       libelf_acquire_all (elf);
     90 
     91       if (elf->maximum_size == ~((size_t) 0))
     92 	{
     93 	  /* We don't yet know how large the file is.   Determine that now.  */
     94 	  struct stat st;
     95 
     96 	  if (fstat (elf->fildes, &st) < 0)
     97 	    goto read_error;
     98 
     99 	  if (sizeof (size_t) >= sizeof (st.st_size)
    100 	      || st.st_size <= ~((size_t) 0))
    101 	    elf->maximum_size = (size_t) st.st_size;
    102 	  else
    103 	    {
    104 	      errno = EOVERFLOW;
    105 	      goto read_error;
    106 	    }
    107 	}
    108 
    109       /* Allocate all the memory we need.  */
    110       mem = (char *) malloc (elf->maximum_size);
    111       if (mem != NULL)
    112 	{
    113 	  /* Read the file content.  */
    114 	  if (unlikely ((size_t) pread_retry (elf->fildes, mem,
    115 					      elf->maximum_size,
    116 					      elf->start_offset)
    117 			!= elf->maximum_size))
    118 	    {
    119 	      /* Something went wrong.  */
    120 	    read_error:
    121 	      __libelf_seterrno (ELF_E_READ_ERROR);
    122 	      free (mem);
    123 	    }
    124 	  else
    125 	    {
    126 	      /* Remember the address.  */
    127 	      elf->map_address = mem;
    128 
    129 	      /* Also remember that we allocated the memory.  */
    130 	      elf->flags |= ELF_F_MALLOCED;
    131 
    132 	      /* Propagate the information down to all children and
    133 		 their children.  */
    134 	      set_address (elf, elf->start_offset);
    135 
    136 	      /* Correct the own offsets.  */
    137 	      if (elf->kind == ELF_K_AR)
    138 		elf->state.ar.offset -= elf->start_offset;
    139 	      elf->start_offset = 0;
    140 	    }
    141 	}
    142       else
    143 	__libelf_seterrno (ELF_E_NOMEM);
    144 
    145       /* Free the locks on the children.  */
    146       libelf_release_all (elf);
    147     }
    148 
    149   rwlock_unlock (elf->lock);
    150 
    151   return (char *) elf->map_address;
    152 }
    153