Branch data Line data Source code
1 : : /* Return converted data from raw chunk of ELF file.
2 : : Copyright (C) 2007, 2014, 2015 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #ifdef HAVE_CONFIG_H
30 : : # include <config.h>
31 : : #endif
32 : :
33 : : #include <assert.h>
34 : : #include <errno.h>
35 : : #include <stdlib.h>
36 : : #include <string.h>
37 : : #include <unistd.h>
38 : :
39 : : #include <system.h>
40 : : #include "libelfP.h"
41 : : #include "common.h"
42 : :
43 : : Elf_Data *
44 : 1133 : elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
45 : : {
46 [ + - ]: 1133 : if (unlikely (elf == NULL))
47 : : return NULL;
48 : :
49 [ - + ]: 1133 : if (unlikely (elf->kind != ELF_K_ELF))
50 : : {
51 : : /* No valid descriptor. */
52 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
53 : 0 : return NULL;
54 : : }
55 : :
56 [ + - ][ + + ]: 1133 : if (unlikely (offset < 0 || (uint64_t) offset > elf->maximum_size
[ - + ]
57 : : || elf->maximum_size - (uint64_t) offset < size))
58 : :
59 : : {
60 : : /* Invalid request. */
61 : 12 : __libelf_seterrno (ELF_E_INVALID_OP);
62 : 12 : return NULL;
63 : : }
64 : :
65 [ - + ]: 1121 : if (type >= ELF_T_NUM)
66 : : {
67 : 0 : __libelf_seterrno (ELF_E_UNKNOWN_TYPE);
68 : 0 : return NULL;
69 : : }
70 : :
71 : : /* Get the raw bytes from the file. */
72 : 1121 : void *rawchunk;
73 : 1121 : int flags = 0;
74 : 1121 : Elf_Data *result = NULL;
75 : :
76 : 1121 : rwlock_rdlock (elf->lock);
77 : :
78 [ + + ]: 1121 : size_t align = __libelf_type_align (elf->class, type);
79 [ + + ]: 1121 : if (elf->map_address != NULL)
80 : : {
81 : : /* If the file is mmap'ed we can use it directly, if aligned for type. */
82 : 880 : char *rawdata = elf->map_address + elf->start_offset + offset;
83 [ + + ]: 880 : if (((uintptr_t) rawdata & (align - 1)) == 0)
84 : : rawchunk = rawdata;
85 : : else
86 : : {
87 : : /* We allocate the memory and memcpy it to get aligned data. */
88 : 3 : rawchunk = malloc (size);
89 [ + - ]: 3 : if (rawchunk == NULL)
90 : : goto nomem;
91 : 3 : memcpy (rawchunk, rawdata, size);
92 : 3 : flags = ELF_F_MALLOCED;
93 : : }
94 : : }
95 : : else
96 : : {
97 : : /* We allocate the memory and read the data from the file. */
98 : 241 : rawchunk = malloc (size);
99 [ - + ]: 241 : if (rawchunk == NULL)
100 : : {
101 : 0 : nomem:
102 : 0 : __libelf_seterrno (ELF_E_NOMEM);
103 : 0 : goto out;
104 : : }
105 : :
106 : : /* Read the file content. */
107 [ - + ]: 241 : if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size,
108 : : elf->start_offset + offset)
109 : : != size))
110 : : {
111 : : /* Something went wrong. */
112 : 0 : free (rawchunk);
113 : 0 : __libelf_seterrno (ELF_E_READ_ERROR);
114 : 0 : goto out;
115 : : }
116 : :
117 : : flags = ELF_F_MALLOCED;
118 : : }
119 : :
120 : : /* Copy and/or convert the data as needed for aligned native-order access. */
121 : 1121 : void *buffer;
122 [ + + ]: 1121 : if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA)
123 : : {
124 [ - + ]: 757 : if (((uintptr_t) rawchunk & (align - 1)) == 0)
125 : : /* No need to copy, we can use the raw data. */
126 : : buffer = rawchunk;
127 : : else
128 : : {
129 : : /* A malloc'd block is always sufficiently aligned. */
130 [ # # ]: 0 : assert (flags == 0);
131 : :
132 : 0 : buffer = malloc (size);
133 [ # # ]: 0 : if (unlikely (buffer == NULL))
134 : : goto nomem;
135 : 0 : flags = ELF_F_MALLOCED;
136 : :
137 : : /* The copy will be appropriately aligned for direct access. */
138 : 0 : memcpy (buffer, rawchunk, size);
139 : : }
140 : : }
141 : : else
142 : : {
143 [ + + ]: 364 : if (flags)
144 : : buffer = rawchunk;
145 : : else
146 : : {
147 : 338 : buffer = malloc (size);
148 [ - + ]: 338 : if (unlikely (buffer == NULL))
149 : : goto nomem;
150 : : flags = ELF_F_MALLOCED;
151 : : }
152 : :
153 : : /* Call the conversion function. */
154 : 364 : (*__elf_xfctstom[elf->class - 1][type])(buffer, rawchunk, size, 0);
155 : : }
156 : :
157 : : /* Allocate the dummy container to point at this buffer. */
158 : 1121 : Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk);
159 [ - + ]: 1121 : if (chunk == NULL)
160 : : {
161 [ # # ]: 0 : if (flags)
162 : 0 : free (buffer);
163 : 0 : goto nomem;
164 : : }
165 : :
166 : 1121 : chunk->dummy_scn.elf = elf;
167 : 1121 : chunk->dummy_scn.flags = flags;
168 : 1121 : chunk->data.s = &chunk->dummy_scn;
169 : 1121 : chunk->data.d.d_buf = buffer;
170 : 1121 : chunk->data.d.d_size = size;
171 : 1121 : chunk->data.d.d_type = type;
172 : 1121 : chunk->data.d.d_align = align;
173 : 1121 : chunk->data.d.d_version = EV_CURRENT;
174 : :
175 : 1121 : rwlock_unlock (elf->lock);
176 : 1121 : rwlock_wrlock (elf->lock);
177 : :
178 : 1121 : chunk->next = elf->state.elf.rawchunks;
179 : 1121 : elf->state.elf.rawchunks = chunk;
180 : 1121 : result = &chunk->data.d;
181 : :
182 : : out:
183 : : rwlock_unlock (elf->lock);
184 : : return result;
185 : : }
|