Line data Source code
1 : /* Return unsigned constant represented by attribute.
2 : Copyright (C) 2003-2012, 2014, 2017 Red Hat, Inc.
3 : This file is part of elfutils.
4 : Written by Ulrich Drepper <drepper@redhat.com>, 2003.
5 :
6 : This file is free software; you can redistribute it and/or modify
7 : it under the terms of either
8 :
9 : * the GNU Lesser General Public License as published by the Free
10 : Software Foundation; either version 3 of the License, or (at
11 : your option) any later version
12 :
13 : or
14 :
15 : * the GNU General Public License as published by the Free
16 : Software Foundation; either version 2 of the License, or (at
17 : your option) any later version
18 :
19 : or both in parallel, as here.
20 :
21 : elfutils is distributed in the hope that it will be useful, but
22 : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : General Public License for more details.
25 :
26 : You should have received copies of the GNU General Public License and
27 : the GNU Lesser General Public License along with this program. If
28 : not, see <http://www.gnu.org/licenses/>. */
29 :
30 : #ifdef HAVE_CONFIG_H
31 : # include <config.h>
32 : #endif
33 :
34 : #include <dwarf.h>
35 : #include "libdwP.h"
36 :
37 : internal_function const unsigned char *
38 416340 : __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
39 : int err_nodata, const unsigned char **endpp,
40 : Dwarf_Off *offsetp)
41 : {
42 416340 : if (attr == NULL)
43 : return NULL;
44 :
45 416340 : const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
46 416340 : Dwarf_CU *skel = NULL; /* See below, needed for GNU DebugFission. */
47 416340 : if (unlikely (d == NULL
48 : && sec_index == IDX_debug_ranges
49 : && attr->cu->version < 5
50 : && attr->cu->unit_type == DW_UT_split_compile))
51 : {
52 10 : skel = __libdw_find_split_unit (attr->cu);
53 10 : if (skel != NULL)
54 10 : d = skel->dbg->sectiondata[IDX_debug_ranges];
55 : }
56 :
57 416340 : if (unlikely (d == NULL))
58 : {
59 9 : __libdw_seterrno (err_nodata);
60 9 : return NULL;
61 : }
62 :
63 : Dwarf_Word offset;
64 416331 : if (attr->form == DW_FORM_sec_offset)
65 : {
66 : /* GNU DebugFission is slightly odd. It uses DW_FORM_sec_offset
67 : in split units, but they are really (unrelocated) offsets
68 : from the skeleton DW_AT_GNU_ranges_base (which is only used
69 : for the split unit, not the skeleton ranges itself, see also
70 : DW_AT_rnglists_base, which is used in DWARF5 for both, but
71 : points to the offsets index). So it isn't really a formptr,
72 : but an offset + base calculation. */
73 328818 : if (unlikely (skel != NULL))
74 : {
75 10 : Elf_Data *data = attr->cu->dbg->sectiondata[cu_sec_idx (attr->cu)];
76 10 : const unsigned char *datap = attr->valp;
77 10 : size_t size = attr->cu->offset_size;
78 10 : if (unlikely (data == NULL
79 : || datap < (const unsigned char *) data->d_buf
80 : || data->d_size < size
81 : || ((size_t) (datap
82 : - (const unsigned char *) data->d_buf)
83 : > data->d_size - size)))
84 : goto invalid;
85 :
86 10 : if (size == 4)
87 10 : offset = read_4ubyte_unaligned (attr->cu->dbg, datap);
88 : else
89 0 : offset = read_8ubyte_unaligned (attr->cu->dbg, datap);
90 :
91 10 : offset += __libdw_cu_ranges_base (skel);
92 : }
93 : else
94 : {
95 657616 : if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
96 328808 : cu_sec_idx (attr->cu), attr->valp,
97 328808 : attr->cu->offset_size, &offset,
98 : sec_index, 0))
99 : return NULL;
100 : }
101 : }
102 87513 : else if (attr->cu->version > 3)
103 : goto invalid;
104 : else
105 504 : switch (attr->form)
106 : {
107 504 : case DW_FORM_data4:
108 : case DW_FORM_data8:
109 1008 : if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
110 504 : cu_sec_idx (attr->cu),
111 504 : attr->valp,
112 : attr->form == DW_FORM_data4 ? 4 : 8,
113 : &offset, sec_index, 0))
114 : return NULL;
115 : break;
116 :
117 0 : default:
118 0 : if (INTUSE(dwarf_formudata) (attr, &offset))
119 : return NULL;
120 : };
121 :
122 329322 : unsigned char *readp = d->d_buf + offset;
123 329322 : unsigned char *endp = d->d_buf + d->d_size;
124 329322 : if (unlikely (readp >= endp))
125 : {
126 87009 : invalid:
127 87009 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
128 87009 : return NULL;
129 : }
130 :
131 329322 : if (endpp != NULL)
132 0 : *endpp = endp;
133 329322 : if (offsetp != NULL)
134 329322 : *offsetp = offset;
135 : return readp;
136 : }
137 :
138 : int
139 1587967 : dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
140 : {
141 1587967 : if (attr == NULL)
142 : return -1;
143 :
144 1585449 : const unsigned char *datap = attr->valp;
145 1585449 : const unsigned char *endp = attr->cu->endp;
146 :
147 1585449 : switch (attr->form)
148 : {
149 1267203 : case DW_FORM_data1:
150 1267203 : if (datap + 1 > endp)
151 : {
152 0 : invalid:
153 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
154 0 : return -1;
155 : }
156 1267203 : *return_uval = *attr->valp;
157 1267203 : break;
158 :
159 202405 : case DW_FORM_data2:
160 202405 : if (datap + 2 > endp)
161 : goto invalid;
162 213565 : *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
163 202405 : break;
164 :
165 95631 : case DW_FORM_data4:
166 : case DW_FORM_data8:
167 : case DW_FORM_sec_offset:
168 : /* Before DWARF4 data4 and data8 are pure constants unless the
169 : attribute also allows offsets (*ptr classes), since DWARF4
170 : they are always just constants (start_scope is special though,
171 : since it only could express a rangelist since DWARF4). */
172 95631 : if (attr->form == DW_FORM_sec_offset
173 41585 : || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
174 : {
175 54444 : switch (attr->code)
176 : {
177 41593 : case DW_AT_data_member_location:
178 : case DW_AT_frame_base:
179 : case DW_AT_location:
180 : case DW_AT_return_addr:
181 : case DW_AT_segment:
182 : case DW_AT_static_link:
183 : case DW_AT_string_length:
184 : case DW_AT_use_location:
185 : case DW_AT_vtable_elem_location:
186 : case DW_AT_GNU_locviews:
187 : case DW_AT_loclists_base:
188 41593 : if (attr->cu->version < 5)
189 : {
190 : /* loclistptr */
191 41554 : if (__libdw_formptr (attr, IDX_debug_loc,
192 : DWARF_E_NO_DEBUG_LOC, NULL,
193 : return_uval) == NULL)
194 : return -1;
195 : }
196 : else
197 : {
198 : /* loclist, loclistsptr */
199 39 : if (__libdw_formptr (attr, IDX_debug_loclists,
200 : DWARF_E_NO_DEBUG_LOCLISTS, NULL,
201 : return_uval) == NULL)
202 : return -1;
203 : }
204 : break;
205 :
206 267 : case DW_AT_macro_info:
207 : /* macptr into .debug_macinfo */
208 267 : if (__libdw_formptr (attr, IDX_debug_macinfo,
209 : DWARF_E_NO_ENTRY, NULL,
210 : return_uval) == NULL)
211 : return -1;
212 : break;
213 :
214 283 : case DW_AT_GNU_macros:
215 : case DW_AT_macros:
216 : /* macptr into .debug_macro */
217 283 : if (__libdw_formptr (attr, IDX_debug_macro,
218 : DWARF_E_NO_ENTRY, NULL,
219 : return_uval) == NULL)
220 : return -1;
221 : break;
222 :
223 11029 : case DW_AT_ranges:
224 : case DW_AT_start_scope:
225 : case DW_AT_GNU_ranges_base:
226 : case DW_AT_rnglists_base:
227 11029 : if (attr->cu->version < 5)
228 : {
229 : /* rangelistptr */
230 11014 : if (__libdw_formptr (attr, IDX_debug_ranges,
231 : DWARF_E_NO_DEBUG_RANGES, NULL,
232 : return_uval) == NULL)
233 : return -1;
234 : }
235 : else
236 : {
237 : /* rnglistsptr */
238 15 : if (__libdw_formptr (attr, IDX_debug_rnglists,
239 : DWARF_E_NO_DEBUG_RNGLISTS, NULL,
240 : return_uval) == NULL)
241 : return -1;
242 : }
243 : break;
244 :
245 1183 : case DW_AT_stmt_list:
246 : /* lineptr */
247 1183 : if (__libdw_formptr (attr, IDX_debug_line,
248 : DWARF_E_NO_DEBUG_LINE, NULL,
249 : return_uval) == NULL)
250 : return -1;
251 : break;
252 :
253 65 : case DW_AT_addr_base:
254 : case DW_AT_GNU_addr_base:
255 : /* addrptr */
256 65 : if (__libdw_formptr (attr, IDX_debug_addr,
257 : DWARF_E_NO_DEBUG_ADDR, NULL,
258 : return_uval) == NULL)
259 : return -1;
260 : break;
261 :
262 0 : case DW_AT_str_offsets_base:
263 : /* stroffsetsptr */
264 0 : if (__libdw_formptr (attr, IDX_debug_str_offsets,
265 : DWARF_E_NO_STR_OFFSETS, NULL,
266 : return_uval) == NULL)
267 : return -1;
268 : break;
269 :
270 24 : default:
271 : /* sec_offset can only be used by one of the above attrs. */
272 24 : if (attr->form == DW_FORM_sec_offset)
273 : {
274 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
275 0 : return -1;
276 : }
277 :
278 : /* Not one of the special attributes, just a constant. */
279 24 : if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
280 : attr->valp,
281 : attr->form == DW_FORM_data4 ? 4 : 8,
282 : return_uval))
283 : return -1;
284 : break;
285 : }
286 : }
287 : else
288 : {
289 : /* We are dealing with a constant data4 or data8. */
290 41187 : if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
291 : attr->valp,
292 : attr->form == DW_FORM_data4 ? 4 : 8,
293 : return_uval))
294 : return -1;
295 : }
296 : break;
297 :
298 20031 : case DW_FORM_sdata:
299 20031 : if (datap + 1 > endp)
300 : goto invalid;
301 20031 : get_sleb128 (*return_uval, datap, endp);
302 20031 : break;
303 :
304 78 : case DW_FORM_udata:
305 : case DW_FORM_rnglistx:
306 : case DW_FORM_loclistx:
307 78 : if (datap + 1 > endp)
308 : goto invalid;
309 78 : get_uleb128 (*return_uval, datap, endp);
310 78 : break;
311 :
312 93 : case DW_FORM_implicit_const:
313 : // The data comes from the abbrev, which has been bounds checked.
314 93 : get_sleb128_unchecked (*return_uval, datap);
315 93 : break;
316 :
317 : /* These are indexes into the .debug_addr section, normally resolved
318 : with dwarf_formaddr. Here treat as constants. */
319 8 : case DW_FORM_GNU_addr_index:
320 : case DW_FORM_addrx:
321 8 : if (datap >= endp)
322 : goto invalid;
323 8 : get_uleb128 (*return_uval, datap, endp);
324 8 : break;
325 :
326 0 : case DW_FORM_addrx1:
327 0 : if (datap >= endp - 1)
328 : goto invalid;
329 0 : *return_uval = *datap;
330 0 : break;
331 :
332 0 : case DW_FORM_addrx2:
333 0 : if (datap >= endp - 2)
334 : goto invalid;
335 0 : *return_uval = read_2ubyte_unaligned (attr->cu->dbg, datap);
336 0 : break;
337 :
338 0 : case DW_FORM_addrx3:
339 0 : if (datap >= endp - 3)
340 : goto invalid;
341 0 : *return_uval = read_3ubyte_unaligned (attr->cu->dbg, datap);
342 0 : break;
343 :
344 0 : case DW_FORM_addrx4:
345 0 : if (datap >= endp - 4)
346 : goto invalid;
347 0 : *return_uval = read_4ubyte_unaligned (attr->cu->dbg, datap);
348 0 : break;
349 :
350 0 : default:
351 0 : __libdw_seterrno (DWARF_E_NO_CONSTANT);
352 0 : return -1;
353 : }
354 :
355 : return 0;
356 : }
357 : INTDEF(dwarf_formudata)
|