Branch data Line data Source code
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 *
38 : 454 : get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
39 : : {
40 : 454 : Dwarf_Die *type = INTUSE(dwarf_formref_die)
41 : : (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
42 : :
43 [ + + - + ]: 454 : if (type == NULL || INTUSE(dwarf_peel_type) (type, type) != 0)
44 : 197 : 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
53 : 226 : array_size (Dwarf_Die *die, Dwarf_Word *size,
54 : : Dwarf_Attribute *attr_mem, int depth)
55 : : {
56 : 226 : Dwarf_Word eltsize;
57 : 226 : Dwarf_Die type_mem, aggregate_type_mem;
58 [ - + ]: 226 : 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 : 226 : Dwarf_Die child;
66 [ - + ]: 226 : if (INTUSE(dwarf_child) (die, &child) != 0)
67 : : return -1;
68 : :
69 : : bool any = false;
70 : : Dwarf_Word count_total = 1;
71 : 228 : do
72 : : {
73 : 228 : Dwarf_Word count;
74 [ + - - ]: 228 : switch (INTUSE(dwarf_tag) (&child))
75 : 0 : {
76 : 228 : case DW_TAG_subrange_type:
77 : : /* This has either DW_AT_count or DW_AT_upper_bound. */
78 [ - + ]: 228 : if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_count,
79 : : attr_mem) != NULL)
80 : : {
81 [ # # ]: 0 : if (INTUSE(dwarf_formudata) (attr_mem, &count) != 0)
82 : 0 : return -1;
83 : : }
84 : : else
85 : : {
86 : 228 : bool is_signed = true;
87 [ + + ]: 228 : if (INTUSE(dwarf_attr) (get_type (&child, attr_mem, &type_mem),
88 : : DW_AT_encoding, attr_mem) != NULL)
89 : : {
90 : 31 : Dwarf_Word encoding;
91 [ - + ]: 31 : if (INTUSE(dwarf_formudata) (attr_mem, &encoding) == 0)
92 : 31 : is_signed = (encoding == DW_ATE_signed
93 : 31 : || encoding == DW_ATE_signed_char);
94 : : }
95 : :
96 : 31 : Dwarf_Sword upper;
97 : 31 : Dwarf_Sword lower;
98 [ + + ]: 31 : if (is_signed)
99 : : {
100 [ + - ]: 201 : if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate)
101 : : (&child, DW_AT_upper_bound,
102 : : attr_mem), &upper) != 0)
103 : 0 : return -1;
104 : : }
105 : : else
106 : : {
107 : 27 : Dwarf_Word unsigned_upper;
108 [ - + ]: 27 : if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
109 : : (&child, DW_AT_upper_bound,
110 : : attr_mem), &unsigned_upper) != 0)
111 : 0 : return -1;
112 : 27 : upper = unsigned_upper;
113 : : }
114 : :
115 : : /* Having DW_AT_lower_bound is optional. */
116 [ + + ]: 228 : if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
117 : : attr_mem) != NULL)
118 : : {
119 [ + - ]: 1 : if (is_signed)
120 : : {
121 [ + - ]: 1 : if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
122 : : return -1;
123 : : }
124 : : else
125 : : {
126 : 0 : Dwarf_Word unsigned_lower;
127 [ # # ]: 0 : if (INTUSE(dwarf_formudata) (attr_mem, &unsigned_lower) != 0)
128 : 0 : return -1;
129 : 0 : lower = unsigned_lower;
130 : : }
131 : : }
132 : : else
133 : : {
134 : 227 : Dwarf_Die cu = CUDIE (die->cu);
135 : 227 : int lang = INTUSE(dwarf_srclang) (&cu);
136 [ + - ]: 227 : if (lang == -1
137 [ - + ]: 227 : || INTUSE(dwarf_default_lower_bound) (lang, &lower) != 0)
138 : 0 : return -1;
139 : : }
140 [ + - ]: 228 : if (unlikely (lower > upper))
141 : : return -1;
142 : 228 : count = upper - lower + 1;
143 : : }
144 : 228 : break;
145 : :
146 : 0 : 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 : 0 : count = 0;
150 : 0 : Dwarf_Die enum_child;
151 : 0 : int has_children = INTUSE(dwarf_child) (die, &enum_child);
152 [ # # ]: 0 : if (has_children < 0)
153 : : return -1;
154 [ # # ]: 0 : if (has_children > 0)
155 : 0 : do
156 [ # # ]: 0 : if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
157 : : {
158 : 0 : Dwarf_Word value;
159 [ # # ]: 0 : if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
160 : : (&enum_child, DW_AT_const_value,
161 : : attr_mem), &value) != 0)
162 : 0 : return -1;
163 [ # # ]: 0 : if (value >= count)
164 : 0 : count = value + 1;
165 : : }
166 [ # # ]: 0 : while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
167 : : break;
168 : :
169 : 0 : default:
170 : 0 : continue;
171 : : }
172 : :
173 : 228 : count_total *= count;
174 : :
175 : 228 : any = true;
176 : : }
177 [ + + ]: 228 : while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
178 : :
179 [ - + ]: 226 : 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 : 226 : Dwarf_Word stride = eltsize;
185 [ - + ]: 226 : if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_stride,
186 : : attr_mem) != NULL)
187 : : {
188 [ # # ]: 0 : if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
189 : : return -1;
190 : : }
191 [ - + ]: 226 : else if (INTUSE(dwarf_attr_integrate) (die, DW_AT_bit_stride,
192 : : attr_mem) != NULL)
193 : : {
194 [ # # ]: 0 : if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
195 : : return -1;
196 [ # # ]: 0 : if (stride % 8) /* XXX maybe compute in bits? */
197 : : return -1;
198 : 0 : stride /= 8;
199 : : }
200 : :
201 : 226 : *size = count_total * stride;
202 : 226 : return 0;
203 : : }
204 : :
205 : : static int
206 : 996 : aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
207 : : Dwarf_Die *type_mem, int depth)
208 : : {
209 : 996 : 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 [ + - - + ]: 996 : if (die == NULL || depth++ >= MAX_DEPTH)
214 : : return -1;
215 : :
216 [ + + ]: 996 : if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
217 : 768 : return INTUSE(dwarf_formudata) (&attr_mem, size);
218 : :
219 [ - - + + ]: 228 : switch (INTUSE(dwarf_tag) (die))
220 : : {
221 : 0 : case DW_TAG_subrange_type:
222 : : {
223 : 0 : Dwarf_Die aggregate_type_mem;
224 : 0 : return aggregate_size (get_type (die, &attr_mem, type_mem),
225 : : size, &aggregate_type_mem, depth);
226 : : }
227 : :
228 : 226 : case DW_TAG_array_type:
229 : 226 : 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 : 2 : case DW_TAG_pointer_type:
234 : : case DW_TAG_reference_type:
235 : : case DW_TAG_rvalue_reference_type:
236 : 2 : *size = die->cu->address_size;
237 : 2 : 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
246 : 770 : dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
247 : : {
248 : 770 : Dwarf_Die die_mem, type_mem;
249 : :
250 [ + - ]: 770 : if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
251 : : return -1;
252 : :
253 : 770 : 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)
|