• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 <sys/stat.h>
36 
37 #include "libelfP.h"
38 #include "common.h"
39 
40 
41 static void
set_address(Elf * elf,size_t offset)42 set_address (Elf *elf, size_t offset)
43 {
44   if (elf->kind == ELF_K_AR)
45     {
46       Elf *child = elf->state.ar.children;
47 
48       while (child != NULL)
49 	{
50 	  if (child->map_address == NULL)
51 	    {
52 	      child->map_address = elf->map_address;
53 	      child->start_offset -= offset;
54 	      if (child->kind == ELF_K_AR)
55 		child->state.ar.offset -= offset;
56 
57 	      set_address (child, offset);
58 	    }
59 
60 	  child = child->next;
61 	}
62     }
63 }
64 
65 
66 char *
67 internal_function
__libelf_readall(Elf * elf)68 __libelf_readall (Elf *elf)
69 {
70   /* Get the file.  */
71   rwlock_wrlock (elf->lock);
72 
73   if (elf->map_address == NULL && unlikely (elf->fildes == -1))
74     {
75       __libelf_seterrno (ELF_E_INVALID_HANDLE);
76       rwlock_unlock (elf->lock);
77       return NULL;
78     }
79 
80   /* If the file is not mmap'ed and not previously loaded, do it now.  */
81   if (elf->map_address == NULL)
82     {
83       char *mem = NULL;
84 
85       /* If this is an archive and we have derived descriptors get the
86 	 locks for all of them.  */
87       libelf_acquire_all (elf);
88 
89       if (elf->maximum_size == ~((size_t) 0))
90 	{
91 	  /* We don't yet know how large the file is.   Determine that now.  */
92 	  struct stat st;
93 
94 	  if (fstat (elf->fildes, &st) < 0)
95 	    goto read_error;
96 
97 	  if (sizeof (size_t) >= sizeof (st.st_size)
98 	      || st.st_size <= ~((size_t) 0))
99 	    elf->maximum_size = (size_t) st.st_size;
100 	  else
101 	    {
102 	      errno = EOVERFLOW;
103 	      goto read_error;
104 	    }
105 	}
106 
107       /* Allocate all the memory we need.  */
108       mem = malloc (elf->maximum_size);
109       if (mem != NULL)
110 	{
111 	  /* Read the file content.  */
112 	  if (unlikely ((size_t) pread_retry (elf->fildes, mem,
113 					      elf->maximum_size,
114 					      elf->start_offset)
115 			!= elf->maximum_size))
116 	    {
117 	      /* Something went wrong.  */
118 	    read_error:
119 	      __libelf_seterrno (ELF_E_READ_ERROR);
120 	      free (mem);
121 	    }
122 	  else
123 	    {
124 	      /* Remember the address.  */
125 	      elf->map_address = mem;
126 
127 	      /* Also remember that we allocated the memory.  */
128 	      elf->flags |= ELF_F_MALLOCED;
129 
130 	      /* Propagate the information down to all children and
131 		 their children.  */
132 	      set_address (elf, elf->start_offset);
133 
134 	      /* Correct the own offsets.  */
135 	      if (elf->kind == ELF_K_AR)
136 		elf->state.ar.offset -= elf->start_offset;
137 	      elf->start_offset = 0;
138 	    }
139 	}
140       else
141 	__libelf_seterrno (ELF_E_NOMEM);
142 
143       /* Free the locks on the children.  */
144       libelf_release_all (elf);
145     }
146 
147   rwlock_unlock (elf->lock);
148 
149   return (char *) elf->map_address;
150 }
151