Fix dynamic type resolution for LOC_CONST and LOC_CONST_BYTES symbols

Message ID 20231128215422.1697343-1-tom@tromey.com
State New
Headers
Series Fix dynamic type resolution for LOC_CONST and LOC_CONST_BYTES symbols |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm fail Testing failed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed

Commit Message

Tom Tromey Nov. 28, 2023, 9:54 p.m. UTC
  PR rust/31005 points out that dynamic type resolution of a LOC_CONST
or LOC_CONST_BYTES symbol will fail, leading to output like:

    from_index=<error reading variable: Cannot access memory at address 0x0>

This patch fixes the problem by using the constant value or bytes when
performing type resolution.

Thanks for tpzker@thepuzzlemaker.info for a first version of this
patch.

I also tested this on a big-endian PPC system (cfarm203).

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31005
---
 gdb/findvar.c                          |  19 +++-
 gdb/testsuite/gdb.dwarf2/rust-enum.exp | 120 +++++++++++++++++++++++++
 2 files changed, 135 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.dwarf2/rust-enum.exp
  

Comments

Tom Tromey Nov. 29, 2023, 9:30 p.m. UTC | #1
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> +	  size_t len = std::min (sizeof (LONGEST), type->length ());

One of the build robots pointed out that these types aren't the same on
some platform.  Locally I've added a cast to size_t for the second
argument.

Tom
  
Tom Tromey Dec. 8, 2023, 3:17 p.m. UTC | #2
>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> PR rust/31005 points out that dynamic type resolution of a LOC_CONST
Tom> or LOC_CONST_BYTES symbol will fail, leading to output like:

Tom>     from_index=<error reading variable: Cannot access memory at address 0x0>

Tom> This patch fixes the problem by using the constant value or bytes when
Tom> performing type resolution.

Tom> Thanks for tpzker@thepuzzlemaker.info for a first version of this
Tom> patch.

Tom> I also tested this on a big-endian PPC system (cfarm203).

I'm checking this in.

Tom
  

Patch

diff --git a/gdb/findvar.c b/gdb/findvar.c
index 952ec20c0b7..c23b26febd7 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -534,8 +534,16 @@  language_defn::read_var_value (struct symbol *var,
     case LOC_CONST:
       if (is_dynamic_type (type))
 	{
-	  /* Value is a constant byte-sequence and needs no memory access.  */
-	  type = resolve_dynamic_type (type, {}, /* Unused address.  */ 0);
+	  gdb_byte bytes[sizeof (LONGEST)];
+
+	  size_t len = std::min (sizeof (LONGEST), type->length ());
+	  store_unsigned_integer (bytes, len,
+				  type_byte_order (type),
+				  var->value_longest ());
+	  gdb::array_view<const gdb_byte> view (bytes, len);
+
+	  /* Value is a constant byte-sequence.  */
+	  type = resolve_dynamic_type (type, view, /* Unused address.  */ 0);
 	}
       /* Put the constant back in target format. */
       v = value::allocate (type);
@@ -575,8 +583,11 @@  language_defn::read_var_value (struct symbol *var,
     case LOC_CONST_BYTES:
       if (is_dynamic_type (type))
 	{
-	  /* Value is a constant byte-sequence and needs no memory access.  */
-	  type = resolve_dynamic_type (type, {}, /* Unused address.  */ 0);
+	  gdb::array_view<const gdb_byte> view (var->value_bytes (),
+						type->length ());
+
+	  /* Value is a constant byte-sequence.  */
+	  type = resolve_dynamic_type (type, view, /* Unused address.  */ 0);
 	}
       v = value::allocate (type);
       memcpy (v->contents_raw ().data (), var->value_bytes (),
diff --git a/gdb/testsuite/gdb.dwarf2/rust-enum.exp b/gdb/testsuite/gdb.dwarf2/rust-enum.exp
new file mode 100644
index 00000000000..a052c11fe46
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/rust-enum.exp
@@ -0,0 +1,120 @@ 
+# Copyright 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 <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+standard_testfile main.c -dw.S
+
+# Make some DWARF for the test.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    upvar cu_lang cu_lang
+
+    declare_labels uinteger_label discr_1_label
+    declare_labels one_label two_label simple_label
+
+    cu { addr_size 4 } {
+	compile_unit {
+	    {name file1.txt}
+	    {language @DW_LANG_Rust}
+	} {
+	    uinteger_label: DW_TAG_base_type {
+		{DW_AT_byte_size 1 DW_FORM_sdata}
+		{DW_AT_encoding	 @DW_ATE_unsigned}
+		{DW_AT_name	 {unsigned integer}}
+	    }
+
+	    one_label: structure_type {
+		{name One}
+		{byte_size 1 DW_FORM_sdata}
+	    } {
+		member {
+		    {name __0}
+		    {type :$uinteger_label}
+		    {data_member_location 0 data1}
+		}
+	    }
+
+	    two_label: structure_type {
+		{name Two}
+		{byte_size 1 DW_FORM_sdata}
+	    } {
+		member {
+		    {name __0}
+		    {type :$uinteger_label}
+		    {data_member_location 0 data1}
+		}
+	    }
+
+	    simple_label: structure_type {
+		{name Simple}
+		{byte_size 2 DW_FORM_sdata}
+	    } {
+		variant_part {
+		    {discr :$discr_1_label DW_FORM_ref4}
+		} {
+		    discr_1_label: member {
+			{type :$uinteger_label}
+			{data_member_location 0 data1}
+			{artificial 1 DW_FORM_flag_present}
+		    }
+
+		    variant {
+			{discr_value 65 udata}
+		    } {
+			member {
+			    {type :$one_label}
+			    {data_member_location 1 data1}
+			}
+		    }
+
+		    variant {
+		    } {
+			member {
+			    {type :$two_label}
+			    {data_member_location 1 data1}
+			}
+		    }
+		}
+	    }
+
+	    # In PR rust/31005, a constant Rust enum value could not
+	    # be correctly resolved.
+	    DW_TAG_variable {
+		{name constant_variable}
+		{const_value 0x4141 udata}
+		{type :$simple_label}
+	    }
+	    DW_TAG_variable {
+		{name constant_variable2}
+		{const_value "AA" DW_FORM_block1}
+		{type :$simple_label}
+	    }
+	}
+    }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	  [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+gdb_test_no_output "set language rust"
+
+gdb_test "print constant_variable" [string_to_regexp "One(65)"]
+gdb_test "print constant_variable2" [string_to_regexp "One(65)"]