1da0c48c4Sopenharmony_ci/* Return string associated with given attribute.
2da0c48c4Sopenharmony_ci   Copyright (C) 2003-2010, 2013, 2017, 2018 Red Hat, Inc.
3da0c48c4Sopenharmony_ci   This file is part of elfutils.
4da0c48c4Sopenharmony_ci
5da0c48c4Sopenharmony_ci   This file is free software; you can redistribute it and/or modify
6da0c48c4Sopenharmony_ci   it under the terms of either
7da0c48c4Sopenharmony_ci
8da0c48c4Sopenharmony_ci     * the GNU Lesser General Public License as published by the Free
9da0c48c4Sopenharmony_ci       Software Foundation; either version 3 of the License, or (at
10da0c48c4Sopenharmony_ci       your option) any later version
11da0c48c4Sopenharmony_ci
12da0c48c4Sopenharmony_ci   or
13da0c48c4Sopenharmony_ci
14da0c48c4Sopenharmony_ci     * the GNU General Public License as published by the Free
15da0c48c4Sopenharmony_ci       Software Foundation; either version 2 of the License, or (at
16da0c48c4Sopenharmony_ci       your option) any later version
17da0c48c4Sopenharmony_ci
18da0c48c4Sopenharmony_ci   or both in parallel, as here.
19da0c48c4Sopenharmony_ci
20da0c48c4Sopenharmony_ci   elfutils is distributed in the hope that it will be useful, but
21da0c48c4Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
22da0c48c4Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23da0c48c4Sopenharmony_ci   General Public License for more details.
24da0c48c4Sopenharmony_ci
25da0c48c4Sopenharmony_ci   You should have received copies of the GNU General Public License and
26da0c48c4Sopenharmony_ci   the GNU Lesser General Public License along with this program.  If
27da0c48c4Sopenharmony_ci   not, see <http://www.gnu.org/licenses/>.  */
28da0c48c4Sopenharmony_ci
29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H
30da0c48c4Sopenharmony_ci# include <config.h>
31da0c48c4Sopenharmony_ci#endif
32da0c48c4Sopenharmony_ci
33da0c48c4Sopenharmony_ci#include <dwarf.h>
34da0c48c4Sopenharmony_ci#include "libdwP.h"
35da0c48c4Sopenharmony_ci
36da0c48c4Sopenharmony_ci
37da0c48c4Sopenharmony_ciconst char *
38da0c48c4Sopenharmony_cidwarf_formstring (Dwarf_Attribute *attrp)
39da0c48c4Sopenharmony_ci{
40da0c48c4Sopenharmony_ci  /* Ignore earlier errors.  */
41da0c48c4Sopenharmony_ci  if (attrp == NULL)
42da0c48c4Sopenharmony_ci    return NULL;
43da0c48c4Sopenharmony_ci
44da0c48c4Sopenharmony_ci  /* We found it.  Now determine where the string is stored.  */
45da0c48c4Sopenharmony_ci  if (attrp->form == DW_FORM_string)
46da0c48c4Sopenharmony_ci    /* A simple inlined string.  */
47da0c48c4Sopenharmony_ci    return (const char *) attrp->valp;
48da0c48c4Sopenharmony_ci
49da0c48c4Sopenharmony_ci  Dwarf_CU *cu = attrp->cu;
50da0c48c4Sopenharmony_ci  Dwarf *dbg = cu->dbg;
51da0c48c4Sopenharmony_ci  Dwarf *dbg_ret = ((attrp->form == DW_FORM_GNU_strp_alt
52da0c48c4Sopenharmony_ci		     || attrp->form == DW_FORM_strp_sup)
53da0c48c4Sopenharmony_ci		    ? INTUSE(dwarf_getalt) (dbg) : dbg);
54da0c48c4Sopenharmony_ci
55da0c48c4Sopenharmony_ci  if (unlikely (dbg_ret == NULL))
56da0c48c4Sopenharmony_ci    {
57da0c48c4Sopenharmony_ci      __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
58da0c48c4Sopenharmony_ci      return NULL;
59da0c48c4Sopenharmony_ci    }
60da0c48c4Sopenharmony_ci
61da0c48c4Sopenharmony_ci  Elf_Data *data = ((attrp->form == DW_FORM_line_strp)
62da0c48c4Sopenharmony_ci		    ? dbg_ret->sectiondata[IDX_debug_line_str]
63da0c48c4Sopenharmony_ci		    : dbg_ret->sectiondata[IDX_debug_str]);
64da0c48c4Sopenharmony_ci  if (data == NULL)
65da0c48c4Sopenharmony_ci    {
66da0c48c4Sopenharmony_ci      __libdw_seterrno ((attrp->form == DW_FORM_line_strp)
67da0c48c4Sopenharmony_ci			? DWARF_E_NO_DEBUG_LINE_STR
68da0c48c4Sopenharmony_ci			: DWARF_E_NO_DEBUG_STR);
69da0c48c4Sopenharmony_ci      return NULL;
70da0c48c4Sopenharmony_ci    }
71da0c48c4Sopenharmony_ci
72da0c48c4Sopenharmony_ci  uint64_t off;
73da0c48c4Sopenharmony_ci  if (attrp->form == DW_FORM_strp
74da0c48c4Sopenharmony_ci      || attrp->form == DW_FORM_GNU_strp_alt
75da0c48c4Sopenharmony_ci      || attrp->form == DW_FORM_strp_sup)
76da0c48c4Sopenharmony_ci    {
77da0c48c4Sopenharmony_ci      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
78da0c48c4Sopenharmony_ci			       attrp->valp, cu->offset_size, &off,
79da0c48c4Sopenharmony_ci			       IDX_debug_str, 1))
80da0c48c4Sopenharmony_ci	return NULL;
81da0c48c4Sopenharmony_ci    }
82da0c48c4Sopenharmony_ci  else if (attrp->form == DW_FORM_line_strp)
83da0c48c4Sopenharmony_ci    {
84da0c48c4Sopenharmony_ci      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
85da0c48c4Sopenharmony_ci			       attrp->valp, cu->offset_size, &off,
86da0c48c4Sopenharmony_ci			       IDX_debug_line_str, 1))
87da0c48c4Sopenharmony_ci	return NULL;
88da0c48c4Sopenharmony_ci    }
89da0c48c4Sopenharmony_ci  else
90da0c48c4Sopenharmony_ci    {
91da0c48c4Sopenharmony_ci      Dwarf_Word idx;
92da0c48c4Sopenharmony_ci      const unsigned char *datap = attrp->valp;
93da0c48c4Sopenharmony_ci      const unsigned char *endp = cu->endp;
94da0c48c4Sopenharmony_ci      switch (attrp->form)
95da0c48c4Sopenharmony_ci	{
96da0c48c4Sopenharmony_ci	case DW_FORM_strx:
97da0c48c4Sopenharmony_ci	case DW_FORM_GNU_str_index:
98da0c48c4Sopenharmony_ci	  if (datap >= endp)
99da0c48c4Sopenharmony_ci	    {
100da0c48c4Sopenharmony_ci	    invalid:
101da0c48c4Sopenharmony_ci	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
102da0c48c4Sopenharmony_ci	      return NULL;
103da0c48c4Sopenharmony_ci	    }
104da0c48c4Sopenharmony_ci	  get_uleb128 (idx, datap, endp);
105da0c48c4Sopenharmony_ci	  break;
106da0c48c4Sopenharmony_ci
107da0c48c4Sopenharmony_ci	case DW_FORM_strx1:
108da0c48c4Sopenharmony_ci	  if (datap >= endp - 1)
109da0c48c4Sopenharmony_ci	    goto invalid;
110da0c48c4Sopenharmony_ci	  idx = *datap;
111da0c48c4Sopenharmony_ci	  break;
112da0c48c4Sopenharmony_ci
113da0c48c4Sopenharmony_ci	case DW_FORM_strx2:
114da0c48c4Sopenharmony_ci	  if (datap >= endp - 2)
115da0c48c4Sopenharmony_ci	    goto invalid;
116da0c48c4Sopenharmony_ci	  idx = read_2ubyte_unaligned (dbg, datap);
117da0c48c4Sopenharmony_ci	  break;
118da0c48c4Sopenharmony_ci
119da0c48c4Sopenharmony_ci	case DW_FORM_strx3:
120da0c48c4Sopenharmony_ci	  if (datap >= endp - 3)
121da0c48c4Sopenharmony_ci	    goto invalid;
122da0c48c4Sopenharmony_ci	  idx = read_3ubyte_unaligned (dbg, datap);
123da0c48c4Sopenharmony_ci	  break;
124da0c48c4Sopenharmony_ci
125da0c48c4Sopenharmony_ci	case DW_FORM_strx4:
126da0c48c4Sopenharmony_ci	  if (datap >= endp - 4)
127da0c48c4Sopenharmony_ci	    goto invalid;
128da0c48c4Sopenharmony_ci	  idx = read_4ubyte_unaligned (dbg, datap);
129da0c48c4Sopenharmony_ci	  break;
130da0c48c4Sopenharmony_ci
131da0c48c4Sopenharmony_ci	default:
132da0c48c4Sopenharmony_ci	  __libdw_seterrno (DWARF_E_NO_STRING);
133da0c48c4Sopenharmony_ci	  return NULL;
134da0c48c4Sopenharmony_ci	}
135da0c48c4Sopenharmony_ci
136da0c48c4Sopenharmony_ci      /* So we got an index in the .debug_str_offsets.  Lets see if it
137da0c48c4Sopenharmony_ci	 is valid and we can get the actual .debug_str offset.  */
138da0c48c4Sopenharmony_ci      Dwarf_Off str_off = __libdw_cu_str_off_base (cu);
139da0c48c4Sopenharmony_ci      if (str_off == (Dwarf_Off) -1)
140da0c48c4Sopenharmony_ci	return NULL;
141da0c48c4Sopenharmony_ci
142da0c48c4Sopenharmony_ci      if (dbg->sectiondata[IDX_debug_str_offsets] == NULL)
143da0c48c4Sopenharmony_ci	{
144da0c48c4Sopenharmony_ci	  __libdw_seterrno (DWARF_E_NO_STR_OFFSETS);
145da0c48c4Sopenharmony_ci	  return NULL;
146da0c48c4Sopenharmony_ci	}
147da0c48c4Sopenharmony_ci
148da0c48c4Sopenharmony_ci      /* The section should at least contain room for one offset.  */
149da0c48c4Sopenharmony_ci      int offset_size = cu->offset_size;
150da0c48c4Sopenharmony_ci      if (cu->offset_size > dbg->sectiondata[IDX_debug_str_offsets]->d_size)
151da0c48c4Sopenharmony_ci	{
152da0c48c4Sopenharmony_ci	invalid_offset:
153da0c48c4Sopenharmony_ci	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
154da0c48c4Sopenharmony_ci	  return NULL;
155da0c48c4Sopenharmony_ci	}
156da0c48c4Sopenharmony_ci
157da0c48c4Sopenharmony_ci      /* And the base offset should be at least inside the section.  */
158da0c48c4Sopenharmony_ci      if (str_off > (dbg->sectiondata[IDX_debug_str_offsets]->d_size
159da0c48c4Sopenharmony_ci		     - offset_size))
160da0c48c4Sopenharmony_ci	goto invalid_offset;
161da0c48c4Sopenharmony_ci
162da0c48c4Sopenharmony_ci      size_t max_idx = (dbg->sectiondata[IDX_debug_str_offsets]->d_size
163da0c48c4Sopenharmony_ci			- offset_size - str_off) / offset_size;
164da0c48c4Sopenharmony_ci      if (idx > max_idx)
165da0c48c4Sopenharmony_ci	goto invalid_offset;
166da0c48c4Sopenharmony_ci
167da0c48c4Sopenharmony_ci      datap = (dbg->sectiondata[IDX_debug_str_offsets]->d_buf
168da0c48c4Sopenharmony_ci	       + str_off + (idx * offset_size));
169da0c48c4Sopenharmony_ci      if (offset_size == 4)
170da0c48c4Sopenharmony_ci	off = read_4ubyte_unaligned (dbg, datap);
171da0c48c4Sopenharmony_ci      else
172da0c48c4Sopenharmony_ci	off = read_8ubyte_unaligned (dbg, datap);
173da0c48c4Sopenharmony_ci
174da0c48c4Sopenharmony_ci      if (off > dbg->sectiondata[IDX_debug_str]->d_size)
175da0c48c4Sopenharmony_ci	goto invalid_offset;
176da0c48c4Sopenharmony_ci    }
177da0c48c4Sopenharmony_ci
178da0c48c4Sopenharmony_ci  return (const char *) data->d_buf + off;
179da0c48c4Sopenharmony_ci}
180da0c48c4Sopenharmony_ciINTDEF(dwarf_formstring)
181