Blame libdw/dwarf_begin_elf.c

Packit Service 97d2fb
/* Create descriptor from ELF descriptor for processing file.
Packit Service 97d2fb
   Copyright (C) 2002-2011, 2014, 2015, 2017, 2018 Red Hat, Inc.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of either
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU Lesser General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 3 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 2 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or both in parallel, as here.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 97d2fb
   General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received copies of the GNU General Public License and
Packit Service 97d2fb
   the GNU Lesser General Public License along with this program.  If
Packit Service 97d2fb
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef HAVE_CONFIG_H
Packit Service 97d2fb
# include <config.h>
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
#include <assert.h>
Packit Service 97d2fb
#include <stdbool.h>
Packit Service 97d2fb
#include <stddef.h>
Packit Service 97d2fb
#include <stdlib.h>
Packit Service 97d2fb
#include <stdio.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
#include <unistd.h>
Packit Service 97d2fb
#include <sys/types.h>
Packit Service 97d2fb
#include <sys/stat.h>
Packit Service 97d2fb
#include <fcntl.h>
Packit Service 97d2fb
#include <endian.h>
Packit Service 97d2fb
Packit Service 97d2fb
#include "libelfP.h"
Packit Service 97d2fb
#include "libdwP.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Section names.  (Note .debug_str_offsets is the largest 19 chars.)  */
Packit Service 97d2fb
static const char dwarf_scnnames[IDX_last][19] =
Packit Service 97d2fb
{
Packit Service 97d2fb
  [IDX_debug_info] = ".debug_info",
Packit Service 97d2fb
  [IDX_debug_types] = ".debug_types",
Packit Service 97d2fb
  [IDX_debug_abbrev] = ".debug_abbrev",
Packit Service 97d2fb
  [IDX_debug_addr] = ".debug_addr",
Packit Service 97d2fb
  [IDX_debug_aranges] = ".debug_aranges",
Packit Service 97d2fb
  [IDX_debug_line] = ".debug_line",
Packit Service 97d2fb
  [IDX_debug_line_str] = ".debug_line_str",
Packit Service 97d2fb
  [IDX_debug_frame] = ".debug_frame",
Packit Service 97d2fb
  [IDX_debug_loc] = ".debug_loc",
Packit Service 97d2fb
  [IDX_debug_loclists] = ".debug_loclists",
Packit Service 97d2fb
  [IDX_debug_pubnames] = ".debug_pubnames",
Packit Service 97d2fb
  [IDX_debug_str] = ".debug_str",
Packit Service 97d2fb
  [IDX_debug_str_offsets] = ".debug_str_offsets",
Packit Service 97d2fb
  [IDX_debug_macinfo] = ".debug_macinfo",
Packit Service 97d2fb
  [IDX_debug_macro] = ".debug_macro",
Packit Service 97d2fb
  [IDX_debug_ranges] = ".debug_ranges",
Packit Service 97d2fb
  [IDX_debug_rnglists] = ".debug_rnglists",
Packit Service 97d2fb
  [IDX_gnu_debugaltlink] = ".gnu_debugaltlink"
Packit Service 97d2fb
};
Packit Service 97d2fb
#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
Packit Service 97d2fb
Packit Service 97d2fb
static Dwarf *
Packit Service 97d2fb
check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  GElf_Shdr shdr_mem;
Packit Service 97d2fb
  GElf_Shdr *shdr;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Get the section header data.  */
Packit Service 97d2fb
  shdr = gelf_getshdr (scn, &shdr_mem);
Packit Service 97d2fb
  if (shdr == NULL)
Packit Service 97d2fb
    /* We may read /proc/PID/mem with only program headers mapped and section
Packit Service 97d2fb
       headers out of the mapped pages.  */
Packit Service 97d2fb
    goto err;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Ignore any SHT_NOBITS sections.  Debugging sections should not
Packit Service 97d2fb
     have been stripped, but in case of a corrupt file we won't try
Packit Service 97d2fb
     to look at the missing data.  */
Packit Service 97d2fb
  if (unlikely (shdr->sh_type == SHT_NOBITS))
Packit Service 97d2fb
    return result;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Make sure the section is part of a section group only iff we
Packit Service 97d2fb
     really need it.  If we are looking for the global (= non-section
Packit Service 97d2fb
     group debug info) we have to ignore all the info in section
Packit Service 97d2fb
     groups.  If we are looking into a section group we cannot look at
Packit Service 97d2fb
     a section which isn't part of the section group.  */
Packit Service 97d2fb
  if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
Packit Service 97d2fb
    /* Ignore the section.  */
Packit Service 97d2fb
    return result;
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
  /* We recognize the DWARF section by their names.  This is not very
Packit Service 97d2fb
     safe and stable but the best we can do.  */
Packit Service 97d2fb
  const char *scnname = elf_strptr (result->elf, shstrndx,
Packit Service 97d2fb
				    shdr->sh_name);
Packit Service 97d2fb
  if (scnname == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* The section name must be valid.  Otherwise is the ELF file
Packit Service 97d2fb
	 invalid.  */
Packit Service 97d2fb
    err:
Packit Service 97d2fb
      Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_INVALID_ELF);
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Recognize the various sections.  Most names start with .debug_.  */
Packit Service 97d2fb
  size_t cnt;
Packit Service 97d2fb
  bool gnu_compressed = false;
Packit Service 97d2fb
  for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      size_t dbglen = strlen (dwarf_scnnames[cnt]);
Packit Service 97d2fb
      size_t scnlen = strlen (scnname);
Packit Service 97d2fb
      if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
Packit Service 97d2fb
	  && (dbglen == scnlen
Packit Service 97d2fb
	      || (scnlen == dbglen + 4
Packit Service 97d2fb
		  && strstr (scnname, ".dwo") == scnname + dbglen)))
Packit Service 97d2fb
	break;
Packit Service 97d2fb
      else if (scnname[0] == '.' && scnname[1] == 'z'
Packit Service 97d2fb
	       && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
Packit Service 97d2fb
			    dbglen - 1) == 0
Packit Service 97d2fb
		   && (scnlen == dbglen + 1
Packit Service 97d2fb
		       || (scnlen == dbglen + 5
Packit Service 97d2fb
			   && strstr (scnname,
Packit Service 97d2fb
				      ".dwo") == scnname + dbglen + 1))))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  gnu_compressed = true;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
Packit Service 97d2fb
	       && strncmp (scnname, ".gnu.debuglto_", 14) == 0
Packit Service 97d2fb
	       && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
Packit Service 97d2fb
	break;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (cnt >= ndwarf_scnnames)
Packit Service 97d2fb
    /* Not a debug section; ignore it. */
Packit Service 97d2fb
    return result;
Packit Service 97d2fb
Packit Service 97d2fb
  if (unlikely (result->sectiondata[cnt] != NULL))
Packit Service 97d2fb
    /* A section appears twice.  That's bad.  We ignore the section.  */
Packit Service 97d2fb
    return result;
Packit Service 97d2fb
Packit Service 97d2fb
  /* We cannot know whether or not a GNU compressed section has already
Packit Service 97d2fb
     been uncompressed or not, so ignore any errors.  */
Packit Service 97d2fb
  if (gnu_compressed)
Packit Service 97d2fb
    elf_compress_gnu (scn, 0, 0);
Packit Service 97d2fb
Packit Service 97d2fb
  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (elf_compress (scn, 0, 0) < 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* It would be nice if we could fail with a specific error.
Packit Service 97d2fb
	     But we don't know if this was an essential section or not.
Packit Service 97d2fb
	     So just continue for now. See also valid_p().  */
Packit Service 97d2fb
	  return result;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Get the section data.  */
Packit Service 97d2fb
  Elf_Data *data = elf_getdata (scn, NULL);
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    goto err;
Packit Service 97d2fb
Packit Service 97d2fb
  if (data->d_buf == NULL || data->d_size == 0)
Packit Service 97d2fb
    /* No data actually available, ignore it. */
Packit Service 97d2fb
    return result;
Packit Service 97d2fb
Packit Service 97d2fb
  /* We can now read the section data into results. */
Packit Service 97d2fb
  result->sectiondata[cnt] = data;
Packit Service 97d2fb
Packit Service 97d2fb
  return result;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Helper function to set debugdir field.  We want to cache the dir
Packit Service 97d2fb
   where we found this Dwarf ELF file to locate alt and dwo files.  */
Packit Service 97d2fb
char *
Packit Service 97d2fb
__libdw_debugdir (int fd)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25.  */
Packit Service 97d2fb
  char devfdpath[25];
Packit Service 97d2fb
  sprintf (devfdpath, "/proc/self/fd/%u", fd);
Packit Service 97d2fb
  char *fdpath = realpath (devfdpath, NULL);
Packit Service 97d2fb
  char *fddir;
Packit Service 97d2fb
  if (fdpath != NULL && fdpath[0] == '/'
Packit Service 97d2fb
      && (fddir = strrchr (fdpath, '/')) != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      *++fddir = '\0';
Packit Service 97d2fb
      return fdpath;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  return NULL;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Check whether all the necessary DWARF information is available.  */
Packit Service 97d2fb
static Dwarf *
Packit Service 97d2fb
valid_p (Dwarf *result)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* We looked at all the sections.  Now determine whether all the
Packit Service 97d2fb
     sections with debugging information we need are there.
Packit Service 97d2fb
Packit Service 97d2fb
     Require at least one section that can be read "standalone".  */
Packit Service 97d2fb
  if (likely (result != NULL)
Packit Service 97d2fb
      && unlikely (result->sectiondata[IDX_debug_info] == NULL
Packit Service 97d2fb
		   && result->sectiondata[IDX_debug_line] == NULL
Packit Service 97d2fb
		   && result->sectiondata[IDX_debug_frame] == NULL))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_NO_DWARF);
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      result = NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* For dwarf_location_attr () we need a "fake" CU to indicate
Packit Service 97d2fb
     where the "fake" attribute data comes from.  This is a block
Packit Service 97d2fb
     inside the .debug_loc or .debug_loclists section.  */
Packit Service 97d2fb
  if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      result->fake_loc_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
Packit Service 97d2fb
      if (unlikely (result->fake_loc_cu == NULL))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_NOMEM);
Packit Service 97d2fb
	  free (result);
Packit Service 97d2fb
	  result = NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  result->fake_loc_cu->sec_idx = IDX_debug_loc;
Packit Service 97d2fb
	  result->fake_loc_cu->dbg = result;
Packit Service 97d2fb
	  result->fake_loc_cu->startp
Packit Service 97d2fb
	    = result->sectiondata[IDX_debug_loc]->d_buf;
Packit Service 97d2fb
	  result->fake_loc_cu->endp
Packit Service 97d2fb
	    = (result->sectiondata[IDX_debug_loc]->d_buf
Packit Service 97d2fb
	       + result->sectiondata[IDX_debug_loc]->d_size);
Packit Service 97d2fb
	  result->fake_loc_cu->locs = NULL;
Packit Service 97d2fb
	  result->fake_loc_cu->address_size = 0;
Packit Service 97d2fb
	  result->fake_loc_cu->version = 0;
Packit Service 97d2fb
	  result->fake_loc_cu->split = NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      result->fake_loclists_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
Packit Service 97d2fb
      if (unlikely (result->fake_loclists_cu == NULL))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_NOMEM);
Packit Service 97d2fb
	  free (result->fake_loc_cu);
Packit Service 97d2fb
	  free (result);
Packit Service 97d2fb
	  result = NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
Packit Service 97d2fb
	  result->fake_loclists_cu->dbg = result;
Packit Service 97d2fb
	  result->fake_loclists_cu->startp
Packit Service 97d2fb
	    = result->sectiondata[IDX_debug_loclists]->d_buf;
Packit Service 97d2fb
	  result->fake_loclists_cu->endp
Packit Service 97d2fb
	    = (result->sectiondata[IDX_debug_loclists]->d_buf
Packit Service 97d2fb
	       + result->sectiondata[IDX_debug_loclists]->d_size);
Packit Service 97d2fb
	  result->fake_loclists_cu->locs = NULL;
Packit Service 97d2fb
	  result->fake_loclists_cu->address_size = 0;
Packit Service 97d2fb
	  result->fake_loclists_cu->version = 0;
Packit Service 97d2fb
	  result->fake_loclists_cu->split = NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
Packit Service 97d2fb
     the dwarf_location_attr () will need a "fake" address CU to
Packit Service 97d2fb
     indicate where the attribute data comes from.  This is a just
Packit Service 97d2fb
     inside the .debug_addr section, if it exists.  */
Packit Service 97d2fb
  if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      result->fake_addr_cu = (Dwarf_CU *) malloc (sizeof (Dwarf_CU));
Packit Service 97d2fb
      if (unlikely (result->fake_addr_cu == NULL))
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_NOMEM);
Packit Service 97d2fb
	  free (result->fake_loc_cu);
Packit Service 97d2fb
	  free (result->fake_loclists_cu);
Packit Service 97d2fb
	  free (result);
Packit Service 97d2fb
	  result = NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
      else
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  result->fake_addr_cu->sec_idx = IDX_debug_addr;
Packit Service 97d2fb
	  result->fake_addr_cu->dbg = result;
Packit Service 97d2fb
	  result->fake_addr_cu->startp
Packit Service 97d2fb
	    = result->sectiondata[IDX_debug_addr]->d_buf;
Packit Service 97d2fb
	  result->fake_addr_cu->endp
Packit Service 97d2fb
	    = (result->sectiondata[IDX_debug_addr]->d_buf
Packit Service 97d2fb
	       + result->sectiondata[IDX_debug_addr]->d_size);
Packit Service 97d2fb
	  result->fake_addr_cu->locs = NULL;
Packit Service 97d2fb
	  result->fake_addr_cu->address_size = 0;
Packit Service 97d2fb
	  result->fake_addr_cu->version = 0;
Packit Service 97d2fb
	  result->fake_addr_cu->split = NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if (result != NULL)
Packit Service 97d2fb
    result->debugdir = __libdw_debugdir (result->elf->fildes);
Packit Service 97d2fb
Packit Service 97d2fb
  return result;
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
static Dwarf *
Packit Service 97d2fb
global_read (Dwarf *result, Elf *elf, size_t shstrndx)
Packit Service 97d2fb
{
Packit Service 97d2fb
  Elf_Scn *scn = NULL;
Packit Service 97d2fb
Packit Service 97d2fb
  while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
Packit Service 97d2fb
    result = check_section (result, shstrndx, scn, false);
Packit Service 97d2fb
Packit Service 97d2fb
  return valid_p (result);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
static Dwarf *
Packit Service 97d2fb
scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  GElf_Shdr shdr_mem;
Packit Service 97d2fb
  GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
Packit Service 97d2fb
  if (shdr == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_INVALID_ELF);
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  if ((shdr->sh_flags & SHF_COMPRESSED) != 0
Packit Service 97d2fb
      && elf_compress (scngrp, 0, 0) < 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* SCNGRP is the section descriptor for a section group which might
Packit Service 97d2fb
     contain debug sections.  */
Packit Service 97d2fb
  Elf_Data *data = elf_getdata (scngrp, NULL);
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* We cannot read the section content.  Fail!  */
Packit Service 97d2fb
      Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* The content of the section is a number of 32-bit words which
Packit Service 97d2fb
     represent section indices.  The first word is a flag word.  */
Packit Service 97d2fb
  Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
Packit Service 97d2fb
  size_t cnt;
Packit Service 97d2fb
  for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
Packit Service 97d2fb
      if (scn == NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  /* A section group refers to a non-existing section.  Should
Packit Service 97d2fb
	     never happen.  */
Packit Service 97d2fb
	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_INVALID_ELF);
Packit Service 97d2fb
	  free (result);
Packit Service 97d2fb
	  return NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      result = check_section (result, shstrndx, scn, true);
Packit Service 97d2fb
      if (result == NULL)
Packit Service 97d2fb
	break;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return valid_p (result);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
Dwarf *
Packit Service 97d2fb
dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  GElf_Ehdr *ehdr;
Packit Service 97d2fb
  GElf_Ehdr ehdr_mem;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Get the ELF header of the file.  We need various pieces of
Packit Service 97d2fb
     information from it.  */
Packit Service 97d2fb
  ehdr = gelf_getehdr (elf, &ehdr_mem);
Packit Service 97d2fb
  if (ehdr == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (elf_kind (elf) != ELF_K_ELF)
Packit Service 97d2fb
	__libdw_seterrno (DWARF_E_NOELF);
Packit Service 97d2fb
      else
Packit Service 97d2fb
	__libdw_seterrno (DWARF_E_GETEHDR_ERROR);
Packit Service 97d2fb
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
  /* Default memory allocation size.  */
Packit Service 97d2fb
  size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
Packit Service 97d2fb
  assert (sizeof (struct Dwarf) < mem_default_size);
Packit Service 97d2fb
Packit Service 97d2fb
  /* Allocate the data structure.  */
Packit Service 97d2fb
  Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf));
Packit Service 97d2fb
  if (unlikely (result == NULL)
Packit Service 97d2fb
      || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_NOMEM);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  /* Fill in some values.  */
Packit Service 97d2fb
  if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
Packit Service 97d2fb
      || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
Packit Service 97d2fb
    result->other_byte_order = true;
Packit Service 97d2fb
Packit Service 97d2fb
  result->elf = elf;
Packit Service 97d2fb
  result->alt_fd = -1;
Packit Service 97d2fb
Packit Service 97d2fb
  /* Initialize the memory handling.  Initial blocks are allocated on first
Packit Service 97d2fb
     actual allocation.  */
Packit Service 97d2fb
  result->mem_default_size = mem_default_size;
Packit Service 97d2fb
  result->oom_handler = __libdw_oom;
Packit Service 97d2fb
  if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  result->mem_stacks = 0;
Packit Service 97d2fb
  result->mem_tails = NULL;
Packit Service 97d2fb
Packit Service 97d2fb
  if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      /* All sections are recognized by name, so pass the section header
Packit Service 97d2fb
	 string index along to easily get the section names.  */
Packit Service 97d2fb
      size_t shstrndx;
Packit Service 97d2fb
      if (elf_getshdrstrndx (elf, &shstrndx) != 0)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_INVALID_ELF);
Packit Service 97d2fb
	  free (result);
Packit Service 97d2fb
	  return NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* If the caller provides a section group we get the DWARF
Packit Service 97d2fb
	 sections only from this setion group.  Otherwise we search
Packit Service 97d2fb
	 for the first section with the required name.  Further
Packit Service 97d2fb
	 sections with the name are ignored.  The DWARF specification
Packit Service 97d2fb
	 does not really say this is allowed.  */
Packit Service 97d2fb
      if (scngrp == NULL)
Packit Service 97d2fb
	return global_read (result, elf, shstrndx);
Packit Service 97d2fb
      else
Packit Service 97d2fb
	return scngrp_read (result, elf, shstrndx, scngrp);
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else if (cmd == DWARF_C_WRITE)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_UNIMPL);
Packit Service 97d2fb
      free (result);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_Sig8_Hash_free (&result->sig8_hash);
Packit Service 97d2fb
  __libdw_seterrno (DWARF_E_INVALID_CMD);
Packit Service 97d2fb
  free (result);
Packit Service 97d2fb
  return NULL;
Packit Service 97d2fb
}
Packit Service 97d2fb
INTDEF(dwarf_begin_elf)