Commit | Line | Data |
---|---|---|
7c161838 SDJ |
1 | # This testcase is part of GDB, the GNU debugger. |
2 | ||
42a4f53d | 3 | # Copyright 2017-2019 Free Software Foundation, Inc. |
7c161838 SDJ |
4 | |
5 | # This program is free software; you can redistribute it and/or modify | |
6 | # it under the terms of the GNU General Public License as published by | |
7 | # the Free Software Foundation; either version 3 of the License, or | |
8 | # (at your option) any later version. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License | |
16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | ||
18 | # This testcase exercises the "ptype /o" feature, which can be used to | |
19 | # print the offsets and sizes of each field of a struct/union/class. | |
20 | ||
21 | standard_testfile .cc | |
22 | ||
23 | # Test only works on LP64 targets. That's how we guarantee that the | |
24 | # expected holes will be present in the struct. | |
25 | if { ![is_lp64_target] } { | |
26 | untested "test work only on lp64 targets" | |
27 | return 0 | |
28 | } | |
29 | ||
30 | if { [prepare_for_testing "failed to prepare" $testfile $srcfile \ | |
31 | { debug c++ }] } { | |
32 | return -1 | |
33 | } | |
34 | ||
35 | # Test general offset printing, ctor/dtor printing, union, formatting. | |
36 | gdb_test "ptype /o struct abc" \ | |
844333e2 TT |
37 | [string_to_regexp [multi_line \ |
38 | "/* offset | size */ type = struct abc \{" \ | |
39 | " public:" \ | |
40 | "/* 8 | 8 */ void *field1;" \ | |
9d3421af | 41 | "/* 16: 0 | 4 */ unsigned int field2 : 1;" \ |
844333e2 TT |
42 | "/* XXX 7-bit hole */" \ |
43 | "/* XXX 3-byte hole */" \ | |
44 | "/* 20 | 4 */ int field3;" \ | |
45 | "/* 24 | 1 */ signed char field4;" \ | |
46 | "/* XXX 7-byte hole */" \ | |
47 | "/* 32 | 8 */ uint64_t field5;" \ | |
48 | "/* 40 | 8 */ union \{" \ | |
49 | "/* 8 */ void *field6;" \ | |
50 | "/* 4 */ int field7;" \ | |
51 | "" \ | |
52 | " /* total size (bytes): 8 */" \ | |
53 | " \} field8;" \ | |
54 | "/* 48 | 2 */ my_int_type field9;" \ | |
55 | "/* XXX 6-byte padding */" \ | |
56 | "" \ | |
57 | " /* total size (bytes): 56 */" \ | |
58 | " \}"]] | |
7c161838 SDJ |
59 | |
60 | # Test "ptype /oTM". | |
61 | gdb_test "ptype /oTM struct abc" \ | |
844333e2 TT |
62 | [string_to_regexp [multi_line \ |
63 | "/* offset | size */ type = struct abc \{" \ | |
64 | " public:" \ | |
65 | "/* 8 | 8 */ void *field1;" \ | |
9d3421af | 66 | "/* 16: 0 | 4 */ unsigned int field2 : 1;" \ |
844333e2 TT |
67 | "/* XXX 7-bit hole */" \ |
68 | "/* XXX 3-byte hole */" \ | |
69 | "/* 20 | 4 */ int field3;" \ | |
70 | "/* 24 | 1 */ signed char field4;" \ | |
71 | "/* XXX 7-byte hole */" \ | |
72 | "/* 32 | 8 */ uint64_t field5;" \ | |
73 | "/* 40 | 8 */ union \{" \ | |
74 | "/* 8 */ void *field6;" \ | |
75 | "/* 4 */ int field7;" \ | |
76 | "" \ | |
77 | " /* total size (bytes): 8 */" \ | |
78 | " \} field8;" \ | |
79 | "/* 48 | 2 */ my_int_type field9;" \ | |
80 | "" \ | |
81 | " abc(void);" \ | |
82 | " ~abc();" \ | |
83 | "" \ | |
84 | " typedef short my_int_type;" \ | |
85 | "/* XXX 6-byte padding */" \ | |
86 | "" \ | |
87 | " /* total size (bytes): 56 */" \ | |
88 | " \}"]] | |
7c161838 SDJ |
89 | |
90 | # Test "ptype /TMo". This should be the same as "ptype /o". | |
91 | gdb_test "ptype /TMo struct abc" \ | |
844333e2 TT |
92 | [string_to_regexp [multi_line \ |
93 | "/* offset | size */ type = struct abc \{" \ | |
94 | " public:" \ | |
95 | "/* 8 | 8 */ void *field1;" \ | |
9d3421af | 96 | "/* 16: 0 | 4 */ unsigned int field2 : 1;" \ |
844333e2 TT |
97 | "/* XXX 7-bit hole */" \ |
98 | "/* XXX 3-byte hole */" \ | |
99 | "/* 20 | 4 */ int field3;" \ | |
100 | "/* 24 | 1 */ signed char field4;" \ | |
101 | "/* XXX 7-byte hole */" \ | |
102 | "/* 32 | 8 */ uint64_t field5;" \ | |
103 | "/* 40 | 8 */ union \{" \ | |
104 | "/* 8 */ void *field6;" \ | |
105 | "/* 4 */ int field7;" \ | |
106 | "" \ | |
107 | " /* total size (bytes): 8 */" \ | |
108 | " \} field8;" \ | |
109 | "/* 48 | 2 */ my_int_type field9;" \ | |
110 | "/* XXX 6-byte padding */" \ | |
111 | "" \ | |
112 | " /* total size (bytes): 56 */" \ | |
113 | " \}"]] | |
7c161838 SDJ |
114 | |
115 | # Test nested structs. | |
116 | gdb_test "ptype /o struct pqr" \ | |
844333e2 TT |
117 | [string_to_regexp [multi_line \ |
118 | "/* offset | size */ type = struct pqr \{" \ | |
119 | "/* 0 | 4 */ int ff1;" \ | |
120 | "/* XXX 4-byte hole */" \ | |
121 | "/* 8 | 40 */ struct xyz \{" \ | |
122 | "/* 8 | 4 */ int f1;" \ | |
123 | "/* 12 | 1 */ signed char f2;" \ | |
124 | "/* XXX 3-byte hole */" \ | |
125 | "/* 16 | 8 */ void *f3;" \ | |
126 | "/* 24 | 24 */ struct tuv \{" \ | |
127 | "/* 24 | 4 */ int a1;" \ | |
128 | "/* XXX 4-byte hole */" \ | |
129 | "/* 32 | 8 */ signed char *a2;" \ | |
130 | "/* 40 | 4 */ int a3;" \ | |
131 | "/* XXX 4-byte padding */" \ | |
132 | "" \ | |
133 | " /* total size (bytes): 24 */" \ | |
134 | " \} f4;" \ | |
135 | "" \ | |
136 | " /* total size (bytes): 40 */" \ | |
137 | " \} ff2;" \ | |
138 | "/* 48 | 1 */ signed char ff3;" \ | |
139 | "/* XXX 7-byte padding */" \ | |
140 | "" \ | |
141 | " /* total size (bytes): 56 */" \ | |
142 | " \}"]] | |
7c161838 SDJ |
143 | |
144 | # Test that the offset is properly reset when we are printing a union | |
145 | # and go inside two inner structs. | |
146 | # This also tests a struct inside a struct inside a union. | |
147 | gdb_test "ptype /o union qwe" \ | |
844333e2 TT |
148 | [string_to_regexp [multi_line \ |
149 | "/* offset | size */ type = union qwe \{" \ | |
150 | "/* 24 */ struct tuv \{" \ | |
151 | "/* 0 | 4 */ int a1;" \ | |
152 | "/* XXX 4-byte hole */" \ | |
153 | "/* 8 | 8 */ signed char *a2;" \ | |
154 | "/* 16 | 4 */ int a3;" \ | |
155 | "/* XXX 4-byte padding */" \ | |
156 | "" \ | |
157 | " /* total size (bytes): 24 */" \ | |
158 | " \} fff1;" \ | |
159 | "/* 40 */ struct xyz \{" \ | |
160 | "/* 0 | 4 */ int f1;" \ | |
161 | "/* 4 | 1 */ signed char f2;" \ | |
162 | "/* XXX 3-byte hole */" \ | |
163 | "/* 8 | 8 */ void *f3;" \ | |
164 | "/* 16 | 24 */ struct tuv \{" \ | |
165 | "/* 16 | 4 */ int a1;" \ | |
166 | "/* XXX 4-byte hole */" \ | |
167 | "/* 24 | 8 */ signed char *a2;" \ | |
168 | "/* 32 | 4 */ int a3;" \ | |
169 | "/* XXX 4-byte padding */" \ | |
170 | "" \ | |
171 | " /* total size (bytes): 24 */" \ | |
172 | " \} f4;" \ | |
173 | "" \ | |
174 | " /* total size (bytes): 40 */" \ | |
175 | " \} fff2;" \ | |
176 | "" \ | |
177 | " /* total size (bytes): 40 */" \ | |
178 | " \}"]] | |
7c161838 SDJ |
179 | |
180 | # Test printing a struct that contains a union, and that also | |
181 | # contains a struct. | |
182 | gdb_test "ptype /o struct poi" \ | |
844333e2 TT |
183 | [string_to_regexp [multi_line \ |
184 | "/* offset | size */ type = struct poi \{" \ | |
185 | "/* 0 | 4 */ int f1;" \ | |
186 | "/* XXX 4-byte hole */" \ | |
187 | "/* 8 | 40 */ union qwe \{" \ | |
188 | "/* 24 */ struct tuv \{" \ | |
189 | "/* 8 | 4 */ int a1;" \ | |
190 | "/* XXX 4-byte hole */" \ | |
191 | "/* 16 | 8 */ signed char *a2;" \ | |
192 | "/* 24 | 4 */ int a3;" \ | |
193 | "/* XXX 4-byte padding */" \ | |
194 | "" \ | |
195 | " /* total size (bytes): 24 */" \ | |
196 | " \} fff1;" \ | |
197 | "/* 40 */ struct xyz \{" \ | |
198 | "/* 8 | 4 */ int f1;" \ | |
199 | "/* 12 | 1 */ signed char f2;" \ | |
200 | "/* XXX 3-byte hole */" \ | |
201 | "/* 16 | 8 */ void *f3;" \ | |
202 | "/* 24 | 24 */ struct tuv \{" \ | |
203 | "/* 24 | 4 */ int a1;" \ | |
204 | "/* XXX 4-byte hole */" \ | |
205 | "/* 32 | 8 */ signed char *a2;" \ | |
206 | "/* 40 | 4 */ int a3;" \ | |
207 | "/* XXX 4-byte padding */" \ | |
208 | "" \ | |
209 | " /* total size (bytes): 24 */" \ | |
210 | " \} f4;" \ | |
211 | "" \ | |
212 | " /* total size (bytes): 40 */" \ | |
213 | " \} fff2;" \ | |
214 | "/* XXX 32-byte padding */" \ | |
215 | "" \ | |
216 | " /* total size (bytes): 40 */" \ | |
217 | " \} f2;" \ | |
218 | "/* 48 | 2 */ uint16_t f3;" \ | |
219 | "/* XXX 6-byte hole */" \ | |
220 | "/* 56 | 56 */ struct pqr \{" \ | |
221 | "/* 56 | 4 */ int ff1;" \ | |
222 | "/* XXX 4-byte hole */" \ | |
223 | "/* 64 | 40 */ struct xyz \{" \ | |
224 | "/* 64 | 4 */ int f1;" \ | |
225 | "/* 68 | 1 */ signed char f2;" \ | |
226 | "/* XXX 3-byte hole */" \ | |
227 | "/* 72 | 8 */ void *f3;" \ | |
228 | "/* 80 | 24 */ struct tuv \{" \ | |
229 | "/* 80 | 4 */ int a1;" \ | |
230 | "/* XXX 4-byte hole */" \ | |
231 | "/* 88 | 8 */ signed char *a2;" \ | |
232 | "/* 96 | 4 */ int a3;" \ | |
233 | "/* XXX 4-byte padding */" \ | |
234 | "" \ | |
235 | " /* total size (bytes): 24 */" \ | |
236 | " \} f4;" \ | |
237 | "" \ | |
238 | " /* total size (bytes): 40 */" \ | |
239 | " \} ff2;" \ | |
240 | "/* 104 | 1 */ signed char ff3;" \ | |
241 | "/* XXX 7-byte padding */" \ | |
242 | "" \ | |
243 | " /* total size (bytes): 56 */" \ | |
244 | " \} f4;" \ | |
245 | "" \ | |
246 | " /* total size (bytes): 112 */" \ | |
247 | " \}"]] | |
7c161838 SDJ |
248 | |
249 | # Test printing a struct with several bitfields, laid out in various | |
250 | # ways. | |
251 | # | |
252 | # Because dealing with bitfields and offsets is difficult, it can be | |
253 | # tricky to confirm that the output of this command is accurate. A | |
254 | # nice way to do that is to use GDB's "x" command and print the actual | |
255 | # memory layout of the struct. In order to differentiate between | |
256 | # bitfields and non-bitfield variables, one can assign "-1" to every | |
257 | # bitfield in the struct. An example of the output of "x" using | |
258 | # "struct tyu" is: | |
259 | # | |
260 | # (gdb) x/24xb &e | |
261 | # 0x7fffffffd540: 0xff 0xff 0xff 0x1f 0x00 0x00 0x00 0x00 | |
262 | # 0x7fffffffd548: 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff | |
263 | # 0x7fffffffd550: 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 | |
264 | gdb_test "ptype /o struct tyu" \ | |
844333e2 TT |
265 | [string_to_regexp [multi_line \ |
266 | "/* offset | size */ type = struct tyu \{" \ | |
9d3421af TT |
267 | "/* 0: 0 | 4 */ int a1 : 1;" \ |
268 | "/* 0: 1 | 4 */ int a2 : 3;" \ | |
269 | "/* 0: 4 | 4 */ int a3 : 23;" \ | |
844333e2 TT |
270 | "/* 3: 3 | 1 */ signed char a4 : 2;" \ |
271 | "/* XXX 3-bit hole */" \ | |
272 | "/* XXX 4-byte hole */" \ | |
273 | "/* 8 | 8 */ int64_t a5;" \ | |
9d3421af TT |
274 | "/* 16: 0 | 4 */ int a6 : 5;" \ |
275 | "/* 16: 5 | 8 */ int64_t a7 : 3;" \ | |
844333e2 TT |
276 | "/* XXX 7-byte padding */" \ |
277 | "" \ | |
278 | " /* total size (bytes): 24 */" \ | |
279 | " \}"]] | |
7c161838 SDJ |
280 | |
281 | gdb_test "ptype /o struct asd" \ | |
844333e2 TT |
282 | [string_to_regexp [multi_line \ |
283 | "/* offset | size */ type = struct asd \{" \ | |
284 | "/* 0 | 32 */ struct asd::jkl \{" \ | |
285 | "/* 0 | 8 */ signed char *f1;" \ | |
286 | "/* 8 | 8 */ union \{" \ | |
287 | "/* 8 */ void *ff1;" \ | |
288 | "" \ | |
289 | " /* total size (bytes): 8 */" \ | |
290 | " \} f2;" \ | |
291 | "/* 16 | 8 */ union \{" \ | |
292 | "/* 8 */ signed char *ff2;" \ | |
293 | "" \ | |
294 | " /* total size (bytes): 8 */" \ | |
295 | " \} f3;" \ | |
9d3421af TT |
296 | "/* 24: 0 | 4 */ int f4 : 5;" \ |
297 | "/* 24: 5 | 4 */ unsigned int f5 : 1;" \ | |
844333e2 TT |
298 | "/* XXX 2-bit hole */" \ |
299 | "/* XXX 1-byte hole */" \ | |
300 | "/* 26 | 2 */ short f6;" \ | |
301 | "/* XXX 4-byte padding */" \ | |
302 | "" \ | |
303 | " /* total size (bytes): 32 */" \ | |
304 | " \} f7;" \ | |
305 | "/* 32 | 8 */ unsigned long f8;" \ | |
306 | "/* 40 | 8 */ signed char *f9;" \ | |
9d3421af TT |
307 | "/* 48: 0 | 4 */ int f10 : 4;" \ |
308 | "/* 48: 4 | 4 */ unsigned int f11 : 1;" \ | |
309 | "/* 48: 5 | 4 */ unsigned int f12 : 1;" \ | |
310 | "/* 48: 6 | 4 */ unsigned int f13 : 1;" \ | |
311 | "/* 48: 7 | 4 */ unsigned int f14 : 1;" \ | |
844333e2 TT |
312 | "/* XXX 7-byte hole */" \ |
313 | "/* 56 | 8 */ void *f15;" \ | |
314 | "/* 64 | 8 */ void *f16;" \ | |
315 | "" \ | |
316 | " /* total size (bytes): 72 */" \ | |
317 | " \}"]] | |
7c161838 SDJ |
318 | |
319 | # Test that we don't print any header when issuing a "ptype /o" on a | |
320 | # non-struct, non-union, non-class type. | |
321 | gdb_test "ptype /o int" "int" | |
322 | gdb_test "ptype /o uint8_t" "char" | |
323 | ||
324 | # Test that the "whatis" command doesn't print anything related to the | |
325 | # "offsets" feature, even when receiving the "/o" parameter. | |
326 | set test "whatis /o asd" | |
327 | gdb_test_multiple "$test" "$test" { | |
328 | -re "^$test\r\ntype = asd\r\n$gdb_prompt $" { | |
329 | pass $test | |
330 | } | |
331 | } | |
16ff70dd SDJ |
332 | |
333 | # Test that printing a struct with a static member of itself doesn't | |
334 | # get us into an infinite loop. | |
335 | gdb_test "ptype/o static_member" \ | |
844333e2 TT |
336 | [string_to_regexp [multi_line \ |
337 | "/* offset | size */ type = struct static_member \{" \ | |
338 | " static static_member Empty;" \ | |
339 | "\/* 0 | 4 */ int abc;" \ | |
340 | "" \ | |
341 | " /* total size (bytes): 4 */" \ | |
342 | " \}"]] |