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.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
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
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
19 or both in parallel, as here.
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.
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/>. */
37 internal_function const unsigned char *
38 __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
39 int err_nodata, const unsigned char **endpp,
45 const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
46 Dwarf_CU *skel = NULL; /* See below, needed for GNU DebugFission. */
47 if (unlikely (d == NULL
48 && sec_index == IDX_debug_ranges
49 && attr->cu->version < 5
50 && attr->cu->unit_type == DW_UT_split_compile))
52 skel = __libdw_find_split_unit (attr->cu);
54 d = skel->dbg->sectiondata[IDX_debug_ranges];
57 if (unlikely (d == NULL))
59 __libdw_seterrno (err_nodata);
64 if (attr->form == DW_FORM_sec_offset)
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 if (unlikely (skel != NULL))
75 Elf_Data *data = attr->cu->dbg->sectiondata[cu_sec_idx (attr->cu)];
76 const unsigned char *datap = attr->valp;
77 size_t size = attr->cu->offset_size;
78 if (unlikely (data == NULL
79 || datap < (const unsigned char *) data->d_buf
80 || data->d_size < size
82 - (const unsigned char *) data->d_buf)
83 > data->d_size - size)))
87 offset = read_4ubyte_unaligned (attr->cu->dbg, datap);
89 offset = read_8ubyte_unaligned (attr->cu->dbg, datap);
91 offset += __libdw_cu_ranges_base (skel);
95 if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
96 cu_sec_idx (attr->cu), attr->valp,
97 attr->cu->offset_size, &offset,
102 else if (attr->cu->version > 3)
109 if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
110 cu_sec_idx (attr->cu),
112 attr->form == DW_FORM_data4 ? 4 : 8,
113 &offset, sec_index, 0))
118 if (INTUSE(dwarf_formudata) (attr, &offset))
122 unsigned char *readp = d->d_buf + offset;
123 unsigned char *endp = d->d_buf + d->d_size;
124 if (unlikely (readp >= endp))
127 __libdw_seterrno (DWARF_E_INVALID_DWARF);
139 dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
144 const unsigned char *datap = attr->valp;
145 const unsigned char *endp = attr->cu->endp;
150 if (datap + 1 > endp)
153 __libdw_seterrno (DWARF_E_INVALID_DWARF);
156 *return_uval = *attr->valp;
160 if (datap + 2 > endp)
162 *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
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 if (attr->form == DW_FORM_sec_offset
173 || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
177 case DW_AT_data_member_location:
178 case DW_AT_frame_base:
180 case DW_AT_return_addr:
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 if (attr->cu->version < 5)
191 if (__libdw_formptr (attr, IDX_debug_loc,
192 DWARF_E_NO_DEBUG_LOC, NULL,
193 return_uval) == NULL)
198 /* loclist, loclistsptr */
199 if (__libdw_formptr (attr, IDX_debug_loclists,
200 DWARF_E_NO_DEBUG_LOCLISTS, NULL,
201 return_uval) == NULL)
206 case DW_AT_macro_info:
207 /* macptr into .debug_macinfo */
208 if (__libdw_formptr (attr, IDX_debug_macinfo,
209 DWARF_E_NO_ENTRY, NULL,
210 return_uval) == NULL)
214 case DW_AT_GNU_macros:
216 /* macptr into .debug_macro */
217 if (__libdw_formptr (attr, IDX_debug_macro,
218 DWARF_E_NO_ENTRY, NULL,
219 return_uval) == NULL)
224 case DW_AT_start_scope:
225 case DW_AT_GNU_ranges_base:
226 case DW_AT_rnglists_base:
227 if (attr->cu->version < 5)
230 if (__libdw_formptr (attr, IDX_debug_ranges,
231 DWARF_E_NO_DEBUG_RANGES, NULL,
232 return_uval) == NULL)
238 if (__libdw_formptr (attr, IDX_debug_rnglists,
239 DWARF_E_NO_DEBUG_RNGLISTS, NULL,
240 return_uval) == NULL)
245 case DW_AT_stmt_list:
247 if (__libdw_formptr (attr, IDX_debug_line,
248 DWARF_E_NO_DEBUG_LINE, NULL,
249 return_uval) == NULL)
253 case DW_AT_addr_base:
254 case DW_AT_GNU_addr_base:
256 if (__libdw_formptr (attr, IDX_debug_addr,
257 DWARF_E_NO_DEBUG_ADDR, NULL,
258 return_uval) == NULL)
262 case DW_AT_str_offsets_base:
264 if (__libdw_formptr (attr, IDX_debug_str_offsets,
265 DWARF_E_NO_STR_OFFSETS, NULL,
266 return_uval) == NULL)
271 /* sec_offset can only be used by one of the above attrs. */
272 if (attr->form == DW_FORM_sec_offset)
274 __libdw_seterrno (DWARF_E_INVALID_DWARF);
278 /* Not one of the special attributes, just a constant. */
279 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
281 attr->form == DW_FORM_data4 ? 4 : 8,
289 /* We are dealing with a constant data4 or data8. */
290 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
292 attr->form == DW_FORM_data4 ? 4 : 8,
299 if (datap + 1 > endp)
301 get_sleb128 (*return_uval, datap, endp);
305 case DW_FORM_rnglistx:
306 case DW_FORM_loclistx:
307 if (datap + 1 > endp)
309 get_uleb128 (*return_uval, datap, endp);
312 case DW_FORM_implicit_const:
313 // The data comes from the abbrev, which has been bounds checked.
314 get_sleb128_unchecked (*return_uval, datap);
317 /* These are indexes into the .debug_addr section, normally resolved
318 with dwarf_formaddr. Here treat as constants. */
319 case DW_FORM_GNU_addr_index:
323 get_uleb128 (*return_uval, datap, endp);
327 if (datap >= endp - 1)
329 *return_uval = *datap;
333 if (datap >= endp - 2)
335 *return_uval = read_2ubyte_unaligned (attr->cu->dbg, datap);
339 if (datap >= endp - 3)
341 *return_uval = read_3ubyte_unaligned (attr->cu->dbg, datap);
345 if (datap >= endp - 4)
347 *return_uval = read_4ubyte_unaligned (attr->cu->dbg, datap);
351 __libdw_seterrno (DWARF_E_NO_CONSTANT);
357 INTDEF(dwarf_formudata)