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