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