public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* Extract the return value in finish_command on Xtensa.
@ 2004-07-12 23:38 Chris Zankel
  2004-07-14 19:40 ` Andrew Cagney
  0 siblings, 1 reply; 7+ messages in thread
From: Chris Zankel @ 2004-07-12 23:38 UTC (permalink / raw)
  To: gdb

[-- Attachment #1: Type: text/plain, Size: 1860 bytes --]

I am working on a port of GDB to the Xtensa architecture.

Unfortunately, it is impossible on Xtensa to extract the return value 
once the 'callee' has returned to the 'caller' without analyzing the 
call instruction (if there was one). Depending on the call instruction, 
the return value can be in register a6, a10, oder a14.

There are, however, only two cases where this is needed: dummy frames 
(where the register number is known) and 'finish'. The second case is 
the more interesting one. Fortunately, GDB has enough information about 
the frame to determine the register number before the target program 
returns to the caller. In case of Xtensa, GDB would save the register 
number before it continues the target program and uses it once it has 
returned.

The attached patch shows roughly an idea how this could be accomplished.
There is, however, one caveat, GDB now passes the two (struct value*) 
values (read and write) to return_value() instead of the buffer 
addresses, so all architectures would have to be modified.

A short overview over the attached patch:

The return value 'value' is now allocated before finish_command() 
continues the target and not after it has returned to the caller 
function. The new function gdbarch_setup_return_value() is used by 
Xtensa to set the register number for the return register with help from 
the frame information.
[@@ -1237,6 +1197,38 @@]

Because of this change, finish_command() saves the values of 
'value_type' and 'value' instead of 'function' (in case of an async 
target). [@@ -1257,12 +1249,16 @@]

Once the temporary breakpoint is hit, GDB prints the return value, if 
any. [@@ -1276,27 +1272,8 @@]

print_return_value() is now called with the return value only if there 
is a valid return value [@@ -1075,41 +1075,18 @@].


Please let me know if you have a better idea.


Thanks,
Chris


[-- Attachment #2: diff_infcmd_c --]
[-- Type: text/plain, Size: 7040 bytes --]

--- ../../cvs/src/gdb/infcmd.c	2004-06-28 23:39:06.000000000 -0700
+++ ./infcmd.c	2004-07-12 15:45:51.000000000 -0700
@@ -64,7 +64,7 @@
 
 static void nofp_registers_info (char *, int);
 
-static void print_return_value (int struct_return, struct type *value_type);
+static void print_return_value (struct type *value_type, struct value *value);
 
 static void finish_command_continuation (struct continuation_arg *);
 
@@ -1075,41 +1075,18 @@
 /* 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)
+print_return_value (struct type *value_type, struct value *value)
 {
-  struct gdbarch *gdbarch = current_gdbarch;
   struct cleanup *old_chain;
   struct ui_stream *stb;
-  struct value *value;
 
   gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID);
 
-  /* 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.  */
-
-  switch (gdbarch_return_value (gdbarch, value_type, NULL, NULL, NULL))
-    {
-    case RETURN_VALUE_REGISTER_CONVENTION:
-    case RETURN_VALUE_ABI_RETURNS_ADDRESS:
-      value = allocate_value (value_type);
-      CHECK_TYPEDEF (value_type);
-      gdbarch_return_value (current_gdbarch, value_type, stop_registers,
-			    VALUE_CONTENTS_RAW (value), NULL);
-      break;
-    case RETURN_VALUE_STRUCT_CONVENTION:
-      value = NULL;
-      break;
-    default:
-      internal_error (__FILE__, __LINE__, "bad switch");
-    }
-
   if (value)
     {
       /* Print it.  */
+      gdbarch_return_value (current_gdbarch, value_type, stop_registers,
+			    value, NULL);
       stb = ui_out_stream_new (uiout);
       old_chain = make_cleanup_ui_out_stream_delete (stb);
       ui_out_text (uiout, "Value returned is ");
@@ -1142,39 +1119,19 @@
 static void
 finish_command_continuation (struct continuation_arg *arg)
 {
-  struct symbol *function;
   struct breakpoint *breakpoint;
   struct cleanup *cleanups;
+  struct type *value_type;
+  struct value *value;
 
   breakpoint = (struct breakpoint *) arg->data.pointer;
-  function = (struct symbol *) arg->next->data.pointer;
+  value_type = (struct type *) arg->next->data.pointer;
   cleanups = (struct cleanup *) arg->next->next->data.pointer;
+  value = (struct value *) arg->next->next->next->data.pointer;
 
   if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
-      && function != NULL)
-    {
-      struct type *value_type;
-      int struct_return;
-      int gcc_compiled;
-
-      value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
-      if (!value_type)
-	internal_error (__FILE__, __LINE__,
-			"finish_command: function has no target type");
-
-      if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
-	{
-	  do_exec_cleanups (cleanups);
-	  return;
-	}
-
-      CHECK_TYPEDEF (value_type);
-      gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function));
-      struct_return = using_struct_return (value_type, gcc_compiled);
-
-      print_return_value (struct_return, value_type); 
-    }
-
+      && value_type != NULL && TYPE_CODE (value_type) != TYPE_CODE_VOID)
+      print_return_value (value_type, value);
   do_exec_cleanups (cleanups);
 }
 
@@ -1184,13 +1141,16 @@
 static void
 finish_command (char *arg, int from_tty)
 {
+  struct gdbarch *gdbarch = current_gdbarch;
   struct symtab_and_line sal;
   struct frame_info *frame;
   struct symbol *function;
   struct breakpoint *breakpoint;
   struct cleanup *old_chain;
-  struct continuation_arg *arg1, *arg2, *arg3;
+  struct continuation_arg *arg1, *arg2, *arg3, *arg4;
 
+  struct type *value_type = NULL;
+  struct value *value = NULL;
   int async_exec = 0;
 
   /* Find out whether we must run in the background.  */
@@ -1237,6 +1197,38 @@
 
   function = find_pc_function (get_frame_pc (deprecated_selected_frame));
 
+  if (function != NULL)
+    {
+      value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
+      if (!value_type)
+	internal_error (__FILE__, __LINE__,
+			"finish_command: function has no target type");
+
+      /* 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.  */
+
+      switch (gdbarch_return_value (gdbarch, value_type, NULL, NULL, NULL))
+      {
+	case RETURN_VALUE_REGISTER_CONVENTION:
+	case RETURN_VALUE_ABI_RETURNS_ADDRESS:
+	  value = allocate_value (value_type);
+	  CHECK_TYPEDEF (value_type);
+	  gdbarch_setup_return_value (gdbarch, deprecated_selected_frame, 
+				      value_type, value);
+	  VALUE_FRAME_REGNUM(value) = 4;
+	  break;
+	case RETURN_VALUE_STRUCT_CONVENTION:
+	  value = NULL;
+	  break;
+	default:
+	  internal_error (__FILE__, __LINE__, "bad switch");
+      }
+    }
+
   /* Print info on the selected frame, including level number but not
      source.  */
   if (from_tty)
@@ -1257,12 +1249,16 @@
 	(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
       arg3 =
 	(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
+      arg4 =
+	(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
       arg1->next = arg2;
       arg2->next = arg3;
-      arg3->next = NULL;
+      arg3->next = arg4;
+      arg4->next = NULL;
       arg1->data.pointer = breakpoint;
-      arg2->data.pointer = function;
+      arg2->data.pointer = value_type;
       arg3->data.pointer = old_chain;
+      arg4->data.pointer = value;
       add_continuation (finish_command_continuation, arg1);
     }
 
@@ -1276,27 +1272,8 @@
     {
       /* Did we stop at our breakpoint?  */
       if (bpstat_find_breakpoint (stop_bpstat, breakpoint) != NULL
-	  && function != NULL)
-	{
-	  struct type *value_type;
-	  int struct_return;
-	  int gcc_compiled;
-
-	  value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
-	  if (!value_type)
-	    internal_error (__FILE__, __LINE__,
-			    "finish_command: function has no target type");
-
-	  /* FIXME: Shouldn't we do the cleanups before returning?  */
-	  if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
-	    return;
-
-	  CHECK_TYPEDEF (value_type);
-	  gcc_compiled = BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function));
-	  struct_return = using_struct_return (value_type, gcc_compiled);
-
-	  print_return_value (struct_return, value_type); 
-	}
+	  && value_type != NULL && TYPE_CODE (value_type) != TYPE_CODE_VOID)
+	  print_return_value (value_type, value);
 
       do_cleanups (old_chain);
     }

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Extract the return value in finish_command on Xtensa.
  2004-07-12 23:38 Extract the return value in finish_command on Xtensa Chris Zankel
@ 2004-07-14 19:40 ` Andrew Cagney
  2004-07-14 20:37   ` Daniel Jacobowitz
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Cagney @ 2004-07-14 19:40 UTC (permalink / raw)
  To: Chris Zankel; +Cc: gdb

> I am working on a port of GDB to the Xtensa architecture.
> 
> Unfortunately, it is impossible on Xtensa to extract the return value once the 'callee' has returned to the 'caller' without analyzing the call instruction (if there was one). Depending on the call instruction, the return value can be in register a6, a10, oder a14.

Puzzled expression.  The ABI should specify which return-value 
convention will be used?

I suspect you'll need to explain a little more about your architecture.

Andrew


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Extract the return value in finish_command on Xtensa.
  2004-07-14 19:40 ` Andrew Cagney
@ 2004-07-14 20:37   ` Daniel Jacobowitz
  2004-07-15 14:36     ` Andrew Cagney
  2004-07-15 17:58     ` Chris Zankel
  0 siblings, 2 replies; 7+ messages in thread
From: Daniel Jacobowitz @ 2004-07-14 20:37 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Chris Zankel, gdb

On Wed, Jul 14, 2004 at 03:38:34PM -0400, Andrew Cagney wrote:
> >I am working on a port of GDB to the Xtensa architecture.
> >
> >Unfortunately, it is impossible on Xtensa to extract the return value once 
> >the 'callee' has returned to the 'caller' without analyzing the call 
> >instruction (if there was one). Depending on the call instruction, the 
> >return value can be in register a6, a10, oder a14.
> 
> Puzzled expression.  The ABI should specify which return-value 
> convention will be used?
> 
> I suspect you'll need to explain a little more about your architecture.

Xtensa has register windows.  The call instruction determines how far
the window shifts; the return value is always going to be in some fixed
register (a0?) at the end of the function, but the caller has to choose
which call instruction to use and expect the return value in the
correct location based on that.

-- 
Daniel Jacobowitz

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Extract the return value in finish_command on Xtensa.
  2004-07-14 20:37   ` Daniel Jacobowitz
@ 2004-07-15 14:36     ` Andrew Cagney
  2004-07-15 14:42       ` Daniel Jacobowitz
  2004-07-15 17:58     ` Chris Zankel
  1 sibling, 1 reply; 7+ messages in thread
From: Andrew Cagney @ 2004-07-15 14:36 UTC (permalink / raw)
  To: Daniel Jacobowitz, Chris Zankel; +Cc: gdb

> On Wed, Jul 14, 2004 at 03:38:34PM -0400, Andrew Cagney wrote:
> 
>>>> >I am working on a port of GDB to the Xtensa architecture.
>>>> >
>>>> >Unfortunately, it is impossible on Xtensa to extract the return value once 
>>>> >the 'callee' has returned to the 'caller' without analyzing the call 
>>>> >instruction (if there was one). Depending on the call instruction, the 
>>>> >return value can be in register a6, a10, oder a14.
>>
>>> 
>>> Puzzled expression.  The ABI should specify which return-value 
>>> convention will be used?
>>> 
>>> I suspect you'll need to explain a little more about your architecture.
> 
> 
> Xtensa has register windows.  The call instruction determines how far
> the window shifts; the return value is always going to be in some fixed
> register (a0?) at the end of the function, but the caller has to choose
> which call instruction to use and expect the return value in the
> correct location based on that.

Keep going :-)  For instance, what logic determines the shift amount 
(the insn just reflects that decision), and how does the mechanism 
compare to ia64 and SPARC?

Andrew


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Extract the return value in finish_command on Xtensa.
  2004-07-15 14:36     ` Andrew Cagney
@ 2004-07-15 14:42       ` Daniel Jacobowitz
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Jacobowitz @ 2004-07-15 14:42 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: Chris Zankel, gdb

On Thu, Jul 15, 2004 at 10:21:39AM -0400, Andrew Cagney wrote:
> >On Wed, Jul 14, 2004 at 03:38:34PM -0400, Andrew Cagney wrote:
> >
> >>>>>I am working on a port of GDB to the Xtensa architecture.
> >>>>>
> >>>>>Unfortunately, it is impossible on Xtensa to extract the return value 
> >>>>once >the 'callee' has returned to the 'caller' without analyzing the 
> >>>>call >instruction (if there was one). Depending on the call 
> >>>>instruction, the >return value can be in register a6, a10, oder a14.
> >>
> >>>
> >>>Puzzled expression.  The ABI should specify which return-value 
> >>>convention will be used?
> >>>
> >>>I suspect you'll need to explain a little more about your architecture.
> >
> >
> >Xtensa has register windows.  The call instruction determines how far
> >the window shifts; the return value is always going to be in some fixed
> >register (a0?) at the end of the function, but the caller has to choose
> >which call instruction to use and expect the return value in the
> >correct location based on that.
> 
> Keep going :-)  For instance, what logic determines the shift amount 
> (the insn just reflects that decision), and how does the mechanism 
> compare to ia64 and SPARC?

That I'll have to leave to Chris :-)  I don't know.  SPARC only has
fixed size windows; I have labored hard and long not to know anything
about ia64.

-- 
Daniel Jacobowitz

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Extract the return value in finish_command on Xtensa.
  2004-07-14 20:37   ` Daniel Jacobowitz
  2004-07-15 14:36     ` Andrew Cagney
@ 2004-07-15 17:58     ` Chris Zankel
  2004-07-18 21:49       ` Andrew Cagney
  1 sibling, 1 reply; 7+ messages in thread
From: Chris Zankel @ 2004-07-15 17:58 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: Andrew Cagney, gdb

Daniel Jacobowitz wrote:
> On Wed, Jul 14, 2004 at 03:38:34PM -0400, Andrew Cagney wrote:
> 
>>>I am working on a port of GDB to the Xtensa architecture.
>>>
>>>Unfortunately, it is impossible on Xtensa to extract the return value once 
>>>the 'callee' has returned to the 'caller' without analyzing the call 
>>>instruction (if there was one). Depending on the call instruction, the 
>>>return value can be in register a6, a10, oder a14.
>>
>>Puzzled expression.  The ABI should specify which return-value 
>>convention will be used?
>>
>>I suspect you'll need to explain a little more about your architecture.

What Daniel said is basically correct. Xtensa uses register windows much 
like Sparc but with the difference that is doesn't always shift 8 
registers but a variable number of registers (4, 8, or 12). That number 
is encoded in the call instruction (call4, call8, or call12).
The shift walue is also encoded in the return address, so the return 
instruction knows how many registers it has to shift backwards.

The 'callee' always returns the return value in a2. For the caller the 
return value thus is in either a6 (call4), a10 (call8), or a14 (call12).

The calling function obviously knows what call instruction it used to 
extract the return value. The easiest way for GDB to find the return 
register would be to look at the return address of the 'callee', but 
once that function has returned, the information is lost. Because this 
problem only arises for the finish command, GDB could save the return 
address (from the 'callee' frame) before it resumes the target and then 
use that value to extract the return value.

Thanks,
Chris

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Extract the return value in finish_command on Xtensa.
  2004-07-15 17:58     ` Chris Zankel
@ 2004-07-18 21:49       ` Andrew Cagney
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Cagney @ 2004-07-18 21:49 UTC (permalink / raw)
  To: Chris Zankel; +Cc: Daniel Jacobowitz, gdb

Can you point us at a published abi document?

> Daniel Jacobowitz wrote:
> 
>> On Wed, Jul 14, 2004 at 03:38:34PM -0400, Andrew Cagney wrote:
>>
>>>> I am working on a port of GDB to the Xtensa architecture.
>>>>
>>>> Unfortunately, it is impossible on Xtensa to extract the return value once the 'callee' has returned to the 'caller' without analyzing the call instruction (if there was one). Depending on the call instruction, the return value can be in register a6, a10, oder a14.
>>>
>>>
>>> Puzzled expression.  The ABI should specify which return-value convention will be used?
>>>
>>> I suspect you'll need to explain a little more about your architecture.
> 
> 
> What Daniel said is basically correct. Xtensa uses register windows much like Sparc but with the difference that is doesn't always shift 8 registers but a variable number of registers (4, 8, or 12). That number is encoded in the call instruction (call4, call8, or call12).
> The shift walue is also encoded in the return address, so the return instruction knows how many registers it has to shift backwards.

That doesn't sound much like the sparc.  I'm wondering more about ia64. 
  Do the same feature work on that architecture.

> The 'callee' always returns the return value in a2. For the caller the return value thus is in either a6 (call4), a10 (call8), or a14 (call12).
> 
> The calling function obviously knows what call instruction it used to extract the return value.

So the information can (with a bit of effort) be extracted from the 
calling function.  Perhaphs using prolog analysis, CFI, other registers, 
or examining the instruction.

> The easiest way for GDB to find the return register would be to look at the return address of the 'callee', but once that function has returned, the information is lost. Because this problem only arises for the finish command, GDB could save the return address (from the 'callee' frame) before it resumes the target and then use that value to extract the return value.

Your original post didn't discuss "return <value>".  That has the same 
problem as finish (except more extreem since GDB blows away the callee 
frame).

Andrew


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-07-18 21:07 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-12 23:38 Extract the return value in finish_command on Xtensa Chris Zankel
2004-07-14 19:40 ` Andrew Cagney
2004-07-14 20:37   ` Daniel Jacobowitz
2004-07-15 14:36     ` Andrew Cagney
2004-07-15 14:42       ` Daniel Jacobowitz
2004-07-15 17:58     ` Chris Zankel
2004-07-18 21:49       ` Andrew Cagney

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).