elf_begin.c revision 237188e4d764598300a577e08fd872339812fb2c
1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Create descriptor for processing file.
2720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek   Copyright (C) 1998-2010, 2012, 2014 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
8b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
21de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
25b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
28de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <ctype.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <errno.h>
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h>
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stddef.h>
40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h>
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/mman.h>
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/param.h>
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/stat.h>
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
46fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper#include <system.h>
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "libelfP.h"
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "common.h"
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Create descriptor for archive in memory.  */
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic inline Elf *
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperfile_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      Elf_Cmd cmd, Elf *parent)
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *elf;
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Create a descriptor.  */
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper                      ELF_K_AR, 0);
61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf != NULL)
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We don't read all the symbol tables in advance.  All this will
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 happen on demand.  */
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.ar.offset = offset + SARMAG;
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return elf;
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic size_t
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperget_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   size_t maxsize)
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t result;
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  union
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  {
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf32_Ehdr *e32;
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    Elf64_Ehdr *e64;
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    void *p;
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  } ehdr;
850f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper  union
860f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper  {
870f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper    Elf32_Ehdr e32;
880f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper    Elf64_Ehdr e64;
890f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper  } ehdr_mem;
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Make the ELF header available.  */
939cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath  if (e_ident[EI_DATA] == MY_ELFDATA
949cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath      && (ALLOW_UNALIGNED
959cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	  || (((size_t) e_ident
969cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	       & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
979cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath		  - 1)) == 0)))
98fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper    ehdr.p = e_ident;
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
101fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      /* We already read the ELF header.  We have to copy the header
102fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	 since we possibly modify the data here and the caller
103fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	 expects the memory it passes in to be preserved.  */
104fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      ehdr.p = &ehdr_mem;
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
106fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if (is32)
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
108fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (ALLOW_UNALIGNED)
109969bda4a47575b33af814c62ea876b0bbf8c5713Ulrich Drepper	    {
110fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	      ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
111fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	      ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
112969bda4a47575b33af814c62ea876b0bbf8c5713Ulrich Drepper	    }
113969bda4a47575b33af814c62ea876b0bbf8c5713Ulrich Drepper	  else
114fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	    memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
115fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper
1169cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	  if (e_ident[EI_DATA] != MY_ELFDATA)
1179cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	    {
1189cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	      CONVERT (ehdr_mem.e32.e_shnum);
1199cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	      CONVERT (ehdr_mem.e32.e_shoff);
1209cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	    }
121fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	}
122fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      else
123fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	{
124fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (ALLOW_UNALIGNED)
1254c305da9de0ecfe9af64cb6787b2b4b8a6aa8dd5Roland McGrath	    {
126fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	      ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
127fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	      ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
1284c305da9de0ecfe9af64cb6787b2b4b8a6aa8dd5Roland McGrath	    }
129fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  else
130fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	    memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
131fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper
1329cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	  if (e_ident[EI_DATA] != MY_ELFDATA)
1339cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	    {
1349cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	      CONVERT (ehdr_mem.e64.e_shnum);
1359cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	      CONVERT (ehdr_mem.e64.e_shoff);
1369cf28e4f899f97ecdc983a0af8e2be62f3d69058Roland McGrath	    }
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (is32)
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get the number of sections from the ELF header.  */
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = ehdr.e32->e_shnum;
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
147720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	  if (unlikely (ehdr.e32->e_shoff >= maxsize)
148720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Cannot read the first section header.  */
150c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper	    return 0;
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && (ALLOW_UNALIGNED
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (((size_t) ((char *) map_address + offset))
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We can directly access the memory.  */
1570f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	    result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				      + offset))->sh_size;
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      Elf32_Word size;
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1630f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	      if (likely (map_address != NULL))
1640f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		/* gcc will optimize the memcpy to a simple memory
1650f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		   access while taking care of alignment issues.  */
1660f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		memcpy (&size, &((Elf32_Shdr *) ((char *) map_address
1670f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper						 + ehdr.e32->e_shoff
1680f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper						 + offset))->sh_size,
1690f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper			sizeof (Elf32_Word));
1700f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	      else
171fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word),
172fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					   offset + ehdr.e32->e_shoff
173fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					   + offsetof (Elf32_Shdr, sh_size))
174fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			      != sizeof (Elf32_Word)))
1750f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		  return (size_t) -1l;
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (e_ident[EI_DATA] != MY_ELFDATA)
178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		CONVERT (size);
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      result = size;
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
183c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper
184c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper      /* If the section headers were truncated, pretend none were there.  */
185c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper      if (ehdr.e32->e_shoff > maxsize
186c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper	  || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
187c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper	result = 0;
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Get the number of sections from the ELF header.  */
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result = ehdr.e64->e_shnum;
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
196720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	  if (unlikely (ehdr.e64->e_shoff >= maxsize)
197720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Cannot read the first section header.  */
199c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper	    return 0;
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2010f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	  Elf64_Xword size;
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && (ALLOW_UNALIGNED
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (((size_t) ((char *) map_address + offset))
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* We can directly access the memory.  */
2070f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	    size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
2080f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper				    + offset))->sh_size;
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
2110f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	      if (likely (map_address != NULL))
2120f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		/* gcc will optimize the memcpy to a simple memory
2130f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		   access while taking care of alignment issues.  */
2140f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		memcpy (&size, &((Elf64_Shdr *) ((char *) map_address
2150f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper						 + ehdr.e64->e_shoff
2160f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper						 + offset))->sh_size,
2170f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper			sizeof (Elf64_Xword));
2180f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	      else
219fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Word),
220fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					   offset + ehdr.e64->e_shoff
221fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					   + offsetof (Elf64_Shdr, sh_size))
222fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			      != sizeof (Elf64_Xword)))
2230f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper		  return (size_t) -1l;
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (e_ident[EI_DATA] != MY_ELFDATA)
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		CONVERT (size);
227e53d04af5fbf8486933821c81c8fe6637a546f48Roland McGrath	    }
2280f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper
2290f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	  if (size > ~((GElf_Word) 0))
2300f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	    /* Invalid value, it is too large.  */
2310f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	    return (size_t) -1l;
2320f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper
2330f6abbbc08ee259a1a702e7dd3be3e2c6b82305eUlrich Drepper	  result = size;
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
235c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper
236c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper      /* If the section headers were truncated, pretend none were there.  */
237c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper      if (ehdr.e64->e_shoff > maxsize
238c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper	  || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
239c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper	result = 0;
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Create descriptor for ELF file in memory.  */
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *
248fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepperfile_read_elf (int fildes, void *map_address, unsigned char *e_ident,
249fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	       off_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Verify the binary is of the class we can handle.  */
252fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
253fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		 && e_ident[EI_CLASS] != ELFCLASS64)
254fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		/* We also can only handle two encodings.  */
255fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		|| (e_ident[EI_DATA] != ELFDATA2LSB
256fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		    && e_ident[EI_DATA] != ELFDATA2MSB)))
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Cannot handle this.  */
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_INVALID_FILE);
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Determine the number of sections.  */
264fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (scncnt == (size_t) -1l)
266b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Could not determine the number of sections.  */
267b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return NULL;
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
269720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek  /* Check for too many sections.  */
270720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek  if (e_ident[EI_CLASS] == ELFCLASS32)
271720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek    {
272720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek      if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
273720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	return NULL;
274720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek    }
275720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek  else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
276720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek    return NULL;
277720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek
2786fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath  /* We can now allocate the memory.  Even if there are no section headers,
2796fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath     we allocate space for a zeroth section in case we need it later.  */
2806fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath  const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
2816fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath			 ? 1 : 0);
282fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
2836fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath			   ELF_K_ELF, scnmax * sizeof (Elf_Scn));
284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf == NULL)
285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Not enough memory.  */
286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return NULL;
287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
2886fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath  assert ((unsigned int) scncnt == scncnt);
2896fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath  assert (offsetof (struct Elf, state.elf32.scns)
2906fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath	  == offsetof (struct Elf, state.elf64.scns));
2916fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath  elf->state.elf32.scns.cnt = scncnt;
2926fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath  elf->state.elf32.scns.max = scnmax;
2936fd3cd104adf4107aa64e1c1e84028b4ea0b3296Roland McGrath
294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Some more or less arbitrary value.  */
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf->state.elf.scnincr = 10;
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
297fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  /* Make the class easily available.  */
298fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  elf->class = e_ident[EI_CLASS];
299fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (e_ident[EI_CLASS] == ELFCLASS32)
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This pointer might not be directly usable if the alignment is
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 not sufficient for the architecture.  */
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset);
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This is a 32-bit binary.  */
307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (ALLOW_UNALIGNED
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || ((((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & (__alignof__ (Elf32_Shdr) - 1)) == 0
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & (__alignof__ (Elf32_Phdr) - 1)) == 0)))
314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We can use the mmapped memory.  */
316fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf32.ehdr = ehdr;
317720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek
318720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	  if (unlikely (ehdr->e_shoff >= maxsize)
319720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      || unlikely (maxsize - ehdr->e_shoff
320720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek			   < scncnt * sizeof (Elf32_Shdr)))
321720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    {
322720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    free_and_out:
323720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      free (elf);
324720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      __libelf_seterrno (ELF_E_INVALID_FILE);
325720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      return NULL;
326720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    }
327fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf32.shdr
328fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	    = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff);
329957072c18a906a43f0b428997d0c2b0da478213bRoland McGrath
330957072c18a906a43f0b428997d0c2b0da478213bRoland McGrath	  /* Don't precache the phdr pointer here.
331957072c18a906a43f0b428997d0c2b0da478213bRoland McGrath	     elf32_getphdr will validate it against the size when asked.  */
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].index = cnt;
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].elf = elf;
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].shdr.e32 =
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&elf->state.elf32.shdr[cnt];
339429502fd324d731feb939a5db4b7e0723adac616Roland McGrath	      if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
340429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  && likely (maxsize - elf->state.elf32.shdr[cnt].sh_offset
341429502fd324d731feb939a5db4b7e0723adac616Roland McGrath			     <= elf->state.elf32.shdr[cnt].sh_size))
342429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		elf->state.elf32.scns.data[cnt].rawdata_base =
343429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  elf->state.elf32.scns.data[cnt].data_base =
344429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  ((char *) map_address + offset
345429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		   + elf->state.elf32.shdr[cnt].sh_offset);
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
3473cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
3483cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* If this is a section with an extended index add a
3493cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 reference in the section which uses the extended
3503cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 index.  */
3513cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
3523cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  && elf->state.elf32.shdr[cnt].sh_link < scncnt)
3533cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
3543cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  = cnt;
3553cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
3563cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* Set the own shndx_index field in case it has not yet
3573cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 been set.  */
3583cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
3593cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf32.scns.data[cnt].shndx_index = -1;
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
364fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  /* Copy the ELF header.  */
365fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
366fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					  sizeof (Elf32_Ehdr));
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (e_ident[EI_DATA] != MY_ELFDATA)
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_type);
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_machine);
372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_version);
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_entry);
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_flags);
377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
378b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
379b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
380b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].index = cnt;
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].elf = elf;
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* So far only one block with sections.  */
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.elf32.scns_last = &elf->state.elf32.scns;
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This pointer might not be directly usable if the alignment is
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 not sufficient for the architecture.  */
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This is a 64-bit binary.  */
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (ALLOW_UNALIGNED
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || ((((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & (__alignof__ (Elf64_Shdr) - 1)) == 0
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      & (__alignof__ (Elf64_Phdr) - 1)) == 0)))
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We can use the mmapped memory.  */
412fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf64.ehdr = ehdr;
413720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek
414720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	  if (unlikely (ehdr->e_shoff >= maxsize)
415720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      || unlikely (ehdr->e_shoff
416720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek			   + scncnt * sizeof (Elf32_Shdr) > maxsize))
417720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    goto free_and_out;
418fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf64.shdr
419fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	    = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff);
420957072c18a906a43f0b428997d0c2b0da478213bRoland McGrath
421957072c18a906a43f0b428997d0c2b0da478213bRoland McGrath	  /* Don't precache the phdr pointer here.
422957072c18a906a43f0b428997d0c2b0da478213bRoland McGrath	     elf64_getphdr will validate it against the size when asked.  */
423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].index = cnt;
427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].elf = elf;
428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].shdr.e64 =
429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&elf->state.elf64.shdr[cnt];
430429502fd324d731feb939a5db4b7e0723adac616Roland McGrath	      if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
431429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  && likely (maxsize - elf->state.elf64.shdr[cnt].sh_offset
432429502fd324d731feb939a5db4b7e0723adac616Roland McGrath			     <= elf->state.elf64.shdr[cnt].sh_size))
433429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		elf->state.elf64.scns.data[cnt].rawdata_base =
434429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  elf->state.elf64.scns.data[cnt].data_base =
435429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  ((char *) map_address + offset
436429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		   + elf->state.elf64.shdr[cnt].sh_offset);
437b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
4383cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
4393cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* If this is a section with an extended index add a
4403cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 reference in the section which uses the extended
4413cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 index.  */
4423cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
4433cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  && elf->state.elf64.shdr[cnt].sh_link < scncnt)
4443cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
4453cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  = cnt;
4463cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
4473cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* Set the own shndx_index field in case it has not yet
4483cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 been set.  */
4493cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
4503cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf64.scns.data[cnt].shndx_index = -1;
451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
453b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
455fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  /* Copy the ELF header.  */
456fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
457fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					  sizeof (Elf64_Ehdr));
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (e_ident[EI_DATA] != MY_ELFDATA)
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_type);
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_machine);
463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_version);
464b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_entry);
465b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
466b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
467b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_flags);
468b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
469b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
471b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
472b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
473b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
474b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
475b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
476b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
477b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
478b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].index = cnt;
479b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].elf = elf;
480b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
481b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
482b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
483b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* So far only one block with sections.  */
485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.elf64.scns_last = &elf->state.elf64.scns;
486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return elf;
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperElf *
493077c65f3be02e5d01b0c4dea3f6c854077d156fcUlrich Drepperinternal_function
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper__libelf_read_mmaped_file (int fildes, void *map_address,  off_t offset,
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   size_t maxsize, Elf_Cmd cmd, Elf *parent)
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have to find out what kind of file this is.  We handle ELF
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     files and archives.  To find out what we have we must look at the
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     header.  The header for an ELF file is EI_NIDENT bytes in size,
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     the header for an archive file SARMAG bytes long.  */
501fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  unsigned char *e_ident = (unsigned char *) map_address + offset;
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* See what kind of object we have here.  */
504fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  Elf_Kind kind = determine_kind (e_ident, maxsize);
505b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (kind)
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
509fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
510fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			    cmd, parent);
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
513b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
516b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* This case is easy.  Since we cannot do anything with this file
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     create a dummy descriptor.  */
521b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
522b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ELF_K_NONE, 0);
523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperread_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd,
528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    Elf *parent)
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have to find out what kind of file this is.  We handle ELF
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     files and archives.  To find out what we have we must read the
532fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     header.  The identification header for an ELF file is EI_NIDENT
533fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     bytes in size, but we read the whole ELF header since we will
534fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     need it anyway later.  For archives the header in SARMAG bytes
535fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     long.  Read the maximum of these numbers.
536fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper
537fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     XXX We have to change this for the extended `ar' format some day.
538490063eb2bd6a131104c0070aa0fa37d0b037c49Ulrich Drepper
539fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     Use a union to ensure alignment.  We might later access the
540fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     memory as a ElfXX_Ehdr.  */
541fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  union
542fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  {
543fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper    Elf64_Ehdr ehdr;
544fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper    unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
545fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  } mem;
546b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
547b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Read the head of the file.  */
548fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  ssize_t nread = pread_retry (fildes, mem.header,
549fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			       MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
550fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper				    maxsize),
551fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			       offset);
552fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (nread == -1))
553237188e4d764598300a577e08fd872339812fb2cPetr Machata    {
554237188e4d764598300a577e08fd872339812fb2cPetr Machata      /* We cannot even read the head of the file.  Maybe FILDES is associated
555237188e4d764598300a577e08fd872339812fb2cPetr Machata	 with an unseekable device.  This is nothing we can handle.  */
556237188e4d764598300a577e08fd872339812fb2cPetr Machata      __libelf_seterrno (ELF_E_INVALID_FILE);
557237188e4d764598300a577e08fd872339812fb2cPetr Machata      return NULL;
558237188e4d764598300a577e08fd872339812fb2cPetr Machata    }
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
560b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* See what kind of object we have here.  */
561fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  Elf_Kind kind = determine_kind (mem.header, nread);
562b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
563b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (kind)
564b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
565b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
566b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
567b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
568b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
569b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Make sure at least the ELF header is contained in the file.  */
570fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
571fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			     ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
572fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
573fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			      parent);
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* FALLTHROUGH */
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* This case is easy.  Since we cannot do anything with this file
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     create a dummy descriptor.  */
582b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
583b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ELF_K_NONE, 0);
584b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
585b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Open a file for reading.  If possible we will try to mmap() the file.  */
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct Elf *
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperread_file (int fildes, off_t offset, size_t maxsize,
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   Elf_Cmd cmd, Elf *parent)
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  void *map_address = NULL;
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || cmd == ELF_C_WRITE_MMAP
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || cmd == ELF_C_READ_MMAP_PRIVATE);
596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (use_mmap)
598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (parent == NULL)
600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (maxsize == ~((size_t) 0))
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* We don't know in the moment how large the file is.
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 Determine it now.  */
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      struct stat st;
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (fstat (fildes, &st) == 0
608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && (sizeof (size_t) >= sizeof (st.st_size)
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      || st.st_size <= ~((size_t) 0)))
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		maxsize = (size_t) st.st_size;
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We try to map the file ourself.  */
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      ? PROT_READ
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      : PROT_READ|PROT_WRITE),
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      cmd == ELF_C_READ_MMAP_PRIVATE
618ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || cmd == ELF_C_READ_MMAP
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      ? MAP_PRIVATE : MAP_SHARED,
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      fildes, offset);
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (map_address == MAP_FAILED)
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    map_address = NULL;
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* The parent is already loaded.  Use it.  */
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (maxsize != ~((size_t) 0));
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  map_address = parent->map_address;
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If we have the file in memory optimize the access.  */
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (map_address != NULL)
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
637fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      assert (map_address != MAP_FAILED);
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
639fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
640fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper						      offset, maxsize, cmd,
641fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper						      parent);
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If something went wrong during the initialization unmap the
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 memory if we mmaped here.  */
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (result == NULL
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (parent == NULL
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || parent->map_address != map_address))
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	munmap (map_address, maxsize);
649b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (parent == NULL)
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Remember that we mmap()ed the memory.  */
651b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result->flags |= ELF_F_MMAPPED;
652b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return result;
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Otherwise we have to do it the hard way.  We read as much as necessary
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     from the file whenever we need information which is not available.  */
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Find the entry with the long names for the content of this archive.  */
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperread_long_names (Elf *elf)
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  off_t offset = SARMAG;	/* This is the first entry.  */
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct ar_hdr hdrm;
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct ar_hdr *hdr;
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *newp;
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t len;
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (1)
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf->map_address != NULL)
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (offset + sizeof (struct ar_hdr) > elf->maximum_size)
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    return NULL;
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* The data is mapped.  */
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  hdr = (struct ar_hdr *) (elf->map_address + offset);
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Read the header from the file.  */
685fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
686fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper				     elf->start_offset + offset)
687fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			!= sizeof (hdrm)))
688b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    return NULL;
689b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  hdr = &hdrm;
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      len = atol (hdr->ar_size);
694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (memcmp (hdr->ar_name, "//              ", 16) == 0)
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	break;
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
698b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
699b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
700b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Due to the stupid format of the long name table entry (which are not
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     NUL terminted) we have to provide an appropriate representation anyhow.
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Therefore we always make a copy which has the appropriate form.  */
704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newp = (char *) malloc (len);
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (newp != NULL)
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char *runp;
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf->map_address != NULL)
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Simply copy it over.  */
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	elf->state.ar.long_names = (char *) memcpy (newp,
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						    elf->map_address + offset
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						    + sizeof (struct ar_hdr),
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						    len);
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
717fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
718fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					      elf->start_offset + offset
719fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					      + sizeof (struct ar_hdr))
720fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			!= len))
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* We were not able to read all data.  */
723b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      free (newp);
724b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.ar.long_names = NULL;
725b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return NULL;
726b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
727b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  elf->state.ar.long_names = newp;
728b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
729b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
730b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.ar.long_names_len = len;
731b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Now NUL-terminate the strings.  */
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      runp = newp;
734b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (1)
735b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper        {
736b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  runp = (char *) memchr (runp, '/', newp + len - runp);
737b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (runp == NULL)
738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* This was the last entry.  */
739b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    break;
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* NUL-terminate the string.  */
742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  *runp = '\0';
743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
744ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper	  /* Skip the NUL byte and the \012.  */
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  runp += 2;
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* A sanity check.  Somebody might have generated invalid
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     archive.  */
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (runp >= newp + len)
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    break;
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
754b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return newp;
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
757b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
758b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Read the next archive header.  */
759b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
760077c65f3be02e5d01b0c4dea3f6c854077d156fcUlrich Drepperinternal_function
76102f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper__libelf_next_arhdr_wrlock (elf)
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Elf *elf;
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
764b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct ar_hdr *ar_hdr;
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Arhdr *elf_ar_hdr;
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf->map_address != NULL)
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* See whether this entry is in the file.  */
770fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if (unlikely (elf->state.ar.offset + sizeof (struct ar_hdr)
771fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		    > elf->start_offset + elf->maximum_size))
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* This record is not anymore in the file.  */
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_RANGE);
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return -1;
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
779b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
780b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ar_hdr = &elf->state.ar.ar_hdr;
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
783fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
784fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper				 elf->state.ar.offset)
785fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		    != sizeof (struct ar_hdr)))
786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Something went wrong while reading the file.  */
788b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_RANGE);
789b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return -1;
790b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
791b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* One little consistency check.  */
794fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This is no valid archive.  */
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return -1;
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Copy the raw name over to a NUL terminated buffer.  */
802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  *((char *) __mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
803b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
804b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
805b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Determine whether this is a special entry.  */
808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ar_hdr->ar_name[0] == '/')
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ar_hdr->ar_name[1] == ' '
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && memcmp (ar_hdr->ar_name, "/               ", 16) == 0)
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* This is the index.  */
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
814e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata      else if (ar_hdr->ar_name[1] == 'S'
815e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata	       && memcmp (ar_hdr->ar_name, "/SYM64/         ", 16) == 0)
816e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata	/* 64-bit index.  */
817e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ar_hdr->ar_name[1] == '/'
819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && memcmp (ar_hdr->ar_name, "//              ", 16) == 0)
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* This is the array with the long names.  */
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
822fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      else if (likely  (isdigit (ar_hdr->ar_name[1])))
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t offset;
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* This is a long name.  First we have to read the long name
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     table, if this hasn't happened already.  */
828fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (elf->state.ar.long_names == NULL
829fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			&& read_long_names (elf) == NULL))
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* No long name table although it is reference.  The archive is
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 broken.  */
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
834b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return -1;
835b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
836b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
837b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  offset = atol (ar_hdr->ar_name + 1);
838fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (offset >= elf->state.ar.long_names_len))
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The index in the long name table is larger than the table.  */
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
842b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return -1;
843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
848b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* This is none of the known special entries.  */
849b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return -1;
851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char *endp;
856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* It is a normal entry.  Copy over the name.  */
858b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       '/', 16);
860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (endp != NULL)
861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	endp[-1] = '\0';
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
863b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
864b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  /* In the old BSD style of archive, there is no / terminator.
865b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	     Instead, there is space padding at the end of the name.  */
866b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  size_t i = 15;
867b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  do
868b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    elf->state.ar.ar_name[i] = '\0';
869b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
870b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf_ar_hdr->ar_name = elf->state.ar.ar_name;
873b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
875059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (unlikely (ar_hdr->ar_size[0] == ' '))
876059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    /* Something is really wrong.  We cannot live without a size for
877059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath       the member since it will not be possible to find the next
878059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath       archive member.  */
879059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
880059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
881059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return -1;
882059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
883059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
884b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Since there are no specialized functions to convert ASCII to
885b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
886b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     atoll depending on the size of the types.  We are also prepared
887b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     for the case where the whole field in the `struct ar_hdr' is
888b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     filled in which case we cannot simply use atol/l but instead have
889b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     to create a temporary copy.  */
890b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
891059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#define INT_FIELD(FIELD)						      \
892059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  do									      \
893059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {									      \
894059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      char buf[sizeof (ar_hdr->FIELD) + 1];				      \
895059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      const char *string = ar_hdr->FIELD;				      \
896059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
897059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{								      \
898059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  *((char *) __mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
899059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    = '\0';							      \
900059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  string = buf;							      \
901059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}								      \
902059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
903059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string);     \
904059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      else								      \
905059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string);    \
906059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }									      \
907059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  while (0)
908059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
909059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_date);
910059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_uid);
911059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_gid);
912059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_mode);
913059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_size);
914b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
915b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
916b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
917b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
918b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
919b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* We were asked to return a clone of an existing descriptor.  This
920b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   function must be called with the lock on the parent descriptor
921b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   being held. */
922b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *
923b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperdup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
924b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
925b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct Elf *result;
926b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
927b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fildes == -1)
928b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Allow the user to pass -1 as the file descriptor for the new file.  */
929b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    fildes = ref->fildes;
930b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The file descriptor better should be the same.  If it was disconnected
931b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     already (using `elf_cntl') we do not test it.  */
932fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
933b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
934b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_FD_MISMATCH);
935b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
936b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
937b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
938b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The mode must allow reading.  I.e., a descriptor creating with a
939b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
940b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     not allowed.  */
941fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
942fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
943fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
944fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		&& ref->cmd != ELF_C_READ_MMAP_PRIVATE))
945b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
946b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_INVALID_OP);
947b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now it is time to distinguish between reading normal files and
951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     archives.  Normal files can easily be handled be incrementing the
952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     reference counter and return the same descriptor.  */
953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref->kind != ELF_K_AR)
954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ++ref->ref_count;
956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ref;
957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* This is an archive.  We must create a descriptor for the archive
960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     member the internal pointer of the archive file desriptor is
961b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     pointing to.  First read the header of the next member if this
962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     has not happened already.  */
963b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref->state.ar.elf_ar_hdr.ar_name == NULL
96402f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper      && __libelf_next_arhdr_wrlock (ref) != 0)
965b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Something went wrong.  Maybe there is no member left.  */
966b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return NULL;
967b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have all the information we need about the next archive member.
969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Now create a descriptor for it.  */
970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Enlist this new descriptor in the list of children.  */
974b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (result != NULL)
975b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
976b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->next = ref->state.ar.children;
977b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ref->state.ar.children = result;
978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Return desriptor for empty file ready for writing.  */
985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct Elf *
986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwrite_file (int fd, Elf_Cmd cmd)
987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We simply create an empty `Elf' structure.  */
989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define NSCNSALLOC	10
990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      NSCNSALLOC * sizeof (Elf_Scn));
992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (result != NULL)
994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We have to write to the file in any case.  */
996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->flags = ELF_F_DIRTY;
997b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Some more or less arbitrary value.  */
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->state.elf.scnincr = NSCNSALLOC;
1000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We have allocated room for some sections.  */
1002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      assert (offsetof (struct Elf, state.elf32.scns)
1003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      == offsetof (struct Elf, state.elf64.scns));
1004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->state.elf.scns_last = &result->state.elf32.scns;
1005b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->state.elf32.scns.max = NSCNSALLOC;
1006b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1007b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1008b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
1009b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1010b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1011b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1012b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Return a descriptor for the file belonging to FILDES.  */
1013b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperElf *
1014b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperelf_begin (fildes, cmd, ref)
1015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     int fildes;
1016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Elf_Cmd cmd;
1017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Elf *ref;
1018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1019b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *retval;
1020b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1021fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (! __libelf_version_initialized))
1022b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1023b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Version wasn't set so far.  */
1024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_NO_VERSION);
1025b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
1026b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1027b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1028b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref != NULL)
1029b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Make sure the descriptor is not suddenly going away.  */
1030b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath    rwlock_rdlock (ref->lock);
1031fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  else if (unlikely (fcntl (fildes, F_GETFL) == -1 && errno == EBADF))
1032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We cannot do anything productive without a file descriptor.  */
1034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_INVALID_FILE);
1035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
1036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
103802f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper  Elf *lock_dup_elf ()
103902f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper  {
104002f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper    /* We need wrlock to dup an archive.  */
104102f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper    if (ref->kind == ELF_K_AR)
104202f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper      {
104302f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper	rwlock_unlock (ref->lock);
104402f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper	rwlock_wrlock (ref->lock);
104502f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper      }
104602f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper
104702f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper    /* Duplicate the descriptor.  */
104802f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper    return dup_elf (fildes, cmd, ref);
104902f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper  }
105002f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper
1051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (cmd)
1052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_NULL:
1054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We simply return a NULL pointer.  */
1055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      retval = NULL;
1056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_READ_MMAP_PRIVATE:
1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have a reference it must also be opened this way.  */
1060fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_INVALID_CMD);
1063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  retval = NULL;
1064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* FALLTHROUGH */
1067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_READ:
1069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_READ_MMAP:
1070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ref != NULL)
107102f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper	retval = lock_dup_elf ();
1072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
1073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create descriptor for existing file.  */
1074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_RDWR:
1078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_RDWR_MMAP:
1079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have a REF object it must also be opened using this
1080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 command.  */
1081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ref != NULL)
1082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1083fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1084fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			&& ref->cmd != ELF_C_WRITE
1085fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			&& ref->cmd != ELF_C_WRITE_MMAP))
1086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* This is not ok.  REF must also be opened for writing.  */
1088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      __libelf_seterrno (ELF_E_INVALID_CMD);
1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      retval = NULL;
1090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
109202f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper	    retval = lock_dup_elf ();
1093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create descriptor for existing file.  */
1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_WRITE:
1100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_WRITE_MMAP:
1101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We ignore REF and prepare a descriptor to write a new file.  */
1102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      retval = write_file (fildes, cmd);
1103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
1106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_INVALID_CMD);
1107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      retval = NULL;
1108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Release the lock.  */
1112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref != NULL)
1113b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath    rwlock_unlock (ref->lock);
1114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return retval;
1116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1117b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperINTDEF(elf_begin)
1118