From debd0556e519c3d258299cf5f14a44cc01c795da Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 9 Feb 2023 12:12:42 -0700 Subject: [PATCH] Fix crash with "finish" in Rust PR rust/30090 points out that a certain "finish" in a Rust program will cause gdb to crash. This happens due to some confusion about field indices in rust_language::print_enum. The fix is to use value_primitive_field so that the correct type can be passed; other spots in rust-lang.c already do this. Note that the enclosed test case comes with an xfail. This is needed because for this function, rustc doesn't follow the platform ABI. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30090 --- gdb/rust-lang.c | 2 +- gdb/testsuite/gdb.rust/finish.exp | 39 +++++++++++++++++++++++++++++++ gdb/testsuite/gdb.rust/finish.rs | 30 ++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.rust/finish.exp create mode 100644 gdb/testsuite/gdb.rust/finish.rs diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index fe260f175f8..6fc73b262f5 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -470,7 +470,7 @@ rust_language::print_enum (struct value *val, struct ui_file *stream, } int variant_fieldno = rust_enum_variant (type); - val = value_field (val, variant_fieldno); + val = val->primitive_field (0, variant_fieldno, type); struct type *variant_type = type->field (variant_fieldno).type (); int nfields = variant_type->num_fields (); diff --git a/gdb/testsuite/gdb.rust/finish.exp b/gdb/testsuite/gdb.rust/finish.exp new file mode 100644 index 00000000000..ab0250df277 --- /dev/null +++ b/gdb/testsuite/gdb.rust/finish.exp @@ -0,0 +1,39 @@ +# Copyright (C) 2023 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 . + +# Test a certain 'finish' in Rust. + +load_lib rust-support.exp +require allow_rust_tests + +standard_testfile .rs +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "BREAK"] +if {![runto ${srcfile}:$line]} { + untested "could not run to breakpoint" + return -1 +} + +# This 'finish' used to crash. See PR rust/30090. Also, this does +# not currently print the correct value, because rustc does not use +# the standard ABI here. This is being tracked here: +# https://github.com/rust-lang/rust/issues/85641 +setup_xfail *-*-* +gdb_test "finish" [string_to_regexp " = finish::MyResult::Some(97)"] +gdb_test "next" +gdb_test "print dei" [string_to_regexp " = finish::MyResult::Some(97)"] diff --git a/gdb/testsuite/gdb.rust/finish.rs b/gdb/testsuite/gdb.rust/finish.rs new file mode 100644 index 00000000000..e9dfcd89b0f --- /dev/null +++ b/gdb/testsuite/gdb.rust/finish.rs @@ -0,0 +1,30 @@ +// Copyright (C) 2023 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 . + +#![allow(warnings)] + +enum MyResult { + None, + Some(u32) +} + +fn return_some() -> MyResult { + MyResult::Some(97) // BREAK +} + +fn main() { + let dei = return_some(); + let another = return_some(); +} -- 2.30.2