125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Create descriptor for processing file.
203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   Copyright (C) 1998-2010, 2012, 2014 Red Hat, Inc.
303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is part of elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is free software; you can redistribute it and/or modify
703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   it under the terms of either
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU Lesser General Public License as published by the Free
1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 3 of the License, or (at
1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or
1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU General Public License as published by the Free
1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 2 of the License, or (at
1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or both in parallel, as here.
2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   elfutils is distributed in the hope that it will be useful, but
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   You should have received copies of the GNU General Public License and
2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   the GNU Lesser General Public License along with this program.  If
2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   not, see <http://www.gnu.org/licenses/>.  */
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <ctype.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <errno.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stddef.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/mman.h>
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h>
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libelfP.h"
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "common.h"
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Create descriptor for archive in memory.  */
5225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic inline Elf *
5325b3c049e70834cf33790a28643ab058b507b35cBen Chengfile_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      Elf_Cmd cmd, Elf *parent)
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf;
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create a descriptor.  */
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng                      ELF_K_AR, 0);
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf != NULL)
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We don't read all the symbol tables in advance.  All this will
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 happen on demand.  */
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ar.offset = offset + SARMAG;
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return elf;
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t
7525b3c049e70834cf33790a28643ab058b507b35cBen Chengget_shnum (void *map_address, unsigned char *e_ident, int fildes, off_t offset,
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   size_t maxsize)
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t result;
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  union
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    Elf32_Ehdr *e32;
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    Elf64_Ehdr *e64;
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    void *p;
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  } ehdr;
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  union
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    Elf32_Ehdr e32;
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    Elf64_Ehdr e64;
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  } ehdr_mem;
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make the ELF header available.  */
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (e_ident[EI_DATA] == MY_ELFDATA
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && (ALLOW_UNALIGNED
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || (((size_t) e_ident
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  - 1)) == 0)))
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    ehdr.p = e_ident;
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We already read the ELF header.  We have to copy the header
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 since we possibly modify the data here and the caller
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 expects the memory it passes in to be preserved.  */
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ehdr.p = &ehdr_mem;
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (is32)
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ALLOW_UNALIGNED)
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (e_ident[EI_DATA] != MY_ELFDATA)
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (ehdr_mem.e32.e_shnum);
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (ehdr_mem.e32.e_shoff);
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ALLOW_UNALIGNED)
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (e_ident[EI_DATA] != MY_ELFDATA)
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (ehdr_mem.e64.e_shnum);
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (ehdr_mem.e64.e_shoff);
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (is32)
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the number of sections from the ELF header.  */
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = ehdr.e32->e_shnum;
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (unlikely (ehdr.e32->e_shoff >= maxsize)
14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Cannot read the first section header.  */
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return 0;
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (ALLOW_UNALIGNED
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (((size_t) ((char *) map_address + offset))
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* We can directly access the memory.  */
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      + offset))->sh_size;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      Elf32_Word size;
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (likely (map_address != NULL))
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* gcc will optimize the memcpy to a simple memory
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   access while taking care of alignment issues.  */
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		memcpy (&size, &((Elf32_Shdr *) ((char *) map_address
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 + ehdr.e32->e_shoff
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 + offset))->sh_size,
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			sizeof (Elf32_Word));
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word),
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   offset + ehdr.e32->e_shoff
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   + offsetof (Elf32_Shdr, sh_size))
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      != sizeof (Elf32_Word)))
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  return (size_t) -1l;
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (e_ident[EI_DATA] != MY_ELFDATA)
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		CONVERT (size);
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      result = size;
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If the section headers were truncated, pretend none were there.  */
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr.e32->e_shoff > maxsize
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = 0;
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Get the number of sections from the ELF header.  */
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = ehdr.e64->e_shnum;
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
19603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (unlikely (ehdr.e64->e_shoff >= maxsize)
19703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Cannot read the first section header.  */
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return 0;
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf64_Xword size;
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && (ALLOW_UNALIGNED
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (((size_t) ((char *) map_address + offset))
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* We can directly access the memory.  */
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    + offset))->sh_size;
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (likely (map_address != NULL))
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* gcc will optimize the memcpy to a simple memory
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   access while taking care of alignment issues.  */
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		memcpy (&size, &((Elf64_Shdr *) ((char *) map_address
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 + ehdr.e64->e_shoff
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng						 + offset))->sh_size,
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			sizeof (Elf64_Xword));
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Word),
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   offset + ehdr.e64->e_shoff
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng					   + offsetof (Elf64_Shdr, sh_size))
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      != sizeof (Elf64_Xword)))
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  return (size_t) -1l;
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (e_ident[EI_DATA] != MY_ELFDATA)
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		CONVERT (size);
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (size > ~((GElf_Word) 0))
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Invalid value, it is too large.  */
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return (size_t) -1l;
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  result = size;
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If the section headers were truncated, pretend none were there.  */
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr.e64->e_shoff > maxsize
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = 0;
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Create descriptor for ELF file in memory.  */
24725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf *
24825b3c049e70834cf33790a28643ab058b507b35cBen Chengfile_read_elf (int fildes, void *map_address, unsigned char *e_ident,
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       off_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Verify the binary is of the class we can handle.  */
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 && e_ident[EI_CLASS] != ELFCLASS64)
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* We also can only handle two encodings.  */
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		|| (e_ident[EI_DATA] != ELFDATA2LSB
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    && e_ident[EI_DATA] != ELFDATA2MSB)))
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Cannot handle this.  */
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_INVALID_FILE);
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return NULL;
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Determine the number of sections.  */
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scncnt == (size_t) -1l)
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Could not determine the number of sections.  */
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Check for too many sections.  */
27003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (e_ident[EI_CLASS] == ELFCLASS32)
27103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
27203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
27303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	return NULL;
27403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
27503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
27603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return NULL;
27703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We can now allocate the memory.  Even if there are no section headers,
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     we allocate space for a zeroth section in case we need it later.  */
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 ? 1 : 0);
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   ELF_K_ELF, scnmax * sizeof (Elf_Scn));
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf == NULL)
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Not enough memory.  */
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert ((unsigned int) scncnt == scncnt);
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (offsetof (struct Elf, state.elf32.scns)
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  == offsetof (struct Elf, state.elf64.scns));
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->state.elf32.scns.cnt = scncnt;
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->state.elf32.scns.max = scnmax;
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Some more or less arbitrary value.  */
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->state.elf.scnincr = 10;
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make the class easily available.  */
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->class = e_ident[EI_CLASS];
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (e_ident[EI_CLASS] == ELFCLASS32)
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This pointer might not be directly usable if the alignment is
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 not sufficient for the architecture.  */
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf32_Ehdr *ehdr = (Elf32_Ehdr *) ((char *) map_address + offset);
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is a 32-bit binary.  */
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && (ALLOW_UNALIGNED
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || ((((uintptr_t) ehdr) & (__alignof__ (Elf32_Ehdr) - 1)) == 0
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      & (__alignof__ (Elf32_Shdr) - 1)) == 0
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      & (__alignof__ (Elf32_Phdr) - 1)) == 0)))
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We can use the mmapped memory.  */
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf->state.elf32.ehdr = ehdr;
31703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
31803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (unlikely (ehdr->e_shoff >= maxsize)
31903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      || unlikely (maxsize - ehdr->e_shoff
32003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   < scncnt * sizeof (Elf32_Shdr)))
32103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
32203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    free_and_out:
32303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      free (elf);
32403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      __libelf_seterrno (ELF_E_INVALID_FILE);
32503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      return NULL;
32603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf->state.elf32.shdr
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    = (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff);
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Don't precache the phdr pointer here.
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf32_getphdr will validate it against the size when asked.  */
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf32.scns.data[cnt].index = cnt;
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf32.scns.data[cnt].elf = elf;
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf32.scns.data[cnt].shdr.e32 =
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&elf->state.elf32.shdr[cnt];
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
34003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  && likely (elf->state.elf32.shdr[cnt].sh_size
34103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			     <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.elf32.scns.data[cnt].rawdata_base =
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf->state.elf32.scns.data[cnt].data_base =
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ((char *) map_address + offset
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   + elf->state.elf32.shdr[cnt].sh_offset);
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If this is a section with an extended index add a
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 reference in the section which uses the extended
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 index.  */
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && elf->state.elf32.shdr[cnt].sh_link < scncnt)
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  = cnt;
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Set the own shndx_index field in case it has not yet
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 been set.  */
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.elf32.scns.data[cnt].shndx_index = -1;
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Copy the ELF header.  */
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  sizeof (Elf32_Ehdr));
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (e_ident[EI_DATA] != MY_ELFDATA)
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_type);
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_machine);
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_version);
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_entry);
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_flags);
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf32.scns.data[cnt].index = cnt;
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf32.scns.data[cnt].elf = elf;
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* So far only one block with sections.  */
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.elf32.scns_last = &elf->state.elf32.scns;
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This pointer might not be directly usable if the alignment is
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 not sufficient for the architecture.  */
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf64_Ehdr *ehdr = (Elf64_Ehdr *) ((char *) map_address + offset);
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is a 64-bit binary.  */
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && (ALLOW_UNALIGNED
40525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || ((((uintptr_t) ehdr) & (__alignof__ (Elf64_Ehdr) - 1)) == 0
40625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && ((uintptr_t) ((char *) ehdr + ehdr->e_shoff)
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      & (__alignof__ (Elf64_Shdr) - 1)) == 0
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && ((uintptr_t) ((char *) ehdr + ehdr->e_phoff)
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      & (__alignof__ (Elf64_Phdr) - 1)) == 0)))
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We can use the mmapped memory.  */
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf->state.elf64.ehdr = ehdr;
41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (unlikely (ehdr->e_shoff >= maxsize)
41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      || unlikely (maxsize - ehdr->e_shoff
41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   < scncnt * sizeof (Elf64_Shdr)))
41703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto free_and_out;
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf->state.elf64.shdr
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    = (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff);
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Don't precache the phdr pointer here.
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     elf64_getphdr will validate it against the size when asked.  */
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf64.scns.data[cnt].index = cnt;
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf64.scns.data[cnt].elf = elf;
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf64.scns.data[cnt].shdr.e64 =
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&elf->state.elf64.shdr[cnt];
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
43103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  && likely (elf->state.elf64.shdr[cnt].sh_size
43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			     <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.elf64.scns.data[cnt].rawdata_base =
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  elf->state.elf64.scns.data[cnt].data_base =
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  ((char *) map_address + offset
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   + elf->state.elf64.shdr[cnt].sh_offset);
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If this is a section with an extended index add a
44025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 reference in the section which uses the extended
44125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 index.  */
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && elf->state.elf64.shdr[cnt].sh_link < scncnt)
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  = cnt;
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Set the own shndx_index field in case it has not yet
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 been set.  */
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.elf64.scns.data[cnt].shndx_index = -1;
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Copy the ELF header.  */
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng					  sizeof (Elf64_Ehdr));
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (e_ident[EI_DATA] != MY_ELFDATA)
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_type);
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_machine);
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_version);
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_entry);
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_flags);
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf64.scns.data[cnt].index = cnt;
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf64.scns.data[cnt].elf = elf;
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* So far only one block with sections.  */
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.elf64.scns_last = &elf->state.elf64.scns;
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return elf;
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49225b3c049e70834cf33790a28643ab058b507b35cBen ChengElf *
49325b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libelf_read_mmaped_file (int fildes, void *map_address,  off_t offset,
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   size_t maxsize, Elf_Cmd cmd, Elf *parent)
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We have to find out what kind of file this is.  We handle ELF
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     files and archives.  To find out what we have we must look at the
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     header.  The header for an ELF file is EI_NIDENT bytes in size,
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     the header for an archive file SARMAG bytes long.  */
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  unsigned char *e_ident = (unsigned char *) map_address + offset;
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* See what kind of object we have here.  */
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Kind kind = determine_kind (e_ident, maxsize);
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (kind)
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_K_ELF:
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    cmd, parent);
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_K_AR:
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* This case is easy.  Since we cannot do anything with this file
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     create a dummy descriptor.  */
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       ELF_K_NONE, 0);
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf *
52725b3c049e70834cf33790a28643ab058b507b35cBen Chengread_unmmaped_file (int fildes, off_t offset, size_t maxsize, Elf_Cmd cmd,
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    Elf *parent)
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We have to find out what kind of file this is.  We handle ELF
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     files and archives.  To find out what we have we must read the
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     header.  The identification header for an ELF file is EI_NIDENT
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     bytes in size, but we read the whole ELF header since we will
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     need it anyway later.  For archives the header in SARMAG bytes
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     long.  Read the maximum of these numbers.
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     XXX We have to change this for the extended `ar' format some day.
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Use a union to ensure alignment.  We might later access the
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     memory as a ElfXX_Ehdr.  */
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  union
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    Elf64_Ehdr ehdr;
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  } mem;
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Read the head of the file.  */
54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ssize_t nread = pread_retry (fildes, mem.header,
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				    maxsize),
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       offset);
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (nread == -1))
55303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
55403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* We cannot even read the head of the file.  Maybe FILDES is associated
55503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 with an unseekable device.  This is nothing we can handle.  */
55603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      __libelf_seterrno (ELF_E_INVALID_FILE);
55703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return NULL;
55803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* See what kind of object we have here.  */
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Kind kind = determine_kind (mem.header, nread);
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (kind)
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_K_AR:
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_K_ELF:
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Make sure at least the ELF header is contained in the file.  */
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      parent);
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* FALLTHROUGH */
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* This case is easy.  Since we cannot do anything with this file
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     create a dummy descriptor.  */
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       ELF_K_NONE, 0);
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Open a file for reading.  If possible we will try to mmap() the file.  */
58825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct Elf *
58925b3c049e70834cf33790a28643ab058b507b35cBen Chengread_file (int fildes, off_t offset, size_t maxsize,
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   Elf_Cmd cmd, Elf *parent)
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *map_address = NULL;
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || cmd == ELF_C_WRITE_MMAP
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || cmd == ELF_C_READ_MMAP_PRIVATE);
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (use_mmap)
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (parent == NULL)
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (maxsize == ~((size_t) 0))
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* We don't know in the moment how large the file is.
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 Determine it now.  */
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct stat st;
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (fstat (fildes, &st) == 0
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && (sizeof (size_t) >= sizeof (st.st_size)
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      || st.st_size <= ~((size_t) 0)))
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		maxsize = (size_t) st.st_size;
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We try to map the file ourself.  */
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      ? PROT_READ
61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      : PROT_READ|PROT_WRITE),
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      cmd == ELF_C_READ_MMAP_PRIVATE
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      || cmd == ELF_C_READ_MMAP
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      ? MAP_PRIVATE : MAP_SHARED,
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      fildes, offset);
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (map_address == MAP_FAILED)
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    map_address = NULL;
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The parent is already loaded.  Use it.  */
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  assert (maxsize != ~((size_t) 0));
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  map_address = parent->map_address;
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If we have the file in memory optimize the access.  */
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (map_address != NULL)
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (map_address != MAP_FAILED);
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng						      offset, maxsize, cmd,
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng						      parent);
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If something went wrong during the initialization unmap the
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 memory if we mmaped here.  */
64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (result == NULL
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && (parent == NULL
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || parent->map_address != map_address))
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	munmap (map_address, maxsize);
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (parent == NULL)
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Remember that we mmap()ed the memory.  */
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result->flags |= ELF_F_MMAPPED;
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return result;
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Otherwise we have to do it the hard way.  We read as much as necessary
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     from the file whenever we need information which is not available.  */
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Find the entry with the long names for the content of this archive.  */
66325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char *
66425b3c049e70834cf33790a28643ab058b507b35cBen Chengread_long_names (Elf *elf)
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t offset = SARMAG;	/* This is the first entry.  */
66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct ar_hdr hdrm;
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct ar_hdr *hdr;
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *newp;
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t len;
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (1)
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf->map_address != NULL)
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
67603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if ((size_t) offset > elf->maximum_size
67703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      || elf->maximum_size - offset < sizeof (struct ar_hdr))
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return NULL;
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* The data is mapped.  */
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  hdr = (struct ar_hdr *) (elf->map_address + offset);
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Read the header from the file.  */
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     elf->start_offset + offset)
68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			!= sizeof (hdrm)))
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return NULL;
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  hdr = &hdrm;
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      len = atol (hdr->ar_size);
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (memcmp (hdr->ar_name, "//              ", 16) == 0)
69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	break;
69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Due to the stupid format of the long name table entry (which are not
70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     NUL terminted) we have to provide an appropriate representation anyhow.
70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Therefore we always make a copy which has the appropriate form.  */
70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  newp = (char *) malloc (len);
70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (newp != NULL)
70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *runp;
70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf->map_address != NULL)
71103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
71203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
71303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    goto too_much;
71403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* Simply copy it over.  */
71503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  elf->state.ar.long_names = (char *) memcpy (newp,
71603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						      elf->map_address + offset
71703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						      + sizeof (struct ar_hdr),
71803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes						      len);
71903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      elf->start_offset + offset
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      + sizeof (struct ar_hdr))
72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			!= len))
72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
72703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    too_much:
72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* We were not able to read all data.  */
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      free (newp);
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      elf->state.ar.long_names = NULL;
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return NULL;
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf->state.ar.long_names = newp;
73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ar.long_names_len = len;
73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Now NUL-terminate the strings.  */
73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      runp = newp;
74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (1)
74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng        {
74203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  char *startp = runp;
74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  runp = (char *) memchr (runp, '/', newp + len - runp);
74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (runp == NULL)
74503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
74603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      /* This was the last entry.  Clear any left overs.  */
74703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      memset (startp, '\0', newp + len - startp);
74803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      break;
74903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* NUL-terminate the string.  */
75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *runp = '\0';
75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Skip the NUL byte and the \012.  */
75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  runp += 2;
75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* A sanity check.  Somebody might have generated invalid
75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     archive.  */
75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (runp >= newp + len)
76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    break;
76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return newp;
76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Read the next archive header.  */
76925b3c049e70834cf33790a28643ab058b507b35cBen Chengint
77025b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function
77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libelf_next_arhdr_wrlock (elf)
77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Elf *elf;
77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct ar_hdr *ar_hdr;
77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Arhdr *elf_ar_hdr;
77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->map_address != NULL)
77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* See whether this entry is in the file.  */
78003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely ((size_t) elf->state.ar.offset
78103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    > elf->start_offset + elf->maximum_size
78203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    || (elf->start_offset + elf->maximum_size
78303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			- elf->state.ar.offset) < sizeof (struct ar_hdr)))
78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This record is not anymore in the file.  */
78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_RANGE);
78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ar_hdr = &elf->state.ar.ar_hdr;
79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 elf->state.ar.offset)
79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    != sizeof (struct ar_hdr)))
79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Something went wrong while reading the file.  */
80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_RANGE);
80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* One little consistency check.  */
80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* This is no valid archive.  */
80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Copy the raw name over to a NUL terminated buffer.  */
81403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Determine whether this is a special entry.  */
82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ar_hdr->ar_name[0] == '/')
82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ar_hdr->ar_name[1] == ' '
82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && memcmp (ar_hdr->ar_name, "/               ", 16) == 0)
82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* This is the index.  */
82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
82603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else if (ar_hdr->ar_name[1] == 'S'
82703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	       && memcmp (ar_hdr->ar_name, "/SYM64/         ", 16) == 0)
82803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	/* 64-bit index.  */
82903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (ar_hdr->ar_name[1] == '/'
83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       && memcmp (ar_hdr->ar_name, "//              ", 16) == 0)
83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* This is the array with the long names.  */
83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (likely  (isdigit (ar_hdr->ar_name[1])))
83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t offset;
83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This is a long name.  First we have to read the long name
83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     table, if this hasn't happened already.  */
84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (elf->state.ar.long_names == NULL
84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			&& read_long_names (elf) == NULL))
84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* No long name table although it is reference.  The archive is
84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 broken.  */
84525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return -1;
84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  offset = atol (ar_hdr->ar_name + 1);
85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (offset >= elf->state.ar.long_names_len))
85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* The index in the long name table is larger than the table.  */
85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return -1;
85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This is none of the known special entries.  */
86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *endp;
86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* It is a normal entry.  Copy over the name.  */
87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       '/', 16);
87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (endp != NULL)
87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	endp[-1] = '\0';
87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* In the old BSD style of archive, there is no / terminator.
87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     Instead, there is space padding at the end of the name.  */
87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t i = 15;
87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  do
88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf->state.ar.ar_name[i] = '\0';
88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf_ar_hdr->ar_name = elf->state.ar.ar_name;
88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ar_hdr->ar_size[0] == ' '))
88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Something is really wrong.  We cannot live without a size for
88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng       the member since it will not be possible to find the next
89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng       archive member.  */
89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Since there are no specialized functions to convert ASCII to
89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     atoll depending on the size of the types.  We are also prepared
89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     for the case where the whole field in the `struct ar_hdr' is
90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     filled in which case we cannot simply use atol/l but instead have
90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     to create a temporary copy.  */
90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define INT_FIELD(FIELD)						      \
90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do									      \
90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {									      \
90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char buf[sizeof (ar_hdr->FIELD) + 1];				      \
90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      const char *string = ar_hdr->FIELD;				      \
90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{								      \
91003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    = '\0';							      \
91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  string = buf;							      \
91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}								      \
91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string);     \
91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else								      \
91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string);    \
91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }									      \
91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (0)
92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  INT_FIELD (ar_date);
92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  INT_FIELD (ar_uid);
92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  INT_FIELD (ar_gid);
92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  INT_FIELD (ar_mode);
92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  INT_FIELD (ar_size);
92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Truncated file?  */
92803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t maxsize;
92903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  maxsize = elf->maximum_size - elf->state.ar.offset - sizeof (struct ar_hdr);
93003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if ((size_t) elf_ar_hdr->ar_size > maxsize)
93103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    elf_ar_hdr->ar_size = maxsize;
93203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* We were asked to return a clone of an existing descriptor.  This
93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   function must be called with the lock on the parent descriptor
93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   being held. */
94025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf *
94125b3c049e70834cf33790a28643ab058b507b35cBen Chengdup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct Elf *result;
94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fildes == -1)
94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Allow the user to pass -1 as the file descriptor for the new file.  */
94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    fildes = ref->fildes;
94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The file descriptor better should be the same.  If it was disconnected
94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     already (using `elf_cntl') we do not test it.  */
95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_FD_MISMATCH);
95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return NULL;
95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* The mode must allow reading.  I.e., a descriptor creating with a
95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     not allowed.  */
95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& ref->cmd != ELF_C_READ_MMAP_PRIVATE))
96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_INVALID_OP);
96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return NULL;
96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now it is time to distinguish between reading normal files and
96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     archives.  Normal files can easily be handled be incrementing the
97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     reference counter and return the same descriptor.  */
97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ref->kind != ELF_K_AR)
97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++ref->ref_count;
97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ref;
97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* This is an archive.  We must create a descriptor for the archive
97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng     member the internal pointer of the archive file desriptor is
97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     pointing to.  First read the header of the next member if this
98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     has not happened already.  */
98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ref->state.ar.elf_ar_hdr.ar_name == NULL
98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && __libelf_next_arhdr_wrlock (ref) != 0)
98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Something went wrong.  Maybe there is no member left.  */
98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We have all the information we need about the next archive member.
98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Now create a descriptor for it.  */
98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Enlist this new descriptor in the list of children.  */
99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result != NULL)
99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->next = ref->state.ar.children;
99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ref->state.ar.children = result;
99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Return desriptor for empty file ready for writing.  */
100325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct Elf *
100425b3c049e70834cf33790a28643ab058b507b35cBen Chengwrite_file (int fd, Elf_Cmd cmd)
100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We simply create an empty `Elf' structure.  */
100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define NSCNSALLOC	10
100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      NSCNSALLOC * sizeof (Elf_Scn));
101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result != NULL)
101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We have to write to the file in any case.  */
101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->flags = ELF_F_DIRTY;
101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Some more or less arbitrary value.  */
101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->state.elf.scnincr = NSCNSALLOC;
101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We have allocated room for some sections.  */
102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (offsetof (struct Elf, state.elf32.scns)
102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      == offsetof (struct Elf, state.elf64.scns));
102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->state.elf.scns_last = &result->state.elf32.scns;
102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result->state.elf32.scns.max = NSCNSALLOC;
102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Return a descriptor for the file belonging to FILDES.  */
103125b3c049e70834cf33790a28643ab058b507b35cBen ChengElf *
103225b3c049e70834cf33790a28643ab058b507b35cBen Chengelf_begin (fildes, cmd, ref)
103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     int fildes;
103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Elf_Cmd cmd;
103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Elf *ref;
103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *retval;
103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (! __libelf_version_initialized))
104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Version wasn't set so far.  */
104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_NO_VERSION);
104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return NULL;
104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ref != NULL)
104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Make sure the descriptor is not suddenly going away.  */
104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    rwlock_rdlock (ref->lock);
104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (unlikely (fcntl (fildes, F_GETFL) == -1 && errno == EBADF))
105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We cannot do anything productive without a file descriptor.  */
105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_INVALID_FILE);
105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return NULL;
105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *lock_dup_elf ()
105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* We need wrlock to dup an archive.  */
105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (ref->kind == ELF_K_AR)
106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	rwlock_unlock (ref->lock);
106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	rwlock_wrlock (ref->lock);
106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Duplicate the descriptor.  */
106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return dup_elf (fildes, cmd, ref);
106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (cmd)
107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_NULL:
107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We simply return a NULL pointer.  */
107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      retval = NULL;
107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_READ_MMAP_PRIVATE:
107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If we have a reference it must also be opened this way.  */
107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_INVALID_CMD);
108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  retval = NULL;
108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* FALLTHROUGH */
108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_READ:
108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_READ_MMAP:
108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ref != NULL)
108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	retval = lock_dup_elf ();
109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Create descriptor for existing file.  */
109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_RDWR:
109625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_RDWR_MMAP:
109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If we have a REF object it must also be opened using this
109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 command.  */
109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ref != NULL)
110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			&& ref->cmd != ELF_C_WRITE
110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			&& ref->cmd != ELF_C_WRITE_MMAP))
110425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
110525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is not ok.  REF must also be opened for writing.  */
110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      __libelf_seterrno (ELF_E_INVALID_CMD);
110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      retval = NULL;
110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    retval = lock_dup_elf ();
111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Create descriptor for existing file.  */
111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_WRITE:
111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case ELF_C_WRITE_MMAP:
111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We ignore REF and prepare a descriptor to write a new file.  */
112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      retval = write_file (fildes, cmd);
112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_INVALID_CMD);
112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      retval = NULL;
112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Release the lock.  */
113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ref != NULL)
113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    rwlock_unlock (ref->lock);
113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return retval;
113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
113525b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF(elf_begin)
1136