Branch data Line data Source code
1 : : /* Return converted data from raw chunk of ELF file.
2 : : Copyright (C) 2007 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 : 61 : elf_getdata_rawchunk (elf, offset, size, type)
45 : : Elf *elf;
46 : : off64_t offset;
47 : : size_t size;
48 : : Elf_Type type;
49 : : {
50 [ + - ]: 61 : if (unlikely (elf == NULL))
51 : : return NULL;
52 : :
53 [ - + ]: 61 : if (unlikely (elf->kind != ELF_K_ELF))
54 : : {
55 : : /* No valid descriptor. */
56 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
57 : 0 : return NULL;
58 : : }
59 : :
60 [ + - ][ + - ]: 61 : if (unlikely (offset < 0 || offset + (off64_t) size < offset
[ + - ][ - + ]
61 : : || offset + size > elf->maximum_size))
62 : : {
63 : : /* Invalid request. */
64 : 0 : __libelf_seterrno (ELF_E_INVALID_OP);
65 : 0 : return NULL;
66 : : }
67 : :
68 [ - + ]: 61 : if (type >= ELF_T_NUM)
69 : : {
70 : 0 : __libelf_seterrno (ELF_E_UNKNOWN_TYPE);
71 : 0 : return NULL;
72 : : }
73 : :
74 : : /* Get the raw bytes from the file. */
75 : : void *rawchunk;
76 : 61 : int flags = 0;
77 : 61 : Elf_Data *result = NULL;
78 : :
79 : : rwlock_rdlock (elf->lock);
80 : :
81 : : /* If the file is mmap'ed we can use it directly. */
82 [ + - ]: 61 : if (elf->map_address != NULL)
83 : 61 : rawchunk = elf->map_address + elf->start_offset + offset;
84 : : else
85 : : {
86 : : /* We allocate the memory and read the data from the file. */
87 : 0 : rawchunk = malloc (size);
88 [ # # ]: 0 : if (rawchunk == NULL)
89 : : {
90 : : nomem:
91 : 0 : __libelf_seterrno (ELF_E_NOMEM);
92 : 0 : goto out;
93 : : }
94 : :
95 : : /* Read the file content. */
96 [ # # ]: 0 : if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size,
97 : : elf->start_offset + offset)
98 : : != size))
99 : : {
100 : : /* Something went wrong. */
101 : 0 : free (rawchunk);
102 : 0 : __libelf_seterrno (ELF_E_READ_ERROR);
103 : 0 : goto out;
104 : : }
105 : :
106 : : flags = ELF_F_MALLOCED;
107 : : }
108 : :
109 : : /* Copy and/or convert the data as needed for aligned native-order access. */
110 : 61 : size_t align = __libelf_type_align (elf->class, type);
111 : : void *buffer;
112 [ + + ]: 61 : if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA)
113 : : {
114 : : if (((uintptr_t) rawchunk & (align - 1)) == 0)
115 : : /* No need to copy, we can use the raw data. */
116 : : buffer = rawchunk;
117 : : else
118 : : {
119 : : /* A malloc'd block is always sufficiently aligned. */
120 : : assert (flags == 0);
121 : :
122 : : buffer = malloc (size);
123 : : if (unlikely (buffer == NULL))
124 : : goto nomem;
125 : : flags = ELF_F_MALLOCED;
126 : :
127 : : /* The copy will be appropriately aligned for direct access. */
128 : : memcpy (buffer, rawchunk, size);
129 : : }
130 : : }
131 : : else
132 : : {
133 [ + - ]: 7 : if (flags)
134 : : buffer = rawchunk;
135 : : else
136 : : {
137 : 7 : buffer = malloc (size);
138 [ - + ]: 7 : if (unlikely (buffer == NULL))
139 : : goto nomem;
140 : : flags = ELF_F_MALLOCED;
141 : : }
142 : :
143 : : /* Call the conversion function. */
144 : 7 : (*__elf_xfctstom[LIBELF_EV_IDX][LIBELF_EV_IDX][elf->class - 1][type])
145 : 7 : (buffer, rawchunk, size, 0);
146 : : }
147 : :
148 : : /* Allocate the dummy container to point at this buffer. */
149 : 61 : Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk);
150 [ - + ]: 61 : if (chunk == NULL)
151 : : {
152 [ # # ]: 0 : if (flags)
153 : 0 : free (buffer);
154 : : goto nomem;
155 : : }
156 : :
157 : 61 : chunk->dummy_scn.elf = elf;
158 : 61 : chunk->dummy_scn.flags = flags;
159 : 61 : chunk->data.s = &chunk->dummy_scn;
160 : 61 : chunk->data.d.d_buf = buffer;
161 : 61 : chunk->data.d.d_size = size;
162 : 61 : chunk->data.d.d_type = type;
163 : 61 : chunk->data.d.d_align = align;
164 : 61 : chunk->data.d.d_version = __libelf_version;
165 : :
166 : : rwlock_unlock (elf->lock);
167 : : rwlock_wrlock (elf->lock);
168 : :
169 : 61 : chunk->next = elf->state.elf.rawchunks;
170 : 61 : elf->state.elf.rawchunks = chunk;
171 : 61 : result = &chunk->data.d;
172 : :
173 : : out:
174 : : rwlock_unlock (elf->lock);
175 : 61 : return result;
176 : : }
|