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 13656 : 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 13656 : bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
90 :
91 : /* Make the ELF header available. */
92 13656 : 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 345 : ehdr.p = &ehdr_mem;
104 :
105 345 : if (is32)
106 : {
107 : if (ALLOW_UNALIGNED)
108 : {
109 169 : ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
110 169 : 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 169 : CONVERT (ehdr_mem.e32.e_shnum);
118 338 : CONVERT (ehdr_mem.e32.e_shoff);
119 : }
120 : }
121 : else
122 : {
123 : if (ALLOW_UNALIGNED)
124 : {
125 176 : ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
126 176 : 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 176 : CONVERT (ehdr_mem.e64.e_shnum);
134 352 : CONVERT (ehdr_mem.e64.e_shoff);
135 : }
136 : }
137 : }
138 :
139 13656 : if (is32)
140 : {
141 : /* Get the number of sections from the ELF header. */
142 481 : result = ehdr.e32->e_shnum;
143 :
144 481 : if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
145 : {
146 3 : if (unlikely (ehdr.e32->e_shoff >= maxsize)
147 3 : || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
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 + ehdr.e32->e_shoff))
154 : & (__alignof__ (Elf32_Shdr) - 1)) == 0))
155 : /* We can directly access the memory. */
156 6 : result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
157 6 : + offset))->sh_size;
158 : else
159 : {
160 : Elf32_Word size;
161 : ssize_t r;
162 :
163 0 : if (likely (map_address != NULL))
164 : /* gcc will optimize the memcpy to a simple memory
165 : access while taking care of alignment issues. */
166 0 : memcpy (&size, &((Elf32_Shdr *) ((char *) map_address
167 : + ehdr.e32->e_shoff
168 0 : + offset))->sh_size,
169 : sizeof (Elf32_Word));
170 : else
171 0 : 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 0 : if (e_ident[EI_DATA] != MY_ELFDATA)
186 0 : CONVERT (size);
187 :
188 0 : result = size;
189 : }
190 : }
191 :
192 : /* If the section headers were truncated, pretend none were there. */
193 481 : if (ehdr.e32->e_shoff > maxsize
194 481 : || 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 13175 : result = ehdr.e64->e_shnum;
201 :
202 13175 : if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
203 : {
204 0 : if (unlikely (ehdr.e64->e_shoff >= maxsize)
205 0 : || 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 0 : if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
211 0 : && (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 0 : size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
216 0 : + offset))->sh_size;
217 : else
218 : {
219 : ssize_t r;
220 0 : if (likely (map_address != NULL))
221 : /* gcc will optimize the memcpy to a simple memory
222 : access while taking care of alignment issues. */
223 0 : memcpy (&size, &((Elf64_Shdr *) ((char *) map_address
224 : + ehdr.e64->e_shoff
225 0 : + offset))->sh_size,
226 : sizeof (Elf64_Xword));
227 : else
228 0 : 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 0 : if (e_ident[EI_DATA] != MY_ELFDATA)
243 0 : CONVERT (size);
244 : }
245 :
246 0 : 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 0 : result = size;
254 : }
255 :
256 : /* If the section headers were truncated, pretend none were there. */
257 13175 : if (ehdr.e64->e_shoff > maxsize
258 13172 : || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
259 3 : result = 0;
260 : }
261 :
262 : return result;
263 : }
264 :
265 :
266 : /* Create descriptor for ELF file in memory. */
267 : static Elf *
268 13656 : 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 13656 : 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 13656 : size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
287 13656 : if (scncnt == (size_t) -1l)
288 : /* Could not determine the number of sections. */
289 : return NULL;
290 :
291 : /* Check for too many sections. */
292 13656 : if (e_ident[EI_CLASS] == ELFCLASS32)
293 : {
294 481 : 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 13175 : 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 13723 : const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
309 67 : ? 1 : 0);
310 13656 : Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
311 : ELF_K_ELF, scnmax * sizeof (Elf_Scn));
312 13656 : if (elf == NULL)
313 : /* Not enough memory. allocate_elf will have set libelf errno. */
314 : return NULL;
315 :
316 13656 : assert ((unsigned int) scncnt == scncnt);
317 : assert (offsetof (struct Elf, state.elf32.scns)
318 : == offsetof (struct Elf, state.elf64.scns));
319 13656 : elf->state.elf32.scns.cnt = scncnt;
320 13656 : elf->state.elf32.scns.max = scnmax;
321 :
322 : /* Some more or less arbitrary value. */
323 13656 : elf->state.elf.scnincr = 10;
324 :
325 : /* Make the class easily available. */
326 13656 : elf->class = e_ident[EI_CLASS];
327 :
328 13656 : 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 481 : Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset);
333 :
334 : /* This is a 32-bit binary. */
335 481 : if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
336 317 : && (ALLOW_UNALIGNED
337 : || (((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
338 : {
339 : /* We can use the mmapped memory. */
340 211 : elf->state.elf32.ehdr = ehdr;
341 : }
342 : else
343 : {
344 : /* Copy the ELF header. */
345 540 : elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
346 : sizeof (Elf32_Ehdr));
347 :
348 270 : if (e_ident[EI_DATA] != MY_ELFDATA)
349 : {
350 169 : CONVERT (elf->state.elf32.ehdr_mem.e_type);
351 169 : CONVERT (elf->state.elf32.ehdr_mem.e_machine);
352 338 : CONVERT (elf->state.elf32.ehdr_mem.e_version);
353 338 : CONVERT (elf->state.elf32.ehdr_mem.e_entry);
354 338 : CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
355 338 : CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
356 338 : CONVERT (elf->state.elf32.ehdr_mem.e_flags);
357 169 : CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
358 169 : CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
359 169 : CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
360 169 : CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
361 169 : CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
362 169 : 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 481 : Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
370 481 : 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 211 : && (ALLOW_UNALIGNED
373 : || (((uintptr_t) ((char *) ehdr + e_shoff)
374 : & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
375 : {
376 115 : if (unlikely (scncnt > 0 && e_shoff >= maxsize)
377 115 : || 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 115 : = (Elf32_Shdr *) ((char *) ehdr + e_shoff);
387 :
388 3187 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
389 : {
390 3072 : elf->state.elf32.scns.data[cnt].index = cnt;
391 3072 : elf->state.elf32.scns.data[cnt].elf = elf;
392 3072 : elf->state.elf32.scns.data[cnt].shdr.e32 =
393 3072 : &elf->state.elf32.shdr[cnt];
394 3072 : if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
395 3070 : && likely (elf->state.elf32.shdr[cnt].sh_size
396 : <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
397 3062 : elf->state.elf32.scns.data[cnt].rawdata_base =
398 3062 : elf->state.elf32.scns.data[cnt].data_base =
399 : ((char *) map_address + offset
400 3062 : + elf->state.elf32.shdr[cnt].sh_offset);
401 3072 : 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 3072 : 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 3072 : if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
414 3072 : elf->state.elf32.scns.data[cnt].shndx_index = -1;
415 : }
416 : }
417 : else
418 : {
419 205892 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
420 : {
421 205892 : elf->state.elf32.scns.data[cnt].index = cnt;
422 205892 : elf->state.elf32.scns.data[cnt].elf = elf;
423 205892 : elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
424 : }
425 : }
426 :
427 : /* So far only one block with sections. */
428 481 : 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 13175 : Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
435 :
436 : /* This is a 64-bit binary. */
437 13175 : if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
438 6044 : && (ALLOW_UNALIGNED
439 : || (((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
440 : {
441 : /* We can use the mmapped memory. */
442 5924 : elf->state.elf64.ehdr = ehdr;
443 : }
444 : else
445 : {
446 : /* Copy the ELF header. */
447 14502 : elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
448 : sizeof (Elf64_Ehdr));
449 :
450 7251 : if (e_ident[EI_DATA] != MY_ELFDATA)
451 : {
452 176 : CONVERT (elf->state.elf64.ehdr_mem.e_type);
453 176 : CONVERT (elf->state.elf64.ehdr_mem.e_machine);
454 352 : CONVERT (elf->state.elf64.ehdr_mem.e_version);
455 352 : CONVERT (elf->state.elf64.ehdr_mem.e_entry);
456 352 : CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
457 352 : CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
458 352 : CONVERT (elf->state.elf64.ehdr_mem.e_flags);
459 176 : CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
460 176 : CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
461 176 : CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
462 176 : CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
463 176 : CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
464 176 : 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 13175 : Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
472 13175 : 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 5924 : && (ALLOW_UNALIGNED
475 : || (((uintptr_t) ((char *) ehdr + e_shoff)
476 : & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
477 : {
478 5419 : if (unlikely (scncnt > 0 && e_shoff >= maxsize)
479 5419 : || unlikely (maxsize - e_shoff
480 : < scncnt * sizeof (Elf64_Shdr)))
481 : goto free_and_out;
482 : elf->state.elf64.shdr
483 5419 : = (Elf64_Shdr *) ((char *) ehdr + e_shoff);
484 :
485 213191 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
486 : {
487 207772 : elf->state.elf64.scns.data[cnt].index = cnt;
488 207772 : elf->state.elf64.scns.data[cnt].elf = elf;
489 207772 : elf->state.elf64.scns.data[cnt].shdr.e64 =
490 207772 : &elf->state.elf64.shdr[cnt];
491 207772 : if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
492 207770 : && likely (elf->state.elf64.shdr[cnt].sh_size
493 : <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
494 207756 : elf->state.elf64.scns.data[cnt].rawdata_base =
495 207756 : elf->state.elf64.scns.data[cnt].data_base =
496 : ((char *) map_address + offset
497 207756 : + elf->state.elf64.shdr[cnt].sh_offset);
498 207772 : 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 207772 : 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 207772 : if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
511 207772 : elf->state.elf64.scns.data[cnt].shndx_index = -1;
512 : }
513 : }
514 : else
515 : {
516 265250 : for (size_t cnt = 0; cnt < scncnt; ++cnt)
517 : {
518 265250 : elf->state.elf64.scns.data[cnt].index = cnt;
519 265250 : elf->state.elf64.scns.data[cnt].elf = elf;
520 265250 : elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
521 : }
522 : }
523 :
524 : /* So far only one block with sections. */
525 13175 : elf->state.elf64.scns_last = &elf->state.elf64.scns;
526 : }
527 :
528 : return elf;
529 : }
530 :
531 :
532 : Elf *
533 : internal_function
534 6384 : __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 6384 : unsigned char *e_ident = (unsigned char *) map_address + offset;
542 :
543 : /* See what kind of object we have here. */
544 6384 : Elf_Kind kind = determine_kind (e_ident, maxsize);
545 :
546 6384 : switch (kind)
547 : {
548 6361 : case ELF_K_ELF:
549 6361 : 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 13 : return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
562 : ELF_K_NONE, 0);
563 : }
564 :
565 :
566 : static Elf *
567 7644 : 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 7644 : ssize_t nread = pread_retry (fildes, mem.header,
589 7644 : MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
590 : maxsize),
591 : offset);
592 7644 : 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 7644 : Elf_Kind kind = determine_kind (mem.header, nread);
602 :
603 7644 : switch (kind)
604 : {
605 117 : case ELF_K_AR:
606 : return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
607 :
608 7295 : case ELF_K_ELF:
609 : /* Make sure at least the ELF header is contained in the file. */
610 14590 : if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
611 7295 : ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
612 7295 : 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 13972 : read_file (int fildes, off_t offset, size_t maxsize,
630 : Elf_Cmd cmd, Elf *parent)
631 : {
632 13972 : void *map_address = NULL;
633 13972 : int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
634 : || cmd == ELF_C_WRITE_MMAP
635 13972 : || cmd == ELF_C_READ_MMAP_PRIVATE);
636 :
637 13972 : if (parent == NULL)
638 : {
639 6741 : 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 6741 : if (fstat (fildes, &st) == 0
646 : && (sizeof (size_t) >= sizeof (st.st_size)
647 : || st.st_size <= ~((size_t) 0)))
648 6741 : maxsize = (size_t) st.st_size;
649 : }
650 : }
651 : else
652 : {
653 : /* The parent is already loaded. Use it. */
654 7231 : assert (maxsize != ~((size_t) 0));
655 : }
656 :
657 13972 : if (use_mmap)
658 : {
659 6334 : if (parent == NULL)
660 : {
661 : /* We try to map the file ourself. */
662 6273 : map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
663 : ? PROT_READ
664 : : PROT_READ|PROT_WRITE),
665 6273 : cmd == ELF_C_READ_MMAP_PRIVATE
666 6273 : || cmd == ELF_C_READ_MMAP
667 : ? MAP_PRIVATE : MAP_SHARED,
668 : fildes, offset);
669 :
670 6273 : 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 6328 : if (map_address != NULL)
681 : {
682 6328 : assert (map_address != MAP_FAILED);
683 :
684 6328 : 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 6328 : if (result == NULL
691 0 : && (parent == NULL
692 0 : || parent->map_address != map_address))
693 0 : munmap (map_address, maxsize);
694 6328 : else if (parent == NULL)
695 : /* Remember that we mmap()ed the memory. */
696 6267 : 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 7644 : 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 : {
719 306 : 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 : 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 408 : len = atol (hdr->ar_size);
740 :
741 204 : if (memcmp (hdr->ar_name, "// ", 16) == 0)
742 : break;
743 :
744 102 : offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
745 : }
746 :
747 : /* Due to the stupid format of the long name table entry (which are not
748 : NUL terminted) we have to provide an appropriate representation anyhow.
749 : Therefore we always make a copy which has the appropriate form. */
750 102 : newp = (char *) malloc (len);
751 102 : if (newp != NULL)
752 : {
753 : char *runp;
754 :
755 102 : if (elf->map_address != NULL)
756 : {
757 0 : if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
758 : goto too_much;
759 : /* Simply copy it over. */
760 0 : elf->state.ar.long_names = (char *) memcpy (newp,
761 : elf->map_address + offset
762 0 : + sizeof (struct ar_hdr),
763 : len);
764 : }
765 : else
766 : {
767 102 : if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
768 : elf->start_offset + offset
769 : + sizeof (struct ar_hdr))
770 : != len))
771 : {
772 0 : too_much:
773 : /* We were not able to read all data. */
774 0 : free (newp);
775 0 : elf->state.ar.long_names = NULL;
776 0 : return NULL;
777 : }
778 102 : elf->state.ar.long_names = newp;
779 : }
780 :
781 102 : elf->state.ar.long_names_len = len;
782 :
783 : /* Now NUL-terminate the strings. */
784 102 : runp = newp;
785 : while (1)
786 : {
787 4182 : char *startp = runp;
788 4182 : runp = (char *) memchr (runp, '/', newp + len - runp);
789 4182 : if (runp == NULL)
790 : {
791 : /* This was the last entry. Clear any left overs. */
792 102 : memset (startp, '\0', newp + len - startp);
793 : break;
794 : }
795 :
796 : /* NUL-terminate the string. */
797 4080 : *runp++ = '\0';
798 :
799 : /* A sanity check. Somebody might have generated invalid
800 : archive. */
801 4080 : if (runp >= newp + len)
802 : break;
803 : }
804 : }
805 :
806 : return newp;
807 : }
808 :
809 :
810 : /* Read the next archive header. */
811 : int
812 : internal_function
813 7239 : __libelf_next_arhdr_wrlock (Elf *elf)
814 : {
815 : struct ar_hdr *ar_hdr;
816 : Elf_Arhdr *elf_ar_hdr;
817 :
818 7239 : if (elf->map_address != NULL)
819 : {
820 : /* See whether this entry is in the file. */
821 69 : if (unlikely ((size_t) elf->state.ar.offset
822 : > elf->start_offset + elf->maximum_size
823 : || (elf->start_offset + elf->maximum_size
824 : - elf->state.ar.offset) < sizeof (struct ar_hdr)))
825 : {
826 : /* This record is not anymore in the file. */
827 8 : __libelf_seterrno (ELF_E_RANGE);
828 8 : return -1;
829 : }
830 61 : ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
831 : }
832 : else
833 : {
834 7170 : ar_hdr = &elf->state.ar.ar_hdr;
835 :
836 7170 : if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
837 : elf->state.ar.offset)
838 : != sizeof (struct ar_hdr)))
839 : {
840 : /* Something went wrong while reading the file. */
841 0 : __libelf_seterrno (ELF_E_RANGE);
842 0 : return -1;
843 : }
844 : }
845 :
846 : /* One little consistency check. */
847 7231 : if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
848 : {
849 : /* This is no valid archive. */
850 0 : __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
851 0 : return -1;
852 : }
853 :
854 : /* Copy the raw name over to a NUL terminated buffer. */
855 14462 : *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
856 :
857 7231 : elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
858 :
859 : /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
860 : Determine whether this is a special entry. */
861 7231 : if (ar_hdr->ar_name[0] == '/')
862 : {
863 2077 : if (ar_hdr->ar_name[1] == ' '
864 120 : && memcmp (ar_hdr->ar_name, "/ ", 16) == 0)
865 : /* This is the index. */
866 240 : elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
867 1957 : else if (ar_hdr->ar_name[1] == 'S'
868 1 : && memcmp (ar_hdr->ar_name, "/SYM64/ ", 16) == 0)
869 : /* 64-bit index. */
870 2 : elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
871 1956 : else if (ar_hdr->ar_name[1] == '/'
872 116 : && memcmp (ar_hdr->ar_name, "// ", 16) == 0)
873 : /* This is the array with the long names. */
874 232 : elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
875 1840 : else if (likely (isdigit (ar_hdr->ar_name[1])))
876 : {
877 : size_t offset;
878 :
879 : /* This is a long name. First we have to read the long name
880 : table, if this hasn't happened already. */
881 1840 : if (unlikely (elf->state.ar.long_names == NULL
882 : && read_long_names (elf) == NULL))
883 : {
884 : /* No long name table although it is reference. The archive is
885 : broken. */
886 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
887 0 : return -1;
888 : }
889 :
890 3680 : offset = atol (ar_hdr->ar_name + 1);
891 1840 : if (unlikely (offset >= elf->state.ar.long_names_len))
892 : {
893 : /* The index in the long name table is larger than the table. */
894 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
895 0 : return -1;
896 : }
897 1840 : elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
898 : }
899 : else
900 : {
901 : /* This is none of the known special entries. */
902 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
903 0 : return -1;
904 : }
905 : }
906 : else
907 : {
908 : char *endp;
909 :
910 : /* It is a normal entry. Copy over the name. */
911 5154 : endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
912 : '/', 16);
913 5154 : if (endp != NULL)
914 5154 : endp[-1] = '\0';
915 : else
916 : {
917 : /* In the old BSD style of archive, there is no / terminator.
918 : Instead, there is space padding at the end of the name. */
919 : size_t i = 15;
920 : do
921 0 : elf->state.ar.ar_name[i] = '\0';
922 0 : while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
923 : }
924 :
925 5154 : elf_ar_hdr->ar_name = elf->state.ar.ar_name;
926 : }
927 :
928 7231 : if (unlikely (ar_hdr->ar_size[0] == ' '))
929 : /* Something is really wrong. We cannot live without a size for
930 : the member since it will not be possible to find the next
931 : archive member. */
932 : {
933 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
934 0 : return -1;
935 : }
936 :
937 : /* Since there are no specialized functions to convert ASCII to
938 : time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
939 : atoll depending on the size of the types. We are also prepared
940 : for the case where the whole field in the `struct ar_hdr' is
941 : filled in which case we cannot simply use atol/l but instead have
942 : to create a temporary copy. */
943 :
944 : #define INT_FIELD(FIELD) \
945 : do \
946 : { \
947 : char buf[sizeof (ar_hdr->FIELD) + 1]; \
948 : const char *string = ar_hdr->FIELD; \
949 : if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ') \
950 : { \
951 : *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD))) \
952 : = '\0'; \
953 : string = buf; \
954 : } \
955 : if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int)) \
956 : elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string); \
957 : else \
958 : elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string); \
959 : } \
960 : while (0)
961 :
962 14462 : INT_FIELD (ar_date);
963 14462 : INT_FIELD (ar_uid);
964 14462 : INT_FIELD (ar_gid);
965 14462 : INT_FIELD (ar_mode);
966 14462 : INT_FIELD (ar_size);
967 :
968 7231 : if (elf_ar_hdr->ar_size < 0)
969 : {
970 0 : __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
971 0 : return -1;
972 : }
973 :
974 : /* Truncated file? */
975 : size_t maxsize;
976 14462 : maxsize = (elf->start_offset + elf->maximum_size
977 7231 : - elf->state.ar.offset - sizeof (struct ar_hdr));
978 7231 : if ((size_t) elf_ar_hdr->ar_size > maxsize)
979 0 : elf_ar_hdr->ar_size = maxsize;
980 :
981 : return 0;
982 : }
983 :
984 :
985 : /* We were asked to return a clone of an existing descriptor. This
986 : function must be called with the lock on the parent descriptor
987 : being held. */
988 : static Elf *
989 7232 : dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
990 : {
991 : struct Elf *result;
992 :
993 7232 : if (fildes == -1)
994 : /* Allow the user to pass -1 as the file descriptor for the new file. */
995 6 : fildes = ref->fildes;
996 : /* The file descriptor better should be the same. If it was disconnected
997 : already (using `elf_cntl') we do not test it. */
998 7226 : else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
999 : {
1000 0 : __libelf_seterrno (ELF_E_FD_MISMATCH);
1001 0 : return NULL;
1002 : }
1003 :
1004 : /* The mode must allow reading. I.e., a descriptor creating with a
1005 : command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
1006 : not allowed. */
1007 7232 : if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
1008 : && ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
1009 : && ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1010 : && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1011 : {
1012 0 : __libelf_seterrno (ELF_E_INVALID_OP);
1013 0 : return NULL;
1014 : }
1015 :
1016 : /* Now it is time to distinguish between reading normal files and
1017 : archives. Normal files can easily be handled be incrementing the
1018 : reference counter and return the same descriptor. */
1019 7232 : if (ref->kind != ELF_K_AR)
1020 : {
1021 0 : ++ref->ref_count;
1022 0 : return ref;
1023 : }
1024 :
1025 : /* This is an archive. We must create a descriptor for the archive
1026 : member the internal pointer of the archive file desriptor is
1027 : pointing to. First read the header of the next member if this
1028 : has not happened already. */
1029 7232 : if (ref->state.ar.elf_ar_hdr.ar_name == NULL
1030 124 : && __libelf_next_arhdr_wrlock (ref) != 0)
1031 : /* Something went wrong. Maybe there is no member left. */
1032 : return NULL;
1033 :
1034 : /* We have all the information we need about the next archive member.
1035 : Now create a descriptor for it. */
1036 7231 : result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
1037 7231 : ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
1038 :
1039 : /* Enlist this new descriptor in the list of children. */
1040 7231 : if (result != NULL)
1041 : {
1042 7231 : result->next = ref->state.ar.children;
1043 7231 : ref->state.ar.children = result;
1044 : }
1045 :
1046 : return result;
1047 : }
1048 :
1049 :
1050 : /* Return desriptor for empty file ready for writing. */
1051 : static struct Elf *
1052 322 : write_file (int fd, Elf_Cmd cmd)
1053 : {
1054 : /* We simply create an empty `Elf' structure. */
1055 : #define NSCNSALLOC 10
1056 322 : Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
1057 : NSCNSALLOC * sizeof (Elf_Scn));
1058 :
1059 322 : if (result != NULL)
1060 : {
1061 : /* We have to write to the file in any case. */
1062 322 : result->flags = ELF_F_DIRTY;
1063 :
1064 : /* Some more or less arbitrary value. */
1065 322 : result->state.elf.scnincr = NSCNSALLOC;
1066 :
1067 : /* We have allocated room for some sections. */
1068 : assert (offsetof (struct Elf, state.elf32.scns)
1069 : == offsetof (struct Elf, state.elf64.scns));
1070 322 : result->state.elf.scns_last = &result->state.elf32.scns;
1071 322 : result->state.elf32.scns.max = NSCNSALLOC;
1072 : }
1073 :
1074 322 : return result;
1075 : }
1076 :
1077 : /* Lock if necessary before dup an archive. */
1078 : static inline Elf *
1079 : lock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1080 : {
1081 : /* We need wrlock to dup an archive. */
1082 : if (ref->kind == ELF_K_AR)
1083 : {
1084 : rwlock_unlock (ref->lock);
1085 : rwlock_wrlock (ref->lock);
1086 : }
1087 : /* Duplicate the descriptor. */
1088 7232 : return dup_elf (fildes, cmd, ref);
1089 : }
1090 :
1091 : /* Return a descriptor for the file belonging to FILDES. */
1092 : Elf *
1093 14302 : elf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
1094 : {
1095 : Elf *retval;
1096 :
1097 14302 : if (unlikely (! __libelf_version_initialized))
1098 : {
1099 : /* Version wasn't set so far. */
1100 0 : __libelf_seterrno (ELF_E_NO_VERSION);
1101 0 : return NULL;
1102 : }
1103 :
1104 14302 : if (ref != NULL)
1105 : /* Make sure the descriptor is not suddenly going away. */
1106 : rwlock_rdlock (ref->lock);
1107 7063 : else if (unlikely (fcntl (fildes, F_GETFD) == -1 && errno == EBADF))
1108 : {
1109 : /* We cannot do anything productive without a file descriptor. */
1110 0 : __libelf_seterrno (ELF_E_INVALID_FILE);
1111 0 : return NULL;
1112 : }
1113 :
1114 14302 : switch (cmd)
1115 : {
1116 : case ELF_C_NULL:
1117 : /* We simply return a NULL pointer. */
1118 : retval = NULL;
1119 : break;
1120 :
1121 5564 : case ELF_C_READ_MMAP_PRIVATE:
1122 : /* If we have a reference it must also be opened this way. */
1123 5564 : if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1124 : {
1125 0 : __libelf_seterrno (ELF_E_INVALID_CMD);
1126 0 : retval = NULL;
1127 0 : break;
1128 : }
1129 : FALLTHROUGH;
1130 :
1131 : case ELF_C_READ:
1132 : case ELF_C_READ_MMAP:
1133 13929 : if (ref != NULL)
1134 7232 : retval = lock_dup_elf (fildes, cmd, ref);
1135 : else
1136 : /* Create descriptor for existing file. */
1137 6697 : retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1138 : break;
1139 :
1140 44 : case ELF_C_RDWR:
1141 : case ELF_C_RDWR_MMAP:
1142 : /* If we have a REF object it must also be opened using this
1143 : command. */
1144 44 : if (ref != NULL)
1145 : {
1146 0 : if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1147 : && ref->cmd != ELF_C_WRITE
1148 : && ref->cmd != ELF_C_WRITE_MMAP))
1149 : {
1150 : /* This is not ok. REF must also be opened for writing. */
1151 0 : __libelf_seterrno (ELF_E_INVALID_CMD);
1152 0 : retval = NULL;
1153 : }
1154 : else
1155 0 : retval = lock_dup_elf (fildes, cmd, ref);
1156 : }
1157 : else
1158 : /* Create descriptor for existing file. */
1159 44 : retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1160 : break;
1161 :
1162 322 : case ELF_C_WRITE:
1163 : case ELF_C_WRITE_MMAP:
1164 : /* We ignore REF and prepare a descriptor to write a new file. */
1165 322 : retval = write_file (fildes, cmd);
1166 322 : break;
1167 :
1168 0 : default:
1169 0 : __libelf_seterrno (ELF_E_INVALID_CMD);
1170 0 : retval = NULL;
1171 0 : break;
1172 : }
1173 :
1174 : /* Release the lock. */
1175 : if (ref != NULL)
1176 : rwlock_unlock (ref->lock);
1177 :
1178 : return retval;
1179 : }
1180 : INTDEF(elf_begin)
|