Line data Source code
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 <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 1 : set_address (Elf *elf, size_t offset)
45 : {
46 1 : if (elf->kind == ELF_K_AR)
47 : {
48 0 : Elf *child = elf->state.ar.children;
49 :
50 0 : while (child != NULL)
51 : {
52 0 : if (child->map_address == NULL)
53 : {
54 0 : child->map_address = elf->map_address;
55 0 : child->start_offset -= offset;
56 0 : if (child->kind == ELF_K_AR)
57 0 : child->state.ar.offset -= offset;
58 :
59 0 : set_address (child, offset);
60 : }
61 :
62 0 : child = child->next;
63 : }
64 : }
65 1 : }
66 :
67 :
68 : char *
69 : internal_function
70 1 : __libelf_readall (Elf *elf)
71 : {
72 : /* Get the file. */
73 : rwlock_wrlock (elf->lock);
74 :
75 1 : if (elf->map_address == NULL && unlikely (elf->fildes == -1))
76 : {
77 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
78 : rwlock_unlock (elf->lock);
79 0 : return NULL;
80 : }
81 :
82 : /* If the file is not mmap'ed and not previously loaded, do it now. */
83 1 : if (elf->map_address == NULL)
84 : {
85 1 : char *mem = NULL;
86 :
87 : /* If this is an archive and we have derived descriptors get the
88 : locks for all of them. */
89 1 : libelf_acquire_all (elf);
90 :
91 1 : 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 0 : 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 0 : 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 1 : mem = (char *) malloc (elf->maximum_size);
111 1 : if (mem != NULL)
112 : {
113 : /* Read the file content. */
114 1 : 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 0 : read_error:
121 0 : __libelf_seterrno (ELF_E_READ_ERROR);
122 0 : free (mem);
123 : }
124 : else
125 : {
126 : /* Remember the address. */
127 1 : elf->map_address = mem;
128 :
129 : /* Also remember that we allocated the memory. */
130 1 : elf->flags |= ELF_F_MALLOCED;
131 :
132 : /* Propagate the information down to all children and
133 : their children. */
134 1 : set_address (elf, elf->start_offset);
135 :
136 : /* Correct the own offsets. */
137 1 : if (elf->kind == ELF_K_AR)
138 0 : elf->state.ar.offset -= elf->start_offset;
139 1 : elf->start_offset = 0;
140 : }
141 : }
142 : else
143 0 : __libelf_seterrno (ELF_E_NOMEM);
144 :
145 : /* Free the locks on the children. */
146 1 : libelf_release_all (elf);
147 : }
148 :
149 : rwlock_unlock (elf->lock);
150 :
151 1 : return (char *) elf->map_address;
152 : }
|