1 /* Compute size of an aggregate type from DWARF.
2 Copyright (C) 2010, 2014, 2016 Red Hat, Inc.
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
7
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
11
12 or
13
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
17
18 or both in parallel, as here.
19
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include <dwarf.h>
34 #include "libdwP.h"
35
36
37 static Dwarf_Die *
get_type(Dwarf_Die * die,Dwarf_Attribute * attr_mem,Dwarf_Die * type_mem)38 get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
39 {
40 Dwarf_Die *type = INTUSE(dwarf_formref_die)
41 (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
42
43 if (type == NULL || INTUSE(dwarf_peel_type) (type, type) != 0)
44 return NULL;
45
46 return type;
47 }
48
49 static int aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
50 Dwarf_Die *type_mem, int depth);
51
52 static int
array_size(Dwarf_Die * die,Dwarf_Word * size,Dwarf_Attribute * attr_mem,int depth)53 array_size (Dwarf_Die *die, Dwarf_Word *size,
54 Dwarf_Attribute *attr_mem, int depth)
55 {
56 Dwarf_Word eltsize;
57 Dwarf_Die type_mem, aggregate_type_mem;
58 if (aggregate_size (get_type (die, attr_mem, &type_mem), &eltsize,
59 &aggregate_type_mem, depth) != 0)
60 return -1;
61
62 /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type
63 children instead that give the size of each dimension. */
64
65 Dwarf_Die child;
66 if (INTUSE(dwarf_child) (die, &child) != 0)
67 return -1;
68
69 bool any = false;
70 Dwarf_Word count_total = 1;
71 do
72 {
73 Dwarf_Word count;
74 switch (INTUSE(dwarf_tag) (&child))
75 {
76 case DW_TAG_subrange_type:
77 /* This has either DW_AT_count or DW_AT_upper_bound. */
78 if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_count,
79 attr_mem) != NULL)
80 {
81 if (INTUSE(dwarf_formudata) (attr_mem, &count) != 0)
82 return -1;
83 }
84 else
85 {
86 bool is_signed = true;
87 if (INTUSE(dwarf_attr) (get_type (&child, attr_mem, &type_mem),
88 DW_AT_encoding, attr_mem) != NULL)
89 {
90 Dwarf_Word encoding;
91 if (INTUSE(dwarf_formudata) (attr_mem, &encoding) == 0)
92 is_signed = (encoding == DW_ATE_signed
93 || encoding == DW_ATE_signed_char);
94 }
95
96 Dwarf_Sword upper;
97 Dwarf_Sword lower;
98 if (is_signed)
99 {
100 if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate)
101 (&child, DW_AT_upper_bound,
102 attr_mem), &upper) != 0)
103 return -1;
104 }
105 else
106 {
107 Dwarf_Word unsigned_upper;
108 if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
109 (&child, DW_AT_upper_bound,
110 attr_mem), &unsigned_upper) != 0)
111 return -1;
112 upper = unsigned_upper;
113 }
114
115 /* Having DW_AT_lower_bound is optional. */
116 if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
117 attr_mem) != NULL)
118 {
119 if (is_signed)
120 {
121 if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
122 return -1;
123 }
124 else
125 {
126 Dwarf_Word unsigned_lower;
127 if (INTUSE(dwarf_formudata) (attr_mem, &unsigned_lower) != 0)
128 return -1;
129 lower = unsigned_lower;
130 }
131 }
132 else
133 {
134 Dwarf_Die cu = CUDIE (die->cu);
135 int lang = INTUSE(dwarf_srclang) (&cu);
136 if (lang == -1
137 || INTUSE(dwarf_default_lower_bound) (lang, &lower) != 0)
138 return -1;
139 }
140 if (unlikely (lower > upper))
141 return -1;
142 count = upper - lower + 1;
143 }
144 break;
145
146 case DW_TAG_enumeration_type:
147 /* We have to find the DW_TAG_enumerator child with the
148 highest value to know the array's element count. */
149 count = 0;
150 Dwarf_Die enum_child;
151 int has_children = INTUSE(dwarf_child) (die, &enum_child);
152 if (has_children < 0)
153 return -1;
154 if (has_children > 0)
155 do
156 if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
157 {
158 Dwarf_Word value;
159 if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
160 (&enum_child, DW_AT_const_value,
161 attr_mem), &value) != 0)
162 return -1;
163 if (value >= count)
164 count = value + 1;
165 }
166 while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
167 break;
168
169 default:
170 continue;
171 }
172
173 count_total *= count;
174
175 any = true;
176 }
177 while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
178
179 if (!any)
180 return -1;
181
182 /* This is a subrange_type or enumeration_type and we've set COUNT.
183 Now determine the stride for this array. */
184 Dwarf_Word stride = eltsize;
185 if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_stride,
186 attr_mem) != NULL)
187 {
188 if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
189 return -1;
190 }
191 else if (INTUSE(dwarf_attr_integrate) (die, DW_AT_bit_stride,
192 attr_mem) != NULL)
193 {
194 if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
195 return -1;
196 if (stride % 8) /* XXX maybe compute in bits? */
197 return -1;
198 stride /= 8;
199 }
200
201 *size = count_total * stride;
202 return 0;
203 }
204
205 static int
aggregate_size(Dwarf_Die * die,Dwarf_Word * size,Dwarf_Die * type_mem,int depth)206 aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
207 Dwarf_Die *type_mem, int depth)
208 {
209 Dwarf_Attribute attr_mem;
210
211 /* Arrays of arrays of subrange types of arrays... Don't recurse too deep. */
212 #define MAX_DEPTH 256
213 if (die == NULL || depth++ >= MAX_DEPTH)
214 return -1;
215
216 if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
217 return INTUSE(dwarf_formudata) (&attr_mem, size);
218
219 switch (INTUSE(dwarf_tag) (die))
220 {
221 case DW_TAG_subrange_type:
222 {
223 Dwarf_Die aggregate_type_mem;
224 return aggregate_size (get_type (die, &attr_mem, type_mem),
225 size, &aggregate_type_mem, depth);
226 }
227
228 case DW_TAG_array_type:
229 return array_size (die, size, &attr_mem, depth);
230
231 /* Assume references and pointers have pointer size if not given an
232 explicit DW_AT_byte_size. */
233 case DW_TAG_pointer_type:
234 case DW_TAG_reference_type:
235 case DW_TAG_rvalue_reference_type:
236 *size = die->cu->address_size;
237 return 0;
238 }
239
240 /* Most types must give their size directly. */
241 return -1;
242 }
243
244 NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)
245 int
dwarf_aggregate_size(Dwarf_Die * die,Dwarf_Word * size)246 dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
247 {
248 Dwarf_Die die_mem, type_mem;
249
250 if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
251 return -1;
252
253 return aggregate_size (&die_mem, size, &type_mem, 0);
254 }
255 NEW_INTDEF (dwarf_aggregate_size)
256 OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
257