Blame libdw/dwarf_formstring.c

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