1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Create descriptor for processing file.
2b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard   Copyright (C) 1998-2010, 2012, 2014, 2015 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
154560aa98b9aaa89ce345239de865eda0ba403af68Mark Wielaard		  || (((size_t) ((char *) map_address + ehdr.e32->e_shoff))
155560aa98b9aaa89ce345239de865eda0ba403af68Mark Wielaard		      & (__alignof__ (Elf32_Shdr) - 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
204560aa98b9aaa89ce345239de865eda0ba403af68Mark Wielaard		  || (((size_t) ((char *) map_address + ehdr.e64->e_shoff))
205560aa98b9aaa89ce345239de865eda0ba403af68Mark Wielaard		      & (__alignof__ (Elf64_Shdr) - 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
2191ed7195ea8f6ccb47c2e5b911fbc4105f18a5d2eJose E. Marchesi		if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Xword),
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
309b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      || (((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We can use the mmapped memory.  */
312fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf32.ehdr = ehdr;
313b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	}
314b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      else
315b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	{
316b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  /* Copy the ELF header.  */
317b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
318b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard					  sizeof (Elf32_Ehdr));
319b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard
320b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  if (e_ident[EI_DATA] != MY_ELFDATA)
321b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	    {
322b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_type);
323b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_machine);
324b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_version);
325b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_entry);
326b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
327b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
328b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_flags);
329b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
330b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
331b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
332b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
333b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
334b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
335b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	    }
336b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	}
337b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard
338b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      /* Don't precache the phdr pointer here.
339b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	 elf32_getphdr will validate it against the size when asked.  */
340720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek
341b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
342b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
343272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
344b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  && (ALLOW_UNALIGNED
345b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      || (((uintptr_t) ((char *) ehdr + e_shoff)
346b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard		   & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
347b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	{
348b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  if (unlikely (e_shoff >= maxsize)
349b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      || unlikely (maxsize - e_shoff
350720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek			   < scncnt * sizeof (Elf32_Shdr)))
351720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    {
352720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    free_and_out:
353720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      free (elf);
354720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      __libelf_seterrno (ELF_E_INVALID_FILE);
355720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	      return NULL;
356720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    }
357fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf32.shdr
358b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	    = (Elf32_Shdr *) ((char *) ehdr + e_shoff);
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].index = cnt;
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].elf = elf;
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].shdr.e32 =
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&elf->state.elf32.shdr[cnt];
366429502fd324d731feb939a5db4b7e0723adac616Roland McGrath	      if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
367b635b8dcb097a25de96d9788deea509beac1518dMark Wielaard		  && likely (elf->state.elf32.shdr[cnt].sh_size
368b635b8dcb097a25de96d9788deea509beac1518dMark Wielaard			     <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
369429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		elf->state.elf32.scns.data[cnt].rawdata_base =
370429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  elf->state.elf32.scns.data[cnt].data_base =
371429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  ((char *) map_address + offset
372429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		   + elf->state.elf32.shdr[cnt].sh_offset);
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
3743cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
3753cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* If this is a section with an extended index add a
3763cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 reference in the section which uses the extended
3773cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 index.  */
3783cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
3793cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  && elf->state.elf32.shdr[cnt].sh_link < scncnt)
3803cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
3813cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  = cnt;
3823cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
3833cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* Set the own shndx_index field in case it has not yet
3843cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 been set.  */
3853cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
3863cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf32.scns.data[cnt].shndx_index = -1;
387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].index = cnt;
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].elf = elf;
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* So far only one block with sections.  */
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.elf32.scns_last = &elf->state.elf32.scns;
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This pointer might not be directly usable if the alignment is
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 not sufficient for the architecture.  */
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This is a 64-bit binary.  */
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (ALLOW_UNALIGNED
411b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      || (((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We can use the mmapped memory.  */
414fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf64.ehdr = ehdr;
415b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	}
416b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      else
417b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	{
418b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  /* Copy the ELF header.  */
419b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
420b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard					  sizeof (Elf64_Ehdr));
421b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard
422b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  if (e_ident[EI_DATA] != MY_ELFDATA)
423b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	    {
424b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_type);
425b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_machine);
426b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_version);
427b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_entry);
428b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
429b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
430b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_flags);
431b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
432b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
433b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
434b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
435b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
436b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
437b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	    }
438b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	}
439b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard
440b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      /* Don't precache the phdr pointer here.
441b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	 elf64_getphdr will validate it against the size when asked.  */
442720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek
443b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
444b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
445272018bba1f253bae00b5ba280ad0e0f18c04006Mark Wielaard	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
446b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  && (ALLOW_UNALIGNED
447b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      || (((uintptr_t) ((char *) ehdr + e_shoff)
448b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard		   & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
449b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	{
450b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	  if (unlikely (e_shoff >= maxsize)
451b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	      || unlikely (maxsize - e_shoff
45265a556fc865657ada6355686dedd282d6f1ad863Mark Wielaard			   < scncnt * sizeof (Elf64_Shdr)))
453720383c53b435de6647edd78060dd7d38ade25a5Jakub Jelinek	    goto free_and_out;
454fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  elf->state.elf64.shdr
455b9fd0eee50b028e4752595a8cc293bf2c331b1b9Mark Wielaard	    = (Elf64_Shdr *) ((char *) ehdr + e_shoff);
456b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
457b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
458b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
459b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].index = cnt;
460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].elf = elf;
461b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].shdr.e64 =
462b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		&elf->state.elf64.shdr[cnt];
463429502fd324d731feb939a5db4b7e0723adac616Roland McGrath	      if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
464b635b8dcb097a25de96d9788deea509beac1518dMark Wielaard		  && likely (elf->state.elf64.shdr[cnt].sh_size
465b635b8dcb097a25de96d9788deea509beac1518dMark Wielaard			     <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
466429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		elf->state.elf64.scns.data[cnt].rawdata_base =
467429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  elf->state.elf64.scns.data[cnt].data_base =
468429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		  ((char *) map_address + offset
469429502fd324d731feb939a5db4b7e0723adac616Roland McGrath		   + elf->state.elf64.shdr[cnt].sh_offset);
470b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
4713cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
4723cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* If this is a section with an extended index add a
4733cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 reference in the section which uses the extended
4743cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 index.  */
4753cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
4763cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  && elf->state.elf64.shdr[cnt].sh_link < scncnt)
4773cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
4783cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		  = cnt;
4793cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper
4803cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      /* Set the own shndx_index field in case it has not yet
4813cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		 been set.  */
4823cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper	      if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
4833cbdd387c752999255aea91600b5cfdefbeac7d0Ulrich Drepper		elf->state.elf64.scns.data[cnt].shndx_index = -1;
484b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
485b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
486b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
487b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
488b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
489b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
490b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].index = cnt;
491b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].elf = elf;
492b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
493b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
494b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
495b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
496b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* So far only one block with sections.  */
497b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.elf64.scns_last = &elf->state.elf64.scns;
498b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
499b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
500b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return elf;
501b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
502b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
503b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
504b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperElf *
505077c65f3be02e5d01b0c4dea3f6c854077d156fcUlrich Drepperinternal_function
506b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper__libelf_read_mmaped_file (int fildes, void *map_address,  off_t offset,
507b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			   size_t maxsize, Elf_Cmd cmd, Elf *parent)
508b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
509b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have to find out what kind of file this is.  We handle ELF
510b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     files and archives.  To find out what we have we must look at the
511b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     header.  The header for an ELF file is EI_NIDENT bytes in size,
512b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     the header for an archive file SARMAG bytes long.  */
513fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  unsigned char *e_ident = (unsigned char *) map_address + offset;
514b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
515b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* See what kind of object we have here.  */
516fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  Elf_Kind kind = determine_kind (e_ident, maxsize);
517b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
518b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (kind)
519b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
520b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
521fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
522fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			    cmd, parent);
523b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
524b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
525b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
526b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
527b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
528b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
529b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
530b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* This case is easy.  Since we cannot do anything with this file
532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     create a dummy descriptor.  */
533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ELF_K_NONE, 0);
535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
537b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
538b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *
539b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperread_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd,
540b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    Elf *parent)
541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have to find out what kind of file this is.  We handle ELF
543b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     files and archives.  To find out what we have we must read the
544fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     header.  The identification header for an ELF file is EI_NIDENT
545fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     bytes in size, but we read the whole ELF header since we will
546fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     need it anyway later.  For archives the header in SARMAG bytes
547fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     long.  Read the maximum of these numbers.
548fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper
549fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     XXX We have to change this for the extended `ar' format some day.
550490063eb2bd6a131104c0070aa0fa37d0b037c49Ulrich Drepper
551fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     Use a union to ensure alignment.  We might later access the
552fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper     memory as a ElfXX_Ehdr.  */
553fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  union
554fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  {
555fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper    Elf64_Ehdr ehdr;
556fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper    unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
557fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  } mem;
558b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
559b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Read the head of the file.  */
560fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  ssize_t nread = pread_retry (fildes, mem.header,
561fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			       MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
562fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper				    maxsize),
563fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			       offset);
564fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (nread == -1))
565237188e4d764598300a577e08fd872339812fb2cPetr Machata    {
566237188e4d764598300a577e08fd872339812fb2cPetr Machata      /* We cannot even read the head of the file.  Maybe FILDES is associated
567237188e4d764598300a577e08fd872339812fb2cPetr Machata	 with an unseekable device.  This is nothing we can handle.  */
568237188e4d764598300a577e08fd872339812fb2cPetr Machata      __libelf_seterrno (ELF_E_INVALID_FILE);
569237188e4d764598300a577e08fd872339812fb2cPetr Machata      return NULL;
570237188e4d764598300a577e08fd872339812fb2cPetr Machata    }
571b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
572b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* See what kind of object we have here.  */
573fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  Elf_Kind kind = determine_kind (mem.header, nread);
574b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
575b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (kind)
576b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
577b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_AR:
578b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
579b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
580b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_K_ELF:
581b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Make sure at least the ELF header is contained in the file.  */
582fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
583fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			     ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
584fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
585fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			      parent);
586b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* FALLTHROUGH */
587b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
588b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
589b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
590b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
591b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* This case is easy.  Since we cannot do anything with this file
593b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     create a dummy descriptor.  */
594b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
595b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		       ELF_K_NONE, 0);
596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
599b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Open a file for reading.  If possible we will try to mmap() the file.  */
600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct Elf *
601b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperread_file (int fildes, off_t offset, size_t maxsize,
602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	   Elf_Cmd cmd, Elf *parent)
603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  void *map_address = NULL;
605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || cmd == ELF_C_WRITE_MMAP
607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || cmd == ELF_C_READ_MMAP_PRIVATE);
608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (use_mmap)
610b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
611b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (parent == NULL)
612b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (maxsize == ~((size_t) 0))
614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* We don't know in the moment how large the file is.
616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 Determine it now.  */
617b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      struct stat st;
618b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (fstat (fildes, &st) == 0
620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && (sizeof (size_t) >= sizeof (st.st_size)
621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      || st.st_size <= ~((size_t) 0)))
622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		maxsize = (size_t) st.st_size;
623b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
624b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* We try to map the file ourself.  */
626b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
627b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      ? PROT_READ
628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      : PROT_READ|PROT_WRITE),
629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      cmd == ELF_C_READ_MMAP_PRIVATE
630ce0bdb6ee5f977af9e565f2871ba2b1b37d162a5Ulrich Drepper			      || cmd == ELF_C_READ_MMAP
631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      ? MAP_PRIVATE : MAP_SHARED,
632b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      fildes, offset);
633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (map_address == MAP_FAILED)
635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    map_address = NULL;
636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
637b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
638b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* The parent is already loaded.  Use it.  */
640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  assert (maxsize != ~((size_t) 0));
641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  map_address = parent->map_address;
643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
645b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
646b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* If we have the file in memory optimize the access.  */
647b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (map_address != NULL)
648b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
649fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      assert (map_address != MAP_FAILED);
650b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
651fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
652fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper						      offset, maxsize, cmd,
653fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper						      parent);
654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If something went wrong during the initialization unmap the
656b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 memory if we mmaped here.  */
657b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (result == NULL
658b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && (parent == NULL
659b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      || parent->map_address != map_address))
660b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	munmap (map_address, maxsize);
661b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (parent == NULL)
662b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Remember that we mmap()ed the memory.  */
663b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	result->flags |= ELF_F_MMAPPED;
664b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
665b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return result;
666b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
667b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
668b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Otherwise we have to do it the hard way.  We read as much as necessary
669b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     from the file whenever we need information which is not available.  */
670b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
671b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
672b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
673b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
674b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Find the entry with the long names for the content of this archive.  */
675b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic const char *
676b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperread_long_names (Elf *elf)
677b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
678b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  off_t offset = SARMAG;	/* This is the first entry.  */
679b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct ar_hdr hdrm;
680b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct ar_hdr *hdr;
681b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  char *newp;
682b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t len;
683b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
684b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while (1)
685b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
686b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf->map_address != NULL)
687b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
6887d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard	  if ((size_t) offset > elf->maximum_size
6897d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard	      || elf->maximum_size - offset < sizeof (struct ar_hdr))
690b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    return NULL;
691b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
692b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* The data is mapped.  */
693b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  hdr = (struct ar_hdr *) (elf->map_address + offset);
694b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
695b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
696b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
697b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Read the header from the file.  */
698fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
699fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper				     elf->start_offset + offset)
700fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			!= sizeof (hdrm)))
701b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    return NULL;
702b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
703b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  hdr = &hdrm;
704b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
705b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
706b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      len = atol (hdr->ar_size);
707b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
708b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (memcmp (hdr->ar_name, "//              ", 16) == 0)
709b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	break;
710b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
711b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
712b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
713b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
714b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Due to the stupid format of the long name table entry (which are not
715b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     NUL terminted) we have to provide an appropriate representation anyhow.
716b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Therefore we always make a copy which has the appropriate form.  */
717b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  newp = (char *) malloc (len);
718b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (newp != NULL)
719b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
720b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char *runp;
721b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
722b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (elf->map_address != NULL)
72355f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard	{
72455f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard	  if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
72555f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard	    goto too_much;
72655f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard	  /* Simply copy it over.  */
72755f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard	  elf->state.ar.long_names = (char *) memcpy (newp,
72855f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard						      elf->map_address + offset
72955f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard						      + sizeof (struct ar_hdr),
73055f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard						      len);
73155f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard	}
732b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
733b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
734fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
735fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					      elf->start_offset + offset
736fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper					      + sizeof (struct ar_hdr))
737fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			!= len))
738b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
73955f847d63ae3ef7d4469628070d2adb74004c584Mark Wielaard	    too_much:
740b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* We were not able to read all data.  */
741b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      free (newp);
742b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      elf->state.ar.long_names = NULL;
743b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return NULL;
744b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
745b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  elf->state.ar.long_names = newp;
746b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
747b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
748b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf->state.ar.long_names_len = len;
749b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
750b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Now NUL-terminate the strings.  */
751b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      runp = newp;
752b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      while (1)
753b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper        {
7549520242b2ab23a3e713f2b7d1a968777feb06bfaMark Wielaard	  char *startp = runp;
755b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  runp = (char *) memchr (runp, '/', newp + len - runp);
756b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (runp == NULL)
7579520242b2ab23a3e713f2b7d1a968777feb06bfaMark Wielaard	    {
7589520242b2ab23a3e713f2b7d1a968777feb06bfaMark Wielaard	      /* This was the last entry.  Clear any left overs.  */
7599520242b2ab23a3e713f2b7d1a968777feb06bfaMark Wielaard	      memset (startp, '\0', newp + len - startp);
7609520242b2ab23a3e713f2b7d1a968777feb06bfaMark Wielaard	      break;
7619520242b2ab23a3e713f2b7d1a968777feb06bfaMark Wielaard	    }
762b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
763b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* NUL-terminate the string.  */
764147018e729e7c22eeabf15b82d26e4bf68a0d18eAlexander Cherepanov	  *runp++ = '\0';
765b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
766b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* A sanity check.  Somebody might have generated invalid
767b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     archive.  */
768b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (runp >= newp + len)
769b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    break;
770b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
771b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
772b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
773b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return newp;
774b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
775b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
776b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
777b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Read the next archive header.  */
778b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
779077c65f3be02e5d01b0c4dea3f6c854077d156fcUlrich Drepperinternal_function
7801ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard__libelf_next_arhdr_wrlock (Elf *elf)
781b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
782b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct ar_hdr *ar_hdr;
783b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf_Arhdr *elf_ar_hdr;
784b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
785b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (elf->map_address != NULL)
786b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
787b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* See whether this entry is in the file.  */
7887d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard      if (unlikely ((size_t) elf->state.ar.offset
7897d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard		    > elf->start_offset + elf->maximum_size
7907d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard		    || (elf->start_offset + elf->maximum_size
7917d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard			- elf->state.ar.offset) < sizeof (struct ar_hdr)))
792b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
793b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* This record is not anymore in the file.  */
794b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_RANGE);
795b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return -1;
796b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
797b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
798b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
799b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
800b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
801b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ar_hdr = &elf->state.ar.ar_hdr;
802b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
803fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
804fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper				 elf->state.ar.offset)
805fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		    != sizeof (struct ar_hdr)))
806b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
807b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Something went wrong while reading the file.  */
808b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_RANGE);
809b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return -1;
810b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
811b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
812b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
813b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* One little consistency check.  */
814fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
815b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
816b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* This is no valid archive.  */
817b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
818b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return -1;
819b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
820b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
821b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Copy the raw name over to a NUL terminated buffer.  */
822babd5b6d9ed844dd63cf812444bbfcbfcadcd6e2Mark Wielaard  *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
823b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
824b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
825b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
826b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
827b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Determine whether this is a special entry.  */
828b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ar_hdr->ar_name[0] == '/')
829b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
830b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ar_hdr->ar_name[1] == ' '
831b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  && memcmp (ar_hdr->ar_name, "/               ", 16) == 0)
832b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* This is the index.  */
833b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
834e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata      else if (ar_hdr->ar_name[1] == 'S'
835e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata	       && memcmp (ar_hdr->ar_name, "/SYM64/         ", 16) == 0)
836e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata	/* 64-bit index.  */
837e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
838b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else if (ar_hdr->ar_name[1] == '/'
839b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       && memcmp (ar_hdr->ar_name, "//              ", 16) == 0)
840b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* This is the array with the long names.  */
841b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
842fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      else if (likely  (isdigit (ar_hdr->ar_name[1])))
843b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
844b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t offset;
845b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
846b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* This is a long name.  First we have to read the long name
847b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	     table, if this hasn't happened already.  */
848fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (elf->state.ar.long_names == NULL
849fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			&& read_long_names (elf) == NULL))
850b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
851b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* No long name table although it is reference.  The archive is
852b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 broken.  */
853b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
854b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return -1;
855b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
856b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
857b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  offset = atol (ar_hdr->ar_name + 1);
858fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (offset >= elf->state.ar.long_names_len))
859b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
860b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* The index in the long name table is larger than the table.  */
861b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
862b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return -1;
863b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
864b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
865b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
866b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
867b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
868b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* This is none of the known special entries.  */
869b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
870b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  return -1;
871b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
872b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
873b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  else
874b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
875b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      char *endp;
876b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
877b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* It is a normal entry.  Copy over the name.  */
878b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
879b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			       '/', 16);
880b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (endp != NULL)
881b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	endp[-1] = '\0';
882b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
883b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
884b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  /* In the old BSD style of archive, there is no / terminator.
885b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	     Instead, there is space padding at the end of the name.  */
886b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  size_t i = 15;
887b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  do
888b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    elf->state.ar.ar_name[i] = '\0';
889b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
890b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
891b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
892b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      elf_ar_hdr->ar_name = elf->state.ar.ar_name;
893b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
894b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
895059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  if (unlikely (ar_hdr->ar_size[0] == ' '))
896059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    /* Something is really wrong.  We cannot live without a size for
897059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath       the member since it will not be possible to find the next
898059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath       archive member.  */
899059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {
900059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
901059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      return -1;
902059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }
903059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
904b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Since there are no specialized functions to convert ASCII to
905b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
906b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     atoll depending on the size of the types.  We are also prepared
907b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     for the case where the whole field in the `struct ar_hdr' is
908b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     filled in which case we cannot simply use atol/l but instead have
909b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     to create a temporary copy.  */
910b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
911059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath#define INT_FIELD(FIELD)						      \
912059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  do									      \
913059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    {									      \
914059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      char buf[sizeof (ar_hdr->FIELD) + 1];				      \
915059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      const char *string = ar_hdr->FIELD;				      \
916059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
917059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	{								      \
918babd5b6d9ed844dd63cf812444bbfcbfcadcd6e2Mark Wielaard	  *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
919059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	    = '\0';							      \
920059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	  string = buf;							      \
921059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	}								      \
922059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
923059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string);     \
924059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath      else								      \
925059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string);    \
926059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath    }									      \
927059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  while (0)
928059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath
929059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_date);
930059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_uid);
931059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_gid);
932059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_mode);
933059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath  INT_FIELD (ar_size);
934b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
93568588d628a464698031323d8eb42a961c0846ba9Mark Wielaard  if (elf_ar_hdr->ar_size < 0)
93668588d628a464698031323d8eb42a961c0846ba9Mark Wielaard    {
93768588d628a464698031323d8eb42a961c0846ba9Mark Wielaard      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
93868588d628a464698031323d8eb42a961c0846ba9Mark Wielaard      return -1;
93968588d628a464698031323d8eb42a961c0846ba9Mark Wielaard    }
94068588d628a464698031323d8eb42a961c0846ba9Mark Wielaard
9417d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard  /* Truncated file?  */
9427d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard  size_t maxsize;
94368588d628a464698031323d8eb42a961c0846ba9Mark Wielaard  maxsize = (elf->start_offset + elf->maximum_size
94468588d628a464698031323d8eb42a961c0846ba9Mark Wielaard	     - elf->state.ar.offset - sizeof (struct ar_hdr));
9457d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard  if ((size_t) elf_ar_hdr->ar_size > maxsize)
9467d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard    elf_ar_hdr->ar_size = maxsize;
9477d63628b8a72dbeefe8976939c7090f3d1a23311Mark Wielaard
948b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return 0;
949b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
950b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
951b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
952b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* We were asked to return a clone of an existing descriptor.  This
953b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   function must be called with the lock on the parent descriptor
954b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   being held. */
955b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Elf *
956b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperdup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
957b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
958b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct Elf *result;
959b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
960b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (fildes == -1)
961b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Allow the user to pass -1 as the file descriptor for the new file.  */
962b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    fildes = ref->fildes;
963b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The file descriptor better should be the same.  If it was disconnected
964b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     already (using `elf_cntl') we do not test it.  */
965fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
966b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
967b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_FD_MISMATCH);
968b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
969b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
970b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
971b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* The mode must allow reading.  I.e., a descriptor creating with a
972b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
973b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     not allowed.  */
974fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
975fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
976fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
977fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper		&& ref->cmd != ELF_C_READ_MMAP_PRIVATE))
978b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
979b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_INVALID_OP);
980b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
981b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
982b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
983b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Now it is time to distinguish between reading normal files and
984b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     archives.  Normal files can easily be handled be incrementing the
985b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     reference counter and return the same descriptor.  */
986b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref->kind != ELF_K_AR)
987b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
988b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ++ref->ref_count;
989b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ref;
990b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
991b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
992b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* This is an archive.  We must create a descriptor for the archive
993b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     member the internal pointer of the archive file desriptor is
994b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     pointing to.  First read the header of the next member if this
995b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     has not happened already.  */
996b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref->state.ar.elf_ar_hdr.ar_name == NULL
99702f66452635df3d01f7e57845c3362ab828e3d89Ulrich Drepper      && __libelf_next_arhdr_wrlock (ref) != 0)
998b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Something went wrong.  Maybe there is no member left.  */
999b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return NULL;
1000b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1001b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We have all the information we need about the next archive member.
1002b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper     Now create a descriptor for it.  */
1003b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
1004b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
1005b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1006b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Enlist this new descriptor in the list of children.  */
1007b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (result != NULL)
1008b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1009b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->next = ref->state.ar.children;
1010b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      ref->state.ar.children = result;
1011b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1012b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1013b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
1014b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1015b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1016b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1017b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Return desriptor for empty file ready for writing.  */
1018b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic struct Elf *
1019b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperwrite_file (int fd, Elf_Cmd cmd)
1020b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1021b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* We simply create an empty `Elf' structure.  */
1022b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define NSCNSALLOC	10
1023b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
1024b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			      NSCNSALLOC * sizeof (Elf_Scn));
1025b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1026b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (result != NULL)
1027b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1028b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We have to write to the file in any case.  */
1029b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->flags = ELF_F_DIRTY;
1030b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1031b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Some more or less arbitrary value.  */
1032b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->state.elf.scnincr = NSCNSALLOC;
1033b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1034b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We have allocated room for some sections.  */
1035b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      assert (offsetof (struct Elf, state.elf32.scns)
1036b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      == offsetof (struct Elf, state.elf64.scns));
1037b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->state.elf.scns_last = &result->state.elf32.scns;
1038b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      result->state.elf32.scns.max = NSCNSALLOC;
1039b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1040b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1041b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return result;
1042b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1043b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1044239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh/* Lock if necessary before dup an archive.  */
1045239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsiehstatic inline Elf *
1046239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsiehlock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1047239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh{
1048239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh  /* We need wrlock to dup an archive.  */
1049239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh  if (ref->kind == ELF_K_AR)
1050239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh    {
1051239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh      rwlock_unlock (ref->lock);
1052239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh      rwlock_wrlock (ref->lock);
1053239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh    }
1054239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh    /* Duplicate the descriptor.  */
1055239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh  return dup_elf (fildes, cmd, ref);
1056239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh}
1057b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1058b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Return a descriptor for the file belonging to FILDES.  */
1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperElf *
10601ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaardelf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
1061b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
1062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Elf *retval;
1063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1064fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  if (unlikely (! __libelf_version_initialized))
1065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Version wasn't set so far.  */
1067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_NO_VERSION);
1068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
1069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref != NULL)
1072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    /* Make sure the descriptor is not suddenly going away.  */
1073b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath    rwlock_rdlock (ref->lock);
1074fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper  else if (unlikely (fcntl (fildes, F_GETFL) == -1 && errno == EBADF))
1075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We cannot do anything productive without a file descriptor.  */
1077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_INVALID_FILE);
1078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return NULL;
1079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1080b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1081b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (cmd)
1082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
1083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_NULL:
1084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We simply return a NULL pointer.  */
1085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      retval = NULL;
1086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_READ_MMAP_PRIVATE:
1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have a reference it must also be opened this way.  */
1090fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper      if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  __libelf_seterrno (ELF_E_INVALID_CMD);
1093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  retval = NULL;
1094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  break;
1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* FALLTHROUGH */
1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1098b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_READ:
1099b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_READ_MMAP:
1100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ref != NULL)
1101239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh	retval = lock_dup_elf (fildes, cmd, ref);
1102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
1103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create descriptor for existing file.  */
1104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_RDWR:
1108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_RDWR_MMAP:
1109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* If we have a REF object it must also be opened using this
1110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 command.  */
1111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      if (ref != NULL)
1112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
1113fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper	  if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1114fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			&& ref->cmd != ELF_C_WRITE
1115fbe998a0b1be1f006bc72e5138fb38c188cc0433Ulrich Drepper			&& ref->cmd != ELF_C_WRITE_MMAP))
1116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
1117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* This is not ok.  REF must also be opened for writing.  */
1118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      __libelf_seterrno (ELF_E_INVALID_CMD);
1119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      retval = NULL;
1120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
1121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
1122239d859169543c21fcb43e27d4a81a9948a2b42dChih-Hung Hsieh	    retval = lock_dup_elf (fildes, cmd, ref);
1123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
1124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      else
1125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/* Create descriptor for existing file.  */
1126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_WRITE:
1130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case ELF_C_WRITE_MMAP:
1131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* We ignore REF and prepare a descriptor to write a new file.  */
1132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      retval = write_file (fildes, cmd);
1133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
1136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      __libelf_seterrno (ELF_E_INVALID_CMD);
1137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      retval = NULL;
1138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      break;
1139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
1140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  /* Release the lock.  */
1142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (ref != NULL)
1143b4d6f0f8064f2b706ea9035ef0393d8299671390Roland McGrath    rwlock_unlock (ref->lock);
1144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
1145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return retval;
1146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
1147b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperINTDEF(elf_begin)
1148