Branch data Line data Source code
1 : : /* Return the next data element from the section after possibly converting it.
2 : : Copyright (C) 1998-2005, 2006, 2007, 2015, 2016 Red Hat, Inc.
3 : : Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
4 : : This file is part of elfutils.
5 : : Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6 : :
7 : : This file is free software; you can redistribute it and/or modify
8 : : it under the terms of either
9 : :
10 : : * the GNU Lesser General Public License as published by the Free
11 : : Software Foundation; either version 3 of the License, or (at
12 : : your option) any later version
13 : :
14 : : or
15 : :
16 : : * the GNU General Public License as published by the Free
17 : : Software Foundation; either version 2 of the License, or (at
18 : : your option) any later version
19 : :
20 : : or both in parallel, as here.
21 : :
22 : : elfutils is distributed in the hope that it will be useful, but
23 : : WITHOUT ANY WARRANTY; without even the implied warranty of
24 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 : : General Public License for more details.
26 : :
27 : : You should have received copies of the GNU General Public License and
28 : : the GNU Lesser General Public License along with this program. If
29 : : not, see <http://www.gnu.org/licenses/>. */
30 : :
31 : : #ifdef HAVE_CONFIG_H
32 : : # include <config.h>
33 : : #endif
34 : :
35 : : #include <errno.h>
36 : : #include <stddef.h>
37 : : #include <string.h>
38 : :
39 : : #include "libelfP.h"
40 : : #include "common.h"
41 : : #include "elf-knowledge.h"
42 : :
43 : :
44 : : #define TYPEIDX(Sh_Type) \
45 : : (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM \
46 : : ? Sh_Type \
47 : : : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW \
48 : : ? SHT_NUM + Sh_Type - SHT_GNU_HASH \
49 : : : 0))
50 : :
51 : : /* Associate section types with libelf types. */
52 : : static const Elf_Type shtype_map[TYPEIDX (SHT_HISUNW) + 1] =
53 : : {
54 : : [SHT_SYMTAB] = ELF_T_SYM,
55 : : [SHT_RELA] = ELF_T_RELA,
56 : : [SHT_HASH] = ELF_T_WORD,
57 : : [SHT_DYNAMIC] = ELF_T_DYN,
58 : : [SHT_REL] = ELF_T_REL,
59 : : [SHT_DYNSYM] = ELF_T_SYM,
60 : : [SHT_INIT_ARRAY] = ELF_T_ADDR,
61 : : [SHT_FINI_ARRAY] = ELF_T_ADDR,
62 : : [SHT_PREINIT_ARRAY] = ELF_T_ADDR,
63 : : [SHT_GROUP] = ELF_T_WORD,
64 : : [SHT_SYMTAB_SHNDX] = ELF_T_WORD,
65 : : [SHT_NOTE] = ELF_T_NHDR, /* Need alignment to guess ELF_T_NHDR8. */
66 : : [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF,
67 : : [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED,
68 : : [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF,
69 : : [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO,
70 : : [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE,
71 : : [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB,
72 : : [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH,
73 : : };
74 : :
75 : : /* Associate libelf types with their internal alignment requirements. */
76 : : const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
77 : : {
78 : : # define TYPE_ALIGNS(Bits) \
79 : : [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)), \
80 : : [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)), \
81 : : [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)), \
82 : : [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)), \
83 : : [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)), \
84 : : [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)), \
85 : : [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)), \
86 : : [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)), \
87 : : [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)), \
88 : : [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)), \
89 : : [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)), \
90 : : [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)), \
91 : : [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)), \
92 : : [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)), \
93 : : [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)), \
94 : : [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)), \
95 : : [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)), \
96 : : [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)), \
97 : : [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)), \
98 : : [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)), \
99 : : [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)), \
100 : : [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)), \
101 : : [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)), \
102 : : [ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)), \
103 : : [ELF_T_NHDR8] = 8 /* Special case for GNU Property note. */
104 : : [ELFCLASS32 - 1] = {
105 : : TYPE_ALIGNS (32),
106 : : [ELF_T_GNUHASH] = __alignof__ (Elf32_Word),
107 : : },
108 : : [ELFCLASS64 - 1] = {
109 : : TYPE_ALIGNS (64),
110 : : [ELF_T_GNUHASH] = __alignof__ (Elf64_Xword),
111 : : },
112 : : # undef TYPE_ALIGNS
113 : : };
114 : :
115 : :
116 : : Elf_Type
117 : : internal_function
118 : 2154754 : __libelf_data_type (GElf_Ehdr *ehdr, int sh_type, GElf_Xword align)
119 : : {
120 : : /* Some broken ELF ABI for 64-bit machines use the wrong hash table
121 : : entry size. See elf-knowledge.h for more information. */
122 [ + + + + ]: 2154754 : if (sh_type == SHT_HASH && ehdr->e_ident[EI_CLASS] == ELFCLASS64)
123 : : {
124 [ + + + + ]: 276 : return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
125 : : }
126 : : else
127 : : {
128 [ + + + + ]: 2154478 : Elf_Type t = shtype_map[TYPEIDX (sh_type)];
129 : : /* Special case for GNU Property notes. */
130 [ + + ]: 2154478 : if (t == ELF_T_NHDR && align == 8)
131 : 392 : t = ELF_T_NHDR8;
132 : 2154478 : return t;
133 : : }
134 : : }
135 : :
136 : : /* Convert the data in the current section. */
137 : : static void
138 : 1531930 : convert_data (Elf_Scn *scn, int eclass,
139 : : int data, size_t size, Elf_Type type)
140 : : {
141 : 1531930 : const size_t align = __libelf_type_align (eclass, type);
142 : :
143 : : /* Do we need to convert the data and/or adjust for alignment? */
144 [ + + ]: 1531930 : if (data == MY_ELFDATA || type == ELF_T_BYTE)
145 : : {
146 [ + + ]: 1526426 : if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
147 : : /* No need to copy, we can use the raw data. */
148 : 1525806 : scn->data_base = scn->rawdata_base;
149 : : else
150 : : {
151 : 620 : scn->data_base = malloc (size);
152 [ - + ]: 620 : if (scn->data_base == NULL)
153 : : {
154 : 0 : __libelf_seterrno (ELF_E_NOMEM);
155 : 0 : return;
156 : : }
157 : :
158 : : /* The copy will be appropriately aligned for direct access. */
159 : 620 : memcpy (scn->data_base, scn->rawdata_base, size);
160 : : }
161 : : }
162 : : else
163 : : {
164 : 5504 : xfct_t fp;
165 : :
166 : 5504 : scn->data_base = malloc (size);
167 [ - + ]: 5504 : if (scn->data_base == NULL)
168 : : {
169 : 0 : __libelf_seterrno (ELF_E_NOMEM);
170 : 0 : return;
171 : : }
172 : :
173 : : /* Make sure the source is correctly aligned for the conversion
174 : : function to directly access the data elements. */
175 : 5504 : char *rawdata_source;
176 [ + + ]: 5504 : if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
177 : : rawdata_source = scn->rawdata_base;
178 : : else
179 : : {
180 : 40 : rawdata_source = malloc (size);
181 [ - + ]: 40 : if (rawdata_source == NULL)
182 : : {
183 : 0 : __libelf_seterrno (ELF_E_NOMEM);
184 : 0 : return;
185 : : }
186 : :
187 : : /* The copy will be appropriately aligned for direct access. */
188 : 40 : memcpy (rawdata_source, scn->rawdata_base, size);
189 : : }
190 : :
191 : : /* Get the conversion function. */
192 : 5504 : fp = __elf_xfctstom[eclass - 1][type];
193 : :
194 : 5504 : fp (scn->data_base, rawdata_source, size, 0);
195 : :
196 [ + + ]: 5504 : if (rawdata_source != scn->rawdata_base)
197 : 40 : free (rawdata_source);
198 : : }
199 : :
200 : 1531930 : scn->data_list.data.d.d_buf = scn->data_base;
201 : 1531930 : scn->data_list.data.d.d_size = size;
202 : 1531930 : scn->data_list.data.d.d_type = type;
203 : 1531930 : scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
204 : 1531930 : scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
205 : 1531930 : scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
206 : :
207 : 1531930 : scn->data_list.data.s = scn;
208 : : }
209 : :
210 : :
211 : : /* Store the information for the raw data in the `rawdata' element. */
212 : : int
213 : : internal_function
214 : 2154670 : __libelf_set_rawdata_wrlock (Elf_Scn *scn)
215 : : {
216 : 2154670 : Elf64_Off offset;
217 : 2154670 : Elf64_Xword size;
218 : 2154670 : Elf64_Xword align;
219 : 2154670 : Elf64_Xword flags;
220 : 2154670 : int type;
221 : 2154670 : Elf *elf = scn->elf;
222 : :
223 [ + + ]: 2154670 : if (elf->class == ELFCLASS32)
224 : : {
225 : 2486950 : Elf32_Shdr *shdr
226 [ + + ]: 1243458 : = scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
227 : :
228 [ - + ]: 34 : if (shdr == NULL)
229 : : /* Something went terribly wrong. */
230 : : return 1;
231 : :
232 : 1243458 : offset = shdr->sh_offset;
233 : 1243458 : size = shdr->sh_size;
234 : 1243458 : type = shdr->sh_type;
235 : 1243458 : align = shdr->sh_addralign;
236 : 1243458 : flags = shdr->sh_flags;
237 : : }
238 : : else
239 : : {
240 : 1822460 : Elf64_Shdr *shdr
241 [ + + ]: 911212 : = scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
242 : :
243 [ - + ]: 36 : if (shdr == NULL)
244 : : /* Something went terribly wrong. */
245 : : return 1;
246 : :
247 : 911212 : offset = shdr->sh_offset;
248 : 911212 : size = shdr->sh_size;
249 : 911212 : type = shdr->sh_type;
250 : 911212 : align = shdr->sh_addralign;
251 : 911212 : flags = shdr->sh_flags;
252 : : }
253 : :
254 : : /* If the section has no data (for whatever reason), leave the `d_buf'
255 : : pointer NULL. */
256 [ + + ]: 2154670 : if (size != 0 && type != SHT_NOBITS)
257 : : {
258 : : /* First a test whether the section is valid at all. */
259 : 2150310 : size_t entsize;
260 : :
261 : : /* Compressed data has a header, but then compressed data.
262 : : Make sure to set the alignment of the header explicitly,
263 : : don't trust the file alignment for the section, it is
264 : : often wrong. */
265 [ + + ]: 2150310 : if ((flags & SHF_COMPRESSED) != 0)
266 : : {
267 : 2608 : entsize = 1;
268 [ + - ]: 2608 : align = __libelf_type_align (elf->class, ELF_T_CHDR);
269 : : }
270 [ + + ]: 2147702 : else if (type == SHT_HASH)
271 : : {
272 : 568 : GElf_Ehdr ehdr_mem;
273 : 568 : GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
274 [ - + ]: 568 : if (unlikely (ehdr == NULL))
275 : 0 : return 1;
276 [ + + + + : 568 : entsize = SH_ENTSIZE_HASH (ehdr);
+ + ]
277 : : }
278 : : else
279 : : {
280 [ + + + + ]: 2147134 : Elf_Type t = shtype_map[TYPEIDX (type)];
281 [ + + ]: 2147134 : if (t == ELF_T_NHDR && align == 8)
282 : 392 : t = ELF_T_NHDR8;
283 [ + + + + ]: 2147134 : if (t == ELF_T_VDEF || t == ELF_T_NHDR || t == ELF_T_NHDR8
284 [ + + + + ]: 2143036 : || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
285 : : entsize = 1;
286 : : else
287 : 2142536 : entsize = __libelf_type_sizes[elf->class - 1][t];
288 : : }
289 : :
290 : : /* We assume it is an array of bytes if it is none of the structured
291 : : sections we know of. */
292 : 2143104 : if (entsize == 0)
293 : 2150310 : entsize = 1;
294 : :
295 [ - + ]: 2150310 : if (unlikely (size % entsize != 0))
296 : : {
297 : 0 : __libelf_seterrno (ELF_E_INVALID_DATA);
298 : 0 : return 1;
299 : : }
300 : :
301 : : /* We can use the mapped or loaded data if available. */
302 [ + + ]: 2150310 : if (elf->map_address != NULL)
303 : : {
304 : : /* First see whether the information in the section header is
305 : : valid and it does not ask for too much. Check for unsigned
306 : : overflow. */
307 [ + - - + ]: 685894 : if (unlikely (offset > elf->maximum_size
308 : : || elf->maximum_size - offset < size))
309 : : {
310 : : /* Something is wrong. */
311 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
312 : 0 : return 1;
313 : : }
314 : :
315 : 685894 : scn->rawdata_base = scn->rawdata.d.d_buf
316 : 685894 : = (char *) elf->map_address + elf->start_offset + offset;
317 : : }
318 [ + - ]: 1464416 : else if (likely (elf->fildes != -1))
319 : : {
320 : : /* First see whether the information in the section header is
321 : : valid and it does not ask for too much. Check for unsigned
322 : : overflow. */
323 [ + - - + ]: 1464416 : if (unlikely (offset > elf->maximum_size
324 : : || elf->maximum_size - offset < size))
325 : : {
326 : : /* Something is wrong. */
327 : 0 : __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
328 : 0 : return 1;
329 : : }
330 : :
331 : : /* We have to read the data from the file. Allocate the needed
332 : : memory. */
333 : 1464416 : scn->rawdata_base = scn->rawdata.d.d_buf = malloc (size);
334 [ - + ]: 1464416 : if (scn->rawdata.d.d_buf == NULL)
335 : : {
336 : 0 : __libelf_seterrno (ELF_E_NOMEM);
337 : 0 : return 1;
338 : : }
339 : :
340 : 2928832 : ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
341 : 1464416 : elf->start_offset + offset);
342 [ - + ]: 1464416 : if (unlikely ((size_t) n != size))
343 : : {
344 : : /* Cannot read the data. */
345 : 0 : free (scn->rawdata.d.d_buf);
346 : 0 : scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
347 : 0 : __libelf_seterrno (ELF_E_READ_ERROR);
348 : 0 : return 1;
349 : : }
350 : : }
351 : : else
352 : : {
353 : : /* The file descriptor is already closed, we cannot get the data
354 : : anymore. */
355 : 0 : __libelf_seterrno (ELF_E_FD_DISABLED);
356 : 0 : return 1;
357 : : }
358 : : }
359 : :
360 : 2154670 : scn->rawdata.d.d_size = size;
361 : :
362 : : /* Compressed data always has type ELF_T_CHDR regardless of the
363 : : section type. */
364 [ + + ]: 2154670 : if ((flags & SHF_COMPRESSED) != 0)
365 : 2608 : scn->rawdata.d.d_type = ELF_T_CHDR;
366 : : else
367 : : {
368 : 2152062 : GElf_Ehdr ehdr_mem;
369 : 2152062 : GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
370 [ - + ]: 2152062 : if (unlikely (ehdr == NULL))
371 : 0 : return 1;
372 : 2152062 : scn->rawdata.d.d_type = __libelf_data_type (ehdr, type, align);
373 : : }
374 : 2154670 : scn->rawdata.d.d_off = 0;
375 : :
376 : : /* Make sure the alignment makes sense. d_align should be aligned both
377 : : in the section (trivially true since d_off is zero) and in the file.
378 : : Unfortunately we cannot be too strict because there are ELF files
379 : : out there that fail this requirement. We will try to fix those up
380 : : in elf_update when writing out the image. But for very large
381 : : alignment values this can bloat the image considerably. So here
382 : : just check and clamp the alignment value to not be bigger than the
383 : : actual offset of the data in the file. Given that there is always
384 : : at least an ehdr this will only trigger for alignment values > 64
385 : : which should be uncommon. */
386 : 2154670 : align = align ?: 1;
387 [ + + ]: 2154670 : if (type != SHT_NOBITS && align > offset)
388 : : {
389 : : /* Align the offset to the next power of two. Uses algorithm from
390 : : https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
391 : 2 : align = offset - 1;
392 : 2 : align |= align >> 1;
393 : 2 : align |= align >> 2;
394 : 2 : align |= align >> 4;
395 : 2 : align |= align >> 8;
396 : 2 : align |= align >> 16;
397 : 2 : align |= align >> 32;
398 : 2 : align++;
399 : : }
400 : 2154670 : scn->rawdata.d.d_align = align;
401 : 2154670 : if (elf->class == ELFCLASS32
402 : : || (offsetof (struct Elf, state.elf32.ehdr)
403 : : == offsetof (struct Elf, state.elf64.ehdr)))
404 : 2154670 : scn->rawdata.d.d_version =
405 : 2154670 : elf->state.elf32.ehdr->e_ident[EI_VERSION];
406 : : else
407 : : scn->rawdata.d.d_version =
408 : : elf->state.elf64.ehdr->e_ident[EI_VERSION];
409 : :
410 : 2154670 : scn->rawdata.s = scn;
411 : :
412 : 2154670 : scn->data_read = 1;
413 : :
414 : : /* We actually read data from the file. At least we tried. */
415 : 2154670 : scn->flags |= ELF_F_FILEDATA;
416 : :
417 : 2154670 : return 0;
418 : : }
419 : :
420 : : int
421 : : internal_function
422 : 92078 : __libelf_set_rawdata (Elf_Scn *scn)
423 : : {
424 : 92078 : int result;
425 : :
426 [ + - ]: 92078 : if (scn == NULL)
427 : : return 1;
428 : :
429 : 92078 : rwlock_wrlock (scn->elf->lock);
430 : 92078 : result = __libelf_set_rawdata_wrlock (scn);
431 : 92078 : rwlock_unlock (scn->elf->lock);
432 : :
433 : 92078 : return result;
434 : : }
435 : :
436 : : void
437 : : internal_function
438 : 1536094 : __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
439 : : {
440 [ + + + + ]: 1536094 : if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
441 : 1531930 : {
442 : 1531930 : Elf *elf = scn->elf;
443 : :
444 : : /* Upgrade the lock to a write lock if necessary and check
445 : : nobody else already did the work. */
446 [ + + ]: 1531930 : if (!wrlocked)
447 : : {
448 : 2082 : rwlock_unlock (elf->lock);
449 : 2082 : rwlock_wrlock (elf->lock);
450 [ + - ]: 2082 : if (scn->data_list_rear != NULL)
451 : : return;
452 : : }
453 : :
454 : : /* Convert according to the version and the type. */
455 : 1531930 : convert_data (scn, elf->class,
456 : : (elf->class == ELFCLASS32
457 : : || (offsetof (struct Elf, state.elf32.ehdr)
458 : : == offsetof (struct Elf, state.elf64.ehdr))
459 : 1531930 : ? elf->state.elf32.ehdr->e_ident[EI_DATA]
460 : : : elf->state.elf64.ehdr->e_ident[EI_DATA]),
461 : : scn->rawdata.d.d_size, scn->rawdata.d.d_type);
462 : : }
463 : : else
464 : : {
465 : : /* This is an empty or NOBITS section. There is no buffer but
466 : : the size information etc is important. */
467 : 4164 : scn->data_list.data.d = scn->rawdata.d;
468 : 4164 : scn->data_list.data.s = scn;
469 : : }
470 : :
471 : 1536094 : scn->data_list_rear = &scn->data_list;
472 : : }
473 : :
474 : : Elf_Data *
475 : : internal_function
476 : 2820004 : __elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
477 : : {
478 : 2820004 : Elf_Data *result = NULL;
479 : 2820004 : Elf *elf;
480 : 2820004 : int locked = 0;
481 : :
482 [ - + ]: 2820004 : if (scn == NULL)
483 : : return NULL;
484 : :
485 [ - + ]: 2820004 : if (unlikely (scn->elf->kind != ELF_K_ELF))
486 : : {
487 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE);
488 : 0 : return NULL;
489 : : }
490 : :
491 : : /* We will need this multiple times later on. */
492 : 2820004 : elf = scn->elf;
493 : :
494 : : /* If `data' is not NULL this means we are not addressing the initial
495 : : data in the file. But this also means this data is already read
496 : : (since otherwise it is not possible to have a valid `data' pointer)
497 : : and all the data structures are initialized as well. In this case
498 : : we can simply walk the list of data records. */
499 [ + + ]: 2820004 : if (data != NULL)
500 : : {
501 : 1054784 : Elf_Data_List *runp;
502 : :
503 : : /* It is not possible that if DATA is not NULL the first entry is
504 : : returned. But this also means that there must be a first data
505 : : entry. */
506 [ + + ]: 1054784 : if (scn->data_list_rear == NULL
507 : : /* The section the reference data is for must match the section
508 : : parameter. */
509 [ - + ]: 1054686 : || unlikely (((Elf_Data_Scn *) data)->s != scn))
510 : : {
511 : 98 : __libelf_seterrno (ELF_E_DATA_MISMATCH);
512 : 98 : goto out;
513 : : }
514 : :
515 : : /* We start searching with the first entry. */
516 : 1054686 : runp = &scn->data_list;
517 : :
518 : 1054746 : while (1)
519 : : {
520 : : /* If `data' does not match any known record punt. */
521 [ + + ]: 1054716 : if (runp == NULL)
522 : : {
523 : 6 : __libelf_seterrno (ELF_E_DATA_MISMATCH);
524 : 6 : goto out;
525 : : }
526 : :
527 [ + + ]: 1054710 : if (&runp->data.d == data)
528 : : /* Found the entry. */
529 : : break;
530 : :
531 : 30 : runp = runp->next;
532 : : }
533 : :
534 : : /* Return the data for the next data record. */
535 [ + + ]: 1054680 : result = runp->next ? &runp->next->data.d : NULL;
536 : 1054680 : goto out;
537 : : }
538 : :
539 : : /* If the data for this section was not yet initialized do it now. */
540 [ + + ]: 1765220 : if (scn->data_read == 0)
541 : : {
542 : : /* We cannot acquire a write lock while we are holding a read
543 : : lock. Therefore give up the read lock and then get the write
544 : : lock. But this means that the data could meanwhile be
545 : : modified, therefore start the tests again. */
546 : 1529618 : rwlock_unlock (elf->lock);
547 : 1529618 : rwlock_wrlock (elf->lock);
548 : 1529618 : locked = 1;
549 : :
550 : : /* Read the data from the file. There is always a file (or
551 : : memory region) associated with this descriptor since
552 : : otherwise the `data_read' flag would be set. */
553 [ - + ]: 1529618 : if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
554 : : /* Something went wrong. The error value is already set. */
555 : 0 : goto out;
556 : : }
557 : :
558 : : /* At this point we know the raw data is available. But it might be
559 : : empty in case the section has size zero (for whatever reason).
560 : : Now create the converted data in case this is necessary. */
561 [ + + ]: 1765220 : if (scn->data_list_rear == NULL)
562 : 1531758 : __libelf_set_data_list_rdlock (scn, locked);
563 : :
564 : : /* Return the first data element in the list. */
565 : 1765220 : result = &scn->data_list.data.d;
566 : :
567 : : out:
568 : : return result;
569 : : }
570 : :
571 : : Elf_Data *
572 : 2819854 : elf_getdata (Elf_Scn *scn, Elf_Data *data)
573 : : {
574 : 2819854 : Elf_Data *result;
575 : :
576 [ + + ]: 2819854 : if (scn == NULL)
577 : : return NULL;
578 : :
579 : 2819638 : rwlock_rdlock (scn->elf->lock);
580 : 2819638 : result = __elf_getdata_rdlock (scn, data);
581 : 2819638 : rwlock_unlock (scn->elf->lock);
582 : :
583 : 2819638 : return result;
584 : : }
585 : :
586 : : Elf_Data *
587 : : internal_function
588 : 18 : __elf_getdata_wrlock (Elf_Scn *scn, Elf_Data *data)
589 : : {
590 : 18 : Elf_Data *result;
591 : :
592 [ + - ]: 18 : if (scn == NULL)
593 : : return NULL;
594 : :
595 : 18 : result = __elf_getdata_rdlock (scn, data);
596 : :
597 : 18 : return result;
598 : : }
599 : : INTDEF(elf_getdata)
|