Line data Source code
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 *
38 1140223 : dwarf_formstring (Dwarf_Attribute *attrp)
39 : {
40 : /* Ignore earlier errors. */
41 1140223 : if (attrp == NULL)
42 : return NULL;
43 :
44 : /* We found it. Now determine where the string is stored. */
45 1001756 : if (attrp->form == DW_FORM_string)
46 : /* A simple inlined string. */
47 69267 : return (const char *) attrp->valp;
48 :
49 932489 : Dwarf_CU *cu = attrp->cu;
50 932489 : Dwarf *dbg = cu->dbg;
51 932489 : Dwarf *dbg_ret = ((attrp->form == DW_FORM_GNU_strp_alt
52 932489 : || attrp->form == DW_FORM_strp_sup)
53 932489 : ? INTUSE(dwarf_getalt) (dbg) : dbg);
54 :
55 932489 : if (unlikely (dbg_ret == NULL))
56 : {
57 0 : __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
58 0 : return NULL;
59 : }
60 :
61 1864978 : Elf_Data *data = ((attrp->form == DW_FORM_line_strp)
62 : ? dbg_ret->sectiondata[IDX_debug_line_str]
63 932489 : : dbg_ret->sectiondata[IDX_debug_str]);
64 932489 : if (data == NULL)
65 : {
66 0 : __libdw_seterrno ((attrp->form == DW_FORM_line_strp)
67 : ? DWARF_E_NO_DEBUG_LINE_STR
68 : : DWARF_E_NO_DEBUG_STR);
69 0 : return NULL;
70 : }
71 :
72 : uint64_t off;
73 932489 : if (attrp->form == DW_FORM_strp
74 932489 : || attrp->form == DW_FORM_GNU_strp_alt
75 158 : || attrp->form == DW_FORM_strp_sup)
76 : {
77 1864662 : if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
78 1864662 : attrp->valp, cu->offset_size, &off,
79 : IDX_debug_str, 1))
80 : return NULL;
81 : }
82 158 : else if (attrp->form == DW_FORM_line_strp)
83 : {
84 36 : if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
85 36 : attrp->valp, cu->offset_size, &off,
86 : IDX_debug_line_str, 1))
87 : return NULL;
88 : }
89 : else
90 : {
91 : Dwarf_Word idx;
92 140 : const unsigned char *datap = attrp->valp;
93 140 : const unsigned char *endp = cu->endp;
94 140 : switch (attrp->form)
95 : {
96 140 : case DW_FORM_strx:
97 : case DW_FORM_GNU_str_index:
98 140 : if (datap >= endp)
99 : {
100 0 : invalid:
101 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
102 0 : return NULL;
103 : }
104 140 : get_uleb128 (idx, datap, endp);
105 140 : break;
106 :
107 0 : case DW_FORM_strx1:
108 0 : if (datap >= endp - 1)
109 : goto invalid;
110 0 : idx = *datap;
111 0 : break;
112 :
113 0 : case DW_FORM_strx2:
114 0 : if (datap >= endp - 2)
115 : goto invalid;
116 0 : idx = read_2ubyte_unaligned (dbg, datap);
117 : break;
118 :
119 0 : case DW_FORM_strx3:
120 0 : if (datap >= endp - 3)
121 : goto invalid;
122 0 : idx = read_3ubyte_unaligned (dbg, datap);
123 0 : break;
124 :
125 0 : case DW_FORM_strx4:
126 0 : if (datap >= endp - 4)
127 : goto invalid;
128 0 : idx = read_4ubyte_unaligned (dbg, datap);
129 : break;
130 :
131 0 : default:
132 0 : __libdw_seterrno (DWARF_E_NO_STRING);
133 0 : return NULL;
134 : }
135 :
136 : /* So we got an index in the .debug_str_offsets. Lets see if it
137 : is valid and we can get the actual .debug_str offset. */
138 140 : Dwarf_Off str_off = __libdw_cu_str_off_base (cu);
139 140 : if (str_off == (Dwarf_Off) -1)
140 : return NULL;
141 :
142 140 : if (dbg->sectiondata[IDX_debug_str_offsets] == NULL)
143 : {
144 0 : __libdw_seterrno (DWARF_E_NO_STR_OFFSETS);
145 0 : return NULL;
146 : }
147 :
148 : /* The section should at least contain room for one offset. */
149 140 : int offset_size = cu->offset_size;
150 140 : if (cu->offset_size > dbg->sectiondata[IDX_debug_str_offsets]->d_size)
151 : {
152 0 : invalid_offset:
153 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET);
154 0 : return NULL;
155 : }
156 :
157 : /* And the base offset should be at least inside the section. */
158 140 : if (str_off > (dbg->sectiondata[IDX_debug_str_offsets]->d_size
159 140 : - offset_size))
160 : goto invalid_offset;
161 :
162 140 : size_t max_idx = (dbg->sectiondata[IDX_debug_str_offsets]->d_size
163 140 : - offset_size - str_off) / offset_size;
164 140 : if (idx > max_idx)
165 : goto invalid_offset;
166 :
167 280 : datap = (dbg->sectiondata[IDX_debug_str_offsets]->d_buf
168 140 : + str_off + (idx * offset_size));
169 140 : if (offset_size == 4)
170 140 : off = read_4ubyte_unaligned (dbg, datap);
171 : else
172 0 : off = read_8ubyte_unaligned (dbg, datap);
173 :
174 140 : if (off > dbg->sectiondata[IDX_debug_str]->d_size)
175 : goto invalid_offset;
176 : }
177 :
178 932489 : return (const char *) data->d_buf + off;
179 : }
180 : INTDEF(dwarf_formstring)
|