Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/libelf/elf_data.c
2066 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 <stdlib.h>
31
32
#include "_libelf.h"
33
34
ELFTC_VCSID("$Id$");
35
36
Elf_Data *
37
elf_getdata(Elf_Scn *s, Elf_Data *ed)
38
{
39
Elf *e;
40
unsigned int sh_type;
41
int elfclass, elftype;
42
size_t count, fsz, msz;
43
struct _Libelf_Data *d;
44
uint64_t sh_align, sh_offset, sh_size;
45
int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s,
46
size_t _c, int _swap);
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)->d_data);
63
64
if (e->e_rawfile == NULL) {
65
/*
66
* In the ELF_C_WRITE case, there is no source that
67
* can provide data for the section.
68
*/
69
LIBELF_SET_ERROR(ARGUMENT, 0);
70
return (NULL);
71
}
72
73
elfclass = e->e_class;
74
75
assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
76
77
if (elfclass == ELFCLASS32) {
78
sh_type = s->s_shdr.s_shdr32.sh_type;
79
sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
80
sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
81
sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
82
} else {
83
sh_type = s->s_shdr.s_shdr64.sh_type;
84
sh_offset = s->s_shdr.s_shdr64.sh_offset;
85
sh_size = s->s_shdr.s_shdr64.sh_size;
86
sh_align = s->s_shdr.s_shdr64.sh_addralign;
87
}
88
89
if (sh_type == SHT_NULL) {
90
LIBELF_SET_ERROR(SECTION, 0);
91
return (NULL);
92
}
93
94
if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
95
elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
96
sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
97
LIBELF_SET_ERROR(SECTION, 0);
98
return (NULL);
99
}
100
101
if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
102
(elftype, (size_t) 1, e->e_version)) == 0) {
103
LIBELF_SET_ERROR(UNIMPL, 0);
104
return (NULL);
105
}
106
107
if (sh_size % fsz) {
108
LIBELF_SET_ERROR(SECTION, 0);
109
return (NULL);
110
}
111
112
if (sh_size / fsz > SIZE_MAX) {
113
LIBELF_SET_ERROR(RANGE, 0);
114
return (NULL);
115
}
116
117
count = (size_t) (sh_size / fsz);
118
119
msz = _libelf_msize(elftype, elfclass, e->e_version);
120
121
if (count > 0 && msz > SIZE_MAX / count) {
122
LIBELF_SET_ERROR(RANGE, 0);
123
return (NULL);
124
}
125
126
assert(msz > 0);
127
assert(count <= SIZE_MAX);
128
assert(msz * count <= SIZE_MAX);
129
130
if ((d = _libelf_allocate_data(s)) == NULL)
131
return (NULL);
132
133
d->d_data.d_buf = NULL;
134
d->d_data.d_off = 0;
135
d->d_data.d_align = sh_align;
136
d->d_data.d_size = msz * count;
137
d->d_data.d_type = elftype;
138
d->d_data.d_version = e->e_version;
139
140
if (sh_type == SHT_NOBITS || sh_size == 0) {
141
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
142
return (&d->d_data);
143
}
144
145
if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {
146
(void) _libelf_release_data(d);
147
LIBELF_SET_ERROR(RESOURCE, 0);
148
return (NULL);
149
}
150
151
d->d_flags |= LIBELF_F_DATA_MALLOCED;
152
153
xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
154
if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,
155
e->e_rawfile + sh_offset, count,
156
e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
157
_libelf_release_data(d);
158
LIBELF_SET_ERROR(DATA, 0);
159
return (NULL);
160
}
161
162
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
163
164
return (&d->d_data);
165
}
166
167
Elf_Data *
168
elf_newdata(Elf_Scn *s)
169
{
170
Elf *e;
171
struct _Libelf_Data *d;
172
173
if (s == NULL || (e = s->s_elf) == NULL) {
174
LIBELF_SET_ERROR(ARGUMENT, 0);
175
return (NULL);
176
}
177
178
assert(e->e_kind == ELF_K_ELF);
179
180
/*
181
* elf_newdata() has to append a data descriptor, so
182
* bring in existing section data if not already present.
183
*/
184
if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))
185
if (elf_getdata(s, NULL) == NULL)
186
return (NULL);
187
188
if ((d = _libelf_allocate_data(s)) == NULL)
189
return (NULL);
190
191
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
192
193
d->d_data.d_align = 1;
194
d->d_data.d_buf = NULL;
195
d->d_data.d_off = (uint64_t) ~0;
196
d->d_data.d_size = 0;
197
d->d_data.d_type = ELF_T_BYTE;
198
d->d_data.d_version = LIBELF_PRIVATE(version);
199
200
(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);
201
202
return (&d->d_data);
203
}
204
205
/*
206
* Retrieve a data descriptor for raw (untranslated) data for section
207
* `s'.
208
*/
209
210
Elf_Data *
211
elf_rawdata(Elf_Scn *s, Elf_Data *ed)
212
{
213
Elf *e;
214
int elf_class;
215
uint32_t sh_type;
216
struct _Libelf_Data *d;
217
uint64_t sh_align, sh_offset, sh_size;
218
219
if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
220
LIBELF_SET_ERROR(ARGUMENT, 0);
221
return (NULL);
222
}
223
224
assert(e->e_kind == ELF_K_ELF);
225
226
d = (struct _Libelf_Data *) ed;
227
228
if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
229
return (&d->d_data);
230
231
if (d != NULL)
232
return (&STAILQ_NEXT(d, d_next)->d_data);
233
234
elf_class = e->e_class;
235
236
assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);
237
238
if (elf_class == ELFCLASS32) {
239
sh_type = s->s_shdr.s_shdr32.sh_type;
240
sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
241
sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size;
242
sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
243
} else {
244
sh_type = s->s_shdr.s_shdr64.sh_type;
245
sh_offset = s->s_shdr.s_shdr64.sh_offset;
246
sh_size = s->s_shdr.s_shdr64.sh_size;
247
sh_align = s->s_shdr.s_shdr64.sh_addralign;
248
}
249
250
if (sh_type == SHT_NULL) {
251
LIBELF_SET_ERROR(SECTION, 0);
252
return (NULL);
253
}
254
255
if ((d = _libelf_allocate_data(s)) == NULL)
256
return (NULL);
257
258
d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
259
e->e_rawfile + sh_offset;
260
d->d_data.d_off = 0;
261
d->d_data.d_align = sh_align;
262
d->d_data.d_size = sh_size;
263
d->d_data.d_type = ELF_T_BYTE;
264
d->d_data.d_version = e->e_version;
265
266
STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);
267
268
return (&d->d_data);
269
}
270
271