Branch data Line data Source code
1 : : /* Create descriptor for processing file.
2 : : Copyright (C) 1998-2010, 2012, 2014, 2015, 2016 Red Hat, Inc.
3 : : Copyright (C) 2021, 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 <assert.h>
36 : : #include <ctype.h>
37 : : #include <errno.h>
38 : : #include <fcntl.h>
39 : : #include <stdbool.h>
40 : : #include <stddef.h>
41 : : #include <string.h>
42 : : #include <unistd.h>
43 : : #include <sys/mman.h>
44 : : #include <sys/stat.h>
45 : :
46 : : #include <system.h>
47 : : #include "libelfP.h"
48 : : #include "common.h"
49 : :
50 : :
51 : : /* Create descriptor for archive in memory. */
52 : : static inline Elf *
53 : 145 : file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
54 : : Elf_Cmd cmd, Elf *parent)
55 : : {
56 : 145 : Elf *elf;
57 : :
58 : : /* Create a descriptor. */
59 : 145 : elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
60 : : ELF_K_AR, 0);
61 [ + - ]: 145 : if (elf != NULL)
62 : : {
63 : : /* We don't read all the symbol tables in advance. All this will
64 : : happen on demand. */
65 : 145 : elf->state.ar.offset = offset + SARMAG;
66 : :
67 : 145 : elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
68 : : }
69 : :
70 : 145 : return elf;
71 : : }
72 : :
73 : :
74 : : static size_t
75 : 15139 : get_shnum (void *map_address, unsigned char *e_ident, int fildes,
76 : : int64_t offset, size_t maxsize)
77 : : {
78 : 15139 : size_t result;
79 : 15139 : union
80 : : {
81 : : Elf32_Ehdr *e32;
82 : : Elf64_Ehdr *e64;
83 : : void *p;
84 : : } ehdr;
85 : 15139 : union
86 : : {
87 : : Elf32_Ehdr e32;
88 : : Elf64_Ehdr e64;
89 : : } ehdr_mem;
90 : 15139 : bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
91 : :
92 [ + - ]: 15139 : if ((is32 && maxsize < sizeof (Elf32_Ehdr))
93 [ - + ]: 15139 : || (!is32 && maxsize < sizeof (Elf64_Ehdr)))
94 : : {
95 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
96 : 0 : return (size_t) -1l;
97 : : }
98 : :
99 : : /* Make the ELF header available. */
100 [ + + ]: 15139 : if (e_ident[EI_DATA] == MY_ELFDATA
101 : 14464 : && (ALLOW_UNALIGNED
102 : 14464 : || (((size_t) e_ident
103 [ + + ]: 14464 : & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
104 [ + + ]: 14464 : - 1)) == 0)))
105 : : ehdr.p = e_ident;
106 : : else
107 : : {
108 : : /* We already read the ELF header. We have to copy the header
109 : : since we possibly modify the data here and the caller
110 : : expects the memory it passes in to be preserved. */
111 : 720 : ehdr.p = &ehdr_mem;
112 : :
113 [ + + ]: 720 : if (is32)
114 : : {
115 : 313 : if (ALLOW_UNALIGNED)
116 : : {
117 : : ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
118 : : ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
119 : : }
120 : : else
121 [ + - ]: 313 : memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
122 : :
123 [ + - ]: 313 : if (e_ident[EI_DATA] != MY_ELFDATA)
124 : : {
125 : 313 : CONVERT (ehdr_mem.e32.e_shnum);
126 : 313 : CONVERT (ehdr_mem.e32.e_shoff);
127 : : }
128 : : }
129 : : else
130 : : {
131 : 407 : if (ALLOW_UNALIGNED)
132 : : {
133 : : ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
134 : : ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
135 : : }
136 : : else
137 [ + + ]: 407 : memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
138 : :
139 [ + + ]: 407 : if (e_ident[EI_DATA] != MY_ELFDATA)
140 : : {
141 : 362 : CONVERT (ehdr_mem.e64.e_shnum);
142 : 362 : CONVERT (ehdr_mem.e64.e_shoff);
143 : : }
144 : : }
145 : : }
146 : :
147 [ + + ]: 15139 : if (is32)
148 : : {
149 : : /* Get the number of sections from the ELF header. */
150 : 909 : result = ehdr.e32->e_shnum;
151 : :
152 [ + + + + ]: 909 : if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
153 : : {
154 [ + - ]: 52 : if (unlikely (ehdr.e32->e_shoff >= maxsize)
155 [ + - ]: 52 : || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
156 : : /* Cannot read the first section header. */
157 : : return 0;
158 : :
159 [ + + + + ]: 52 : if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
160 : 24 : && (ALLOW_UNALIGNED
161 : 24 : || (((size_t) ((char *) (map_address + ehdr.e32->e_shoff
162 : 24 : + offset)))
163 [ + - ]: 24 : & (__alignof__ (Elf32_Shdr) - 1)) == 0))
164 : : /* We can directly access the memory. */
165 : 24 : result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
166 : 24 : + offset))->sh_size;
167 : : else
168 : : {
169 : 28 : Elf32_Word size;
170 : 28 : ssize_t r;
171 : :
172 [ + + ]: 28 : if (likely (map_address != NULL))
173 : : /* gcc will optimize the memcpy to a simple memory
174 : : access while taking care of alignment issues. */
175 : 44 : memcpy (&size, ((char *) map_address
176 : : + ehdr.e32->e_shoff
177 : 16 : + offset
178 : 16 : + offsetof (Elf32_Shdr, sh_size)),
179 : : sizeof (Elf32_Word));
180 : : else
181 [ - + ]: 12 : if (unlikely ((r = pread_retry (fildes, &size,
182 : : sizeof (Elf32_Word),
183 : : offset + ehdr.e32->e_shoff
184 : : + offsetof (Elf32_Shdr,
185 : : sh_size)))
186 : : != sizeof (Elf32_Word)))
187 : : {
188 [ # # ]: 0 : if (r < 0)
189 : 0 : __libelf_seterrno (ELF_E_INVALID_FILE);
190 : : else
191 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
192 : 0 : return (size_t) -1l;
193 : : }
194 : :
195 [ + + ]: 28 : if (e_ident[EI_DATA] != MY_ELFDATA)
196 : 20 : CONVERT (size);
197 : :
198 : 28 : result = size;
199 : : }
200 : : }
201 : :
202 : : /* If the section headers were truncated, pretend none were there. */
203 [ + - ]: 909 : if (ehdr.e32->e_shoff > maxsize
204 [ - + ]: 909 : || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
205 : 0 : result = 0;
206 : : }
207 : : else
208 : : {
209 : : /* Get the number of sections from the ELF header. */
210 : 14230 : result = ehdr.e64->e_shnum;
211 : :
212 [ + + + + ]: 14230 : if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
213 : : {
214 [ + - ]: 41 : if (unlikely (ehdr.e64->e_shoff >= maxsize)
215 [ + - ]: 41 : || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
216 : : /* Cannot read the first section header. */
217 : 0 : return 0;
218 : :
219 : 41 : Elf64_Xword size;
220 [ + + + + ]: 41 : if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
221 : 17 : && (ALLOW_UNALIGNED
222 : 17 : || (((size_t) ((char *) (map_address + ehdr.e64->e_shoff
223 : 17 : + offset)))
224 [ + - ]: 17 : & (__alignof__ (Elf64_Shdr) - 1)) == 0))
225 : : /* We can directly access the memory. */
226 : 17 : size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
227 : 17 : + offset))->sh_size;
228 : : else
229 : : {
230 : 24 : ssize_t r;
231 [ + + ]: 24 : if (likely (map_address != NULL))
232 : : /* gcc will optimize the memcpy to a simple memory
233 : : access while taking care of alignment issues. */
234 : 40 : memcpy (&size, ((char *) map_address
235 : : + ehdr.e64->e_shoff
236 : 16 : + offset
237 : 16 : + offsetof (Elf64_Shdr, sh_size)),
238 : : sizeof (Elf64_Xword));
239 : : else
240 [ - + ]: 8 : if (unlikely ((r = pread_retry (fildes, &size,
241 : : sizeof (Elf64_Xword),
242 : : offset + ehdr.e64->e_shoff
243 : : + offsetof (Elf64_Shdr,
244 : : sh_size)))
245 : : != sizeof (Elf64_Xword)))
246 : : {
247 [ # # ]: 0 : if (r < 0)
248 : 0 : __libelf_seterrno (ELF_E_INVALID_FILE);
249 : : else
250 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
251 : 0 : return (size_t) -1l;
252 : : }
253 : :
254 [ + + ]: 24 : if (e_ident[EI_DATA] != MY_ELFDATA)
255 : 20 : CONVERT (size);
256 : : }
257 : :
258 : : /* Although sh_size is an Elf64_Xword and can contain a 64bit
259 : : value, we only expect an 32bit value max. GElf_Word is
260 : : 32bit unsigned. */
261 [ - + ]: 41 : if (size > ~((GElf_Word) 0))
262 : : {
263 : : /* Invalid value, it is too large. */
264 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
265 : 0 : return (size_t) -1l;
266 : : }
267 : :
268 : 41 : result = size;
269 : : }
270 : :
271 : : /* If the section headers were truncated, pretend none were there. */
272 [ + + ]: 14230 : if (ehdr.e64->e_shoff > maxsize
273 [ - + ]: 14228 : || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
274 : 2 : result = 0;
275 : : }
276 : :
277 : : return result;
278 : : }
279 : :
280 : :
281 : : /* Create descriptor for ELF file in memory. */
282 : : static Elf *
283 : 15139 : file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
284 : : int64_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
285 : : {
286 : : /* Verify the binary is of the class we can handle. */
287 [ + - - + ]: 15139 : if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
288 : : && e_ident[EI_CLASS] != ELFCLASS64)
289 : : /* We also can only handle two encodings. */
290 : : || (e_ident[EI_DATA] != ELFDATA2LSB
291 : : && e_ident[EI_DATA] != ELFDATA2MSB)))
292 : : {
293 : : /* Cannot handle this. */
294 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
295 : 0 : return NULL;
296 : : }
297 : :
298 : : /* Determine the number of sections. Returns -1 and sets libelf errno
299 : : if the file handle or elf file is invalid. Returns zero if there
300 : : are no section headers (or they cannot be read). */
301 : 15139 : size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
302 [ + - ]: 15139 : if (scncnt == (size_t) -1l)
303 : : /* Could not determine the number of sections. */
304 : : return NULL;
305 : :
306 : : /* Check for too many sections. */
307 [ + + ]: 15139 : if (e_ident[EI_CLASS] == ELFCLASS32)
308 : : {
309 [ - + ]: 909 : if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
310 : : {
311 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
312 : 0 : return NULL;
313 : : }
314 : : }
315 [ - + ]: 14230 : else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
316 : : {
317 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
318 : 0 : return NULL;
319 : : }
320 : :
321 : : /* We can now allocate the memory. Even if there are no section headers,
322 : : we allocate space for a zeroth section in case we need it later. */
323 [ + + ]: 15139 : const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
324 : 187 : ? 1 : 0);
325 : 15139 : Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
326 : : ELF_K_ELF, scnmax * sizeof (Elf_Scn));
327 [ + - ]: 15139 : if (elf == NULL)
328 : : /* Not enough memory. allocate_elf will have set libelf errno. */
329 : : return NULL;
330 : :
331 [ - + ]: 15139 : assert ((unsigned int) scncnt == scncnt);
332 : 15139 : assert (offsetof (struct Elf, state.elf32.scns)
333 : : == offsetof (struct Elf, state.elf64.scns));
334 : 15139 : elf->state.elf32.scns.cnt = scncnt;
335 : 15139 : elf->state.elf32.scns.max = scnmax;
336 : :
337 : : /* Some more or less arbitrary value. */
338 : 15139 : elf->state.elf.scnincr = 10;
339 : :
340 : : /* Make the class easily available. */
341 : 15139 : elf->class = e_ident[EI_CLASS];
342 : :
343 [ + + ]: 15139 : if (e_ident[EI_CLASS] == ELFCLASS32)
344 : : {
345 : : /* This pointer might not be directly usable if the alignment is
346 : : not sufficient for the architecture. */
347 : 909 : Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset);
348 : :
349 : : /* This is a 32-bit binary. */
350 [ + + + + ]: 909 : if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
351 : 338 : && (ALLOW_UNALIGNED
352 [ + - ]: 338 : || (((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
353 : : {
354 : : /* We can use the mmapped memory. */
355 : 338 : elf->state.elf32.ehdr = ehdr;
356 : : }
357 : : else
358 : : {
359 : : /* Copy the ELF header. */
360 [ + + ]: 571 : elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
361 : : sizeof (Elf32_Ehdr));
362 : :
363 [ + + ]: 571 : if (e_ident[EI_DATA] != MY_ELFDATA)
364 : : {
365 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_type);
366 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_machine);
367 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_version);
368 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_entry);
369 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
370 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
371 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_flags);
372 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
373 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
374 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
375 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
376 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
377 : 313 : CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
378 : : }
379 : : }
380 : :
381 : : /* Don't precache the phdr pointer here.
382 : : elf32_getphdr will validate it against the size when asked. */
383 : :
384 : 909 : Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
385 [ + + + + ]: 909 : if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
386 [ + + ]: 338 : && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write. */
387 : 194 : && (ALLOW_UNALIGNED
388 : 194 : || ((((uintptr_t) ehdr + e_shoff)
389 [ - + ]: 194 : & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
390 : : {
391 [ + + - + ]: 194 : if (unlikely (scncnt > 0 && e_shoff >= maxsize)
392 [ - + ]: 194 : || unlikely (maxsize - e_shoff
393 : : < scncnt * sizeof (Elf32_Shdr)))
394 : : {
395 : 0 : free_and_out:
396 : 0 : free (elf);
397 : 0 : __libelf_seterrno (ELF_E_INVALID_ELF);
398 : 0 : return NULL;
399 : : }
400 : :
401 [ + + ]: 194 : if (scncnt > 0)
402 : 183 : elf->state.elf32.shdr
403 : 183 : = (Elf32_Shdr *) ((char *) ehdr + e_shoff);
404 : :
405 [ + + ]: 595126 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
406 : : {
407 : 594932 : elf->state.elf32.scns.data[cnt].index = cnt;
408 : 594932 : elf->state.elf32.scns.data[cnt].elf = elf;
409 : 594932 : elf->state.elf32.scns.data[cnt].shdr.e32 =
410 : 594932 : &elf->state.elf32.shdr[cnt];
411 [ + + ]: 594932 : if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
412 [ + + ]: 594930 : && likely (elf->state.elf32.shdr[cnt].sh_size
413 : : <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
414 : 594924 : elf->state.elf32.scns.data[cnt].rawdata_base =
415 : 594924 : elf->state.elf32.scns.data[cnt].data_base =
416 : : ((char *) map_address + offset
417 : 594924 : + elf->state.elf32.shdr[cnt].sh_offset);
418 : 594932 : elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
419 : :
420 : : /* If this is a section with an extended index add a
421 : : reference in the section which uses the extended
422 : : index. */
423 [ - + ]: 594932 : if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
424 [ # # ]: 0 : && elf->state.elf32.shdr[cnt].sh_link < scncnt)
425 : 0 : elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
426 : 0 : = cnt;
427 : :
428 : : /* Set the own shndx_index field in case it has not yet
429 : : been set. */
430 [ + - ]: 594932 : if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
431 : 594932 : elf->state.elf32.scns.data[cnt].shndx_index = -1;
432 : : }
433 : : }
434 : : else
435 : : {
436 [ + + ]: 3228906 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
437 : : {
438 : 3228191 : elf->state.elf32.scns.data[cnt].index = cnt;
439 : 3228191 : elf->state.elf32.scns.data[cnt].elf = elf;
440 : 3228191 : elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
441 : : }
442 : : }
443 : :
444 : : /* So far only one block with sections. */
445 : 909 : elf->state.elf32.scns_last = &elf->state.elf32.scns;
446 : : }
447 : : else
448 : : {
449 : : /* This pointer might not be directly usable if the alignment is
450 : : not sufficient for the architecture. */
451 : 14230 : Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
452 : :
453 : : /* This is a 64-bit binary. */
454 [ + + + + ]: 14230 : if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
455 : 6371 : && (ALLOW_UNALIGNED
456 [ + + ]: 6371 : || (((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
457 : : {
458 : : /* We can use the mmapped memory. */
459 : 6326 : elf->state.elf64.ehdr = ehdr;
460 : : }
461 : : else
462 : : {
463 : : /* Copy the ELF header. */
464 [ + + ]: 7904 : elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
465 : : sizeof (Elf64_Ehdr));
466 : :
467 [ + + ]: 7904 : if (e_ident[EI_DATA] != MY_ELFDATA)
468 : : {
469 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_type);
470 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_machine);
471 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_version);
472 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_entry);
473 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
474 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
475 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_flags);
476 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
477 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
478 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
479 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
480 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
481 : 362 : CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
482 : : }
483 : : }
484 : :
485 : : /* Don't precache the phdr pointer here.
486 : : elf64_getphdr will validate it against the size when asked. */
487 : :
488 : 14230 : Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
489 [ + + + + ]: 14230 : if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
490 [ + + ]: 6371 : && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write. */
491 : 5764 : && (ALLOW_UNALIGNED
492 : 5764 : || ((((uintptr_t) ehdr + e_shoff)
493 [ + + ]: 5764 : & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
494 : : {
495 [ + - ]: 5702 : if (unlikely (scncnt > 0 && e_shoff >= maxsize)
496 [ - + ]: 5702 : || unlikely (maxsize - e_shoff
497 : : < scncnt * sizeof (Elf64_Shdr)))
498 : 0 : goto free_and_out;
499 : :
500 [ + + ]: 5702 : if (scncnt > 0)
501 : 5677 : elf->state.elf64.shdr
502 : 5677 : = (Elf64_Shdr *) ((char *) ehdr + e_shoff);
503 : :
504 [ + + ]: 810983 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
505 : : {
506 : 805281 : elf->state.elf64.scns.data[cnt].index = cnt;
507 : 805281 : elf->state.elf64.scns.data[cnt].elf = elf;
508 : 805281 : elf->state.elf64.scns.data[cnt].shdr.e64 =
509 : 805281 : &elf->state.elf64.shdr[cnt];
510 [ + + ]: 805281 : if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
511 [ + + ]: 805167 : && likely (elf->state.elf64.shdr[cnt].sh_size
512 : : <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
513 : 805125 : elf->state.elf64.scns.data[cnt].rawdata_base =
514 : 805125 : elf->state.elf64.scns.data[cnt].data_base =
515 : : ((char *) map_address + offset
516 : 805125 : + elf->state.elf64.shdr[cnt].sh_offset);
517 : 805281 : elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
518 : :
519 : : /* If this is a section with an extended index add a
520 : : reference in the section which uses the extended
521 : : index. */
522 [ - + ]: 805281 : if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
523 [ # # ]: 0 : && elf->state.elf64.shdr[cnt].sh_link < scncnt)
524 : 0 : elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
525 : 0 : = cnt;
526 : :
527 : : /* Set the own shndx_index field in case it has not yet
528 : : been set. */
529 [ + - ]: 805281 : if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
530 : 805281 : elf->state.elf64.scns.data[cnt].shndx_index = -1;
531 : : }
532 : : }
533 : : else
534 : : {
535 [ + + ]: 2782229 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
536 : : {
537 : 2773701 : elf->state.elf64.scns.data[cnt].index = cnt;
538 : 2773701 : elf->state.elf64.scns.data[cnt].elf = elf;
539 : 2773701 : elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
540 : : }
541 : : }
542 : :
543 : : /* So far only one block with sections. */
544 : 14230 : elf->state.elf64.scns_last = &elf->state.elf64.scns;
545 : : }
546 : :
547 : : return elf;
548 : : }
549 : :
550 : :
551 : : Elf *
552 : : internal_function
553 : 7351 : __libelf_read_mmaped_file (int fildes, void *map_address, int64_t offset,
554 : : size_t maxsize, Elf_Cmd cmd, Elf *parent)
555 : : {
556 : : /* We have to find out what kind of file this is. We handle ELF
557 : : files and archives. To find out what we have we must look at the
558 : : header. The header for an ELF file is EI_NIDENT bytes in size,
559 : : the header for an archive file SARMAG bytes long. */
560 : 7351 : unsigned char *e_ident = (unsigned char *) map_address + offset;
561 : :
562 : : /* See what kind of object we have here. */
563 : 7351 : Elf_Kind kind = determine_kind (e_ident, maxsize);
564 : :
565 [ + + + ]: 7351 : switch (kind)
566 : : {
567 : 7078 : case ELF_K_ELF:
568 : 7078 : return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
569 : : cmd, parent);
570 : :
571 : 18 : case ELF_K_AR:
572 : 18 : return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
573 : :
574 : : default:
575 : 255 : break;
576 : : }
577 : :
578 : : /* This case is easy. Since we cannot do anything with this file
579 : : create a dummy descriptor. */
580 : 255 : return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
581 : : ELF_K_NONE, 0);
582 : : }
583 : :
584 : :
585 : : static Elf *
586 : 8425 : read_unmmaped_file (int fildes, int64_t offset, size_t maxsize, Elf_Cmd cmd,
587 : : Elf *parent)
588 : : {
589 : : /* We have to find out what kind of file this is. We handle ELF
590 : : files and archives. To find out what we have we must read the
591 : : header. The identification header for an ELF file is EI_NIDENT
592 : : bytes in size, but we read the whole ELF header since we will
593 : : need it anyway later. For archives the header in SARMAG bytes
594 : : long. Read the maximum of these numbers.
595 : :
596 : : XXX We have to change this for the extended `ar' format some day.
597 : :
598 : : Use a union to ensure alignment. We might later access the
599 : : memory as a ElfXX_Ehdr. */
600 : 8425 : union
601 : : {
602 : : Elf64_Ehdr ehdr;
603 : : unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
604 : : } mem;
605 : :
606 : : /* Read the head of the file. */
607 : 16850 : ssize_t nread = pread_retry (fildes, mem.header,
608 : 8425 : MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
609 : : maxsize),
610 : : offset);
611 [ - + ]: 8425 : if (unlikely (nread == -1))
612 : : {
613 : : /* We cannot even read the head of the file. Maybe FILDES is associated
614 : : with an unseekable device. This is nothing we can handle. */
615 : 0 : __libelf_seterrno (ELF_E_INVALID_FILE);
616 : 0 : return NULL;
617 : : }
618 : :
619 : : /* See what kind of object we have here. */
620 : 8425 : Elf_Kind kind = determine_kind (mem.header, nread);
621 : :
622 [ + + + ]: 8425 : switch (kind)
623 : : {
624 : 127 : case ELF_K_AR:
625 : 127 : return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
626 : :
627 : 8061 : case ELF_K_ELF:
628 : : /* Make sure at least the ELF header is contained in the file. */
629 [ + - ]: 8061 : if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
630 [ + + ]: 8061 : ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
631 : 8061 : return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
632 : : parent);
633 : 237 : FALLTHROUGH;
634 : :
635 : : default:
636 : 237 : break;
637 : : }
638 : :
639 : : /* This case is easy. Since we cannot do anything with this file
640 : : create a dummy descriptor. */
641 : 237 : return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
642 : : ELF_K_NONE, 0);
643 : : }
644 : :
645 : :
646 : : /* Open a file for reading. If possible we will try to mmap() the file. */
647 : : static struct Elf *
648 : 15681 : read_file (int fildes, int64_t offset, size_t maxsize,
649 : : Elf_Cmd cmd, Elf *parent)
650 : : {
651 : 15681 : void *map_address = NULL;
652 : 15681 : int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
653 : : || cmd == ELF_C_WRITE_MMAP
654 : 15681 : || cmd == ELF_C_READ_MMAP_PRIVATE);
655 : :
656 [ + + ]: 15681 : if (parent == NULL)
657 : : {
658 [ + + ]: 8461 : if (maxsize == ~((size_t) 0))
659 : : {
660 : : /* We don't know in the moment how large the file is.
661 : : Determine it now. */
662 : 8457 : struct stat st;
663 : :
664 [ + + ]: 8457 : if (fstat (fildes, &st) == 0
665 : : && (sizeof (size_t) >= sizeof (st.st_size)
666 : : || st.st_size <= ~((size_t) 0)))
667 : 8460 : maxsize = (size_t) st.st_size;
668 : : }
669 : : }
670 : : else
671 : : {
672 : : /* The parent is already loaded. Use it. */
673 [ - + ]: 7220 : assert (maxsize != ~((size_t) 0));
674 : : }
675 : :
676 [ + + ]: 15685 : if (use_mmap)
677 : : {
678 [ + + ]: 7271 : if (parent == NULL)
679 : : {
680 : : /* We try to map the file ourself. */
681 [ + + ]: 14416 : map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
682 : : ? PROT_READ
683 : : : PROT_READ|PROT_WRITE),
684 : 7208 : cmd == ELF_C_READ_MMAP_PRIVATE
685 [ + + ]: 7208 : || cmd == ELF_C_READ_MMAP
686 : : ? MAP_PRIVATE : MAP_SHARED,
687 : : fildes, offset);
688 : :
689 [ + + ]: 7214 : if (map_address == MAP_FAILED)
690 : : map_address = NULL;
691 : : }
692 : : else
693 : : {
694 : 63 : map_address = parent->map_address;
695 : : }
696 : : }
697 : :
698 : : /* If we have the file in memory optimize the access. */
699 [ + - ]: 7266 : if (map_address != NULL)
700 : : {
701 [ - + ]: 7266 : assert (map_address != MAP_FAILED);
702 : :
703 : 7266 : struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
704 : : offset, maxsize, cmd,
705 : : parent);
706 : :
707 : : /* If something went wrong during the initialization unmap the
708 : : memory if we mmaped here. */
709 [ - + ]: 7265 : if (result == NULL
710 [ # # ]: 0 : && (parent == NULL
711 [ # # ]: 0 : || parent->map_address != map_address))
712 : 0 : munmap (map_address, maxsize);
713 [ + + ]: 7265 : else if (parent == NULL)
714 : : /* Remember that we mmap()ed the memory. */
715 : 7203 : result->flags |= ELF_F_MMAPPED;
716 : :
717 : 7265 : return result;
718 : : }
719 : :
720 : : /* Otherwise we have to do it the hard way. We read as much as necessary
721 : : from the file whenever we need information which is not available. */
722 : 8425 : return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
723 : : }
724 : :
725 : :
726 : : /* Find the entry with the long names for the content of this archive. */
727 : : static const char *
728 : 102 : read_long_names (Elf *elf)
729 : : {
730 : 102 : off_t offset = SARMAG; /* This is the first entry. */
731 : 204 : struct ar_hdr hdrm;
732 : 204 : struct ar_hdr *hdr;
733 : 204 : char *newp;
734 : 204 : size_t len;
735 : :
736 : 306 : while (1)
737 : 102 : {
738 [ - + ]: 204 : if (elf->map_address != NULL)
739 : : {
740 [ # # ]: 0 : if ((size_t) offset > elf->maximum_size
741 [ # # ]: 0 : || elf->maximum_size - offset < sizeof (struct ar_hdr))
742 : 0 : return NULL;
743 : :
744 : : /* The data is mapped. */
745 : 0 : hdr = (struct ar_hdr *) (elf->map_address + offset);
746 : : }
747 : : else
748 : : {
749 : : /* Read the header from the file. */
750 [ + - ]: 204 : if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
751 : : elf->start_offset + offset)
752 : : != sizeof (hdrm)))
753 : : return NULL;
754 : :
755 : : hdr = &hdrm;
756 : : }
757 : :
758 : : /* The ar_size is given as a fixed size decimal string, right
759 : : padded with spaces. Make sure we read it properly even if
760 : : there is no terminating space. */
761 : 204 : char buf[sizeof (hdr->ar_size) + 1];
762 : 204 : const char *string = hdr->ar_size;
763 [ - + ]: 204 : if (hdr->ar_size[sizeof (hdr->ar_size) - 1] != ' ')
764 : : {
765 : 0 : *((char *) mempcpy (buf, hdr->ar_size, sizeof (hdr->ar_size))) = '\0';
766 : 0 : string = buf;
767 : : }
768 : :
769 : : /* atol expects to see at least one digit.
770 : : It also cannot be negative (-). */
771 [ + - ]: 204 : if (!isdigit(string[0]))
772 : : return NULL;
773 : 204 : len = atol (string);
774 : :
775 [ + + ]: 204 : if (memcmp (hdr->ar_name, "// ", 16) == 0)
776 : : break;
777 : :
778 : 102 : offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
779 : : }
780 : :
781 : : /* Sanity check len early if we can. */
782 [ - + ]: 102 : if (elf->map_address != NULL)
783 : : {
784 [ # # ]: 0 : if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
785 : : return NULL;
786 : : }
787 : :
788 : : /* Due to the stupid format of the long name table entry (which are not
789 : : NUL terminted) we have to provide an appropriate representation anyhow.
790 : : Therefore we always make a copy which has the appropriate form. */
791 : 102 : newp = malloc (len);
792 [ + - ]: 102 : if (newp != NULL)
793 : : {
794 : 102 : char *runp;
795 : :
796 [ - + ]: 102 : if (elf->map_address != NULL)
797 : : {
798 : : /* Simply copy it over. */
799 : 0 : elf->state.ar.long_names = (char *) memcpy (newp,
800 : : elf->map_address + offset
801 : 0 : + sizeof (struct ar_hdr),
802 : : len);
803 : : }
804 : : else
805 : : {
806 [ - + ]: 102 : if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
807 : : elf->start_offset + offset
808 : : + sizeof (struct ar_hdr))
809 : : != len))
810 : : {
811 : : /* We were not able to read all data. */
812 : 0 : free (newp);
813 : 0 : elf->state.ar.long_names = NULL;
814 : 0 : return NULL;
815 : : }
816 : 102 : elf->state.ar.long_names = newp;
817 : : }
818 : :
819 : 102 : elf->state.ar.long_names_len = len;
820 : :
821 : : /* Now NUL-terminate the strings. */
822 : 102 : runp = newp;
823 : 4182 : while (1)
824 : : {
825 : 4182 : char *startp = runp;
826 : 4182 : runp = (char *) memchr (runp, '/', newp + len - runp);
827 [ + + ]: 4182 : if (runp == NULL)
828 : : {
829 : : /* This was the last entry. Clear any left overs. */
830 : 102 : memset (startp, '\0', newp + len - startp);
831 : : break;
832 : : }
833 : :
834 : : /* NUL-terminate the string. */
835 : 4080 : *runp++ = '\0';
836 : :
837 : : /* A sanity check. Somebody might have generated invalid
838 : : archive. */
839 [ + - ]: 4080 : if (runp >= newp + len)
840 : : break;
841 : : }
842 : : }
843 : :
844 : : return newp;
845 : : }
846 : :
847 : :
848 : : /* Read the next archive header. */
849 : : int
850 : : internal_function
851 : 7238 : __libelf_next_arhdr_wrlock (Elf *elf)
852 : : {
853 : 7238 : struct ar_hdr *ar_hdr;
854 : 7238 : Elf_Arhdr *elf_ar_hdr;
855 : :
856 [ + + ]: 7238 : if (elf->map_address != NULL)
857 : : {
858 : : /* See whether this entry is in the file. */
859 [ + - + + ]: 71 : if (unlikely ((size_t) elf->state.ar.offset
860 : : > elf->start_offset + elf->maximum_size
861 : : || (elf->start_offset + elf->maximum_size
862 : : - elf->state.ar.offset) < sizeof (struct ar_hdr)))
863 : : {
864 : : /* This record is not anymore in the file. */
865 : 8 : __libelf_seterrno (ELF_E_RANGE);
866 : 8 : return -1;
867 : : }
868 : 63 : ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
869 : : }
870 : : else
871 : : {
872 : 7167 : ar_hdr = &elf->state.ar.ar_hdr;
873 : :
874 [ - + ]: 7167 : if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
875 : : elf->state.ar.offset)
876 : : != sizeof (struct ar_hdr)))
877 : : {
878 : : /* Something went wrong while reading the file. */
879 : 0 : __libelf_seterrno (ELF_E_RANGE);
880 : 0 : return -1;
881 : : }
882 : : }
883 : :
884 : : /* One little consistency check. */
885 [ - + ]: 7230 : if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
886 : : {
887 : : /* This is no valid archive. */
888 : 0 : __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
889 : 0 : return -1;
890 : : }
891 : :
892 : : /* Copy the raw name over to a NUL terminated buffer. */
893 [ + + ]: 7230 : *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
894 : :
895 : 7230 : elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
896 : :
897 : : /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
898 : : Determine whether this is a special entry. */
899 [ + + ]: 7230 : if (ar_hdr->ar_name[0] == '/')
900 : : {
901 [ + + ]: 2077 : if (ar_hdr->ar_name[1] == ' '
902 [ + - ]: 120 : && memcmp (ar_hdr->ar_name, "/ ", 16) == 0)
903 : : /* This is the index. */
904 : 120 : elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
905 [ + + ]: 1957 : else if (ar_hdr->ar_name[1] == 'S'
906 [ + - ]: 1 : && memcmp (ar_hdr->ar_name, "/SYM64/ ", 16) == 0)
907 : : /* 64-bit index. */
908 : 1 : elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
909 [ + + ]: 1956 : else if (ar_hdr->ar_name[1] == '/'
910 [ + - ]: 116 : && memcmp (ar_hdr->ar_name, "// ", 16) == 0)
911 : : /* This is the array with the long names. */
912 : 116 : elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
913 [ + - ]: 1840 : else if (likely (isdigit (ar_hdr->ar_name[1])))
914 : : {
915 : 1840 : size_t offset;
916 : :
917 : : /* This is a long name. First we have to read the long name
918 : : table, if this hasn't happened already. */
919 [ + + - + ]: 1840 : if (unlikely (elf->state.ar.long_names == NULL
920 : : && read_long_names (elf) == NULL))
921 : : {
922 : : /* No long name table although it is reference. The archive is
923 : : broken. */
924 : 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
925 : 0 : return -1;
926 : : }
927 : :
928 : 1840 : offset = atol (ar_hdr->ar_name + 1);
929 [ - + ]: 1840 : if (unlikely (offset >= elf->state.ar.long_names_len))
930 : : {
931 : : /* The index in the long name table is larger than the table. */
932 : 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
933 : 0 : return -1;
934 : : }
935 : 1840 : elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
936 : : }
937 : : else
938 : : {
939 : : /* This is none of the known special entries. */
940 : 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
941 : 0 : return -1;
942 : : }
943 : : }
944 : : else
945 : : {
946 : 5153 : char *endp;
947 : :
948 : : /* It is a normal entry. Copy over the name. */
949 : 5153 : endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
950 : : '/', 16);
951 [ + - ]: 5153 : if (endp != NULL)
952 : 5153 : endp[-1] = '\0';
953 : : else
954 : : {
955 : : /* In the old BSD style of archive, there is no / terminator.
956 : : Instead, there is space padding at the end of the name. */
957 : : size_t i = 15;
958 : 0 : do
959 : 0 : elf->state.ar.ar_name[i] = '\0';
960 [ # # # # ]: 0 : while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
961 : : }
962 : :
963 : 5153 : elf_ar_hdr->ar_name = elf->state.ar.ar_name;
964 : : }
965 : :
966 [ - + ]: 7230 : if (unlikely (ar_hdr->ar_size[0] == ' '))
967 : : /* Something is really wrong. We cannot live without a size for
968 : : the member since it will not be possible to find the next
969 : : archive member. */
970 : : {
971 : 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
972 : 0 : return -1;
973 : : }
974 : :
975 : : /* Since there are no specialized functions to convert ASCII to
976 : : time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
977 : : atoll depending on the size of the types. We are also prepared
978 : : for the case where the whole field in the `struct ar_hdr' is
979 : : filled in which case we cannot simply use atol/l but instead have
980 : : to create a temporary copy. */
981 : :
982 : : #define INT_FIELD(FIELD) \
983 : : do \
984 : : { \
985 : : char buf[sizeof (ar_hdr->FIELD) + 1]; \
986 : : const char *string = ar_hdr->FIELD; \
987 : : if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ') \
988 : : { \
989 : : *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD))) \
990 : : = '\0'; \
991 : : string = buf; \
992 : : } \
993 : : if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int)) \
994 : : elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string); \
995 : : else \
996 : : elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string); \
997 : : } \
998 : : while (0)
999 : :
1000 [ - + ]: 7230 : INT_FIELD (ar_date);
1001 [ - + ]: 7230 : INT_FIELD (ar_uid);
1002 [ - + ]: 7230 : INT_FIELD (ar_gid);
1003 [ - + ]: 7230 : INT_FIELD (ar_mode);
1004 [ - + ]: 7230 : INT_FIELD (ar_size);
1005 : :
1006 [ - + ]: 7230 : if (elf_ar_hdr->ar_size < 0)
1007 : : {
1008 : 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
1009 : 0 : return -1;
1010 : : }
1011 : :
1012 : : /* Truncated file? */
1013 : 7230 : size_t maxsize;
1014 : 7230 : maxsize = (elf->start_offset + elf->maximum_size
1015 : 7230 : - elf->state.ar.offset - sizeof (struct ar_hdr));
1016 [ - + ]: 7230 : if ((size_t) elf_ar_hdr->ar_size > maxsize)
1017 : 0 : elf_ar_hdr->ar_size = maxsize;
1018 : :
1019 : : return 0;
1020 : : }
1021 : :
1022 : :
1023 : : /* We were asked to return a clone of an existing descriptor. This
1024 : : function must be called with the lock on the parent descriptor
1025 : : being held. */
1026 : : static Elf *
1027 : 7231 : dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1028 : : {
1029 : 7231 : struct Elf *result;
1030 : :
1031 [ + + ]: 7231 : if (fildes == -1)
1032 : : /* Allow the user to pass -1 as the file descriptor for the new file. */
1033 : 6 : fildes = ref->fildes;
1034 : : /* The file descriptor better should be the same. If it was disconnected
1035 : : already (using `elf_cntl') we do not test it. */
1036 [ + - - + ]: 7225 : else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
1037 : : {
1038 : 0 : __libelf_seterrno (ELF_E_FD_MISMATCH);
1039 : 0 : return NULL;
1040 : : }
1041 : :
1042 : : /* The mode must allow reading. I.e., a descriptor creating with a
1043 : : command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
1044 : : not allowed. */
1045 [ - + - - : 7231 : if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
- - - - -
- - - ]
1046 : : && ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
1047 : : && ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1048 : : && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1049 : : {
1050 : 0 : __libelf_seterrno (ELF_E_INVALID_OP);
1051 : 0 : return NULL;
1052 : : }
1053 : :
1054 : : /* Now it is time to distinguish between reading normal files and
1055 : : archives. Normal files can easily be handled be incrementing the
1056 : : reference counter and return the same descriptor. */
1057 [ - + ]: 7231 : if (ref->kind != ELF_K_AR)
1058 : : {
1059 : 0 : ++ref->ref_count;
1060 : 0 : return ref;
1061 : : }
1062 : :
1063 : : /* This is an archive. We must create a descriptor for the archive
1064 : : member the internal pointer of the archive file descriptor is
1065 : : pointing to. First read the header of the next member if this
1066 : : has not happened already. */
1067 [ + + ]: 7231 : if (ref->state.ar.elf_ar_hdr.ar_name == NULL
1068 [ + + ]: 124 : && __libelf_next_arhdr_wrlock (ref) != 0)
1069 : : /* Something went wrong. Maybe there is no member left. */
1070 : : return NULL;
1071 : :
1072 : : /* We have all the information we need about the next archive member.
1073 : : Now create a descriptor for it. */
1074 : 14460 : result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
1075 : 7230 : ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
1076 : :
1077 : : /* Enlist this new descriptor in the list of children. */
1078 [ + - ]: 7230 : if (result != NULL)
1079 : : {
1080 : 7230 : result->next = ref->state.ar.children;
1081 : 7230 : ref->state.ar.children = result;
1082 : : }
1083 : :
1084 : : return result;
1085 : : }
1086 : :
1087 : :
1088 : : /* Return descriptor for empty file ready for writing. */
1089 : : static struct Elf *
1090 : 445 : write_file (int fd, Elf_Cmd cmd)
1091 : : {
1092 : : /* We simply create an empty `Elf' structure. */
1093 : : #define NSCNSALLOC 10
1094 : 445 : Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
1095 : : NSCNSALLOC * sizeof (Elf_Scn));
1096 : :
1097 [ + - ]: 445 : if (result != NULL)
1098 : : {
1099 : : /* We have to write to the file in any case. */
1100 : 445 : result->flags = ELF_F_DIRTY;
1101 : :
1102 : : /* Some more or less arbitrary value. */
1103 : 445 : result->state.elf.scnincr = NSCNSALLOC;
1104 : :
1105 : : /* We have allocated room for some sections. */
1106 : 445 : assert (offsetof (struct Elf, state.elf32.scns)
1107 : : == offsetof (struct Elf, state.elf64.scns));
1108 : 445 : result->state.elf.scns_last = &result->state.elf32.scns;
1109 : 445 : result->state.elf32.scns.max = NSCNSALLOC;
1110 : : }
1111 : :
1112 : 445 : return result;
1113 : : }
1114 : :
1115 : : /* Lock if necessary before dup an archive. */
1116 : : static inline Elf *
1117 : 7231 : lock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1118 : : {
1119 : : /* We need wrlock to dup an archive. */
1120 : 7231 : if (ref->kind == ELF_K_AR)
1121 : : {
1122 : 7231 : rwlock_unlock (ref->lock);
1123 : 7231 : rwlock_wrlock (ref->lock);
1124 : : }
1125 : : /* Duplicate the descriptor. */
1126 : 7231 : return dup_elf (fildes, cmd, ref);
1127 : : }
1128 : :
1129 : : /* Return a descriptor for the file belonging to FILDES. */
1130 : : Elf *
1131 : 16141 : elf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
1132 : : {
1133 : 16141 : Elf *retval;
1134 : :
1135 [ - + ]: 16141 : if (unlikely (__libelf_version != EV_CURRENT))
1136 : : {
1137 : : /* Version wasn't set so far. */
1138 : 0 : __libelf_seterrno (ELF_E_NO_VERSION);
1139 : 0 : return NULL;
1140 : : }
1141 : :
1142 [ + + ]: 16141 : if (ref != NULL)
1143 : : /* Make sure the descriptor is not suddenly going away. */
1144 : : rwlock_rdlock (ref->lock);
1145 [ - + - - ]: 8903 : else if (unlikely (fcntl (fildes, F_GETFD) == -1 && errno == EBADF))
1146 : : {
1147 : : /* We cannot do anything productive without a file descriptor. */
1148 : 0 : __libelf_seterrno (ELF_E_INVALID_FILE);
1149 : 0 : return NULL;
1150 : : }
1151 : :
1152 [ + + + + : 16140 : switch (cmd)
- + ]
1153 : : {
1154 : : case ELF_C_NULL:
1155 : : /* We simply return a NULL pointer. */
1156 : : retval = NULL;
1157 : : break;
1158 : :
1159 : 6271 : case ELF_C_READ_MMAP_PRIVATE:
1160 : : /* If we have a reference it must also be opened this way. */
1161 [ - + - - ]: 6271 : if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1162 : : {
1163 : 0 : __libelf_seterrno (ELF_E_INVALID_CMD);
1164 : 0 : retval = NULL;
1165 : 0 : break;
1166 : : }
1167 : 15567 : FALLTHROUGH;
1168 : :
1169 : : case ELF_C_READ:
1170 : : case ELF_C_READ_MMAP:
1171 [ + + ]: 15567 : if (ref != NULL)
1172 : 7231 : retval = lock_dup_elf (fildes, cmd, ref);
1173 : : else
1174 : : /* Create descriptor for existing file. */
1175 : 8336 : retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1176 : : break;
1177 : :
1178 : 121 : case ELF_C_RDWR:
1179 : : case ELF_C_RDWR_MMAP:
1180 : : /* If we have a REF object it must also be opened using this
1181 : : command. */
1182 [ - + ]: 121 : if (ref != NULL)
1183 : : {
1184 [ # # # # : 0 : if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
# # ]
1185 : : && ref->cmd != ELF_C_WRITE
1186 : : && ref->cmd != ELF_C_WRITE_MMAP))
1187 : : {
1188 : : /* This is not ok. REF must also be opened for writing. */
1189 : 0 : __libelf_seterrno (ELF_E_INVALID_CMD);
1190 : 0 : retval = NULL;
1191 : : }
1192 : : else
1193 : 0 : retval = lock_dup_elf (fildes, cmd, ref);
1194 : : }
1195 : : else
1196 : : /* Create descriptor for existing file. */
1197 : 121 : retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1198 : : break;
1199 : :
1200 : 445 : case ELF_C_WRITE:
1201 : : case ELF_C_WRITE_MMAP:
1202 : : /* We ignore REF and prepare a descriptor to write a new file. */
1203 : 445 : retval = write_file (fildes, cmd);
1204 : 445 : break;
1205 : :
1206 : 0 : default:
1207 : 0 : __libelf_seterrno (ELF_E_INVALID_CMD);
1208 : 0 : retval = NULL;
1209 : 0 : break;
1210 : : }
1211 : :
1212 : : /* Release the lock. */
1213 : : if (ref != NULL)
1214 : : rwlock_unlock (ref->lock);
1215 : :
1216 : : return retval;
1217 : : }
1218 : : INTDEF(elf_begin)
|