Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/elftoolchain/libelf/elf_data.c
39478 views
1
/*-
2
* Copyright (c) 2006,2008,2011 Joseph Koshy
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <assert.h>
28
#include <errno.h>
29
#include <libelf.h>
30
#include <stdint.h>
31
#include <stdlib.h>
32
33
#include "_libelf.h"
34
35
ELFTC_VCSID("$Id: elf_data.c 3732 2019-04-22 11:08:38Z jkoshy $");
36
37
Elf_Data *
38
elf_getdata(Elf_Scn *s, Elf_Data *ed)
39
{
40
Elf *e;
41
unsigned int sh_type;
42
int elfclass, elftype;
43
size_t count, fsz, msz;
44
struct _Libelf_Data *d;
45
uint64_t sh_align, sh_offset, sh_size, raw_size;
46
_libelf_translator_function *xlate;
47
48
d = (struct _Libelf_Data *) ed;
49
50
if (s == NULL || (e = s->s_elf) == NULL ||
51
(d != NULL && s != d->d_scn)) {
52
LIBELF_SET_ERROR(ARGUMENT, 0);
53
return (NULL);
54
}
55
56
assert(e->e_kind == ELF_K_ELF);
57
58
if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
59
return (&d->d_data);
60
61
if (d != NULL)
62
return (STAILQ_NEXT(d, d_next) ?
63
&STAILQ_NEXT(d, d_next)->d_data : NULL);
64
65
if (e->e_rawfile == NULL) {
66
/*
67
* In the ELF_C_WRITE case, there is no source that
68
* can provide data for the section.
69
*/
70
LIBELF_SET_ERROR(ARGUMENT, 0);
71
return (NULL);
72
}
73
74
elfclass = e->e_class;
75
76
assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
77
78
if (elfclass == ELFCLASS32) {
79
sh_type = s->s_shdr.s_shdr32.sh_type;
80
sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
81
sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
82
sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
83
} else {
84
sh_type = s->s_shdr.s_shdr64.sh_type;
85
sh_offset = s->s_shdr.s_shdr64.sh_offset;
86
sh_size = s->s_shdr.s_shdr64.sh_size;
87
sh_align = s->s_shdr.s_shdr64.sh_addralign;
88
}
89
90
if (sh_type == SHT_NULL) {
91
LIBELF_SET_ERROR(SECTION, 0);
92
return (NULL);
93
}
94
95
raw_size = (uint64_t) e->e_rawsize;
96
if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
97
elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
98
(sh_offset > raw_size || sh_size > raw_size - sh_offset))) {
99
LIBELF_SET_ERROR(SECTION, 0);
100
return (NULL);
101
}
102
103
if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
104
(elftype, (size_t) 1, e->e_version)) == 0) {
105
LIBELF_SET_ERROR(UNIMPL, 0);
106
return (NULL);
107
}
108
109
if (sh_size % fsz) {
110
LIBELF_SET_ERROR(SECTION, 0);
111
return (NULL);
112
}
113
114
if (sh_size / fsz > SIZE_MAX) {
115
LIBELF_SET_ERROR(RANGE, 0);
116
return (NULL);
117
}
118
119
count = (size_t) (sh_size / fsz);
120
121
if ((msz = _libelf_msize(elftype, elfclass, e->e_version)) == 0)
122
return (NULL);
123
124
if (count > 0 && msz > SIZE_MAX / count) {
125
LIBELF_SET_ERROR(RANGE, 0);
126
return (NULL);
127
}
128
129
assert(msz > 0);
130
assert(count <= SIZE_MAX);
131
assert(msz * count <= SIZE_MAX);
132
133
if ((d = _libelf_allocate_data(s)) == NULL)
134
return (NULL);
135
136
d->d_data.d_buf = NULL;
137
d->d_data.d_off = 0;
138
d->d_data.d_align = sh_align;
139
d->d_data.d_size = msz * count;
140
d->d_data.d_type = elftype;
141
d->d_data.d_version = e->e_version;
142
143
if (sh_type == SHT_NOBITS || sh_size == 0) {
144
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
145
return (&d->d_data);
146
}
147
148
if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {
149
(void) _libelf_release_data(d);
150
LIBELF_SET_ERROR(RESOURCE, 0);
151
return (NULL);
152
}
153
154
d->d_flags |= LIBELF_F_DATA_MALLOCED;
155
156
xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass,
157
_libelf_elfmachine(e));
158
if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,
159
e->e_rawfile + sh_offset, count,
160
e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
161
_libelf_release_data(d);
162
LIBELF_SET_ERROR(DATA, 0);
163
return (NULL);
164
}
165
166
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
167
168
return (&d->d_data);
169
}
170
171
Elf_Data *
172
elf_newdata(Elf_Scn *s)
173
{
174
Elf *e;
175
struct _Libelf_Data *d;
176
177
if (s == NULL || (e = s->s_elf) == NULL) {
178
LIBELF_SET_ERROR(ARGUMENT, 0);
179
return (NULL);
180
}
181
182
assert(e->e_kind == ELF_K_ELF);
183
184
/*
185
* elf_newdata() has to append a data descriptor, so
186
* bring in existing section data if not already present.
187
*/
188
if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))
189
if (elf_getdata(s, NULL) == NULL)
190
return (NULL);
191
192
if ((d = _libelf_allocate_data(s)) == NULL)
193
return (NULL);
194
195
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
196
197
d->d_data.d_align = 1;
198
d->d_data.d_buf = NULL;
199
d->d_data.d_off = (uint64_t) ~0;
200
d->d_data.d_size = 0;
201
d->d_data.d_type = ELF_T_BYTE;
202
d->d_data.d_version = LIBELF_PRIVATE(version);
203
204
(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);
205
206
return (&d->d_data);
207
}
208
209
/*
210
* Retrieve a data descriptor for raw (untranslated) data for section
211
* `s'.
212
*/
213
214
Elf_Data *
215
elf_rawdata(Elf_Scn *s, Elf_Data *ed)
216
{
217
Elf *e;
218
int elf_class;
219
uint32_t sh_type;
220
struct _Libelf_Data *d;
221
uint64_t sh_align, sh_offset, sh_size, raw_size;
222
223
if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
224
LIBELF_SET_ERROR(ARGUMENT, 0);
225
return (NULL);
226
}
227
228
assert(e->e_kind == ELF_K_ELF);
229
230
d = (struct _Libelf_Data *) ed;
231
232
if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
233
return (&d->d_data);
234
235
if (d != NULL)
236
return (&STAILQ_NEXT(d, d_next)->d_data);
237
238
elf_class = e->e_class;
239
240
assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);
241
242
if (elf_class == ELFCLASS32) {
243
sh_type = s->s_shdr.s_shdr32.sh_type;
244
sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
245
sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
246
sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
247
} else {
248
sh_type = s->s_shdr.s_shdr64.sh_type;
249
sh_offset = s->s_shdr.s_shdr64.sh_offset;
250
sh_size = s->s_shdr.s_shdr64.sh_size;
251
sh_align = s->s_shdr.s_shdr64.sh_addralign;
252
}
253
254
if (sh_type == SHT_NULL) {
255
LIBELF_SET_ERROR(SECTION, 0);
256
return (NULL);
257
}
258
259
raw_size = (uint64_t) e->e_rawsize;
260
if (sh_type != SHT_NOBITS &&
261
(sh_offset > raw_size || sh_size > raw_size - sh_offset)) {
262
LIBELF_SET_ERROR(SECTION, 0);
263
return (NULL);
264
}
265
266
if ((d = _libelf_allocate_data(s)) == NULL)
267
return (NULL);
268
269
d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
270
e->e_rawfile + sh_offset;
271
d->d_data.d_off = 0;
272
d->d_data.d_align = sh_align;
273
d->d_data.d_size = sh_size;
274
d->d_data.d_type = ELF_T_BYTE;
275
d->d_data.d_version = e->e_version;
276
277
STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);
278
279
return (&d->d_data);
280
}
281
282