125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Return section header.
203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   Copyright (C) 1998-2002, 2005, 2007, 2009, 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 <errno.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libelfP.h"
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "common.h"
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifndef LIBELFBITS
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng# define LIBELFBITS 32
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic ElfW2(LIBELFBITS,Shdr) *
4925b3c049e70834cf33790a28643ab058b507b35cBen Chengload_shdr_wrlock (Elf_Scn *scn)
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Shdr) *result;
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Read the section header table.  */
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = scn->elf;
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Try again, maybe the data is there now.  */
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = scn->shdr.ELFW(e,LIBELFBITS);
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result != NULL)
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto out;
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t shnum;
6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      || shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto out;
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Allocate memory for the section headers.  We know the number
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     of entries from the ELF header.  */
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_NOMEM);
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto out;
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->map_address != NULL)
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
8103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* First see whether the information in the ELF header is
8203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 valid and it does not ask for too much.  */
8303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (ehdr->e_shoff >= elf->maximum_size)
8403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  || unlikely (elf->maximum_size - ehdr->e_shoff < size))
8503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  /* Something is wrong.  */
8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  goto free_and_out;
8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
9003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ElfW2(LIBELFBITS,Shdr) *notcvt;
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* All the data is already mapped.  If we could use it
9403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 directly this would already have happened.  Unless
9503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 we allocated the memory ourselves and the ELF_F_MALLOCED
9603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 flag is set.  */
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      void *file_shdr = ((char *) elf->map_address
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 + elf->start_offset + ehdr->e_shoff);
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      assert ((elf->flags & ELF_F_MALLOCED)
10103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      || ehdr->e_ident[EI_DATA] != MY_ELFDATA
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || (! ALLOW_UNALIGNED
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && ((uintptr_t) file_shdr
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Now copy the data and at the same time convert the byte order.  */
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
10903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  assert ((elf->flags & ELF_F_MALLOCED) || ! ALLOW_UNALIGNED);
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (shdr, file_shdr, size);
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (ALLOW_UNALIGNED
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || ((uintptr_t) file_shdr
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) == 0)
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    notcvt = (ElfW2(LIBELFBITS,Shdr) *)
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      ((char *) elf->map_address
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       + elf->start_offset + ehdr->e_shoff);
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      notcvt = (ElfW2(LIBELFBITS,Shdr) *) alloca (size);
12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      memcpy (notcvt, ((char *) elf->map_address
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       + elf->start_offset + ehdr->e_shoff),
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      size);
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  for (size_t cnt = 0; cnt < shnum; ++cnt)
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_addralign,
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  notcvt[cnt].sh_addralign);
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If this is a section with an extended index add a
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 reference in the section which uses the extended
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 index.  */
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  && shdr[cnt].sh_link < shnum)
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  = cnt;
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Set the own shndx_index field in case it has not yet
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 been set.  */
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  = -1;
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else if (likely (elf->fildes != -1))
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Read the header.  */
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ssize_t n = pread_retry (elf->fildes,
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       elf->state.ELFW(elf,LIBELFBITS).shdr, size,
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       elf->start_offset + ehdr->e_shoff);
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely ((size_t) n != size))
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Severe problems.  We cannot read the data.  */
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libelf_seterrno (ELF_E_READ_ERROR);
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto free_and_out;
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* If the byte order of the file is not the same as the one
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 of the host convert the data now.  */
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	for (size_t cnt = 0; cnt < shnum; ++cnt)
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_name);
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_type);
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_flags);
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_addr);
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_offset);
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_size);
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_link);
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_info);
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_addralign);
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    CONVERT (shdr[cnt].sh_entsize);
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* The file descriptor was already enabled and not all data was
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 read.  Undo the allocation.  */
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_FD_DISABLED);
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    free_and_out:
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      free (shdr);
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto out;
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set the pointers in the `scn's.  */
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t cnt = 0; cnt < shnum; ++cnt)
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = scn->shdr.ELFW(e,LIBELFBITS);
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (result != NULL);
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21025b3c049e70834cf33790a28643ab058b507b35cBen Chengout:
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool
21525b3c049e70834cf33790a28643ab058b507b35cBen Chengscn_valid (Elf_Scn *scn)
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (scn == NULL)
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (scn->elf->state.elf.ehdr == NULL))
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return false;
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libelf_seterrno (ELF_E_INVALID_CLASS);
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return false;
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return true;
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23525b3c049e70834cf33790a28643ab058b507b35cBen ChengElfW2(LIBELFBITS,Shdr) *
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,getshdr_rdlock) (scn)
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Elf_Scn *scn;
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Shdr) *result;
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!scn_valid (scn))
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = scn->shdr.ELFW(e,LIBELFBITS);
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result == NULL)
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      rwlock_unlock (scn->elf->lock);
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      rwlock_wrlock (scn->elf->lock);
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      result = scn->shdr.ELFW(e,LIBELFBITS);
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (result == NULL)
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	result = load_shdr_wrlock (scn);
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25725b3c049e70834cf33790a28643ab058b507b35cBen ChengElfW2(LIBELFBITS,Shdr) *
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng__elfw2(LIBELFBITS,getshdr_wrlock) (scn)
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Elf_Scn *scn;
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Shdr) *result;
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!scn_valid (scn))
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = scn->shdr.ELFW(e,LIBELFBITS);
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (result == NULL)
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    result = load_shdr_wrlock (scn);
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27325b3c049e70834cf33790a28643ab058b507b35cBen ChengElfW2(LIBELFBITS,Shdr) *
27425b3c049e70834cf33790a28643ab058b507b35cBen Chengelfw2(LIBELFBITS,getshdr) (scn)
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Elf_Scn *scn;
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  ElfW2(LIBELFBITS,Shdr) *result;
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (!scn_valid (scn))
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  rwlock_rdlock (scn->elf->lock);
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  rwlock_unlock (scn->elf->lock);
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
288