1# This testcase is part of GDB, the GNU debugger.
2
3# Copyright 2017-2020 Free Software Foundation, Inc.
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
21standard_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.
25if { ![is_lp64_target] } {
26    untested "test work only on lp64 targets"
27    return 0
28}
29
30if { [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.
36gdb_test "ptype /o struct abc" \
37    [string_to_regexp [multi_line \
38"/* offset    |  size */  type = struct abc \{" \
39"                         public:" \
40"/*    8      |     8 */    void *field1;" \
41"/*   16: 0   |     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      |     2 */    my_int_type field9;" \
55"/* XXX  6-byte padding  */" \
56"" \
57"                           /* total size (bytes):   56 */" \
58"                         \}"]]
59
60# Test "ptype /oTM".
61gdb_test "ptype /oTM struct abc" \
62    [string_to_regexp [multi_line \
63"/* offset    |  size */  type = struct abc \{" \
64"                         public:" \
65"/*    8      |     8 */    void *field1;" \
66"/*   16: 0   |     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      |     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"                         \}"]]
89
90# Test "ptype /TMo".  This should be the same as "ptype /o".
91gdb_test "ptype /TMo struct abc" \
92    [string_to_regexp [multi_line \
93"/* offset    |  size */  type = struct abc \{" \
94"                         public:" \
95"/*    8      |     8 */    void *field1;" \
96"/*   16: 0   |     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      |     2 */    my_int_type field9;" \
110"/* XXX  6-byte padding  */" \
111"" \
112"                           /* total size (bytes):   56 */" \
113"                         \}"]]
114
115# Test nested structs.
116gdb_test "ptype /o struct pqr" \
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"                         \}"]]
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.
147gdb_test "ptype /o union qwe" \
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"                         \}"]]
179
180# Test printing a struct that contains a union, and that also
181# contains a struct.
182gdb_test "ptype /o struct poi" \
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"                         \}"]]
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
264gdb_test "ptype /o struct tyu" \
265    [string_to_regexp [multi_line \
266"/* offset    |  size */  type = struct tyu \{" \
267"/*    0: 0   |     4 */    int a1 : 1;" \
268"/*    0: 1   |     4 */    int a2 : 3;" \
269"/*    0: 4   |     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: 0   |     4 */    int a6 : 5;" \
275"/*   16: 5   |     8 */    int64_t a7 : 3;" \
276"/* XXX  7-byte padding  */" \
277"" \
278"                           /* total size (bytes):   24 */" \
279"                         \}"]]
280
281gdb_test "ptype /o struct asd" \
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;" \
296"/*   24: 0   |     4 */        int f4 : 5;" \
297"/*   24: 5   |     4 */        unsigned int f5 : 1;" \
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;" \
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;" \
312"/* XXX  7-byte hole  */" \
313"/*   56      |     8 */    void *f15;" \
314"/*   64      |     8 */    void *f16;" \
315"" \
316"                           /* total size (bytes):   72 */" \
317"                         \}"]]
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.
321gdb_test "ptype /o int" "int"
322gdb_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.
326set test "whatis /o asd"
327gdb_test_multiple "$test" "$test" {
328   -re "^$test\r\ntype = asd\r\n$gdb_prompt $" {
329       pass $test
330   }
331}
332
333# Test that printing a struct with a static member of itself doesn't
334# get us into an infinite loop.
335gdb_test "ptype/o static_member" \
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"                         \}"]]
343