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