blob: b9d5cea4eb1f6a5e45de7a01270b8123d1a078ff [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Create descriptor for processing file.
Petr Machatae1873142012-08-01 21:37:52 +02002 Copyright (C) 1998-2010, 2012 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008
Mark Wielaardde2ed972012-06-05 17:15:16 +02009 * 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
Ulrich Drepper361df7d2006-04-04 21:38:57 +000022 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.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000025
Mark Wielaardde2ed972012-06-05 17:15:16 +020026 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/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000029
30#ifdef HAVE_CONFIG_H
31# include <config.h>
32#endif
33
34#include <assert.h>
35#include <ctype.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <stdbool.h>
39#include <stddef.h>
40#include <string.h>
41#include <unistd.h>
42#include <sys/mman.h>
43#include <sys/param.h>
44#include <sys/stat.h>
45
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000046#include <system.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000047#include "libelfP.h"
48#include "common.h"
49
50
51/* Create descriptor for archive in memory. */
52static inline Elf *
53file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
54 Elf_Cmd cmd, Elf *parent)
55{
56 Elf *elf;
57
58 /* Create a descriptor. */
59 elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
60 ELF_K_AR, 0);
61 if (elf != NULL)
62 {
63 /* We don't read all the symbol tables in advance. All this will
64 happen on demand. */
65 elf->state.ar.offset = offset + SARMAG;
66
67 elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
68 }
69
70 return elf;
71}
72
73
74static size_t
75get_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
76 size_t maxsize)
77{
78 size_t result;
79 union
80 {
81 Elf32_Ehdr *e32;
82 Elf64_Ehdr *e64;
83 void *p;
84 } ehdr;
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +000085 union
86 {
87 Elf32_Ehdr e32;
88 Elf64_Ehdr e64;
89 } ehdr_mem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000090 bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
91
92 /* Make the ELF header available. */
Roland McGrath9cf28e42008-09-30 06:35:35 +000093 if (e_ident[EI_DATA] == MY_ELFDATA
94 && (ALLOW_UNALIGNED
95 || (((size_t) e_ident
96 & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
97 - 1)) == 0)))
Ulrich Drepperfbe998a2005-08-29 16:27:10 +000098 ehdr.p = e_ident;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000099 else
100 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000101 /* We already read the ELF header. We have to copy the header
102 since we possibly modify the data here and the caller
103 expects the memory it passes in to be preserved. */
104 ehdr.p = &ehdr_mem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000105
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000106 if (is32)
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000107 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000108 if (ALLOW_UNALIGNED)
Ulrich Drepper969bda42005-08-28 08:30:08 +0000109 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000110 ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
111 ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
Ulrich Drepper969bda42005-08-28 08:30:08 +0000112 }
113 else
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000114 memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
115
Roland McGrath9cf28e42008-09-30 06:35:35 +0000116 if (e_ident[EI_DATA] != MY_ELFDATA)
117 {
118 CONVERT (ehdr_mem.e32.e_shnum);
119 CONVERT (ehdr_mem.e32.e_shoff);
120 }
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000121 }
122 else
123 {
124 if (ALLOW_UNALIGNED)
Roland McGrath4c305da2005-08-25 01:49:35 +0000125 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000126 ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
127 ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
Roland McGrath4c305da2005-08-25 01:49:35 +0000128 }
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000129 else
130 memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
131
Roland McGrath9cf28e42008-09-30 06:35:35 +0000132 if (e_ident[EI_DATA] != MY_ELFDATA)
133 {
134 CONVERT (ehdr_mem.e64.e_shnum);
135 CONVERT (ehdr_mem.e64.e_shoff);
136 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000137 }
138 }
139
140 if (is32)
141 {
142 /* Get the number of sections from the ELF header. */
143 result = ehdr.e32->e_shnum;
144
145 if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
146 {
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000147 if (ehdr.e32->e_shoff + sizeof (Elf32_Shdr) > maxsize)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000148 /* Cannot read the first section header. */
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000149 return 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000150
151 if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
152 && (ALLOW_UNALIGNED
153 || (((size_t) ((char *) map_address + offset))
154 & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
155 /* We can directly access the memory. */
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000156 result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000157 + offset))->sh_size;
158 else
159 {
160 Elf32_Word size;
161
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000162 if (likely (map_address != NULL))
163 /* gcc will optimize the memcpy to a simple memory
164 access while taking care of alignment issues. */
165 memcpy (&size, &((Elf32_Shdr *) ((char *) map_address
166 + ehdr.e32->e_shoff
167 + offset))->sh_size,
168 sizeof (Elf32_Word));
169 else
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000170 if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word),
171 offset + ehdr.e32->e_shoff
172 + offsetof (Elf32_Shdr, sh_size))
173 != sizeof (Elf32_Word)))
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000174 return (size_t) -1l;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000175
176 if (e_ident[EI_DATA] != MY_ELFDATA)
177 CONVERT (size);
178
179 result = size;
180 }
181 }
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000182
183 /* If the section headers were truncated, pretend none were there. */
184 if (ehdr.e32->e_shoff > maxsize
185 || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
186 result = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000187 }
188 else
189 {
190 /* Get the number of sections from the ELF header. */
191 result = ehdr.e64->e_shnum;
192
193 if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
194 {
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000195 if (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000196 /* Cannot read the first section header. */
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000197 return 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000198
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000199 Elf64_Xword size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000200 if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
201 && (ALLOW_UNALIGNED
202 || (((size_t) ((char *) map_address + offset))
203 & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
204 /* We can directly access the memory. */
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000205 size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
206 + offset))->sh_size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000207 else
208 {
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000209 if (likely (map_address != NULL))
210 /* gcc will optimize the memcpy to a simple memory
211 access while taking care of alignment issues. */
212 memcpy (&size, &((Elf64_Shdr *) ((char *) map_address
213 + ehdr.e64->e_shoff
214 + offset))->sh_size,
215 sizeof (Elf64_Xword));
216 else
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000217 if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Word),
218 offset + ehdr.e64->e_shoff
219 + offsetof (Elf64_Shdr, sh_size))
220 != sizeof (Elf64_Xword)))
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000221 return (size_t) -1l;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000222
223 if (e_ident[EI_DATA] != MY_ELFDATA)
224 CONVERT (size);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000225 }
Ulrich Drepper0f6abbb2005-08-13 22:35:15 +0000226
227 if (size > ~((GElf_Word) 0))
228 /* Invalid value, it is too large. */
229 return (size_t) -1l;
230
231 result = size;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000232 }
Ulrich Drepperc07fbb32007-03-30 19:14:59 +0000233
234 /* If the section headers were truncated, pretend none were there. */
235 if (ehdr.e64->e_shoff > maxsize
236 || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
237 result = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000238 }
239
240 return result;
241}
242
243
244/* Create descriptor for ELF file in memory. */
245static Elf *
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000246file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
247 off_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000248{
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000249 /* Verify the binary is of the class we can handle. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000250 if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
251 && e_ident[EI_CLASS] != ELFCLASS64)
252 /* We also can only handle two encodings. */
253 || (e_ident[EI_DATA] != ELFDATA2LSB
254 && e_ident[EI_DATA] != ELFDATA2MSB)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000255 {
256 /* Cannot handle this. */
257 __libelf_seterrno (ELF_E_INVALID_FILE);
258 return NULL;
259 }
260
261 /* Determine the number of sections. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000262 size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000263 if (scncnt == (size_t) -1l)
264 /* Could not determine the number of sections. */
265 return NULL;
266
Roland McGrath6fd3cd12010-01-07 19:41:04 -0800267 /* We can now allocate the memory. Even if there are no section headers,
268 we allocate space for a zeroth section in case we need it later. */
269 const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
270 ? 1 : 0);
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000271 Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
Roland McGrath6fd3cd12010-01-07 19:41:04 -0800272 ELF_K_ELF, scnmax * sizeof (Elf_Scn));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000273 if (elf == NULL)
274 /* Not enough memory. */
275 return NULL;
276
Roland McGrath6fd3cd12010-01-07 19:41:04 -0800277 assert ((unsigned int) scncnt == scncnt);
278 assert (offsetof (struct Elf, state.elf32.scns)
279 == offsetof (struct Elf, state.elf64.scns));
280 elf->state.elf32.scns.cnt = scncnt;
281 elf->state.elf32.scns.max = scnmax;
282
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000283 /* Some more or less arbitrary value. */
284 elf->state.elf.scnincr = 10;
285
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000286 /* Make the class easily available. */
287 elf->class = e_ident[EI_CLASS];
288
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000289 if (e_ident[EI_CLASS] == ELFCLASS32)
290 {
291 /* This pointer might not be directly usable if the alignment is
292 not sufficient for the architecture. */
293 Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset);
294
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000295 /* This is a 32-bit binary. */
296 if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
297 && (ALLOW_UNALIGNED
298 || ((((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0
299 && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
300 & (__alignof__ (Elf32_Shdr) - 1)) == 0
301 && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
302 & (__alignof__ (Elf32_Phdr) - 1)) == 0)))
303 {
304 /* We can use the mmapped memory. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000305 elf->state.elf32.ehdr = ehdr;
306 elf->state.elf32.shdr
307 = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff);
Roland McGrath957072c2010-04-14 11:24:15 -0700308
309 /* Don't precache the phdr pointer here.
310 elf32_getphdr will validate it against the size when asked. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000311
312 for (size_t cnt = 0; cnt < scncnt; ++cnt)
313 {
314 elf->state.elf32.scns.data[cnt].index = cnt;
315 elf->state.elf32.scns.data[cnt].elf = elf;
316 elf->state.elf32.scns.data[cnt].shdr.e32 =
317 &elf->state.elf32.shdr[cnt];
Roland McGrath429502f2010-02-17 00:49:46 -0800318 if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
319 && likely (maxsize - elf->state.elf32.shdr[cnt].sh_offset
320 <= elf->state.elf32.shdr[cnt].sh_size))
321 elf->state.elf32.scns.data[cnt].rawdata_base =
322 elf->state.elf32.scns.data[cnt].data_base =
323 ((char *) map_address + offset
324 + elf->state.elf32.shdr[cnt].sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000325 elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000326
327 /* If this is a section with an extended index add a
328 reference in the section which uses the extended
329 index. */
330 if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
331 && elf->state.elf32.shdr[cnt].sh_link < scncnt)
332 elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
333 = cnt;
334
335 /* Set the own shndx_index field in case it has not yet
336 been set. */
337 if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
338 elf->state.elf32.scns.data[cnt].shndx_index = -1;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000339 }
340 }
341 else
342 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000343 /* Copy the ELF header. */
344 elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
345 sizeof (Elf32_Ehdr));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000346
347 if (e_ident[EI_DATA] != MY_ELFDATA)
348 {
349 CONVERT (elf->state.elf32.ehdr_mem.e_type);
350 CONVERT (elf->state.elf32.ehdr_mem.e_machine);
351 CONVERT (elf->state.elf32.ehdr_mem.e_version);
352 CONVERT (elf->state.elf32.ehdr_mem.e_entry);
353 CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
354 CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
355 CONVERT (elf->state.elf32.ehdr_mem.e_flags);
356 CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
357 CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
358 CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
359 CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
360 CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
361 CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
362 }
363
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000364 for (size_t cnt = 0; cnt < scncnt; ++cnt)
365 {
366 elf->state.elf32.scns.data[cnt].index = cnt;
367 elf->state.elf32.scns.data[cnt].elf = elf;
368 elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
369 }
370 }
371
372 /* So far only one block with sections. */
373 elf->state.elf32.scns_last = &elf->state.elf32.scns;
374 }
375 else
376 {
377 /* This pointer might not be directly usable if the alignment is
378 not sufficient for the architecture. */
379 Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
380
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000381 /* This is a 64-bit binary. */
382 if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
383 && (ALLOW_UNALIGNED
384 || ((((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0
385 && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
386 & (__alignof__ (Elf64_Shdr) - 1)) == 0
387 && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
388 & (__alignof__ (Elf64_Phdr) - 1)) == 0)))
389 {
390 /* We can use the mmapped memory. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000391 elf->state.elf64.ehdr = ehdr;
392 elf->state.elf64.shdr
393 = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff);
Roland McGrath957072c2010-04-14 11:24:15 -0700394
395 /* Don't precache the phdr pointer here.
396 elf64_getphdr will validate it against the size when asked. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000397
398 for (size_t cnt = 0; cnt < scncnt; ++cnt)
399 {
400 elf->state.elf64.scns.data[cnt].index = cnt;
401 elf->state.elf64.scns.data[cnt].elf = elf;
402 elf->state.elf64.scns.data[cnt].shdr.e64 =
403 &elf->state.elf64.shdr[cnt];
Roland McGrath429502f2010-02-17 00:49:46 -0800404 if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
405 && likely (maxsize - elf->state.elf64.shdr[cnt].sh_offset
406 <= elf->state.elf64.shdr[cnt].sh_size))
407 elf->state.elf64.scns.data[cnt].rawdata_base =
408 elf->state.elf64.scns.data[cnt].data_base =
409 ((char *) map_address + offset
410 + elf->state.elf64.shdr[cnt].sh_offset);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000411 elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
Ulrich Drepper3cbdd382008-01-02 17:44:39 +0000412
413 /* If this is a section with an extended index add a
414 reference in the section which uses the extended
415 index. */
416 if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
417 && elf->state.elf64.shdr[cnt].sh_link < scncnt)
418 elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
419 = cnt;
420
421 /* Set the own shndx_index field in case it has not yet
422 been set. */
423 if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
424 elf->state.elf64.scns.data[cnt].shndx_index = -1;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000425 }
426 }
427 else
428 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000429 /* Copy the ELF header. */
430 elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
431 sizeof (Elf64_Ehdr));
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000432
433 if (e_ident[EI_DATA] != MY_ELFDATA)
434 {
435 CONVERT (elf->state.elf64.ehdr_mem.e_type);
436 CONVERT (elf->state.elf64.ehdr_mem.e_machine);
437 CONVERT (elf->state.elf64.ehdr_mem.e_version);
438 CONVERT (elf->state.elf64.ehdr_mem.e_entry);
439 CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
440 CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
441 CONVERT (elf->state.elf64.ehdr_mem.e_flags);
442 CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
443 CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
444 CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
445 CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
446 CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
447 CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
448 }
449
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000450 for (size_t cnt = 0; cnt < scncnt; ++cnt)
451 {
452 elf->state.elf64.scns.data[cnt].index = cnt;
453 elf->state.elf64.scns.data[cnt].elf = elf;
454 elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
455 }
456 }
457
458 /* So far only one block with sections. */
459 elf->state.elf64.scns_last = &elf->state.elf64.scns;
460 }
461
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000462 return elf;
463}
464
465
466Elf *
Ulrich Drepper077c65f2006-07-12 19:54:51 +0000467internal_function
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000468__libelf_read_mmaped_file (int fildes, void *map_address, off_t offset,
469 size_t maxsize, Elf_Cmd cmd, Elf *parent)
470{
471 /* We have to find out what kind of file this is. We handle ELF
472 files and archives. To find out what we have we must look at the
473 header. The header for an ELF file is EI_NIDENT bytes in size,
474 the header for an archive file SARMAG bytes long. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000475 unsigned char *e_ident = (unsigned char *) map_address + offset;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000476
477 /* See what kind of object we have here. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000478 Elf_Kind kind = determine_kind (e_ident, maxsize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000479
480 switch (kind)
481 {
482 case ELF_K_ELF:
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000483 return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
484 cmd, parent);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000485
486 case ELF_K_AR:
487 return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
488
489 default:
490 break;
491 }
492
493 /* This case is easy. Since we cannot do anything with this file
494 create a dummy descriptor. */
495 return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
496 ELF_K_NONE, 0);
497}
498
499
500static Elf *
501read_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd,
502 Elf *parent)
503{
504 /* We have to find out what kind of file this is. We handle ELF
505 files and archives. To find out what we have we must read the
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000506 header. The identification header for an ELF file is EI_NIDENT
507 bytes in size, but we read the whole ELF header since we will
508 need it anyway later. For archives the header in SARMAG bytes
509 long. Read the maximum of these numbers.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000510
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000511 XXX We have to change this for the extended `ar' format some day.
512
513 Use a union to ensure alignment. We might later access the
514 memory as a ElfXX_Ehdr. */
515 union
516 {
517 Elf64_Ehdr ehdr;
518 unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
519 } mem;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000520
521 /* Read the head of the file. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000522 ssize_t nread = pread_retry (fildes, mem.header,
523 MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
524 maxsize),
525 offset);
526 if (unlikely (nread == -1))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000527 /* We cannot even read the head of the file. Maybe FILDES is associated
528 with an unseekable device. This is nothing we can handle. */
529 return NULL;
530
531 /* See what kind of object we have here. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000532 Elf_Kind kind = determine_kind (mem.header, nread);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000533
534 switch (kind)
535 {
536 case ELF_K_AR:
537 return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
538
539 case ELF_K_ELF:
540 /* Make sure at least the ELF header is contained in the file. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000541 if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
542 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
543 return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
544 parent);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000545 /* FALLTHROUGH */
546
547 default:
548 break;
549 }
550
551 /* This case is easy. Since we cannot do anything with this file
552 create a dummy descriptor. */
553 return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
554 ELF_K_NONE, 0);
555}
556
557
558/* Open a file for reading. If possible we will try to mmap() the file. */
559static struct Elf *
560read_file (int fildes, off_t offset, size_t maxsize,
561 Elf_Cmd cmd, Elf *parent)
562{
563 void *map_address = NULL;
564 int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
565 || cmd == ELF_C_WRITE_MMAP
566 || cmd == ELF_C_READ_MMAP_PRIVATE);
567
568#if _MUDFLAP
569 /* Mudflap doesn't grok that our mmap'd data is ok. */
570 use_mmap = 0;
571#endif
572
573 if (use_mmap)
574 {
575 if (parent == NULL)
576 {
577 if (maxsize == ~((size_t) 0))
578 {
579 /* We don't know in the moment how large the file is.
580 Determine it now. */
581 struct stat st;
582
583 if (fstat (fildes, &st) == 0
584 && (sizeof (size_t) >= sizeof (st.st_size)
585 || st.st_size <= ~((size_t) 0)))
586 maxsize = (size_t) st.st_size;
587 }
588
589 /* We try to map the file ourself. */
590 map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
591 ? PROT_READ
592 : PROT_READ|PROT_WRITE),
593 cmd == ELF_C_READ_MMAP_PRIVATE
Ulrich Drepperce0bdb62007-02-05 07:13:52 +0000594 || cmd == ELF_C_READ_MMAP
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000595 ? MAP_PRIVATE : MAP_SHARED,
596 fildes, offset);
597
598 if (map_address == MAP_FAILED)
599 map_address = NULL;
600 }
601 else
602 {
603 /* The parent is already loaded. Use it. */
604 assert (maxsize != ~((size_t) 0));
605
606 map_address = parent->map_address;
607 }
608 }
609
610 /* If we have the file in memory optimize the access. */
611 if (map_address != NULL)
612 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000613 assert (map_address != MAP_FAILED);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000614
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000615 struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
616 offset, maxsize, cmd,
617 parent);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000618
619 /* If something went wrong during the initialization unmap the
620 memory if we mmaped here. */
621 if (result == NULL
622 && (parent == NULL
623 || parent->map_address != map_address))
624 munmap (map_address, maxsize);
625 else if (parent == NULL)
626 /* Remember that we mmap()ed the memory. */
627 result->flags |= ELF_F_MMAPPED;
628
629 return result;
630 }
631
632 /* Otherwise we have to do it the hard way. We read as much as necessary
633 from the file whenever we need information which is not available. */
634 return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
635}
636
637
638/* Find the entry with the long names for the content of this archive. */
639static const char *
640read_long_names (Elf *elf)
641{
642 off_t offset = SARMAG; /* This is the first entry. */
643 struct ar_hdr hdrm;
644 struct ar_hdr *hdr;
645 char *newp;
646 size_t len;
647
648 while (1)
649 {
650 if (elf->map_address != NULL)
651 {
652 if (offset + sizeof (struct ar_hdr) > elf->maximum_size)
653 return NULL;
654
655 /* The data is mapped. */
656 hdr = (struct ar_hdr *) (elf->map_address + offset);
657 }
658 else
659 {
660 /* Read the header from the file. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000661 if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
662 elf->start_offset + offset)
663 != sizeof (hdrm)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000664 return NULL;
665
666 hdr = &hdrm;
667 }
668
669 len = atol (hdr->ar_size);
670
671 if (memcmp (hdr->ar_name, "// ", 16) == 0)
672 break;
673
674 offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
675 }
676
677 /* Due to the stupid format of the long name table entry (which are not
678 NUL terminted) we have to provide an appropriate representation anyhow.
679 Therefore we always make a copy which has the appropriate form. */
680 newp = (char *) malloc (len);
681 if (newp != NULL)
682 {
683 char *runp;
684
685 if (elf->map_address != NULL)
686 /* Simply copy it over. */
687 elf->state.ar.long_names = (char *) memcpy (newp,
688 elf->map_address + offset
689 + sizeof (struct ar_hdr),
690 len);
691 else
692 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000693 if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
694 elf->start_offset + offset
695 + sizeof (struct ar_hdr))
696 != len))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000697 {
698 /* We were not able to read all data. */
699 free (newp);
700 elf->state.ar.long_names = NULL;
701 return NULL;
702 }
703 elf->state.ar.long_names = newp;
704 }
705
706 elf->state.ar.long_names_len = len;
707
708 /* Now NUL-terminate the strings. */
709 runp = newp;
710 while (1)
711 {
712 runp = (char *) memchr (runp, '/', newp + len - runp);
713 if (runp == NULL)
714 /* This was the last entry. */
715 break;
716
717 /* NUL-terminate the string. */
718 *runp = '\0';
719
Ulrich Drepperce0bdb62007-02-05 07:13:52 +0000720 /* Skip the NUL byte and the \012. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000721 runp += 2;
722
723 /* A sanity check. Somebody might have generated invalid
724 archive. */
725 if (runp >= newp + len)
726 break;
727 }
728 }
729
730 return newp;
731}
732
733
734/* Read the next archive header. */
735int
Ulrich Drepper077c65f2006-07-12 19:54:51 +0000736internal_function
Ulrich Drepper02f66452008-12-04 05:58:16 +0000737__libelf_next_arhdr_wrlock (elf)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000738 Elf *elf;
739{
740 struct ar_hdr *ar_hdr;
741 Elf_Arhdr *elf_ar_hdr;
742
743 if (elf->map_address != NULL)
744 {
745 /* See whether this entry is in the file. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000746 if (unlikely (elf->state.ar.offset + sizeof (struct ar_hdr)
747 > elf->start_offset + elf->maximum_size))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000748 {
749 /* This record is not anymore in the file. */
750 __libelf_seterrno (ELF_E_RANGE);
751 return -1;
752 }
753 ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
754 }
755 else
756 {
757 ar_hdr = &elf->state.ar.ar_hdr;
758
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000759 if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
760 elf->state.ar.offset)
761 != sizeof (struct ar_hdr)))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000762 {
763 /* Something went wrong while reading the file. */
764 __libelf_seterrno (ELF_E_RANGE);
765 return -1;
766 }
767 }
768
769 /* One little consistency check. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000770 if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000771 {
772 /* This is no valid archive. */
773 __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
774 return -1;
775 }
776
777 /* Copy the raw name over to a NUL terminated buffer. */
778 *((char *) __mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
779
780 elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
781
782 /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
783 Determine whether this is a special entry. */
784 if (ar_hdr->ar_name[0] == '/')
785 {
786 if (ar_hdr->ar_name[1] == ' '
787 && memcmp (ar_hdr->ar_name, "/ ", 16) == 0)
788 /* This is the index. */
789 elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
Petr Machatae1873142012-08-01 21:37:52 +0200790 else if (ar_hdr->ar_name[1] == 'S'
791 && memcmp (ar_hdr->ar_name, "/SYM64/ ", 16) == 0)
792 /* 64-bit index. */
793 elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000794 else if (ar_hdr->ar_name[1] == '/'
795 && memcmp (ar_hdr->ar_name, "// ", 16) == 0)
796 /* This is the array with the long names. */
797 elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000798 else if (likely (isdigit (ar_hdr->ar_name[1])))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000799 {
800 size_t offset;
801
802 /* This is a long name. First we have to read the long name
803 table, if this hasn't happened already. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000804 if (unlikely (elf->state.ar.long_names == NULL
805 && read_long_names (elf) == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000806 {
807 /* No long name table although it is reference. The archive is
808 broken. */
809 __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
810 return -1;
811 }
812
813 offset = atol (ar_hdr->ar_name + 1);
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000814 if (unlikely (offset >= elf->state.ar.long_names_len))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000815 {
816 /* The index in the long name table is larger than the table. */
817 __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
818 return -1;
819 }
820 elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
821 }
822 else
823 {
824 /* This is none of the known special entries. */
825 __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
826 return -1;
827 }
828 }
829 else
830 {
831 char *endp;
832
833 /* It is a normal entry. Copy over the name. */
834 endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
835 '/', 16);
836 if (endp != NULL)
837 endp[-1] = '\0';
838 else
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000839 {
840 /* In the old BSD style of archive, there is no / terminator.
841 Instead, there is space padding at the end of the name. */
842 size_t i = 15;
843 do
844 elf->state.ar.ar_name[i] = '\0';
845 while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
846 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000847
848 elf_ar_hdr->ar_name = elf->state.ar.ar_name;
849 }
850
Roland McGrath059c83e2008-02-21 06:19:39 +0000851 if (unlikely (ar_hdr->ar_size[0] == ' '))
852 /* Something is really wrong. We cannot live without a size for
853 the member since it will not be possible to find the next
854 archive member. */
855 {
856 __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
857 return -1;
858 }
859
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000860 /* Since there are no specialized functions to convert ASCII to
861 time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
862 atoll depending on the size of the types. We are also prepared
863 for the case where the whole field in the `struct ar_hdr' is
864 filled in which case we cannot simply use atol/l but instead have
865 to create a temporary copy. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000866
Roland McGrath059c83e2008-02-21 06:19:39 +0000867#define INT_FIELD(FIELD) \
868 do \
869 { \
870 char buf[sizeof (ar_hdr->FIELD) + 1]; \
871 const char *string = ar_hdr->FIELD; \
872 if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ') \
873 { \
874 *((char *) __mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD))) \
875 = '\0'; \
876 string = buf; \
877 } \
878 if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int)) \
879 elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string); \
880 else \
881 elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string); \
882 } \
883 while (0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000884
Roland McGrath059c83e2008-02-21 06:19:39 +0000885 INT_FIELD (ar_date);
886 INT_FIELD (ar_uid);
887 INT_FIELD (ar_gid);
888 INT_FIELD (ar_mode);
889 INT_FIELD (ar_size);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000890
891 return 0;
892}
893
894
895/* We were asked to return a clone of an existing descriptor. This
896 function must be called with the lock on the parent descriptor
897 being held. */
898static Elf *
899dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
900{
901 struct Elf *result;
902
903 if (fildes == -1)
904 /* Allow the user to pass -1 as the file descriptor for the new file. */
905 fildes = ref->fildes;
906 /* The file descriptor better should be the same. If it was disconnected
907 already (using `elf_cntl') we do not test it. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000908 else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000909 {
910 __libelf_seterrno (ELF_E_FD_MISMATCH);
911 return NULL;
912 }
913
914 /* The mode must allow reading. I.e., a descriptor creating with a
915 command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
916 not allowed. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000917 if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
918 && ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
919 && ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
920 && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000921 {
922 __libelf_seterrno (ELF_E_INVALID_OP);
923 return NULL;
924 }
925
926 /* Now it is time to distinguish between reading normal files and
927 archives. Normal files can easily be handled be incrementing the
928 reference counter and return the same descriptor. */
929 if (ref->kind != ELF_K_AR)
930 {
931 ++ref->ref_count;
932 return ref;
933 }
934
935 /* This is an archive. We must create a descriptor for the archive
936 member the internal pointer of the archive file desriptor is
937 pointing to. First read the header of the next member if this
938 has not happened already. */
939 if (ref->state.ar.elf_ar_hdr.ar_name == NULL
Ulrich Drepper02f66452008-12-04 05:58:16 +0000940 && __libelf_next_arhdr_wrlock (ref) != 0)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000941 /* Something went wrong. Maybe there is no member left. */
942 return NULL;
943
944 /* We have all the information we need about the next archive member.
945 Now create a descriptor for it. */
946 result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
947 ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
948
949 /* Enlist this new descriptor in the list of children. */
950 if (result != NULL)
951 {
952 result->next = ref->state.ar.children;
953 ref->state.ar.children = result;
954 }
955
956 return result;
957}
958
959
960/* Return desriptor for empty file ready for writing. */
961static struct Elf *
962write_file (int fd, Elf_Cmd cmd)
963{
964 /* We simply create an empty `Elf' structure. */
965#define NSCNSALLOC 10
966 Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
967 NSCNSALLOC * sizeof (Elf_Scn));
968
969 if (result != NULL)
970 {
971 /* We have to write to the file in any case. */
972 result->flags = ELF_F_DIRTY;
973
974 /* Some more or less arbitrary value. */
975 result->state.elf.scnincr = NSCNSALLOC;
976
977 /* We have allocated room for some sections. */
978 assert (offsetof (struct Elf, state.elf32.scns)
979 == offsetof (struct Elf, state.elf64.scns));
980 result->state.elf.scns_last = &result->state.elf32.scns;
981 result->state.elf32.scns.max = NSCNSALLOC;
982 }
983
984 return result;
985}
986
987
988/* Return a descriptor for the file belonging to FILDES. */
989Elf *
990elf_begin (fildes, cmd, ref)
991 int fildes;
992 Elf_Cmd cmd;
993 Elf *ref;
994{
995 Elf *retval;
996
Ulrich Drepperfbe998a2005-08-29 16:27:10 +0000997 if (unlikely (! __libelf_version_initialized))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000998 {
999 /* Version wasn't set so far. */
1000 __libelf_seterrno (ELF_E_NO_VERSION);
1001 return NULL;
1002 }
1003
1004 if (ref != NULL)
1005 /* Make sure the descriptor is not suddenly going away. */
Roland McGrathb4d6f0f2008-08-25 22:55:17 +00001006 rwlock_rdlock (ref->lock);
Ulrich Drepperfbe998a2005-08-29 16:27:10 +00001007 else if (unlikely (fcntl (fildes, F_GETFL) == -1 && errno == EBADF))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001008 {
1009 /* We cannot do anything productive without a file descriptor. */
1010 __libelf_seterrno (ELF_E_INVALID_FILE);
1011 return NULL;
1012 }
1013
Ulrich Drepper02f66452008-12-04 05:58:16 +00001014 Elf *lock_dup_elf ()
1015 {
1016 /* We need wrlock to dup an archive. */
1017 if (ref->kind == ELF_K_AR)
1018 {
1019 rwlock_unlock (ref->lock);
1020 rwlock_wrlock (ref->lock);
1021 }
1022
1023 /* Duplicate the descriptor. */
1024 return dup_elf (fildes, cmd, ref);
1025 }
1026
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001027 switch (cmd)
1028 {
1029 case ELF_C_NULL:
1030 /* We simply return a NULL pointer. */
1031 retval = NULL;
1032 break;
1033
1034 case ELF_C_READ_MMAP_PRIVATE:
1035 /* If we have a reference it must also be opened this way. */
Ulrich Drepperfbe998a2005-08-29 16:27:10 +00001036 if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001037 {
1038 __libelf_seterrno (ELF_E_INVALID_CMD);
1039 retval = NULL;
1040 break;
1041 }
1042 /* FALLTHROUGH */
1043
1044 case ELF_C_READ:
1045 case ELF_C_READ_MMAP:
1046 if (ref != NULL)
Ulrich Drepper02f66452008-12-04 05:58:16 +00001047 retval = lock_dup_elf ();
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001048 else
1049 /* Create descriptor for existing file. */
1050 retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1051 break;
1052
1053 case ELF_C_RDWR:
1054 case ELF_C_RDWR_MMAP:
1055 /* If we have a REF object it must also be opened using this
1056 command. */
1057 if (ref != NULL)
1058 {
Ulrich Drepperfbe998a2005-08-29 16:27:10 +00001059 if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1060 && ref->cmd != ELF_C_WRITE
1061 && ref->cmd != ELF_C_WRITE_MMAP))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001062 {
1063 /* This is not ok. REF must also be opened for writing. */
1064 __libelf_seterrno (ELF_E_INVALID_CMD);
1065 retval = NULL;
1066 }
1067 else
Ulrich Drepper02f66452008-12-04 05:58:16 +00001068 retval = lock_dup_elf ();
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001069 }
1070 else
1071 /* Create descriptor for existing file. */
1072 retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1073 break;
1074
1075 case ELF_C_WRITE:
1076 case ELF_C_WRITE_MMAP:
1077 /* We ignore REF and prepare a descriptor to write a new file. */
1078 retval = write_file (fildes, cmd);
1079 break;
1080
1081 default:
1082 __libelf_seterrno (ELF_E_INVALID_CMD);
1083 retval = NULL;
1084 break;
1085 }
1086
1087 /* Release the lock. */
1088 if (ref != NULL)
Roland McGrathb4d6f0f2008-08-25 22:55:17 +00001089 rwlock_unlock (ref->lock);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001090
1091 return retval;
1092}
1093INTDEF(elf_begin)