public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <andrew.burgess@embecosm.com>
To: gdb-patches@sourceware.org
Subject: [PATCH 2/2] gdb/fortran: Access elements of a structure with dynamic type
Date: Fri, 10 Jul 2020 16:22:29 +0100	[thread overview]
Message-ID: <c4e456d14f066681455e1f5e0721a565267ff3c9.1594394486.git.andrew.burgess@embecosm.com> (raw)
In-Reply-To: <cover.1594394486.git.andrew.burgess@embecosm.com>

After the previous commit I noticed this behaviour:

  (gdb) ptype this
  type = Type __class_test_module_Test_type_t
      PTR TO -> ( Type test_type :: _data )
      PTR TO -> ( Type __vtype_test_module_Test_type :: _vptr )
  End Type __class_test_module_Test_type_t
  (gdb) ptype this%_data
  type = PTR TO -> ( Type test_type
      integer(kind=4) :: a
      real(kind=4), allocatable :: b(:,:)
  End Type test_type )
  (gdb) ptype this%_data%b
  Cannot access memory at address 0x50
  (gdb)

When we ask GDB for the type of field `b`, which has dynamic type,
then GDB is unable to correctly resolve the dynamic type, and ends up
trying to access target memory at address 0x50.

When GDB sees 'this%_data%b' the expression tree looks like this:

  Dump of expression @ 0x500d380, after conversion to prefix form:
  Expression: `test_module::test_proc::this._data.b'
  	Language fortran, 14 elements, 16 bytes each.

  	    0  STRUCTOP_STRUCT       Element name: `b'
  	    5    STRUCTOP_STRUCT       Element name: `_data'
  	   10      OP_VAR_VALUE          Block @0x498cca0, symbol @0x498cc20 (this)

GDB will first get a value for `this`, from which it extracts a value
for the element `_data`, and finally GDB dereferences the pointer
`_data` and extracts the element `b`.

The problem is that when looking for the type of an expression GDB
evaluates the expression in EVAL_AVOID_SIDE_EFFECTS mode, as a result
the pointer value `_data` is returned with contents set to the
constant value 0.

Normally this is fine as we only plan to look at the type being
pointed too, but for dynamic types we need the pointer value so we can
correctly fetch the dynamic properties of the value from target
memory.

The solution I present here is to spot the case where:
  (a) we're in EVAL_AVOID_SIDE_EFFECTS mode, and
  (b) the structure element has dynamic type
In this case we fetch the parent object in EVAL_NORMAL mode.  This
means that it will have its actual contents, fetched from the actual
target, rather than the dummy 0 value.  With this done we are able to
correctly evaluate the dynamic type and the above test case now
finishes like this:

  (gdb) ptype this%_data%b
  type = real(kind=4), allocatable (3,2)

You might notice that STRUCTOP_PTR is very similar to STRUCTOP_STRUCT,
but that I have not updated the former.  The reason for this is that
Fortran doesn't make use of STRUCTOP_PTR, so I'm not sure how I would
test any changes to STRUCTOP_PTR.

gdb/ChangeLog:

	* eval.c (evaluate_subexp_standard): Call evaluate_subexp with
	EVAL_NORMAL if we are accessing an element with a dynamic type.

gdb/testsuite/ChangeLog:

	* gdb.fortran/class-allocatable-array.exp: Add more tests.
---
 gdb/ChangeLog                                 |  5 +++++
 gdb/eval.c                                    | 20 ++++++++++++++++++-
 gdb/testsuite/ChangeLog                       |  4 ++++
 .../gdb.fortran/class-allocatable-array.exp   | 16 +++++++++++++++
 4 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/gdb/eval.c b/gdb/eval.c
index f9750816216..9f716ce0624 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -2031,12 +2031,30 @@ evaluate_subexp_standard (struct type *expect_type,
     case STRUCTOP_STRUCT:
       tem = longest_to_int (exp->elts[pc + 1].longconst);
       (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+      oldpos = *pos;
       arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
       if (noside == EVAL_SKIP)
 	return eval_skip_value (exp);
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+	{
+	  /* If the element of the structure has a dynamic type then we
+	     need to get the real value representing the containing
+	     structure so that we can correctly evaluate the type of the
+	     element.  If we're not already avoiding side effects then we
+	     already have the real value of the containing structure, so
+	     this is not needed.  */
+	  type = lookup_struct_elt_type (value_type (arg1),
+					 &exp->elts[pc + 2].string, 1);
+	  if (type != nullptr && is_dynamic_type (type))
+	    {
+	      *pos = oldpos;
+	      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
+	    }
+	}
       arg3 = value_struct_elt (&arg1, NULL, &exp->elts[pc + 2].string,
 			       NULL, "structure");
-      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+      if (noside == EVAL_AVOID_SIDE_EFFECTS
+	  && !is_dynamic_type (check_typedef (value_type (arg3))))
 	arg3 = value_zero (value_type (arg3), VALUE_LVAL (arg3));
       return arg3;
 
diff --git a/gdb/testsuite/gdb.fortran/class-allocatable-array.exp b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
index 9475ba3b393..355fb0ce9cd 100644
--- a/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
+++ b/gdb/testsuite/gdb.fortran/class-allocatable-array.exp
@@ -41,3 +41,19 @@ gdb_continue_to_breakpoint "Break Here"
 gdb_test "print this" " = \\( _data = \[^\r\n\]+, _vptr = \[^\r\n\]+\\)"
 gdb_test "print this%_data" " = \\(PTR TO -> \\( Type test_type \\)\\) \[^\r\n\]+"
 gdb_test "print this%_data%b" " = \\(\\( 1, 2, 3\\) \\( 4, 5, 6\\) \\)"
+
+set integer4 [fortran_int4]
+set real4 [fortran_real4]
+
+# Check we can correctly access the types of these same objects.
+gdb_test "ptype this" [multi_line \
+			   "type = Type \[^\r\n\]+" \
+			   "    PTR TO -> \\( Type test_type :: _data \\)" \
+			   "    PTR TO -> \\( Type \[^\r\n\]+ :: _vptr \\)" \
+			   "End Type \[^\r\n\]+" ]
+gdb_test "ptype this%_data" [multi_line \
+				 "type = PTR TO -> \\( Type test_type" \
+				 "    ${integer4} :: a" \
+				 "    ${real4}, allocatable :: b\\(:,:\\)" \
+				 "End Type test_type \\)" ]
+gdb_test "ptype this%_data%b" "type = ${real4}, allocatable \\(3,2\\)"
-- 
2.25.4


  parent reply	other threads:[~2020-07-10 15:22 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-10 15:22 [PATCH 0/2] Fortran dynamic type related fixes Andrew Burgess
2020-07-10 15:22 ` [PATCH 1/2] gdb/fortran: resolve dynamic types when readjusting after an indirection Andrew Burgess
2020-07-10 15:22 ` Andrew Burgess [this message]
2020-07-13 13:33 ` [PATCHv2 0/2] Fortran dynamic type related fixes Andrew Burgess
2020-07-13 13:33   ` [PATCHv2 1/2] gdb/fortran: resolve dynamic types when readjusting after an indirection Andrew Burgess
2020-07-22 19:10     ` Tom Tromey
2020-07-25  0:31       ` Andrew Burgess
2020-07-13 13:33   ` [PATCHv2 2/2] gdb/fortran: Access elements of a structure with dynamic type Andrew Burgess
2020-07-22 19:19     ` Tom Tromey
2020-07-23 10:28       ` Andrew Burgess
2020-07-24 20:03         ` Tom Tromey
2020-07-26 19:31           ` Tom Tromey
2020-08-04 19:19           ` Tom Tromey
2020-08-06 15:38             ` Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c4e456d14f066681455e1f5e0721a565267ff3c9.1594394486.git.andrew.burgess@embecosm.com \
    --to=andrew.burgess@embecosm.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).