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