Blame libdw/dwarf_formstring.c

Packit Service 97d2fb
/* Return string associated with given attribute.
Packit Service 97d2fb
   Copyright (C) 2003-2010, 2013, 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 <dwarf.h>
Packit Service 97d2fb
#include "libdwP.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
const char *
Packit Service 97d2fb
dwarf_formstring (Dwarf_Attribute *attrp)
Packit Service 97d2fb
{
Packit Service 97d2fb
  /* Ignore earlier errors.  */
Packit Service 97d2fb
  if (attrp == NULL)
Packit Service 97d2fb
    return NULL;
Packit Service 97d2fb
Packit Service 97d2fb
  /* We found it.  Now determine where the string is stored.  */
Packit Service 97d2fb
  if (attrp->form == DW_FORM_string)
Packit Service 97d2fb
    /* A simple inlined string.  */
Packit Service 97d2fb
    return (const char *) attrp->valp;
Packit Service 97d2fb
Packit Service 97d2fb
  Dwarf_CU *cu = attrp->cu;
Packit Service 97d2fb
  Dwarf *dbg = cu->dbg;
Packit Service 97d2fb
  Dwarf *dbg_ret = ((attrp->form == DW_FORM_GNU_strp_alt
Packit Service 97d2fb
		     || attrp->form == DW_FORM_strp_sup)
Packit Service 97d2fb
		    ? INTUSE(dwarf_getalt) (dbg) : dbg);
Packit Service 97d2fb
Packit Service 97d2fb
  if (unlikely (dbg_ret == NULL))
Packit Service 97d2fb
    {
Packit Service 97d2fb
      __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  Elf_Data *data = ((attrp->form == DW_FORM_line_strp)
Packit Service 97d2fb
		    ? dbg_ret->sectiondata[IDX_debug_line_str]
Packit Service 97d2fb
		    : dbg_ret->sectiondata[IDX_debug_str]);
Packit Service 97d2fb
  if (data == NULL)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      __libdw_seterrno ((attrp->form == DW_FORM_line_strp)
Packit Service 97d2fb
			? DWARF_E_NO_DEBUG_LINE_STR
Packit Service 97d2fb
			: DWARF_E_NO_DEBUG_STR);
Packit Service 97d2fb
      return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  uint64_t off;
Packit Service 97d2fb
  if (attrp->form == DW_FORM_strp
Packit Service 97d2fb
      || attrp->form == DW_FORM_GNU_strp_alt
Packit Service 97d2fb
      || attrp->form == DW_FORM_strp_sup)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
Packit Service 97d2fb
			       attrp->valp, cu->offset_size, &off,
Packit Service 97d2fb
			       IDX_debug_str, 1))
Packit Service 97d2fb
	return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else if (attrp->form == DW_FORM_line_strp)
Packit Service 97d2fb
    {
Packit Service 97d2fb
      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
Packit Service 97d2fb
			       attrp->valp, cu->offset_size, &off,
Packit Service 97d2fb
			       IDX_debug_line_str, 1))
Packit Service 97d2fb
	return NULL;
Packit Service 97d2fb
    }
Packit Service 97d2fb
  else
Packit Service 97d2fb
    {
Packit Service 97d2fb
      Dwarf_Word idx;
Packit Service 97d2fb
      const unsigned char *datap = attrp->valp;
Packit Service 97d2fb
      const unsigned char *endp = cu->endp;
Packit Service 97d2fb
      switch (attrp->form)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	case DW_FORM_strx:
Packit Service 97d2fb
	case DW_FORM_GNU_str_index:
Packit Service 97d2fb
	  if (datap >= endp)
Packit Service 97d2fb
	    {
Packit Service 97d2fb
	    invalid:
Packit Service 97d2fb
	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
Packit Service 97d2fb
	      return NULL;
Packit Service 97d2fb
	    }
Packit Service 97d2fb
	  get_uleb128 (idx, datap, endp);
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
Packit Service 97d2fb
	case DW_FORM_strx1:
Packit Service 97d2fb
	  if (datap >= endp - 1)
Packit Service 97d2fb
	    goto invalid;
Packit Service 97d2fb
	  idx = *datap;
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
Packit Service 97d2fb
	case DW_FORM_strx2:
Packit Service 97d2fb
	  if (datap >= endp - 2)
Packit Service 97d2fb
	    goto invalid;
Packit Service 97d2fb
	  idx = read_2ubyte_unaligned (dbg, datap);
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
Packit Service 97d2fb
	case DW_FORM_strx3:
Packit Service 97d2fb
	  if (datap >= endp - 3)
Packit Service 97d2fb
	    goto invalid;
Packit Service 97d2fb
	  idx = read_3ubyte_unaligned (dbg, datap);
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
Packit Service 97d2fb
	case DW_FORM_strx4:
Packit Service 97d2fb
	  if (datap >= endp - 4)
Packit Service 97d2fb
	    goto invalid;
Packit Service 97d2fb
	  idx = read_4ubyte_unaligned (dbg, datap);
Packit Service 97d2fb
	  break;
Packit Service 97d2fb
Packit Service 97d2fb
	default:
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_NO_STRING);
Packit Service 97d2fb
	  return NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* So we got an index in the .debug_str_offsets.  Lets see if it
Packit Service 97d2fb
	 is valid and we can get the actual .debug_str offset.  */
Packit Service 97d2fb
      Dwarf_Off str_off = __libdw_cu_str_off_base (cu);
Packit Service 97d2fb
      if (str_off == (Dwarf_Off) -1)
Packit Service 97d2fb
	return NULL;
Packit Service 97d2fb
Packit Service 97d2fb
      if (dbg->sectiondata[IDX_debug_str_offsets] == NULL)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_NO_STR_OFFSETS);
Packit Service 97d2fb
	  return NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* The section should at least contain room for one offset.  */
Packit Service 97d2fb
      int offset_size = cu->offset_size;
Packit Service 97d2fb
      if (cu->offset_size > dbg->sectiondata[IDX_debug_str_offsets]->d_size)
Packit Service 97d2fb
	{
Packit Service 97d2fb
	invalid_offset:
Packit Service 97d2fb
	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
Packit Service 97d2fb
	  return NULL;
Packit Service 97d2fb
	}
Packit Service 97d2fb
Packit Service 97d2fb
      /* And the base offset should be at least inside the section.  */
Packit Service 97d2fb
      if (str_off > (dbg->sectiondata[IDX_debug_str_offsets]->d_size
Packit Service 97d2fb
		     - offset_size))
Packit Service 97d2fb
	goto invalid_offset;
Packit Service 97d2fb
Packit Service 97d2fb
      size_t max_idx = (dbg->sectiondata[IDX_debug_str_offsets]->d_size
Packit Service 97d2fb
			- offset_size - str_off) / offset_size;
Packit Service 97d2fb
      if (idx > max_idx)
Packit Service 97d2fb
	goto invalid_offset;
Packit Service 97d2fb
Packit Service 97d2fb
      datap = (dbg->sectiondata[IDX_debug_str_offsets]->d_buf
Packit Service 97d2fb
	       + str_off + (idx * offset_size));
Packit Service 97d2fb
      if (offset_size == 4)
Packit Service 97d2fb
	off = read_4ubyte_unaligned (dbg, datap);
Packit Service 97d2fb
      else
Packit Service 97d2fb
	off = read_8ubyte_unaligned (dbg, datap);
Packit Service 97d2fb
Packit Service 97d2fb
      if (off > dbg->sectiondata[IDX_debug_str]->d_size)
Packit Service 97d2fb
	goto invalid_offset;
Packit Service 97d2fb
    }
Packit Service 97d2fb
Packit Service 97d2fb
  return (const char *) data->d_buf + off;
Packit Service 97d2fb
}
Packit Service 97d2fb
INTDEF(dwarf_formstring)