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