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" \ | |
37 | [multi_line \ | |
38 | {/\* offset | size \*/ type = struct abc \{} \ | |
39 | { public:} \ | |
40 | {/\* 8 | 8 \*/ void \*field1;} \ | |
41 | {/\* 16:31 | 4 \*/ unsigned int field2 : 1;} \ | |
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 | 4 \*/ my_int_type field9;} \ | |
ce1e8424 | 55 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
56 | {} \ |
57 | { /\* total size \(bytes\): 56 \*/} \ | |
58 | { \}}] | |
59 | ||
60 | # Test "ptype /oTM". | |
61 | gdb_test "ptype /oTM struct abc" \ | |
62 | [multi_line \ | |
63 | {/\* offset | size \*/ type = struct abc \{} \ | |
64 | { public:} \ | |
65 | {/\* 8 | 8 \*/ void \*field1;} \ | |
66 | {/\* 16:31 | 4 \*/ unsigned int field2 : 1;} \ | |
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 | 4 \*/ my_int_type field9;} \ | |
80 | {} \ | |
81 | { abc\(void\);} \ | |
82 | { ~abc\(\);} \ | |
83 | {} \ | |
84 | { typedef int my_int_type;} \ | |
ce1e8424 | 85 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
86 | {} \ |
87 | { /\* total size \(bytes\): 56 \*/} \ | |
88 | { \}}] | |
89 | ||
90 | # Test "ptype /TMo". This should be the same as "ptype /o". | |
91 | gdb_test "ptype /TMo struct abc" \ | |
92 | [multi_line \ | |
93 | {/\* offset | size \*/ type = struct abc \{} \ | |
94 | { public:} \ | |
95 | {/\* 8 | 8 \*/ void \*field1;} \ | |
96 | {/\* 16:31 | 4 \*/ unsigned int field2 : 1;} \ | |
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 | 4 \*/ my_int_type field9;} \ | |
ce1e8424 | 110 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
111 | {} \ |
112 | { /\* total size \(bytes\): 56 \*/} \ | |
113 | { \}}] | |
114 | ||
115 | # Test nested structs. | |
116 | gdb_test "ptype /o struct pqr" \ | |
117 | [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 | {} \ | |
132 | { /\* total size \(bytes\): 24 \*/} \ | |
133 | { \} f4;} \ | |
134 | {} \ | |
135 | { /\* total size \(bytes\): 40 \*/} \ | |
136 | { \} ff2;} \ | |
137 | {/\* XXX 28-byte hole \*/} \ | |
138 | {/\* 72 | 1 \*/ signed char ff3;} \ | |
ce1e8424 | 139 | {/\* XXX 7-byte padding \*/} \ |
7c161838 SDJ |
140 | {} \ |
141 | { /\* total size \(bytes\): 56 \*/} \ | |
142 | { \}}] | |
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" \ | |
148 | [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;} \ | |
ce1e8424 | 155 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
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;} \ | |
ce1e8424 | 169 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
170 | {} \ |
171 | { /\* total size \(bytes\): 24 \*/} \ | |
172 | { \} f4;} \ | |
173 | {} \ | |
174 | { /\* total size \(bytes\): 40 \*/} \ | |
175 | { \} fff2;} \ | |
176 | {} \ | |
177 | { /\* total size \(bytes\): 40 \*/} \ | |
178 | { \}}] | |
179 | ||
180 | # Test printing a struct that contains a union, and that also | |
181 | # contains a struct. | |
182 | gdb_test "ptype /o struct poi" \ | |
183 | [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;} \ | |
ce1e8424 | 193 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
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;} \ | |
ce1e8424 | 207 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
208 | {} \ |
209 | { /\* total size \(bytes\): 24 \*/} \ | |
210 | { \} f4;} \ | |
ce1e8424 | 211 | {/\* XXX 32-byte padding \*/} \ |
7c161838 SDJ |
212 | {} \ |
213 | { /\* total size \(bytes\): 40 \*/} \ | |
214 | { \} fff2;} \ | |
215 | {} \ | |
216 | { /\* total size \(bytes\): 40 \*/} \ | |
217 | { \} f2;} \ | |
218 | {/\* 72 | 2 \*/ uint16_t f3;} \ | |
219 | {/\* XXX 6-byte hole \*/} \ | |
220 | {/\* 80 | 56 \*/ struct pqr \{} \ | |
221 | {/\* 80 | 4 \*/ int ff1;} \ | |
222 | {/\* XXX 4-byte hole \*/} \ | |
223 | {/\* 88 | 40 \*/ struct xyz \{} \ | |
224 | {/\* 88 | 4 \*/ int f1;} \ | |
225 | {/\* 92 | 1 \*/ signed char f2;} \ | |
226 | {/\* XXX 3-byte hole \*/} \ | |
227 | {/\* 96 | 8 \*/ void \*f3;} \ | |
228 | {/\* 104 | 24 \*/ struct tuv \{} \ | |
229 | {/\* 104 | 4 \*/ int a1;} \ | |
230 | {/\* XXX 4-byte hole \*/} \ | |
231 | {/\* 112 | 8 \*/ signed char \*a2;} \ | |
232 | {/\* 120 | 4 \*/ int a3;} \ | |
ce1e8424 | 233 | {/\* XXX 4-byte padding \*/} \ |
7c161838 SDJ |
234 | {} \ |
235 | { /\* total size \(bytes\): 24 \*/} \ | |
236 | { \} f4;} \ | |
237 | {} \ | |
238 | { /\* total size \(bytes\): 40 \*/} \ | |
239 | { \} ff2;} \ | |
240 | {/\* 152 | 1 \*/ signed char ff3;} \ | |
ce1e8424 | 241 | {/\* XXX 7-byte padding \*/} \ |
7c161838 SDJ |
242 | {} \ |
243 | { /\* total size \(bytes\): 56 \*/} \ | |
244 | { \} f4;} \ | |
245 | {} \ | |
246 | { /\* total size \(bytes\): 112 \*/} \ | |
247 | { \}}] | |
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" \ | |
265 | [multi_line \ | |
266 | {/\* offset | size \*/ type = struct tyu \{} \ | |
267 | {/\* 0:31 | 4 \*/ int a1 : 1;} \ | |
268 | {/\* 0:28 | 4 \*/ int a2 : 3;} \ | |
269 | {/\* 0: 5 | 4 \*/ int a3 : 23;} \ | |
270 | {/\* 3: 3 | 1 \*/ signed char a4 : 2;} \ | |
271 | {/\* XXX 3-bit hole \*/} \ | |
272 | {/\* XXX 4-byte hole \*/} \ | |
273 | {/\* 8 | 8 \*/ int64_t a5;} \ | |
274 | {/\* 16:27 | 4 \*/ int a6 : 5;} \ | |
275 | {/\* 16:56 | 8 \*/ int64_t a7 : 3;} \ | |
ce1e8424 | 276 | {/\* XXX 7-byte padding \*/} \ |
7c161838 SDJ |
277 | {} \ |
278 | { /\* total size \(bytes\): 24 \*/} \ | |
279 | { \}}] | |
280 | ||
281 | gdb_test "ptype /o struct asd" \ | |
282 | [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;} \ | |
296 | {/\* 24:27 | 4 \*/ int f4 : 5;} \ | |
297 | {/\* 24:26 | 4 \*/ unsigned int f5 : 1;} \ | |
298 | {/\* XXX 2-bit hole \*/} \ | |
299 | {/\* XXX 1-byte hole \*/} \ | |
300 | {/\* 26 | 2 \*/ short f6;} \ | |
301 | {} \ | |
302 | { /\* total size \(bytes\): 32 \*/} \ | |
303 | { \} f7;} \ | |
304 | {/\* 32 | 8 \*/ unsigned long f8;} \ | |
305 | {/\* 40 | 8 \*/ signed char \*f9;} \ | |
306 | {/\* 48:28 | 4 \*/ int f10 : 4;} \ | |
307 | {/\* 48:27 | 4 \*/ unsigned int f11 : 1;} \ | |
308 | {/\* 48:26 | 4 \*/ unsigned int f12 : 1;} \ | |
309 | {/\* 48:25 | 4 \*/ unsigned int f13 : 1;} \ | |
310 | {/\* 48:24 | 4 \*/ unsigned int f14 : 1;} \ | |
311 | {/\* XXX 7-byte hole \*/} \ | |
312 | {/\* 56 | 8 \*/ void \*f15;} \ | |
313 | {/\* 64 | 8 \*/ void \*f16;} \ | |
314 | {} \ | |
315 | { /\* total size \(bytes\): 72 \*/} \ | |
316 | { \}}] | |
317 | ||
318 | # Test that we don't print any header when issuing a "ptype /o" on a | |
319 | # non-struct, non-union, non-class type. | |
320 | gdb_test "ptype /o int" "int" | |
321 | gdb_test "ptype /o uint8_t" "char" | |
322 | ||
323 | # Test that the "whatis" command doesn't print anything related to the | |
324 | # "offsets" feature, even when receiving the "/o" parameter. | |
325 | set test "whatis /o asd" | |
326 | gdb_test_multiple "$test" "$test" { | |
327 | -re "^$test\r\ntype = asd\r\n$gdb_prompt $" { | |
328 | pass $test | |
329 | } | |
330 | } | |
16ff70dd SDJ |
331 | |
332 | # Test that printing a struct with a static member of itself doesn't | |
333 | # get us into an infinite loop. | |
334 | gdb_test "ptype/o static_member" \ | |
335 | [multi_line \ | |
336 | {/\* offset | size \*/ type = struct static_member \{} \ | |
337 | { static static_member Empty;} \ | |
338 | {\/* 0 | 4 \*/ int abc;} \ | |
339 | {} \ | |
340 | { /\* total size \(bytes\): 4 \*/} \ | |
341 | { \}}] |