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