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