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 856 : elf_getdata_rawchunk (Elf *elf, off_t offset, size_t size, Elf_Type type)
45 : {
46 856 : if (unlikely (elf == NULL))
47 : return NULL;
48 :
49 856 : 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 856 : if (unlikely (offset < 0 || (uint64_t) offset > elf->maximum_size
57 : || elf->maximum_size - (uint64_t) offset < size))
58 :
59 : {
60 : /* Invalid request. */
61 0 : __libelf_seterrno (ELF_E_INVALID_OP);
62 0 : return NULL;
63 : }
64 :
65 856 : 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 : void *rawchunk;
73 856 : int flags = 0;
74 856 : Elf_Data *result = NULL;
75 :
76 : rwlock_rdlock (elf->lock);
77 :
78 856 : size_t align = __libelf_type_align (elf->class, type);
79 856 : if (elf->map_address != NULL)
80 : {
81 : /* If the file is mmap'ed we can use it directly, if aligned for type. */
82 855 : char *rawdata = elf->map_address + elf->start_offset + offset;
83 855 : 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 1 : rawchunk = malloc (size);
99 1 : 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 1 : 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 : void *buffer;
122 856 : if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA)
123 : {
124 520 : 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 : memcpy (buffer, rawchunk, size);
139 : }
140 : }
141 : else
142 : {
143 336 : if (flags)
144 : buffer = rawchunk;
145 : else
146 : {
147 332 : buffer = malloc (size);
148 332 : if (unlikely (buffer == NULL))
149 : goto nomem;
150 : flags = ELF_F_MALLOCED;
151 : }
152 :
153 : /* Call the conversion function. */
154 336 : (*__elf_xfctstom[LIBELF_EV_IDX][LIBELF_EV_IDX][elf->class - 1][type])
155 : (buffer, rawchunk, size, 0);
156 : }
157 :
158 : /* Allocate the dummy container to point at this buffer. */
159 856 : Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk);
160 856 : if (chunk == NULL)
161 : {
162 0 : if (flags)
163 0 : free (buffer);
164 : goto nomem;
165 : }
166 :
167 856 : chunk->dummy_scn.elf = elf;
168 856 : chunk->dummy_scn.flags = flags;
169 856 : chunk->data.s = &chunk->dummy_scn;
170 856 : chunk->data.d.d_buf = buffer;
171 856 : chunk->data.d.d_size = size;
172 856 : chunk->data.d.d_type = type;
173 856 : chunk->data.d.d_align = align;
174 856 : chunk->data.d.d_version = __libelf_version;
175 :
176 : rwlock_unlock (elf->lock);
177 : rwlock_wrlock (elf->lock);
178 :
179 856 : chunk->next = elf->state.elf.rawchunks;
180 856 : elf->state.elf.rawchunks = chunk;
181 856 : result = &chunk->data.d;
182 :
183 : out:
184 : rwlock_unlock (elf->lock);
185 : return result;
186 : }
|