* defs.h (enum return_value_convention): Add

RETURN_VALUE_ABI_RETURNS_ADDRESS and
RETURN_VALUE_ABI_PRESERVES_ADDRESS.
* infcmd.c (legacy_return_value): New function.
(print_return_value): Rwerite to implement
RETURN_VALUE_ABI_RETURNS_ADDRESS.
* values.c (using_struct_return): Check for inequality to
RETURN_VALUE_REGISTER_CONVENTION instead of equality to
RETURN_VALUE_STRUCT_CONVENTION.
* i386-tdep.c (i386_return_value): Implement
RETURN_VALUE_ABI_RETURNS_ADDRESS.
This commit is contained in:
Mark Kettenis 2004-05-08 23:02:10 +00:00
parent 0543f3876c
commit 31db7b6c38
5 changed files with 120 additions and 57 deletions

View File

@ -1,5 +1,17 @@
2004-05-09 Mark Kettenis <kettenis@gnu.org>
* defs.h (enum return_value_convention): Add
RETURN_VALUE_ABI_RETURNS_ADDRESS and
RETURN_VALUE_ABI_PRESERVES_ADDRESS.
* infcmd.c (legacy_return_value): New function.
(print_return_value): Rwerite to implement
RETURN_VALUE_ABI_RETURNS_ADDRESS.
* values.c (using_struct_return): Check for inequality to
RETURN_VALUE_REGISTER_CONVENTION instead of equality to
RETURN_VALUE_STRUCT_CONVENTION.
* i386-tdep.c (i386_return_value): Implement
RETURN_VALUE_ABI_RETURNS_ADDRESS.
* vax-tdep.c: Tweak comments. Reorder include files. Don't
include "symtab.h", "opcode/vax.h" and "inferior.h".
(vax_skip_prologue): Replace calls to read_memory_integer by calls

View File

@ -250,7 +250,19 @@ 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, but where the ABI
guarantees that the called function stores the address at which
the value being returned is stored in a well-defined location,
such as a register or memory slot in the stack frame. Don't use
this if the ABI doesn't explicitly guarantees this. */
RETURN_VALUE_ABI_RETURNS_ADDRESS,
/* Like the "struct return convention" above, but where the ABI
guarantees that the address at which the value being returned is
stored will be available in a well-defined location, such as a
register or memory slot in the stack frame. Don't use this if
the ABI doesn't explicitly guarantees this. */
RETURN_VALUE_ABI_PRESERVES_ADDRESS,
};
/* the cleanup list records things that have to be undone

View File

@ -1352,7 +1352,28 @@ i386_return_value (struct gdbarch *gdbarch, struct type *type,
if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
&& !i386_reg_struct_return_p (gdbarch, type))
return RETURN_VALUE_STRUCT_CONVENTION;
{
/* The System V ABI says that:
"A function that returns a structure or union also sets %eax
to the value of the original address of the caller's area
before it returns. Thus when the caller receives control
again, the address of the returned object resides in register
%eax and can be used to access the object."
So the ABI guarantees that we can always find the return
value just after the function has returned. */
if (readbuf)
{
ULONGEST addr;
regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr);
read_memory (addr, readbuf, TYPE_LENGTH (type));
}
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
}
/* This special case is for structures consisting of a single
`float' or `double' member. These structures are returned in

View File

@ -1047,79 +1047,97 @@ advance_command (char *arg, int from_tty)
}
/* 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)
static struct value *
legacy_return_value (int struct_return, struct type *value_type)
{
struct cleanup *old_chain;
struct ui_stream *stb;
struct value *value;
if (!struct_return)
{
/* The return value can be found in the inferior's registers. */
value = register_value_being_returned (value_type, stop_registers);
return 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. */
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 = NULL;
/* 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. */
if (gdbarch_return_value_p (gdbarch))
{
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:
break;
}
}
else
value = legacy_return_value (struct_return, value_type);
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
{
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 (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
{
/* 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));
}
}
/* 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);
}
/* Stuff that needs to be done by the finish command after the target

View File

@ -1308,7 +1308,7 @@ using_struct_return (struct type *value_type, int gcc_p)
/* Probe the architecture for the return-value convention. */
return (gdbarch_return_value (current_gdbarch, value_type,
NULL, NULL, NULL)
== RETURN_VALUE_STRUCT_CONVENTION);
!= RETURN_VALUE_REGISTER_CONVENTION);
}
void