1 /* Return unsigned constant represented by attribute.
2 Copyright (C) 2003-2012, 2014 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 unsigned char *
__libdw_formptr(Dwarf_Attribute * attr,int sec_index,int err_nodata,unsigned char ** endpp,Dwarf_Off * offsetp)38 __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
39 int err_nodata, unsigned char **endpp,
40 Dwarf_Off *offsetp)
41 {
42 if (attr == NULL)
43 return NULL;
44
45 const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
46 if (unlikely (d == NULL))
47 {
48 __libdw_seterrno (err_nodata);
49 return NULL;
50 }
51
52 Dwarf_Word offset;
53 if (attr->form == DW_FORM_sec_offset)
54 {
55 if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
56 cu_sec_idx (attr->cu), attr->valp,
57 attr->cu->offset_size, &offset, sec_index, 0))
58 return NULL;
59 }
60 else if (attr->cu->version > 3)
61 goto invalid;
62 else
63 switch (attr->form)
64 {
65 case DW_FORM_data4:
66 case DW_FORM_data8:
67 if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
68 cu_sec_idx (attr->cu),
69 attr->valp,
70 attr->form == DW_FORM_data4 ? 4 : 8,
71 &offset, sec_index, 0))
72 return NULL;
73 break;
74
75 default:
76 if (INTUSE(dwarf_formudata) (attr, &offset))
77 return NULL;
78 };
79
80 unsigned char *readp = d->d_buf + offset;
81 unsigned char *endp = d->d_buf + d->d_size;
82 if (unlikely (readp >= endp))
83 {
84 invalid:
85 __libdw_seterrno (DWARF_E_INVALID_DWARF);
86 return NULL;
87 }
88
89 if (endpp != NULL)
90 *endpp = endp;
91 if (offsetp != NULL)
92 *offsetp = offset;
93 return readp;
94 }
95
96 int
dwarf_formudata(attr,return_uval)97 dwarf_formudata (attr, return_uval)
98 Dwarf_Attribute *attr;
99 Dwarf_Word *return_uval;
100 {
101 if (attr == NULL)
102 return -1;
103
104 const unsigned char *datap = attr->valp;
105 const unsigned char *endp = attr->cu->endp;
106
107 switch (attr->form)
108 {
109 case DW_FORM_data1:
110 if (datap + 1 > endp)
111 {
112 invalid:
113 __libdw_seterrno (DWARF_E_INVALID_DWARF);
114 return -1;
115 }
116 *return_uval = *attr->valp;
117 break;
118
119 case DW_FORM_data2:
120 if (datap + 2 > endp)
121 goto invalid;
122 *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
123 break;
124
125 case DW_FORM_data4:
126 case DW_FORM_data8:
127 case DW_FORM_sec_offset:
128 /* Before DWARF4 data4 and data8 are pure constants unless the
129 attribute also allows offsets (*ptr classes), since DWARF4
130 they are always just constants (start_scope is special though,
131 since it only could express a rangelist since DWARF4). */
132 if (attr->form == DW_FORM_sec_offset
133 || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
134 {
135 switch (attr->code)
136 {
137 case DW_AT_data_member_location:
138 case DW_AT_frame_base:
139 case DW_AT_location:
140 case DW_AT_return_addr:
141 case DW_AT_segment:
142 case DW_AT_static_link:
143 case DW_AT_string_length:
144 case DW_AT_use_location:
145 case DW_AT_vtable_elem_location:
146 /* loclistptr */
147 if (__libdw_formptr (attr, IDX_debug_loc,
148 DWARF_E_NO_LOCLIST, NULL,
149 return_uval) == NULL)
150 return -1;
151 break;
152
153 case DW_AT_macro_info:
154 /* macptr into .debug_macinfo */
155 if (__libdw_formptr (attr, IDX_debug_macinfo,
156 DWARF_E_NO_ENTRY, NULL,
157 return_uval) == NULL)
158 return -1;
159 break;
160
161 case DW_AT_GNU_macros:
162 /* macptr into .debug_macro */
163 if (__libdw_formptr (attr, IDX_debug_macro,
164 DWARF_E_NO_ENTRY, NULL,
165 return_uval) == NULL)
166 return -1;
167 break;
168
169 case DW_AT_ranges:
170 case DW_AT_start_scope:
171 /* rangelistptr */
172 if (__libdw_formptr (attr, IDX_debug_ranges,
173 DWARF_E_NO_DEBUG_RANGES, NULL,
174 return_uval) == NULL)
175 return -1;
176 break;
177
178 case DW_AT_stmt_list:
179 /* lineptr */
180 if (__libdw_formptr (attr, IDX_debug_line,
181 DWARF_E_NO_DEBUG_LINE, NULL,
182 return_uval) == NULL)
183 return -1;
184 break;
185
186 default:
187 /* sec_offset can only be used by one of the above attrs. */
188 if (attr->form == DW_FORM_sec_offset)
189 {
190 __libdw_seterrno (DWARF_E_INVALID_DWARF);
191 return -1;
192 }
193
194 /* Not one of the special attributes, just a constant. */
195 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
196 attr->valp,
197 attr->form == DW_FORM_data4 ? 4 : 8,
198 return_uval))
199 return -1;
200 break;
201 }
202 }
203 else
204 {
205 /* We are dealing with a constant data4 or data8. */
206 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
207 attr->valp,
208 attr->form == DW_FORM_data4 ? 4 : 8,
209 return_uval))
210 return -1;
211 }
212 break;
213
214 case DW_FORM_sdata:
215 if (datap + 1 > endp)
216 goto invalid;
217 get_sleb128 (*return_uval, datap, endp);
218 break;
219
220 case DW_FORM_udata:
221 if (datap + 1 > endp)
222 goto invalid;
223 get_uleb128 (*return_uval, datap, endp);
224 break;
225
226 default:
227 __libdw_seterrno (DWARF_E_NO_CONSTANT);
228 return -1;
229 }
230
231 return 0;
232 }
233 INTDEF(dwarf_formudata)
234