diff options
Diffstat (limited to 'gdb/testsuite/gdb.base')
-rw-r--r-- | gdb/testsuite/gdb.base/ptype-offsets.cc | 193 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/ptype-offsets.exp | 318 |
2 files changed, 511 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.base/ptype-offsets.cc b/gdb/testsuite/gdb.base/ptype-offsets.cc new file mode 100644 index 0000000..8673520 --- /dev/null +++ b/gdb/testsuite/gdb.base/ptype-offsets.cc @@ -0,0 +1,193 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdint.h> + +/* A struct with many types of fields, in order to test 'ptype + /o'. */ + +struct abc +{ + /* Virtual destructor. */ + virtual ~abc () + {} + + /* 8-byte address. Because of the virtual destructor above, this + field's offset will be 8. */ + void *field1; + + /* No hole here. */ + + /* 4-byte int bitfield of 1-bit. */ + unsigned int field2 : 1; + + /* 31-bit hole here. */ + + /* 4-byte int. */ + signed int field3; + + /* No hole here. */ + + /* 1-byte char. */ + signed char field4; + + /* 7-byte hole here. */ + + /* 8-byte int. */ + uint64_t field5; + + /* We just print the offset and size of a union, ignoring its + fields. */ + union + { + /* 8-byte address. */ + void *field6; + + /* 4-byte int. */ + signed int field7; + } field8; + + /* Empty constructor. */ + abc () + {} + + /* Typedef defined in-struct. */ + typedef int my_int_type; + + my_int_type field9; +}; + +/* This struct will be nested inside 'struct xyz'. */ + +struct tuv +{ + signed int a1; + + signed char *a2; + + signed int a3; +}; + +/* This struct will be nested inside 'struct pqr'. */ + +struct xyz +{ + signed int f1; + + signed char f2; + + void *f3; + + struct tuv f4; +}; + +/* A struct with a nested struct. */ + +struct pqr +{ + signed int ff1; + + struct xyz ff2; + + signed char ff3; +}; + +/* A union with two nested structs. */ + +union qwe +{ + struct tuv fff1; + + struct xyz fff2; +}; + +/* A struct with an union. */ + +struct poi +{ + signed int f1; + + union qwe f2; + + uint16_t f3; + + struct pqr f4; +}; + +/* A struct with bitfields. */ + +struct tyu +{ + signed int a1 : 1; + + signed int a2 : 3; + + signed int a3 : 23; + + signed char a4 : 2; + + int64_t a5; + + signed int a6 : 5; + + int64_t a7 : 3; +}; + +/* A struct with structs and unions. */ + +struct asd +{ + struct jkl + { + signed char *f1; + union + { + void *ff1; + } f2; + union + { + signed char *ff2; + } f3; + int f4 : 5; + unsigned int f5 : 1; + short f6; + } f7; + unsigned long f8; + signed char *f9; + int f10 : 4; + unsigned int f11 : 1; + unsigned int f12 : 1; + unsigned int f13 : 1; + unsigned int f14 : 1; + void *f15; + void *f16; +}; + + +int +main (int argc, char *argv[]) +{ + struct abc foo; + struct pqr bar; + union qwe c; + struct poi d; + struct tyu e; + struct asd f; + uint8_t i; + + return 0; +} diff --git a/gdb/testsuite/gdb.base/ptype-offsets.exp b/gdb/testsuite/gdb.base/ptype-offsets.exp new file mode 100644 index 0000000..55b1eb2b --- /dev/null +++ b/gdb/testsuite/gdb.base/ptype-offsets.exp @@ -0,0 +1,318 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2017 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This testcase exercises the "ptype /o" feature, which can be used to +# print the offsets and sizes of each field of a struct/union/class. + +standard_testfile .cc + +# Test only works on LP64 targets. That's how we guarantee that the +# expected holes will be present in the struct. +if { ![is_lp64_target] } { + untested "test work only on lp64 targets" + return 0 +} + +if { [prepare_for_testing "failed to prepare" $testfile $srcfile \ + { debug c++ }] } { + return -1 +} + +# Test general offset printing, ctor/dtor printing, union, formatting. +gdb_test "ptype /o struct abc" \ + [multi_line \ +{/\* offset | size \*/ type = struct abc \{} \ +{ public:} \ +{/\* 8 | 8 \*/ void \*field1;} \ +{/\* 16:31 | 4 \*/ unsigned int field2 : 1;} \ +{/\* XXX 7-bit hole \*/} \ +{/\* XXX 3-byte hole \*/} \ +{/\* 20 | 4 \*/ int field3;} \ +{/\* 24 | 1 \*/ signed char field4;} \ +{/\* XXX 7-byte hole \*/} \ +{/\* 32 | 8 \*/ uint64_t field5;} \ +{/\* 40 | 8 \*/ union \{} \ +{/\* 8 \*/ void \*field6;} \ +{/\* 4 \*/ int field7;} \ +{} \ +{ /\* total size \(bytes\): 8 \*/} \ +{ \} field8;} \ +{/\* 48 | 4 \*/ my_int_type field9;} \ +{} \ +{ /\* total size \(bytes\): 56 \*/} \ +{ \}}] + +# Test "ptype /oTM". +gdb_test "ptype /oTM struct abc" \ + [multi_line \ +{/\* offset | size \*/ type = struct abc \{} \ +{ public:} \ +{/\* 8 | 8 \*/ void \*field1;} \ +{/\* 16:31 | 4 \*/ unsigned int field2 : 1;} \ +{/\* XXX 7-bit hole \*/} \ +{/\* XXX 3-byte hole \*/} \ +{/\* 20 | 4 \*/ int field3;} \ +{/\* 24 | 1 \*/ signed char field4;} \ +{/\* XXX 7-byte hole \*/} \ +{/\* 32 | 8 \*/ uint64_t field5;} \ +{/\* 40 | 8 \*/ union \{} \ +{/\* 8 \*/ void \*field6;} \ +{/\* 4 \*/ int field7;} \ +{} \ +{ /\* total size \(bytes\): 8 \*/} \ +{ \} field8;} \ +{/\* 48 | 4 \*/ my_int_type field9;} \ +{} \ +{ abc\(void\);} \ +{ ~abc\(\);} \ +{} \ +{ typedef int my_int_type;} \ +{} \ +{ /\* total size \(bytes\): 56 \*/} \ +{ \}}] + +# Test "ptype /TMo". This should be the same as "ptype /o". +gdb_test "ptype /TMo struct abc" \ + [multi_line \ +{/\* offset | size \*/ type = struct abc \{} \ +{ public:} \ +{/\* 8 | 8 \*/ void \*field1;} \ +{/\* 16:31 | 4 \*/ unsigned int field2 : 1;} \ +{/\* XXX 7-bit hole \*/} \ +{/\* XXX 3-byte hole \*/} \ +{/\* 20 | 4 \*/ int field3;} \ +{/\* 24 | 1 \*/ signed char field4;} \ +{/\* XXX 7-byte hole \*/} \ +{/\* 32 | 8 \*/ uint64_t field5;} \ +{/\* 40 | 8 \*/ union \{} \ +{/\* 8 \*/ void \*field6;} \ +{/\* 4 \*/ int field7;} \ +{} \ +{ /\* total size \(bytes\): 8 \*/} \ +{ \} field8;} \ +{/\* 48 | 4 \*/ my_int_type field9;} \ +{} \ +{ /\* total size \(bytes\): 56 \*/} \ +{ \}}] + +# Test nested structs. +gdb_test "ptype /o struct pqr" \ + [multi_line \ +{/\* offset | size \*/ type = struct pqr \{} \ +{/\* 0 | 4 \*/ int ff1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 8 | 40 \*/ struct xyz \{} \ +{/\* 8 | 4 \*/ int f1;} \ +{/\* 12 | 1 \*/ signed char f2;} \ +{/\* XXX 3-byte hole \*/} \ +{/\* 16 | 8 \*/ void \*f3;} \ +{/\* 24 | 24 \*/ struct tuv \{} \ +{/\* 24 | 4 \*/ int a1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 32 | 8 \*/ signed char \*a2;} \ +{/\* 40 | 4 \*/ int a3;} \ +{} \ +{ /\* total size \(bytes\): 24 \*/} \ +{ \} f4;} \ +{} \ +{ /\* total size \(bytes\): 40 \*/} \ +{ \} ff2;} \ +{/\* XXX 28-byte hole \*/} \ +{/\* 72 | 1 \*/ signed char ff3;} \ +{} \ +{ /\* total size \(bytes\): 56 \*/} \ +{ \}}] + +# Test that the offset is properly reset when we are printing a union +# and go inside two inner structs. +# This also tests a struct inside a struct inside a union. +gdb_test "ptype /o union qwe" \ + [multi_line \ +{/\* offset | size \*/ type = union qwe \{} \ +{/\* 24 \*/ struct tuv \{} \ +{/\* 0 | 4 \*/ int a1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 8 | 8 \*/ signed char \*a2;} \ +{/\* 16 | 4 \*/ int a3;} \ +{} \ +{ /\* total size \(bytes\): 24 \*/} \ +{ \} fff1;} \ +{/\* 40 \*/ struct xyz \{} \ +{/\* 0 | 4 \*/ int f1;} \ +{/\* 4 | 1 \*/ signed char f2;} \ +{/\* XXX 3-byte hole \*/} \ +{/\* 8 | 8 \*/ void \*f3;} \ +{/\* 16 | 24 \*/ struct tuv \{} \ +{/\* 16 | 4 \*/ int a1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 24 | 8 \*/ signed char \*a2;} \ +{/\* 32 | 4 \*/ int a3;} \ +{} \ +{ /\* total size \(bytes\): 24 \*/} \ +{ \} f4;} \ +{} \ +{ /\* total size \(bytes\): 40 \*/} \ +{ \} fff2;} \ +{} \ +{ /\* total size \(bytes\): 40 \*/} \ +{ \}}] + +# Test printing a struct that contains a union, and that also +# contains a struct. +gdb_test "ptype /o struct poi" \ + [multi_line \ +{/\* offset | size \*/ type = struct poi \{} \ +{/\* 0 | 4 \*/ int f1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 8 | 40 \*/ union qwe \{} \ +{/\* 24 \*/ struct tuv \{} \ +{/\* 8 | 4 \*/ int a1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 16 | 8 \*/ signed char \*a2;} \ +{/\* 24 | 4 \*/ int a3;} \ +{} \ +{ /\* total size \(bytes\): 24 \*/} \ +{ \} fff1;} \ +{/\* 40 \*/ struct xyz \{} \ +{/\* 8 | 4 \*/ int f1;} \ +{/\* 12 | 1 \*/ signed char f2;} \ +{/\* XXX 3-byte hole \*/} \ +{/\* 16 | 8 \*/ void \*f3;} \ +{/\* 24 | 24 \*/ struct tuv \{} \ +{/\* 24 | 4 \*/ int a1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 32 | 8 \*/ signed char \*a2;} \ +{/\* 40 | 4 \*/ int a3;} \ +{} \ +{ /\* total size \(bytes\): 24 \*/} \ +{ \} f4;} \ +{} \ +{ /\* total size \(bytes\): 40 \*/} \ +{ \} fff2;} \ +{} \ +{ /\* total size \(bytes\): 40 \*/} \ +{ \} f2;} \ +{/\* 72 | 2 \*/ uint16_t f3;} \ +{/\* XXX 6-byte hole \*/} \ +{/\* 80 | 56 \*/ struct pqr \{} \ +{/\* 80 | 4 \*/ int ff1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 88 | 40 \*/ struct xyz \{} \ +{/\* 88 | 4 \*/ int f1;} \ +{/\* 92 | 1 \*/ signed char f2;} \ +{/\* XXX 3-byte hole \*/} \ +{/\* 96 | 8 \*/ void \*f3;} \ +{/\* 104 | 24 \*/ struct tuv \{} \ +{/\* 104 | 4 \*/ int a1;} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 112 | 8 \*/ signed char \*a2;} \ +{/\* 120 | 4 \*/ int a3;} \ +{} \ +{ /\* total size \(bytes\): 24 \*/} \ +{ \} f4;} \ +{} \ +{ /\* total size \(bytes\): 40 \*/} \ +{ \} ff2;} \ +{/\* 152 | 1 \*/ signed char ff3;} \ +{} \ +{ /\* total size \(bytes\): 56 \*/} \ +{ \} f4;} \ +{} \ +{ /\* total size \(bytes\): 112 \*/} \ +{ \}}] + +# Test printing a struct with several bitfields, laid out in various +# ways. +# +# Because dealing with bitfields and offsets is difficult, it can be +# tricky to confirm that the output of this command is accurate. A +# nice way to do that is to use GDB's "x" command and print the actual +# memory layout of the struct. In order to differentiate between +# bitfields and non-bitfield variables, one can assign "-1" to every +# bitfield in the struct. An example of the output of "x" using +# "struct tyu" is: +# +# (gdb) x/24xb &e +# 0x7fffffffd540: 0xff 0xff 0xff 0x1f 0x00 0x00 0x00 0x00 +# 0x7fffffffd548: 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff +# 0x7fffffffd550: 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +gdb_test "ptype /o struct tyu" \ + [multi_line \ +{/\* offset | size \*/ type = struct tyu \{} \ +{/\* 0:31 | 4 \*/ int a1 : 1;} \ +{/\* 0:28 | 4 \*/ int a2 : 3;} \ +{/\* 0: 5 | 4 \*/ int a3 : 23;} \ +{/\* 3: 3 | 1 \*/ signed char a4 : 2;} \ +{/\* XXX 3-bit hole \*/} \ +{/\* XXX 4-byte hole \*/} \ +{/\* 8 | 8 \*/ int64_t a5;} \ +{/\* 16:27 | 4 \*/ int a6 : 5;} \ +{/\* 16:56 | 8 \*/ int64_t a7 : 3;} \ +{} \ +{ /\* total size \(bytes\): 24 \*/} \ +{ \}}] + +gdb_test "ptype /o struct asd" \ + [multi_line \ +{/\* offset | size \*/ type = struct asd \{} \ +{/\* 0 | 32 \*/ struct asd::jkl \{} \ +{/\* 0 | 8 \*/ signed char \*f1;} \ +{/\* 8 | 8 \*/ union \{} \ +{/\* 8 \*/ void \*ff1;} \ +{} \ +{ /\* total size \(bytes\): 8 \*/} \ +{ \} f2;} \ +{/\* 16 | 8 \*/ union \{} \ +{/\* 8 \*/ signed char \*ff2;} \ +{} \ +{ /\* total size \(bytes\): 8 \*/} \ +{ \} f3;} \ +{/\* 24:27 | 4 \*/ int f4 : 5;} \ +{/\* 24:26 | 4 \*/ unsigned int f5 : 1;} \ +{/\* XXX 2-bit hole \*/} \ +{/\* XXX 1-byte hole \*/} \ +{/\* 26 | 2 \*/ short f6;} \ +{} \ +{ /\* total size \(bytes\): 32 \*/} \ +{ \} f7;} \ +{/\* 32 | 8 \*/ unsigned long f8;} \ +{/\* 40 | 8 \*/ signed char \*f9;} \ +{/\* 48:28 | 4 \*/ int f10 : 4;} \ +{/\* 48:27 | 4 \*/ unsigned int f11 : 1;} \ +{/\* 48:26 | 4 \*/ unsigned int f12 : 1;} \ +{/\* 48:25 | 4 \*/ unsigned int f13 : 1;} \ +{/\* 48:24 | 4 \*/ unsigned int f14 : 1;} \ +{/\* XXX 7-byte hole \*/} \ +{/\* 56 | 8 \*/ void \*f15;} \ +{/\* 64 | 8 \*/ void \*f16;} \ +{} \ +{ /\* total size \(bytes\): 72 \*/} \ +{ \}}] + +# Test that we don't print any header when issuing a "ptype /o" on a +# non-struct, non-union, non-class type. +gdb_test "ptype /o int" "int" +gdb_test "ptype /o uint8_t" "char" + +# Test that the "whatis" command doesn't print anything related to the +# "offsets" feature, even when receiving the "/o" parameter. +set test "whatis /o asd" +gdb_test_multiple "$test" "$test" { + -re "^$test\r\ntype = asd\r\n$gdb_prompt $" { + pass $test + } +} |