Allow struct 'return' on 32-bit sparc.

gdb/

	* sparc-tdep.c (sparc32_return_value): Handle writing return value when
	using RETURN_VALUE_ABI_PRESERVES_ADDRESS.
	* value.c (struct_return_convention): New function.
	(using_struct_return): Implement in terms of struct_return_convention.
	* value.h (struct_return_convention): Declare.
	* stack.c (return_command): Allow successful overriding of the return
	value when RETURN_VALUE_ABI_PRESERVES_ADDRESS.
This commit is contained in:
David S. Miller 2013-02-06 19:40:04 +00:00
parent bc9abe4a91
commit bbfdfe1c57
5 changed files with 57 additions and 22 deletions

View file

@ -1,3 +1,13 @@
2013-02-06 David S. Miller <davem@davemloft.net>
* sparc-tdep.c (sparc32_return_value): Handle writing return value when
using RETURN_VALUE_ABI_PRESERVES_ADDRESS.
* value.c (struct_return_convention): New function.
(using_struct_return): Implement in terms of struct_return_convention.
* value.h (struct_return_convention): Declare.
* stack.c (return_command): Allow successful overriding of the return
value when RETURN_VALUE_ABI_PRESERVES_ADDRESS.
2013-02-06 Tom Tromey <tromey@redhat.com> 2013-02-06 Tom Tromey <tromey@redhat.com>
* python/py-type.c (typy_strip_typedefs): Don't call check_typedef * python/py-type.c (typy_strip_typedefs): Don't call check_typedef

View file

@ -1370,15 +1370,21 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
if (sparc_structure_or_union_p (type) if (sparc_structure_or_union_p (type)
|| (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
{ {
ULONGEST sp;
CORE_ADDR addr;
if (readbuf) if (readbuf)
{ {
ULONGEST sp;
CORE_ADDR addr;
regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
addr = read_memory_unsigned_integer (sp + 64, 4, byte_order); addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
read_memory (addr, readbuf, TYPE_LENGTH (type)); read_memory (addr, readbuf, TYPE_LENGTH (type));
} }
if (writebuf)
{
regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
write_memory (addr, writebuf, TYPE_LENGTH (type));
}
return RETURN_VALUE_ABI_PRESERVES_ADDRESS; return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
} }

View file

@ -2278,6 +2278,7 @@ down_command (char *count_exp, int from_tty)
void void
return_command (char *retval_exp, int from_tty) return_command (char *retval_exp, int from_tty)
{ {
enum return_value_convention rv_conv;
struct frame_info *thisframe; struct frame_info *thisframe;
struct gdbarch *gdbarch; struct gdbarch *gdbarch;
struct symbol *thisfun; struct symbol *thisfun;
@ -2331,6 +2332,7 @@ return_command (char *retval_exp, int from_tty)
if (thisfun != NULL) if (thisfun != NULL)
function = read_var_value (thisfun, thisframe); function = read_var_value (thisfun, thisframe);
rv_conv = RETURN_VALUE_REGISTER_CONVENTION;
if (TYPE_CODE (return_type) == TYPE_CODE_VOID) if (TYPE_CODE (return_type) == TYPE_CODE_VOID)
/* If the return-type is "void", don't try to find the /* If the return-type is "void", don't try to find the
return-value's location. However, do still evaluate the return-value's location. However, do still evaluate the
@ -2338,14 +2340,18 @@ return_command (char *retval_exp, int from_tty)
is discarded, side effects such as "return i++" still is discarded, side effects such as "return i++" still
occur. */ occur. */
return_value = NULL; return_value = NULL;
else if (thisfun != NULL else if (thisfun != NULL)
&& using_struct_return (gdbarch, function, return_type))
{ {
query_prefix = "The location at which to store the " rv_conv = struct_return_convention (gdbarch, function, return_type);
"function's return value is unknown.\n" if (rv_conv == RETURN_VALUE_STRUCT_CONVENTION
"If you continue, the return value " || rv_conv == RETURN_VALUE_ABI_RETURNS_ADDRESS)
"that you specified will be ignored.\n"; {
return_value = NULL; query_prefix = "The location at which to store the "
"function's return value is unknown.\n"
"If you continue, the return value "
"that you specified will be ignored.\n";
return_value = NULL;
}
} }
} }
@ -2375,9 +2381,8 @@ return_command (char *retval_exp, int from_tty)
struct type *return_type = value_type (return_value); struct type *return_type = value_type (return_value);
struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ()); struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ());
gdb_assert (gdbarch_return_value (gdbarch, function, return_type, NULL, gdb_assert (rv_conv != RETURN_VALUE_STRUCT_CONVENTION
NULL, NULL) && rv_conv != RETURN_VALUE_ABI_RETURNS_ADDRESS);
== RETURN_VALUE_REGISTER_CONVENTION);
gdbarch_return_value (gdbarch, function, return_type, gdbarch_return_value (gdbarch, function, return_type,
get_current_regcache (), NULL /*read*/, get_current_regcache (), NULL /*read*/,
value_contents (return_value) /*write*/); value_contents (return_value) /*write*/);

View file

@ -3323,6 +3323,23 @@ coerce_array (struct value *arg)
} }
/* Return the return value convention that will be used for the
specified type. */
enum return_value_convention
struct_return_convention (struct gdbarch *gdbarch,
struct value *function, struct type *value_type)
{
enum type_code code = TYPE_CODE (value_type);
if (code == TYPE_CODE_ERROR)
error (_("Function return type unknown."));
/* Probe the architecture for the return-value convention. */
return gdbarch_return_value (gdbarch, function, value_type,
NULL, NULL, NULL);
}
/* Return true if the function returning the specified type is using /* Return true if the function returning the specified type is using
the convention of returning structures in memory (passing in the the convention of returning structures in memory (passing in the
address as a hidden first parameter). */ address as a hidden first parameter). */
@ -3331,19 +3348,12 @@ int
using_struct_return (struct gdbarch *gdbarch, using_struct_return (struct gdbarch *gdbarch,
struct value *function, struct type *value_type) struct value *function, struct type *value_type)
{ {
enum type_code code = TYPE_CODE (value_type); if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
if (code == TYPE_CODE_ERROR)
error (_("Function return type unknown."));
if (code == TYPE_CODE_VOID)
/* A void return value is never in memory. See also corresponding /* A void return value is never in memory. See also corresponding
code in "print_return_value". */ code in "print_return_value". */
return 0; return 0;
/* Probe the architecture for the return-value convention. */ return (struct_return_convention (gdbarch, function, value_type)
return (gdbarch_return_value (gdbarch, function, value_type,
NULL, NULL, NULL)
!= RETURN_VALUE_REGISTER_CONVENTION); != RETURN_VALUE_REGISTER_CONVENTION);
} }

View file

@ -696,6 +696,10 @@ extern int value_in (struct value *element, struct value *set);
extern int value_bit_index (struct type *type, const gdb_byte *addr, extern int value_bit_index (struct type *type, const gdb_byte *addr,
int index); int index);
extern enum return_value_convention
struct_return_convention (struct gdbarch *gdbarch, struct value *function,
struct type *value_type);
extern int using_struct_return (struct gdbarch *gdbarch, extern int using_struct_return (struct gdbarch *gdbarch,
struct value *function, struct value *function,
struct type *value_type); struct type *value_type);