From: Chris Zankel <zankel@tensilica.com>
To: gdb@sources.redhat.com
Subject: Extract the return value in finish_command on Xtensa.
Date: Mon, 12 Jul 2004 23:38:00 -0000 [thread overview]
Message-ID: <40F31BA9.2060101@tensilica.com> (raw)
[-- 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);
}
next reply other threads:[~2004-07-12 23:15 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-07-12 23:38 Chris Zankel [this message]
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
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=40F31BA9.2060101@tensilica.com \
--to=zankel@tensilica.com \
--cc=gdb@sources.redhat.com \
/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