Blame libdw/dwarf_begin_elf.c

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