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 12 : get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
39 : {
40 12 : Dwarf_Die *type = INTUSE(dwarf_formref_die)
41 : (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
42 :
43 12 : if (INTUSE(dwarf_peel_type) (type, type) != 0)
44 : return NULL;
45 :
46 12 : return type;
47 : }
48 :
49 : static int
50 12 : array_size (Dwarf_Die *die, Dwarf_Word *size,
51 : Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
52 : {
53 : Dwarf_Word eltsize;
54 12 : if (INTUSE(dwarf_aggregate_size) (get_type (die, attr_mem, type_mem),
55 : &eltsize) != 0)
56 : return -1;
57 :
58 : /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type
59 : children instead that give the size of each dimension. */
60 :
61 : Dwarf_Die child;
62 12 : if (INTUSE(dwarf_child) (die, &child) != 0)
63 : return -1;
64 :
65 : bool any = false;
66 : Dwarf_Word total = 0;
67 : do
68 : {
69 : Dwarf_Word count;
70 12 : switch (INTUSE(dwarf_tag) (&child))
71 : {
72 : case DW_TAG_subrange_type:
73 : /* This has either DW_AT_count or DW_AT_upper_bound. */
74 12 : if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_count,
75 : attr_mem) != NULL)
76 : {
77 0 : if (INTUSE(dwarf_formudata) (attr_mem, &count) != 0)
78 0 : return -1;
79 : }
80 : else
81 : {
82 : Dwarf_Sword upper;
83 : Dwarf_Sword lower;
84 12 : if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate)
85 : (&child, DW_AT_upper_bound,
86 : attr_mem), &upper) != 0)
87 0 : return -1;
88 :
89 : /* Having DW_AT_lower_bound is optional. */
90 12 : if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
91 : attr_mem) != NULL)
92 : {
93 0 : if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
94 : return -1;
95 : }
96 : else
97 : {
98 : /* Determine default lower bound from language,
99 : as per "4.12 Subrange Type Entries". */
100 24 : Dwarf_Die cu = CUDIE (die->cu);
101 12 : switch (INTUSE(dwarf_srclang) (&cu))
102 : {
103 : case DW_LANG_C:
104 : case DW_LANG_C89:
105 : case DW_LANG_C99:
106 : case DW_LANG_C11:
107 : case DW_LANG_C_plus_plus:
108 : case DW_LANG_C_plus_plus_11:
109 : case DW_LANG_C_plus_plus_14:
110 : case DW_LANG_ObjC:
111 : case DW_LANG_ObjC_plus_plus:
112 : case DW_LANG_Java:
113 : case DW_LANG_D:
114 : case DW_LANG_UPC:
115 : case DW_LANG_Go:
116 12 : lower = 0;
117 12 : break;
118 :
119 : case DW_LANG_Ada83:
120 : case DW_LANG_Ada95:
121 : case DW_LANG_Cobol74:
122 : case DW_LANG_Cobol85:
123 : case DW_LANG_Fortran77:
124 : case DW_LANG_Fortran90:
125 : case DW_LANG_Fortran95:
126 : case DW_LANG_Fortran03:
127 : case DW_LANG_Fortran08:
128 : case DW_LANG_Pascal83:
129 : case DW_LANG_Modula2:
130 : case DW_LANG_PLI:
131 0 : lower = 1;
132 0 : break;
133 :
134 : default:
135 0 : return -1;
136 : }
137 : }
138 12 : if (unlikely (lower > upper))
139 : return -1;
140 12 : count = upper - lower + 1;
141 : }
142 12 : break;
143 :
144 : case DW_TAG_enumeration_type:
145 : /* We have to find the DW_TAG_enumerator child with the
146 : highest value to know the array's element count. */
147 0 : count = 0;
148 : Dwarf_Die enum_child;
149 0 : int has_children = INTUSE(dwarf_child) (die, &enum_child);
150 0 : if (has_children < 0)
151 : return -1;
152 0 : if (has_children > 0)
153 : do
154 0 : if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
155 : {
156 : Dwarf_Word value;
157 0 : if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
158 : (&enum_child, DW_AT_const_value,
159 : attr_mem), &value) != 0)
160 0 : return -1;
161 0 : if (value >= count)
162 0 : count = value + 1;
163 : }
164 0 : while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
165 : break;
166 :
167 : default:
168 0 : continue;
169 : }
170 :
171 : /* This is a subrange_type or enumeration_type and we've set COUNT.
172 : Now determine the stride for this array dimension. */
173 12 : Dwarf_Word stride = eltsize;
174 12 : if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_byte_stride,
175 : attr_mem) != NULL)
176 : {
177 0 : if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
178 : return -1;
179 : }
180 12 : else if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_bit_stride,
181 : attr_mem) != NULL)
182 : {
183 0 : if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
184 : return -1;
185 0 : if (stride % 8) /* XXX maybe compute in bits? */
186 : return -1;
187 0 : stride /= 8;
188 : }
189 :
190 12 : any = true;
191 12 : total += stride * count;
192 : }
193 12 : while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
194 :
195 12 : if (!any)
196 : return -1;
197 :
198 12 : *size = total;
199 12 : return 0;
200 : }
201 :
202 : static int
203 41 : aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem)
204 : {
205 : Dwarf_Attribute attr_mem;
206 :
207 41 : if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
208 27 : return INTUSE(dwarf_formudata) (&attr_mem, size);
209 :
210 14 : switch (INTUSE(dwarf_tag) (die))
211 : {
212 : case DW_TAG_subrange_type:
213 0 : return aggregate_size (get_type (die, &attr_mem, type_mem),
214 : size, type_mem); /* Tail call. */
215 :
216 : case DW_TAG_array_type:
217 12 : return array_size (die, size, &attr_mem, type_mem);
218 :
219 : /* Assume references and pointers have pointer size if not given an
220 : explicit DW_AT_byte_size. */
221 : case DW_TAG_pointer_type:
222 : case DW_TAG_reference_type:
223 : case DW_TAG_rvalue_reference_type:
224 2 : *size = die->cu->address_size;
225 2 : return 0;
226 : }
227 :
228 : /* Most types must give their size directly. */
229 : return -1;
230 : }
231 :
232 : int
233 41 : dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
234 : {
235 : Dwarf_Die type_mem;
236 :
237 41 : if (INTUSE (dwarf_peel_type) (die, die) != 0)
238 : return -1;
239 :
240 41 : return aggregate_size (die, size, &type_mem);
241 : }
242 : INTDEF (dwarf_aggregate_size)
243 : OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
244 : NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)
|