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