diff options
| author | Tom Tromey <tromey@adacore.com> | 2024-01-30 10:06:46 -0700 |
|---|---|---|
| committer | Tom Tromey <tromey@adacore.com> | 2024-02-20 13:51:30 -0700 |
| commit | b0dd661fa16a424f059b1e1d80e779508b1a9a12 (patch) | |
| tree | 7d1c9253ab0284c90ab7859d402a7140980e23c3 /gdb/testsuite | |
| parent | 94a75b0363b1e09416e9bd24cac72d98864688d8 (diff) | |
| download | binutils-b0dd661fa16a424f059b1e1d80e779508b1a9a12.tar.gz binutils-b0dd661fa16a424f059b1e1d80e779508b1a9a12.tar.bz2 binutils-b0dd661fa16a424f059b1e1d80e779508b1a9a12.zip | |
Rewrite Rust slice type handling
This patch rewrites the handling of slice types in Rust.
More recent versions of the Rust compiler changed how unsized types
were emitted, letting gdb inspect them more nicely. However, gdb did
not do this, and in fact treated all such types as if they were slices
of arrays, which is incorrect.
This patch rewrites this handling and removes the restriction that
unsized types must be array slices. I've added a comment explaining
how unsized types are represented to rust-lang.c as well.
I looked into a different approach, namely changing the DWARF reader
to fix up slice types to have a dynamic type. However, the approach
taken here turned out to be simpler.
Tested on x86-64 Fedora 38 with a variety of Rust compiler versions.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30330
Diffstat (limited to 'gdb/testsuite')
| -rw-r--r-- | gdb/testsuite/gdb.rust/simple.exp | 2 | ||||
| -rw-r--r-- | gdb/testsuite/gdb.rust/unsized.exp | 2 | ||||
| -rw-r--r-- | gdb/testsuite/gdb.rust/unsized2.exp | 59 | ||||
| -rw-r--r-- | gdb/testsuite/gdb.rust/unsized2.rs | 67 |
4 files changed, 128 insertions, 2 deletions
diff --git a/gdb/testsuite/gdb.rust/simple.exp b/gdb/testsuite/gdb.rust/simple.exp index 1e6fc94400e..7f5fbad7a3f 100644 --- a/gdb/testsuite/gdb.rust/simple.exp +++ b/gdb/testsuite/gdb.rust/simple.exp @@ -317,7 +317,7 @@ proc test_one_slice {svar length base range} { global hex # Just accept any array here. - set result " = &\\\[.*\\\] \\\[.*\\\]" + set result " = \\\[.*\\\]" gdb_test "print $svar" $result gdb_test "print &${base}\[${range}\]" $result diff --git a/gdb/testsuite/gdb.rust/unsized.exp b/gdb/testsuite/gdb.rust/unsized.exp index 94750896288..fab655790e6 100644 --- a/gdb/testsuite/gdb.rust/unsized.exp +++ b/gdb/testsuite/gdb.rust/unsized.exp @@ -33,6 +33,6 @@ if {![runto ${srcfile}:$line]} { gdb_test "ptype us" " = .*V<\\\[u8\\\]>.*" if {[rust_at_least 1.61]} { - gdb_test "print us2" " = .*Box<.*> \\\[1, 2, 3\\\]" + gdb_test "print us2" " = \\\[1, 2, 3\\\]" gdb_test "ptype us2" "type = .*" } diff --git a/gdb/testsuite/gdb.rust/unsized2.exp b/gdb/testsuite/gdb.rust/unsized2.exp new file mode 100644 index 00000000000..5b7be45d8ce --- /dev/null +++ b/gdb/testsuite/gdb.rust/unsized2.exp @@ -0,0 +1,59 @@ +# Copyright (C) 2024 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/>. + +# Test the handling of unsized types. + +load_lib rust-support.exp +require allow_rust_tests +require {can_compile rust} +require {rust_at_least 1.61} + +standard_testfile .rs +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "set breakpoint here"] +if {![runto ${srcfile}:$line]} { + untested "could not run to breakpoint" + return -1 +} + +set base_value \ + [string cat \ + "MaybeUnsizedStruct<.*?>" \ + [string_to_regexp " {regular: 23, rest: \[5, 6, 7\]}"]] + +gdb_test "print *sized_struct" \ + " = .*$base_value" +gdb_test "print *nested_sized_struct" \ + " = .*MaybeUnsizedStruct<.*?> {regular: 91, rest: .*$base_value}" + +gdb_test "print unsized_struct" \ + " = .*$base_value" +gdb_test "print *reference" \ + " = .*$base_value" + +gdb_test "print nested_unsized_struct" \ + " = .*MaybeUnsizedStruct<.*?> {regular: 91, rest: .*$base_value}" + +gdb_test "print alpha" \ + " = .*MaybeUnsizedStruct2<.*?> {value: \\\[97, 98, 99, 0\\\]}" +gdb_test "print beta" \ + " = .*MaybeUnsizedStruct2<.*?> {value: \\\[97, 98, 99, 0\\\]}" + +gdb_test "print sized_struct.regular" " = 23" +gdb_test "print nested_unsized_struct.regular" " = 91" +gdb_test "print unsized_struct.rest\[1\]" " = 6" diff --git a/gdb/testsuite/gdb.rust/unsized2.rs b/gdb/testsuite/gdb.rust/unsized2.rs new file mode 100644 index 00000000000..980a5fe92f3 --- /dev/null +++ b/gdb/testsuite/gdb.rust/unsized2.rs @@ -0,0 +1,67 @@ +// Copyright (C) 2024 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/>. + +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_assignments)] + +fn ignore<T>(x: T) { } + +// A generic struct that is unsized if T is unsized. +pub struct MaybeUnsizedStruct<T: ?Sized> { + pub regular: u32, + pub rest: T, +} + +// Same but without an ordinary part. +pub struct MaybeUnsizedStruct2<T: ?Sized> { + value: T, +} + +fn main() { + // This struct is still sized because T is a fixed-length array + let sized_struct = &MaybeUnsizedStruct { + regular: 23, + rest: [5, 6, 7], + }; + + // This struct is still sized because T is sized + let nested_sized_struct = &MaybeUnsizedStruct { + regular: 91, + rest: MaybeUnsizedStruct { + regular: 23, + rest: [5, 6, 7], + }, + }; + + // This will be a fat pointer, containing the length of the final + // field. + let unsized_struct: &MaybeUnsizedStruct<[u32]> = sized_struct; + + // This will also be a fat pointer, containing the length of the + // final field. + let nested_unsized_struct: + &MaybeUnsizedStruct<MaybeUnsizedStruct<[u32]>> = nested_sized_struct; + + let alpha: MaybeUnsizedStruct2<[u8; 4]> = MaybeUnsizedStruct2 { value: *b"abc\0" }; + let beta: &MaybeUnsizedStruct2<[u8]> = α + + let reference = &unsized_struct; + + ignore(sized_struct); // set breakpoint here + ignore(nested_sized_struct); + ignore(unsized_struct); + ignore(nested_unsized_struct); +} |
