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