Branch data Line data Source code
1 : : /* Read all of the file associated with the descriptor.
2 : : Copyright (C) 1998-2009 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 : 1 : __libelf_readall (elf)
70 : : 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 [ + - ]: 1 : 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 : 1 : 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 : : 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 : 3 : }
|