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]

[wip] return value architecture method


Hello,

This is a work-in-progress version of a "return_value" architecture method. This new method replaces:

USE_STRUCT_CONVENTION
STORE_RETURN_VALUE
EXTRACT_RETURN_VALUE
RETURN_VALUE_ON_STACK

The idea, as illustrated in my recent patch to ppc64:
http://sources.redhat.com/ml/gdb-patches/2003-09/msg00435.html
is to put all the logic needed to determine how return values are handled is written only once.


Notes:

I need to write doco.

It doesn't try to replace EXTRACT_STRUCT_VALUE_ADDRESS. I'm not sure what to do with that one. I've a strong suspision that the architectures that do implement it are actually broken - the callee invalidates the register that contains the needed address so this function can't work. The change does at least clean up the logic though, only calling EXTRACT_STRUCT_VALUE_ADDRESS after consulting RETURN_VALUE.

This doesn't take a GCC_P parameter, but still takes the function's return type. There's a proposal to pass a function "struct value" instead of the return type, but I think that can/should be made separatly.

At present it is modifying value_being_returned. As noted in another post, some of this logic is going to be moved to print_return_value so the final post will end up tweaking that as well.

This also finally makes it possible to fix:
http://sources.redhat.com/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=659
along with many many other cases where GDB was incorrectly claiming that it wasn't able to find a return value.


anyway, thoughts?
Andrew
2003-09-28  Andrew Cagney  <cagney@redhat.com>

	* values.c (value_being_returned): Use "gdbarch_return_value" when
	available.
	(set_return_value): Ditto.
	* defs.h (return_value_convention): Define.
	* gdbarch.sh (gdbarch_return_value): New predicate method.
	* gdbarch.h, gdbarch.c: Re-generate

Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.131
diff -u -r1.131 defs.h
--- defs.h	19 Sep 2003 16:22:38 -0000	1.131
+++ defs.h	28 Sep 2003 16:19:47 -0000
@@ -230,6 +230,21 @@
   AUTO_BOOLEAN_AUTO
 };
 
+/* Potential ways that a function can return a value of a given type.  */
+enum return_value_convention
+{
+  /* Where the return value has been squeezed into one or more
+     registers.  */
+  RETURN_VALUE_REGISTER_CONVENTION,
+  /* Commonly known as the "struct return convention".  The caller
+     passes an additional hidden first parameter to the caller.  That
+     parameter contains the address at which the value being returned
+     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
+};
+
 /* the cleanup list records things that have to be undone
    if an error happens (descriptors to be closed, memory to be freed, etc.)
    Each link in the chain records a function to call and an
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.272
diff -u -r1.272 gdbarch.sh
--- gdbarch.sh	18 Sep 2003 22:39:21 -0000	1.272
+++ gdbarch.sh	28 Sep 2003 16:20:11 -0000
@@ -593,19 +593,33 @@
 f:2:ADDRESS_TO_POINTER:void:address_to_pointer:struct type *type, void *buf, CORE_ADDR addr:type, buf, addr:::unsigned_address_to_pointer::0
 F:2:INTEGER_TO_ADDRESS:CORE_ADDR:integer_to_address:struct type *type, void *buf:type, buf
 #
-f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0
 F:2:DEPRECATED_POP_FRAME:void:deprecated_pop_frame:void:-
 # NOTE: cagney/2003-03-24: Replaced by PUSH_ARGUMENTS.
 F:2:DEPRECATED_STORE_STRUCT_RETURN:void:deprecated_store_struct_return:CORE_ADDR addr, CORE_ADDR sp:addr, sp
-#
+
+# It has been suggested that this, well actually its predecessor,
+# should take the type/value of the function to be called and not the
+# return type.  This is left as an exercise for the reader.
+
+M:::enum return_value_convention:return_value:struct type *valtype, struct regcache *regcache, const void *inval, void *outval:valtype, regcache, inval, outval
+
+# The deprecated methods RETURN_VALUE_ON_STACK, EXTRACT_RETURN_VALUE,
+# STORE_RETURN_VALUE and USE_STRUCT_CONVENTION have all been folded
+# into RETURN_VALUE.  For the moment do not try to fold in
+# EXTRACT_STRUCT_VALUE_ADDRESS as, dependant on the ABI, the debug
+# info, and the level of effort, it may well be possible to find the
+# address of a structure being return on the stack.  Someone else can
+# make that change.
+
+f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0
 f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, struct regcache *regcache, void *valbuf:type, regcache, valbuf:::legacy_extract_return_value::0
 f:2:STORE_RETURN_VALUE:void:store_return_value:struct type *type, struct regcache *regcache, const void *valbuf:type, regcache, valbuf:::legacy_store_return_value::0
 f:2:DEPRECATED_EXTRACT_RETURN_VALUE:void:deprecated_extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf
 f:2:DEPRECATED_STORE_RETURN_VALUE:void:deprecated_store_return_value:struct type *type, char *valbuf:type, valbuf
-#
+f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::generic_use_struct_convention::0
+
 F:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:struct regcache *regcache:regcache
 F:2:DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:deprecated_extract_struct_value_address:char *regbuf:regbuf
-f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::generic_use_struct_convention::0
 #
 F:2:DEPRECATED_FRAME_INIT_SAVED_REGS:void:deprecated_frame_init_saved_regs:struct frame_info *frame:frame
 F:2:DEPRECATED_INIT_EXTRA_FRAME_INFO:void:deprecated_init_extra_frame_info:int fromleaf, struct frame_info *frame:fromleaf, frame
Index: values.c
===================================================================
RCS file: /cvs/src/src/gdb/values.c,v
retrieving revision 1.57
diff -u -r1.57 values.c
--- values.c	21 Sep 2003 01:26:45 -0000	1.57
+++ values.c	28 Sep 2003 16:20:14 -0000
@@ -1216,18 +1216,60 @@
    0 when it is using the value returning conventions (this often
    means returning pointer to where structure is vs. returning value). */
 
+/* FIXME: cagney/2003-09-27: The parameter "struct_return" here is
+   totally redundant.  It's value can be determined from "valtype" and
+   a call to gdbarch_return_value (nee using_struct_return).  */
+
 struct value *
 value_being_returned (struct type *valtype, struct regcache *retbuf,
 		      int struct_return)
 {
   struct value *val;
-  CORE_ADDR addr;
+
+  if (gdbarch_return_value_p (current_gdbarch))
+    {
+      /* If the function returns void, don't bother fetching the
+         return value.  */
+      if (TYPE_CODE (valtype) == TYPE_CODE_VOID)
+	return allocate_value (valtype);
+
+      /* See if the architecture can find the return value.  */
+      switch (gdbarch_return_value (current_gdbarch, valtype,
+				    NULL, NULL, NULL))
+	{
+	case RETURN_VALUE_REGISTER_CONVENTION:
+	  /* Register values are always found.  */
+	  gdbarch_return_value (current_gdbarch, valtype, retbuf,
+				NULL, VALUE_CONTENTS_RAW (val));
+	  return val;
+	case RETURN_VALUE_STRUCT_CONVENTION:
+	  /* NOTE: Being able to find a value being returned using
+             "struct convention" is very very a-typical.  This is
+             because the ABI typically passes the address in via a
+             scratch register and by the time GDB tries to find that
+             register's value, it has well and truely been lost.  */
+	  if (EXTRACT_STRUCT_VALUE_ADDRESS_P ())
+	    {
+	      CORE_ADDR struct_addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
+	      if (struct_addr != 0)
+		return value_at (valtype, struct_addr, NULL);
+	    }
+	  /* FIXME: cagney/2003-09-27: Was this a nested inferior
+	     function call?  If it was, it is still possible to find
+	     the return value - but of course this assumes that the
+	     STRUCT_ADDR has previously been saved in the inferior
+	     function call stack.  */
+	  error ("Function return value unknown.");
+	default:
+	  internal_error (__FILE__, __LINE__, "bad switch");
+	}
+    }
 
   /* If this is not defined, just use EXTRACT_RETURN_VALUE instead.  */
   if (EXTRACT_STRUCT_VALUE_ADDRESS_P ())
     if (struct_return)
       {
-	addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
+	CORE_ADDR addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
 	if (!addr)
 	  error ("Function return value unknown.");
 	return value_at (valtype, addr, NULL);
@@ -1238,7 +1280,7 @@
     if (struct_return)
       {
 	char *buf = deprecated_grub_regcache_for_registers (retbuf);
-	addr = DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS (buf);
+	CORE_ADDR addr = DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS (buf);
 	if (!addr)
 	  error ("Function return value unknown.");
 	return value_at (valtype, addr, NULL);
@@ -1291,6 +1333,14 @@
   if (code == TYPE_CODE_ERROR)
     error ("Function return type unknown.");
 
+  if (gdbarch_return_value_p (current_gdbarch))
+    {
+      /* Probe the architecture for the return-value convention.  */
+      return (gdbarch_return_value (current_gdbarch, value_type,
+				    NULL, NULL, NULL)
+	      == RETURN_VALUE_STRUCT_CONVENTION);
+    }
+
   if (code == TYPE_CODE_STRUCT
       || code == TYPE_CODE_UNION
       || code == TYPE_CODE_ARRAY
@@ -1312,6 +1362,25 @@
 
   if (code == TYPE_CODE_ERROR)
     error ("Function return type unknown.");
+
+  if (gdbarch_return_value_p (current_gdbarch))
+    {
+      switch (gdbarch_return_value (current_gdbarch, type, NULL, NULL, NULL))
+	{
+	case RETURN_VALUE_REGISTER_CONVENTION:
+	  /* Success.  The architecture can deal with it, write it to
+             the regcache.  */
+	  gdbarch_return_value (current_gdbarch, type, current_regcache,
+				VALUE_CONTENTS (val), NULL);
+	  return;
+	case RETURN_VALUE_STRUCT_CONVENTION:
+	  /* Failure.  For the moment, assume that it is not possible
+             to find the location, on the stack, at which the "struct
+             return" value should be stored.  */
+	  error ("Location of return value unknown");
+	}
+    }
+
 
   if (code == TYPE_CODE_STRUCT
       || code == TYPE_CODE_UNION)	/* FIXME, implement struct return.  */

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