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