Branch data 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 : 515869 : __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
39 : : int err_nodata, const unsigned char **endpp,
40 : : Dwarf_Off *offsetp)
41 : : {
42 [ - + ]: 515869 : if (attr == NULL)
43 : : return NULL;
44 : :
45 : 515869 : const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
46 : 515869 : Dwarf_CU *skel = NULL; /* See below, needed for GNU DebugFission. */
47 [ + + - + : 515869 : 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 [ + + ]: 515869 : if (unlikely (d == NULL))
58 : : {
59 : 17 : __libdw_seterrno (err_nodata);
60 : 17 : return NULL;
61 : : }
62 : :
63 : 515852 : Dwarf_Word offset;
64 [ + + ]: 515852 : 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 [ + + ]: 424068 : 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 : 0 : 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 [ - + ]: 424058 : if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
96 : 424058 : cu_sec_idx (attr->cu), attr->valp,
97 : 424058 : attr->cu->offset_size, &offset,
98 : : sec_index, 0))
99 : : return NULL;
100 : : }
101 : : }
102 [ + + ]: 91784 : else if (attr->cu->version > 3)
103 : 91255 : goto invalid;
104 : : else
105 [ + - ]: 529 : switch (attr->form)
106 : : {
107 : 529 : case DW_FORM_data4:
108 : : case DW_FORM_data8:
109 [ - + - + ]: 529 : if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
110 : 529 : cu_sec_idx (attr->cu),
111 : 529 : 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 : 424597 : };
121 : :
122 : 424597 : unsigned char *readp = d->d_buf + offset;
123 : 424597 : unsigned char *endp = d->d_buf + d->d_size;
124 [ - + ]: 424597 : if (unlikely (readp >= endp))
125 : : {
126 : 0 : invalid:
127 : 91255 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
128 : 91255 : return NULL;
129 : : }
130 : :
131 [ - + ]: 424597 : if (endpp != NULL)
132 : 0 : *endpp = endp;
133 [ + - ]: 424597 : if (offsetp != NULL)
134 : 424597 : *offsetp = offset;
135 : : return readp;
136 : : }
137 : :
138 : : int
139 : 2554740 : dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
140 : : {
141 [ + + ]: 2554740 : if (attr == NULL)
142 : : return -1;
143 : :
144 : 2551319 : const unsigned char *datap = attr->valp;
145 : 2551319 : const unsigned char *endp = attr->cu->endp;
146 : :
147 [ + + + + : 2551319 : switch (attr->form)
+ + + - -
- - - ]
148 : : {
149 : 1770714 : case DW_FORM_data1:
150 [ - + ]: 1770714 : if (datap + 1 > endp)
151 : : {
152 : 0 : invalid:
153 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
154 : 0 : return -1;
155 : : }
156 : 1770714 : *return_uval = *attr->valp;
157 : 1770714 : break;
158 : :
159 : 260535 : case DW_FORM_data2:
160 [ - + ]: 260535 : if (datap + 2 > endp)
161 : 0 : goto invalid;
162 [ + + ]: 260535 : *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
163 : 260535 : break;
164 : :
165 : 168657 : 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 [ + + ]: 168657 : if (attr->form == DW_FORM_sec_offset
173 [ + + + - ]: 45482 : || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
174 : : {
175 [ + + + + : 123563 : switch (attr->code)
+ + + + ]
176 : : {
177 : 104985 : 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 [ + + ]: 104985 : if (attr->cu->version < 5)
189 : : {
190 : : /* loclistptr */
191 [ - + ]: 162 : 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 [ - + ]: 104823 : 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 : 16120 : case DW_AT_ranges:
224 : : case DW_AT_start_scope:
225 : : case DW_AT_GNU_ranges_base:
226 : : case DW_AT_rnglists_base:
227 [ + + ]: 16120 : if (attr->cu->version < 5)
228 : : {
229 : : /* rangelistptr */
230 [ - + ]: 60 : 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 [ - + ]: 16060 : 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 : 1833 : case DW_AT_stmt_list:
246 : : /* lineptr */
247 [ - + ]: 1833 : 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 : 67 : case DW_AT_addr_base:
254 : : case DW_AT_GNU_addr_base:
255 : : /* addrptr */
256 [ - + ]: 67 : 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 : 2 : case DW_AT_str_offsets_base:
263 : : /* stroffsetsptr */
264 [ - + ]: 2 : 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 : 6 : default:
271 : : /* sec_offset can only be used by one of the above attrs. */
272 [ - + ]: 6 : 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 [ - + - + ]: 6 : 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 [ + + - + ]: 90136 : 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 : 20022 : case DW_FORM_sdata:
299 [ - + ]: 20022 : if (datap + 1 > endp)
300 : 0 : goto invalid;
301 : 20022 : get_sleb128 (*return_uval, datap, endp);
302 : 20022 : break;
303 : :
304 : 138522 : case DW_FORM_udata:
305 : : case DW_FORM_rnglistx:
306 : : case DW_FORM_loclistx:
307 [ - + ]: 138522 : if (datap + 1 > endp)
308 : 0 : goto invalid;
309 : 138522 : get_uleb128 (*return_uval, datap, endp);
310 : 138522 : break;
311 : :
312 : 192861 : case DW_FORM_implicit_const:
313 : : // The data comes from the abbrev, which has been bounds checked.
314 : 192861 : get_sleb128_unchecked (*return_uval, datap);
315 : 192861 : 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 : 0 : 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 : 0 : goto invalid;
329 : 0 : *return_uval = *datap;
330 : 0 : break;
331 : :
332 : 0 : case DW_FORM_addrx2:
333 [ # # ]: 0 : if (datap >= endp - 2)
334 : 0 : 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 : 0 : 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 : 0 : 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)
|