Blame SOURCES/gdb-rhbz1905701-DWARF-data_location.patch

0c1cd1
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
0c1cd1
From: Keith Seitz <keiths@redhat.com>
0c1cd1
Date: Wed, 2 Dec 2020 17:39:33 -0500
0c1cd1
Subject: gdb-rhbz1905701-DWARF-data_location.patch
0c1cd1
0c1cd1
;; Backport "fortran dynamic type related fixes"
0c1cd1
;; Andrew Burgess (RH BZ 1905701)
0c1cd1
0c1cd1
    commit e79eb02f2f09baecffb144bac6804f975065466f
0c1cd1
0c1cd1
    gdb/fortran: resolve dynamic types when readjusting after an indirection
0c1cd1
0c1cd1
    After dereferencing a pointer (in value_ind) or following a
0c1cd1
    reference (in coerce_ref) we call readjust_indirect_value_type to
0c1cd1
    "fixup" the type of the resulting value object.
0c1cd1
0c1cd1
    This fixup handles cases relating to the type of the resulting object
0c1cd1
    being different (a sub-class) of the original pointers target type.
0c1cd1
0c1cd1
    If we encounter a pointer to a dynamic type then after dereferencing a
0c1cd1
    pointer (in value_ind) the type of the object created will have had
0c1cd1
    its dynamic type resolved.  However, in readjust_indirect_value_type,
0c1cd1
    we use the target type of the original pointer to "fixup" the type of
0c1cd1
    the resulting value.  In this case, the target type will be a dynamic
0c1cd1
    type, so the resulting value object, once again has a dynamic type.
0c1cd1
0c1cd1
    This then triggers an assertion later within GDB.
0c1cd1
0c1cd1
    The solution I propose here is that we call resolve_dynamic_type on
0c1cd1
    the pointer's target type (within readjust_indirect_value_type) so
0c1cd1
    that the resulting value is not converted back to a dynamic type.
0c1cd1
0c1cd1
    The test case is based on the original test in the bug report.
0c1cd1
0c1cd1
    gdb/ChangeLog:
0c1cd1
0c1cd1
            PR fortran/23051
0c1cd1
            PR fortran/26139
0c1cd1
            * valops.c (value_ind): Pass address to
0c1cd1
            readjust_indirect_value_type.
0c1cd1
            * value.c (readjust_indirect_value_type): Make parameter
0c1cd1
            non-const, and add extra address parameter.  Resolve original type
0c1cd1
            before using it.
0c1cd1
            * value.h (readjust_indirect_value_type): Update function
0c1cd1
            signature and comment.
0c1cd1
0c1cd1
    gdb/testsuite/ChangeLog:
0c1cd1
0c1cd1
            PR fortran/23051
0c1cd1
            PR fortran/26139
0c1cd1
            * gdb.fortran/class-allocatable-array.exp: New file.
0c1cd1
            * gdb.fortran/class-allocatable-array.f90: New file.
0c1cd1
            * gdb.fortran/pointer-to-pointer.exp: New file.
0c1cd1
            * gdb.fortran/pointer-to-pointer.f90: New file.
0c1cd1
0c1cd1
diff --git a/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.c b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.c
0c1cd1
new file mode 100644
0c1cd1
--- /dev/null
0c1cd1
+++ b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.c
0c1cd1
@@ -0,0 +1,63 @@
0c1cd1
+/* Copyright 2014-2020 Free Software Foundation, Inc.
0c1cd1
+
0c1cd1
+   This file is part of GDB.
0c1cd1
+
0c1cd1
+   This program is free software; you can redistribute it and/or modify
0c1cd1
+   it under the terms of the GNU General Public License as published by
0c1cd1
+   the Free Software Foundation; either version 3 of the License, or
0c1cd1
+   (at your option) any later version.
0c1cd1
+
0c1cd1
+   This program is distributed in the hope that it will be useful,
0c1cd1
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
0c1cd1
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c1cd1
+   GNU General Public License for more details.
0c1cd1
+
0c1cd1
+   You should have received a copy of the GNU General Public License
0c1cd1
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
0c1cd1
+
0c1cd1
+/* This C file simulates the implementation of object pointers in
0c1cd1
+   GraalVM Java native images where the object data is not addressed
0c1cd1
+   directly. It serves as a regression test for a bug where printing
0c1cd1
+   of such redirected data structures suffers from a gdb exception.
0c1cd1
+
0c1cd1
+   Debugging information on how to decode an object pointer to
0c1cd1
+   identify the address of the underlying data will be generated
0c1cd1
+   separately by the testcase using that file. */
0c1cd1
+
0c1cd1
+#include <stdlib.h>
0c1cd1
+#include <string.h>
0c1cd1
+
0c1cd1
+struct Object {
0c1cd1
+  struct Object *next;
0c1cd1
+  int val;
0c1cd1
+};
0c1cd1
+
0c1cd1
+struct Object *testOop;
0c1cd1
+
0c1cd1
+extern int debugMe() {
0c1cd1
+  return 0;
0c1cd1
+}
0c1cd1
+
0c1cd1
+struct Object *newObject() {
0c1cd1
+  char *bytes = malloc(sizeof(struct Object));
0c1cd1
+  return (struct Object *)bytes;
0c1cd1
+}
0c1cd1
+
0c1cd1
+int
0c1cd1
+main (void)
0c1cd1
+{
0c1cd1
+  struct Object *obj1 = newObject();
0c1cd1
+  struct Object *obj2 = newObject();
0c1cd1
+  struct Object *obj3 = newObject();
0c1cd1
+  obj1->val = 0;
0c1cd1
+  obj2->val = 1;
0c1cd1
+  obj3->val = 2;
0c1cd1
+
0c1cd1
+  obj1->next = obj2;
0c1cd1
+  obj2->next = obj3;
0c1cd1
+  obj3->next = obj1;
0c1cd1
+
0c1cd1
+  testOop = obj1;
0c1cd1
+
0c1cd1
+  return debugMe();
0c1cd1
+}
0c1cd1
diff --git a/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.exp b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.exp
0c1cd1
new file mode 100644
0c1cd1
--- /dev/null
0c1cd1
+++ b/gdb/testsuite/gdb.dwarf2/graalvm-data-loc2.exp
0c1cd1
@@ -0,0 +1,122 @@
0c1cd1
+# Copyright 2014-2020 Free Software Foundation, Inc.
0c1cd1
+
0c1cd1
+# This program is free software; you can redistribute it and/or modify
0c1cd1
+# it under the terms of the GNU General Public License as published by
0c1cd1
+# the Free Software Foundation; either version 3 of the License, or
0c1cd1
+# (at your option) any later version.
0c1cd1
+#
0c1cd1
+# This program is distributed in the hope that it will be useful,
0c1cd1
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
0c1cd1
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c1cd1
+# GNU General Public License for more details.
0c1cd1
+#
0c1cd1
+# You should have received a copy of the GNU General Public License
0c1cd1
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
0c1cd1
+load_lib dwarf.exp
0c1cd1
+
0c1cd1
+# This test can only be run on targets which support DWARF-2 and use gas.
0c1cd1
+if {![dwarf2_support]} {
0c1cd1
+    return 0
0c1cd1
+}
0c1cd1
+
0c1cd1
+standard_testfile .c -dw.S
0c1cd1
+
0c1cd1
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
0c1cd1
+    return -1
0c1cd1
+}
0c1cd1
+
0c1cd1
+# Make some DWARF for the test.
0c1cd1
+set asm_file [standard_output_file $srcfile2]
0c1cd1
+Dwarf::assemble $asm_file {
0c1cd1
+    
0c1cd1
+    cu {} {
0c1cd1
+ 	DW_TAG_compile_unit {
0c1cd1
+                {DW_AT_language @DW_LANG_C99}
0c1cd1
+                {DW_AT_name     data-loc2.c}
0c1cd1
+                {DW_AT_comp_dir /tmp}
0c1cd1
+        } {
0c1cd1
+            declare_labels integer_label struct_label pointer_label
0c1cd1
+
0c1cd1
+            integer_label: DW_TAG_base_type {
0c1cd1
+                {DW_AT_byte_size 4 DW_FORM_sdata}
0c1cd1
+                {DW_AT_encoding  @DW_ATE_signed}
0c1cd1
+                {DW_AT_name      integer}
0c1cd1
+            }
0c1cd1
+
0c1cd1
+	    struct_label: DW_TAG_structure_type {
0c1cd1
+		{DW_AT_name "Object"}
0c1cd1
+		{DW_AT_byte_size 20 DW_FORM_sdata}
0c1cd1
+                {DW_AT_data_location {
0c1cd1
+                    DW_OP_push_object_address
0c1cd1
+                } SPECIAL_expr}
0c1cd1
+	    } {
0c1cd1
+		member {
0c1cd1
+		    {name next}
0c1cd1
+		    {type :$pointer_label}
0c1cd1
+		    {data_member_location 0 data1}
0c1cd1
+		}
0c1cd1
+		member {
0c1cd1
+		    {name val}
0c1cd1
+		    {type :$integer_label}
0c1cd1
+		    {data_member_location 8 data1}
0c1cd1
+		}
0c1cd1
+	    }
0c1cd1
+	    pointer_label: DW_TAG_pointer_type {
0c1cd1
+		{DW_AT_byte_size 4 DW_FORM_sdata}
0c1cd1
+		{DW_AT_type  :$struct_label}
0c1cd1
+	    }
0c1cd1
+            DW_TAG_variable {
0c1cd1
+                {DW_AT_name testOop}
0c1cd1
+                {DW_AT_type :$pointer_label}
0c1cd1
+                {DW_AT_location {
0c1cd1
+                    DW_OP_addr [gdb_target_symbol testOop]
0c1cd1
+                } SPECIAL_expr}
0c1cd1
+                {external 1 flag}
0c1cd1
+            }
0c1cd1
+	}
0c1cd1
+    }
0c1cd1
+}
0c1cd1
+
0c1cd1
+# Now that we've generated the DWARF debugging info, rebuild our
0c1cd1
+# program using our debug info instead of the info generated by
0c1cd1
+# the compiler.
0c1cd1
+
0c1cd1
+if { [prepare_for_testing "failed to prepare" ${testfile} \
0c1cd1
+	  [list $srcfile $asm_file] {nodebug}] } {
0c1cd1
+    return -1
0c1cd1
+}
0c1cd1
+
0c1cd1
+if ![runto_main] {
0c1cd1
+    return -1
0c1cd1
+}
0c1cd1
+
0c1cd1
+# ensure the object network is set up as expected and check that
0c1cd1
+# printing of structs which employ the data_location does not
0c1cd1
+# fail with a gdb exception
0c1cd1
+
0c1cd1
+gdb_test "break debugMe" \
0c1cd1
+         "Breakpoint .*" \
0c1cd1
+         "set breakpoint at debugMe"
0c1cd1
+
0c1cd1
+gdb_continue_to_breakpoint "continue to debugMe"
0c1cd1
+
0c1cd1
+gdb_test "print testOop->val" \
0c1cd1
+         ".* = 0"
0c1cd1
+
0c1cd1
+gdb_test "print testOop->next->val" \
0c1cd1
+         ".* = 1"
0c1cd1
+
0c1cd1
+gdb_test "print testOop->next->next->val" \
0c1cd1
+         ".* = 2"
0c1cd1
+
0c1cd1
+gdb_test "print *testOop" \
0c1cd1
+    ".* = {next = .*, val = 0}" \
0c1cd1
+    "print contents of struct"
0c1cd1
+
0c1cd1
+gdb_test "print *testOop->next" \
0c1cd1
+    ".* = {next = .*, val = 1}" \
0c1cd1
+    "print contents of an indirect struct"
0c1cd1
+
0c1cd1
+gdb_test "print *testOop->next->next" \
0c1cd1
+    ".* = {next = .*, val = 2}" \
0c1cd1
+    "print contents of a double indirect struct"
0c1cd1
diff --git a/gdb/testsuite/gdb.fortran/class-allocatable-array.exp b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
0c1cd1
new file mode 100644
0c1cd1
--- /dev/null
0c1cd1
+++ b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
0c1cd1
@@ -0,0 +1,43 @@
0c1cd1
+# Copyright 2020 Free Software Foundation, Inc.
0c1cd1
+
0c1cd1
+# This program is free software; you can redistribute it and/or modify
0c1cd1
+# it under the terms of the GNU General Public License as published by
0c1cd1
+# the Free Software Foundation; either version 3 of the License, or
0c1cd1
+# (at your option) any later version.
0c1cd1
+#
0c1cd1
+# This program is distributed in the hope that it will be useful,
0c1cd1
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
0c1cd1
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c1cd1
+# GNU General Public License for more details.
0c1cd1
+#
0c1cd1
+# You should have received a copy of the GNU General Public License
0c1cd1
+# along with this program.  If not, see <http://www.gnu.org/licenses/> .
0c1cd1
+
0c1cd1
+# Test that GDB can print an allocatable array that is a data field
0c1cd1
+# within a class like type.
0c1cd1
+
0c1cd1
+if {[skip_fortran_tests]} { return -1 }
0c1cd1
+
0c1cd1
+standard_testfile ".f90"
0c1cd1
+load_lib fortran.exp
0c1cd1
+
0c1cd1
+if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
0c1cd1
+	 {debug f90}]} {
0c1cd1
+    return -1
0c1cd1
+}
0c1cd1
+
0c1cd1
+if {![runto MAIN__]} {
0c1cd1
+    untested main"could not run to main"
0c1cd1
+    return -1
0c1cd1
+}
0c1cd1
+
0c1cd1
+gdb_breakpoint [gdb_get_line_number "Break Here"]
0c1cd1
+gdb_continue_to_breakpoint "Break Here"
0c1cd1
+
0c1cd1
+# If this first test fails then the Fortran compiler being used uses
0c1cd1
+# different names, or maybe a completely different approach, for
0c1cd1
+# representing class like structures.  The following tests are
0c1cd1
+# cetainly going to fail.
0c1cd1
+gdb_test "print this" " = \\( _data = \[^\r\n\]+, _vptr = \[^\r\n\]+\\)"
0c1cd1
+gdb_test "print this%_data" " = \\(PTR TO -> \\( Type test_type \\)\\) \[^\r\n\]+"
0c1cd1
+gdb_test "print this%_data%b" " = \\(\\( 1, 2, 3\\) \\( 4, 5, 6\\) \\)"
0c1cd1
diff --git a/gdb/testsuite/gdb.fortran/class-allocatable-array.f90 b/gdb/testsuite/gdb.fortran/class-allocatable-array.f90
0c1cd1
new file mode 100644
0c1cd1
--- /dev/null
0c1cd1
+++ b/gdb/testsuite/gdb.fortran/class-allocatable-array.f90
0c1cd1
@@ -0,0 +1,54 @@
0c1cd1
+! Copyright 2020 Free Software Foundation, Inc.
0c1cd1
+!
0c1cd1
+! This program is free software; you can redistribute it and/or modify
0c1cd1
+! it under the terms of the GNU General Public License as published by
0c1cd1
+! the Free Software Foundation; either version 3 of the License, or
0c1cd1
+! (at your option) any later version.
0c1cd1
+!
0c1cd1
+! This program is distributed in the hope that it will be useful,
0c1cd1
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
0c1cd1
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c1cd1
+! GNU General Public License for more details.
0c1cd1
+!
0c1cd1
+! You should have received a copy of the GNU General Public License
0c1cd1
+! along with this program.  If not, see <http://www.gnu.org/licenses/>.
0c1cd1
+
0c1cd1
+module test_module
0c1cd1
+  type test_type
0c1cd1
+     integer a
0c1cd1
+     real, allocatable :: b (:, :)
0c1cd1
+   contains
0c1cd1
+     procedure :: test_proc
0c1cd1
+  end type test_type
0c1cd1
+
0c1cd1
+contains
0c1cd1
+
0c1cd1
+  subroutine test_proc (this)
0c1cd1
+    class(test_type), intent (inout) :: this
0c1cd1
+    allocate (this%b (3, 2))
0c1cd1
+    call fill_array_2d (this%b)
0c1cd1
+    print *, ""		! Break Here
0c1cd1
+  contains
0c1cd1
+    ! Helper subroutine to fill 2-dimensional array with unique
0c1cd1
+    ! values.
0c1cd1
+    subroutine fill_array_2d (array)
0c1cd1
+      real, dimension (:,:) :: array
0c1cd1
+      real :: counter
0c1cd1
+
0c1cd1
+      counter = 1.0
0c1cd1
+      do i=LBOUND (array, 2), UBOUND (array, 2), 1
0c1cd1
+         do j=LBOUND (array, 1), UBOUND (array, 1), 1
0c1cd1
+            array (j,i) = counter
0c1cd1
+            counter = counter + 1
0c1cd1
+         end do
0c1cd1
+      end do
0c1cd1
+    end subroutine fill_array_2d
0c1cd1
+  end subroutine test_proc
0c1cd1
+end module
0c1cd1
+
0c1cd1
+program test
0c1cd1
+  use test_module
0c1cd1
+  implicit none
0c1cd1
+  type(test_type) :: t
0c1cd1
+  call t%test_proc ()
0c1cd1
+end program test
0c1cd1
diff --git a/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp
0c1cd1
new file mode 100644
0c1cd1
--- /dev/null
0c1cd1
+++ b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp
0c1cd1
@@ -0,0 +1,46 @@
0c1cd1
+# Copyright 2020 Free Software Foundation, Inc.
0c1cd1
+
0c1cd1
+# This program is free software; you can redistribute it and/or modify
0c1cd1
+# it under the terms of the GNU General Public License as published by
0c1cd1
+# the Free Software Foundation; either version 3 of the License, or
0c1cd1
+# (at your option) any later version.
0c1cd1
+#
0c1cd1
+# This program is distributed in the hope that it will be useful,
0c1cd1
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
0c1cd1
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c1cd1
+# GNU General Public License for more details.
0c1cd1
+#
0c1cd1
+# You should have received a copy of the GNU General Public License
0c1cd1
+# along with this program.  If not, see <http://www.gnu.org/licenses/> .
0c1cd1
+
0c1cd1
+# Test for GDB printing a pointer to a type containing a buffer.
0c1cd1
+
0c1cd1
+if {[skip_fortran_tests]} { return -1 }
0c1cd1
+
0c1cd1
+standard_testfile ".f90"
0c1cd1
+load_lib fortran.exp
0c1cd1
+
0c1cd1
+if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
0c1cd1
+	 {debug f90}]} {
0c1cd1
+    return -1
0c1cd1
+}
0c1cd1
+
0c1cd1
+if {![runto MAIN__]} {
0c1cd1
+    untested "could not run to main"
0c1cd1
+    return -1
0c1cd1
+}
0c1cd1
+
0c1cd1
+gdb_breakpoint [gdb_get_line_number "Break Here"]
0c1cd1
+gdb_continue_to_breakpoint "Break Here"
0c1cd1
+
0c1cd1
+gdb_test "print *buffer" \
0c1cd1
+    " = \\( alpha = \\(1\\.5, 2\\.5, 3\\.5, 4\\.5, 5\\.5\\) \\)"
0c1cd1
+
0c1cd1
+set l_buffer_type [multi_line \
0c1cd1
+		       "Type l_buffer" \
0c1cd1
+		       "    real\\(kind=4\\) :: alpha\\(.\\)" \
0c1cd1
+		       "End Type l_buffer" ]
0c1cd1
+
0c1cd1
+gdb_test "ptype buffer" "type = PTR TO -> \\( ${l_buffer_type} \\)"
0c1cd1
+gdb_test "ptype *buffer" "type = ${l_buffer_type}"
0c1cd1
+gdb_test "ptype buffer%alpha" "type = real\\(kind=4\\) \\(5\\)"
0c1cd1
diff --git a/gdb/testsuite/gdb.fortran/pointer-to-pointer.f90 b/gdb/testsuite/gdb.fortran/pointer-to-pointer.f90
0c1cd1
new file mode 100644
0c1cd1
--- /dev/null
0c1cd1
+++ b/gdb/testsuite/gdb.fortran/pointer-to-pointer.f90
0c1cd1
@@ -0,0 +1,34 @@
0c1cd1
+! Copyright 2020 Free Software Foundation, Inc.
0c1cd1
+!
0c1cd1
+! This program is free software; you can redistribute it and/or modify
0c1cd1
+! it under the terms of the GNU General Public License as published by
0c1cd1
+! the Free Software Foundation; either version 3 of the License, or
0c1cd1
+! (at your option) any later version.
0c1cd1
+!
0c1cd1
+! This program is distributed in the hope that it will be useful,
0c1cd1
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
0c1cd1
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c1cd1
+! GNU General Public License for more details.
0c1cd1
+!
0c1cd1
+! You should have received a copy of the GNU General Public License
0c1cd1
+! along with this program.  If not, see <http://www.gnu.org/licenses/>.
0c1cd1
+
0c1cd1
+program allocate_array
0c1cd1
+
0c1cd1
+  type l_buffer
0c1cd1
+     real, dimension(:), pointer :: alpha
0c1cd1
+  end type l_buffer
0c1cd1
+  type(l_buffer), pointer :: buffer
0c1cd1
+
0c1cd1
+  allocate (buffer)
0c1cd1
+  allocate (buffer%alpha (5))
0c1cd1
+
0c1cd1
+  buffer%alpha (1) = 1.5
0c1cd1
+  buffer%alpha (2) = 2.5
0c1cd1
+  buffer%alpha (3) = 3.5
0c1cd1
+  buffer%alpha (4) = 4.5
0c1cd1
+  buffer%alpha (5) = 5.5
0c1cd1
+
0c1cd1
+  print *, buffer%alpha	! Break Here.
0c1cd1
+
0c1cd1
+end program allocate_array
0c1cd1
diff --git a/gdb/valops.c b/gdb/valops.c
0c1cd1
--- a/gdb/valops.c
0c1cd1
+++ b/gdb/valops.c
0c1cd1
@@ -1573,42 +1573,34 @@ value_ind (struct value *arg1)
0c1cd1
   if (TYPE_CODE (base_type) == TYPE_CODE_PTR)
0c1cd1
     {
0c1cd1
       struct type *enc_type;
0c1cd1
-      CORE_ADDR addr;
0c1cd1
-
0c1cd1
-      if (type_not_associated (base_type))
0c1cd1
-        error (_("Attempt to take contents of a not associated pointer."));
0c1cd1
-
0c1cd1
-      if (NULL != TYPE_DATA_LOCATION (TYPE_TARGET_TYPE (base_type)))
0c1cd1
-	addr = value_address (arg1);
0c1cd1
-      else
0c1cd1
-	addr = value_as_address (arg1);
0c1cd1
-
0c1cd1
-      if (addr != 0)
0c1cd1
-	TYPE_TARGET_TYPE (base_type) =
0c1cd1
-	    resolve_dynamic_type (TYPE_TARGET_TYPE (base_type), NULL, addr);
0c1cd1
 
0c1cd1
       /* We may be pointing to something embedded in a larger object.
0c1cd1
          Get the real type of the enclosing object.  */
0c1cd1
       enc_type = check_typedef (value_enclosing_type (arg1));
0c1cd1
       enc_type = TYPE_TARGET_TYPE (enc_type);
0c1cd1
 
0c1cd1
+      CORE_ADDR base_addr;
0c1cd1
       if (TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_FUNC
0c1cd1
 	  || TYPE_CODE (check_typedef (enc_type)) == TYPE_CODE_METHOD)
0c1cd1
-	/* For functions, go through find_function_addr, which knows
0c1cd1
-	   how to handle function descriptors.  */
0c1cd1
-	arg2 = value_at_lazy (enc_type, 
0c1cd1
-			      find_function_addr (arg1, NULL));
0c1cd1
+	{
0c1cd1
+	  /* For functions, go through find_function_addr, which knows
0c1cd1
+	     how to handle function descriptors.  */
0c1cd1
+	  base_addr = find_function_addr (arg1, NULL);
0c1cd1
+	}
0c1cd1
       else
0c1cd1
-	/* Retrieve the enclosing object pointed to.  */
0c1cd1
-	arg2 = value_at_lazy (enc_type, 
0c1cd1
-			      (addr - value_pointed_to_offset (arg1)));
0c1cd1
+	{
0c1cd1
+	  /* Retrieve the enclosing object pointed to.  */
0c1cd1
+	  base_addr = (value_as_address (arg1)
0c1cd1
+		       - value_pointed_to_offset (arg1));
0c1cd1
+	}
0c1cd1
 
0c1cd1
+      arg2 = value_at_lazy (enc_type, base_addr);
0c1cd1
       enc_type = value_type (arg2);
0c1cd1
-      return readjust_indirect_value_type (arg2, enc_type, base_type, arg1);
0c1cd1
+      return readjust_indirect_value_type (arg2, enc_type, base_type,
0c1cd1
+					   arg1, base_addr);
0c1cd1
     }
0c1cd1
 
0c1cd1
   error (_("Attempt to take contents of a non-pointer value."));
0c1cd1
-  return 0;			/* For lint -- never reached.  */
0c1cd1
 }
0c1cd1
 
0c1cd1
 /* Create a value for an array by allocating space in GDB, copying the
0c1cd1
diff --git a/gdb/value.c b/gdb/value.c
0c1cd1
--- a/gdb/value.c
0c1cd1
+++ b/gdb/value.c
0c1cd1
@@ -3611,10 +3611,19 @@ coerce_ref_if_computed (const struct value *arg)
0c1cd1
 struct value *
0c1cd1
 readjust_indirect_value_type (struct value *value, struct type *enc_type,
0c1cd1
 			      const struct type *original_type,
0c1cd1
-			      const struct value *original_value)
0c1cd1
+			      struct value *original_value,
0c1cd1
+			      CORE_ADDR original_value_address)
0c1cd1
 {
0c1cd1
+  gdb_assert (TYPE_CODE (original_type) == TYPE_CODE_PTR
0c1cd1
+	      || TYPE_IS_REFERENCE (original_type));
0c1cd1
+
0c1cd1
+  struct type *original_target_type = TYPE_TARGET_TYPE (original_type);
0c1cd1
+  struct type *resolved_original_target_type
0c1cd1
+    = resolve_dynamic_type (original_target_type, NULL,
0c1cd1
+			    original_value_address);
0c1cd1
+
0c1cd1
   /* Re-adjust type.  */
0c1cd1
-  deprecated_set_value_type (value, TYPE_TARGET_TYPE (original_type));
0c1cd1
+  deprecated_set_value_type (value, resolved_original_target_type);
0c1cd1
 
0c1cd1
   /* Add embedding info.  */
0c1cd1
   set_value_enclosing_type (value, enc_type);
0c1cd1
@@ -3641,12 +3650,11 @@ coerce_ref (struct value *arg)
0c1cd1
   enc_type = check_typedef (value_enclosing_type (arg));
0c1cd1
   enc_type = TYPE_TARGET_TYPE (enc_type);
0c1cd1
 
0c1cd1
-  retval = value_at_lazy (enc_type,
0c1cd1
-                          unpack_pointer (value_type (arg),
0c1cd1
-                                          value_contents (arg)));
0c1cd1
+  CORE_ADDR addr = unpack_pointer (value_type (arg), value_contents (arg));
0c1cd1
+  retval = value_at_lazy (enc_type, addr);
0c1cd1
   enc_type = value_type (retval);
0c1cd1
-  return readjust_indirect_value_type (retval, enc_type,
0c1cd1
-                                       value_type_arg_tmp, arg);
0c1cd1
+  return readjust_indirect_value_type (retval, enc_type, value_type_arg_tmp,
0c1cd1
+				       arg, addr);
0c1cd1
 }
0c1cd1
 
0c1cd1
 struct value *
0c1cd1
diff --git a/gdb/value.h b/gdb/value.h
0c1cd1
--- a/gdb/value.h
0c1cd1
+++ b/gdb/value.h
0c1cd1
@@ -487,7 +487,9 @@ extern struct value *coerce_ref_if_computed (const struct value *arg);
0c1cd1
 
0c1cd1
 /* Setup a new value type and enclosing value type for dereferenced value VALUE.
0c1cd1
    ENC_TYPE is the new enclosing type that should be set.  ORIGINAL_TYPE and
0c1cd1
-   ORIGINAL_VAL are the type and value of the original reference or pointer.
0c1cd1
+   ORIGINAL_VAL are the type and value of the original reference or
0c1cd1
+   pointer.  ORIGINAL_VALUE_ADDRESS is the address within VALUE, that is
0c1cd1
+   the address that was dereferenced.
0c1cd1
 
0c1cd1
    Note, that VALUE is modified by this function.
0c1cd1
 
0c1cd1
@@ -496,7 +498,8 @@ extern struct value *coerce_ref_if_computed (const struct value *arg);
0c1cd1
 extern struct value * readjust_indirect_value_type (struct value *value,
0c1cd1
 						    struct type *enc_type,
0c1cd1
 						    const struct type *original_type,
0c1cd1
-						    const struct value *original_val);
0c1cd1
+						    struct value *original_val,
0c1cd1
+						    CORE_ADDR original_value_address);
0c1cd1
 
0c1cd1
 /* Convert a REF to the object referenced.  */
0c1cd1