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