This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH/RFC/RFA] Print in-memory struct return values


[ Now *with* patch ]

   Date: Fri, 07 May 2004 18:35:28 -0400
   From: Andrew Cagney <cagney@gnu.org>

   > The current GDB doesn't print the return value when using `finish' for
   > functions return structures that are not returned in registers.  Note
   > that this is a regression from GDB 6.0 for many systems.  Anyway, the
   > attached patch provides a way to fix this, and adds the necessary
   > support to the i386 target.
   > 
   > If there are no comments, I'll check this in in a few days.  Eli, is
   > the doc bit OK?

   Why not add another member to `enum return_value_convention' so that 
   return_value() can directly differentate between these two cases?

I called the new member RETURN_VALUE_ADDRESS_CONVENTION.  I'm not
really satisfied with that name, but I couldn't think of something
better.  The implementation is fairly simple, but I took the
opportunity to re-arrange the code such that the legacy stuff is
separated out, that's why the patch looks a bit more invasive.

Andrew, do you have any objections?

While implementing this stuff, it occured to me that the return value
of gdbarch_return_value() really should be a set of bit flags instead
of an enum.  We should have flags that indicate:

* Whether GDB should allocate some memory to store the return value.

* Whether the location of the return value is known when we've just
  returned from a function.

* Whether the location of the return value is known when we're
  currently executing a function.

I think the ABI's I've seen thus far cover at least six of the eight
posible combinations.  Thoughts?  I'd like to check in the attached
patch regardless of what we decide.

Mark


Index: ChangeLog
from  Mark Kettenis  <kettenis@gnu.org>
 
	* defs.h (enum return_value_convention): Add
	RETURN_VALUE_ADDRESS_CONVENTION.
	* infcmd.c (legacy_return_value): New function.
	(print_return_value): Rwerite to implement
	RETURN_VALUE_ADDRESS_CONVENTION.
	* i386-tdep.c (i386_return_value): Implement
	RETURN_VALUE_ADDRESS_CONVENTION.

Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.145
diff -u -p -r1.145 defs.h
--- defs.h 30 Apr 2004 20:44:58 -0000 1.145
+++ defs.h 8 May 2004 19:42:29 -0000
@@ -250,7 +250,11 @@ enum return_value_convention
      should be stored.  While typically, and historically, used for
      large structs, this is convention is applied to values of many
      different types.  */
-  RETURN_VALUE_STRUCT_CONVENTION
+  RETURN_VALUE_STRUCT_CONVENTION,
+  /* Like the "struct return convention" above, where the called
+     function stores the address at which the value being returned is
+     stored in a register.  */
+  RETURN_VALUE_ADDRESS_CONVENTION
 };
 
 /* the cleanup list records things that have to be undone
Index: infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.108
diff -u -p -r1.108 infcmd.c
--- infcmd.c 28 Apr 2004 16:36:25 -0000 1.108
+++ infcmd.c 8 May 2004 19:42:29 -0000
@@ -1047,79 +1047,97 @@ advance_command (char *arg, int from_tty
 }
 
 
+static struct value *
+legacy_return_value (int struct_return, struct type *value_type)
+{
+  struct value *value;
+
+  if (!struct_return)
+    {
+      /* The return value can be found in the inferior's registers.  */
+      return register_value_being_returned (value_type, stop_registers);
+    }
+
+  if (DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS_P ())
+    {
+      CORE_ADDR addr;
+
+      addr = DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS (stop_registers);
+      if (!addr)
+	error ("Function return value unknown.");
+      return value_at (value_type, addr, NULL);
+    }
+
+  /* It is "struct return" yet the value is being extracted,
+     presumably from registers, using EXTRACT_RETURN_VALUE.  This
+     doesn't make sense.  Unfortunately, the legacy interfaces allowed
+     this behavior.  Sigh!  */
+  value = allocate_value (value_type);
+  CHECK_TYPEDEF (value_type);
+  /* If the function returns void, don't bother fetching the return
+     value.  */
+  EXTRACT_RETURN_VALUE (value_type, stop_registers,
+			VALUE_CONTENTS_RAW (value));
+  return value;
+}
+
 /* Print the result of a function at the end of a 'finish' command.  */
 
 static void
 print_return_value (int struct_return, struct type *value_type)
 {
+  struct gdbarch *gdbarch = current_gdbarch;
   struct cleanup *old_chain;
   struct ui_stream *stb;
-  struct value *value;
+  struct value *value = NULL;
 
-  if (!struct_return)
-    {
-      /* The return value can be found in the inferior's registers.  */
-      value = register_value_being_returned (value_type, stop_registers);
-    }
-  /* FIXME: cagney/2004-01-17: When both return_value and
-     extract_returned_value_address are available, should use that to
-     find the address of and then extract the returned value.  */
   /* FIXME: 2003-09-27: When returning from a nested inferior function
      call, it's possible (with no help from the architecture vector)
      to locate and return/print a "struct return" value.  This is just
      a more complicated case of what is already being done in in the
      inferior function call code.  In fact, when inferior function
      calls are made async, this will likely be made the norm.  */
-  else if (gdbarch_return_value_p (current_gdbarch))
-    /* We cannot determine the contents of the structure because it is
-       on the stack, and we don't know where, since we did not
-       initiate the call, as opposed to the call_function_by_hand
-       case.  */
-    {
-      gdb_assert (gdbarch_return_value (current_gdbarch, value_type,
-					NULL, NULL, NULL)
-		  == RETURN_VALUE_STRUCT_CONVENTION);
-      ui_out_text (uiout, "Value returned has type: ");
-      ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type));
-      ui_out_text (uiout, ".");
-      ui_out_text (uiout, " Cannot determine contents\n");
-      return;
-    }
-  else
+
+  if (gdbarch_return_value_p (gdbarch))
     {
-      if (DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS_P ())
-	{
-	  CORE_ADDR addr = DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS (stop_registers);
-	  if (!addr)
-	    error ("Function return value unknown.");
-	  value = value_at (value_type, addr, NULL);
-	}
-      else
+      switch (gdbarch_return_value (gdbarch, value_type, NULL, NULL, NULL))
 	{
-	  /* It is "struct return" yet the value is being extracted,
-             presumably from registers, using EXTRACT_RETURN_VALUE.
-             This doesn't make sense.  Unfortunately, the legacy
-             interfaces allowed this behavior.  Sigh!  */
+	case RETURN_VALUE_REGISTER_CONVENTION:
+	case RETURN_VALUE_ADDRESS_CONVENTION:
 	  value = allocate_value (value_type);
 	  CHECK_TYPEDEF (value_type);
-	  /* If the function returns void, don't bother fetching the
-	     return value.  */
-	  EXTRACT_RETURN_VALUE (value_type, stop_registers,
-				VALUE_CONTENTS_RAW (value));
+	  gdbarch_return_value (current_gdbarch, value_type, stop_registers,
+				VALUE_CONTENTS_RAW (value), NULL);
+	  break;
+
+	case RETURN_VALUE_STRUCT_CONVENTION:
+	  break;
 	}
     }
+  else
+    value = legacy_return_value (struct_return, value_type);
 
-  /* Print it.  */
-  stb = ui_out_stream_new (uiout);
-  old_chain = make_cleanup_ui_out_stream_delete (stb);
-  ui_out_text (uiout, "Value returned is ");
-  ui_out_field_fmt (uiout, "gdb-result-var", "$%d",
-		    record_latest_value (value));
-  ui_out_text (uiout, " = ");
-  value_print (value, stb->stream, 0, Val_no_prettyprint);
-  ui_out_field_stream (uiout, "return-value", stb);
-  ui_out_text (uiout, "\n");
-  do_cleanups (old_chain);
+  if (value)
+    {
+      /* Print it.  */
+      stb = ui_out_stream_new (uiout);
+      old_chain = make_cleanup_ui_out_stream_delete (stb);
+      ui_out_text (uiout, "Value returned is ");
+      ui_out_field_fmt (uiout, "gdb-result-var", "$%d",
+			record_latest_value (value));
+      ui_out_text (uiout, " = ");
+      value_print (value, stb->stream, 0, Val_no_prettyprint);
+      ui_out_field_stream (uiout, "return-value", stb);
+      ui_out_text (uiout, "\n");
+      do_cleanups (old_chain);
+    }
+  else
+    {
+      ui_out_text (uiout, "Value returned has type: ");
+      ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type));
+      ui_out_text (uiout, ".");
+      ui_out_text (uiout, " Cannot determine contents\n");
+    }
 }
 
 /* Stuff that needs to be done by the finish command after the target
Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.190
diff -u -p -r1.190 i386-tdep.c
--- i386-tdep.c 30 Apr 2004 21:13:58 -0000 1.190
+++ i386-tdep.c 8 May 2004 19:42:30 -0000
@@ -1352,7 +1352,17 @@ i386_return_value (struct gdbarch *gdbar
 
   if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
       && !i386_reg_struct_return_p (gdbarch, type))
-    return RETURN_VALUE_STRUCT_CONVENTION;
+    {
+      if (readbuf)
+	{
+	  ULONGEST addr;
+
+	  regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr);
+	  read_memory (addr, readbuf, TYPE_LENGTH (type));
+	}
+
+      return RETURN_VALUE_ADDRESS_CONVENTION;
+    }
 
   /* This special case is for structures consisting of a single
      `float' or `double' member.  These structures are returned in


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]