forked from Imagelibrary/binutils-gdb
Fix inferior calls with variably-sized return type
This patch updates the gdbarch_return_value_as_value implementations to work correctly with variably-sized return types.
This commit is contained in:
@@ -2334,6 +2334,9 @@ aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type)
|
||||
int elements;
|
||||
struct type *fundamental_type;
|
||||
|
||||
if (TYPE_HAS_DYNAMIC_LENGTH (type))
|
||||
return 1;
|
||||
|
||||
if (aapcs_is_vfp_call_or_return_candidate (type, &elements,
|
||||
&fundamental_type))
|
||||
{
|
||||
@@ -2448,13 +2451,6 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
|
||||
struct type *valtype, struct regcache *regcache,
|
||||
struct value **read_value, const gdb_byte *writebuf)
|
||||
{
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (valtype);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
if (valtype->code () == TYPE_CODE_STRUCT
|
||||
|| valtype->code () == TYPE_CODE_UNION
|
||||
|| valtype->code () == TYPE_CODE_ARRAY)
|
||||
@@ -2470,12 +2466,12 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
|
||||
|
||||
aarch64_debug_printf ("return value in memory");
|
||||
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
|
||||
regcache->cooked_read (AARCH64_STRUCT_RETURN_REGNUM, &addr);
|
||||
read_memory (addr, readbuf, valtype->length ());
|
||||
*read_value = value_at_non_lval (valtype, addr);
|
||||
}
|
||||
|
||||
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
|
||||
@@ -2485,8 +2481,12 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
|
||||
if (writebuf)
|
||||
aarch64_store_return_value (valtype, regcache, writebuf);
|
||||
|
||||
if (readbuf)
|
||||
aarch64_extract_return_value (valtype, regcache, readbuf);
|
||||
if (read_value)
|
||||
{
|
||||
*read_value = allocate_value (valtype);
|
||||
aarch64_extract_return_value (valtype, regcache,
|
||||
value_contents_raw (*read_value).data ());
|
||||
}
|
||||
|
||||
aarch64_debug_printf ("return value in registers");
|
||||
|
||||
|
||||
@@ -801,13 +801,6 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
|
||||
gdb_assert (!(read_value && writebuf));
|
||||
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
/* 1. Classify the return type with the classification algorithm. */
|
||||
amd64_classify (type, theclass);
|
||||
|
||||
@@ -824,17 +817,24 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
can always find the return value just after the function has
|
||||
returned. */
|
||||
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
ULONGEST addr;
|
||||
|
||||
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
|
||||
read_memory (addr, readbuf, type->length ());
|
||||
*read_value = value_at_non_lval (type, addr);
|
||||
}
|
||||
|
||||
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
|
||||
}
|
||||
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
/* 8. If the class is COMPLEX_X87, the real part of the value is
|
||||
returned in %st0 and the imaginary part in %st1. */
|
||||
if (theclass[0] == AMD64_COMPLEX_X87)
|
||||
|
||||
@@ -360,13 +360,6 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
int len = type->length ();
|
||||
int regnum = -1;
|
||||
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
/* See if our value is returned through a register. If it is, then
|
||||
store the associated register number in REGNUM. */
|
||||
switch (type->code ())
|
||||
@@ -401,20 +394,24 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
if (regnum < 0)
|
||||
{
|
||||
/* RAX contains the address where the return value has been stored. */
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
ULONGEST addr;
|
||||
|
||||
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
|
||||
read_memory (addr, readbuf, type->length ());
|
||||
*read_value = value_at_non_lval (type, addr);
|
||||
}
|
||||
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Extract the return value from the register where it was stored. */
|
||||
if (readbuf)
|
||||
regcache->raw_read_part (regnum, 0, len, readbuf);
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
regcache->raw_read_part (regnum, 0, len,
|
||||
value_contents_raw (*read_value).data ());
|
||||
}
|
||||
if (writebuf)
|
||||
regcache->raw_write_part (regnum, 0, len, writebuf);
|
||||
return RETURN_VALUE_REGISTER_CONVENTION;
|
||||
|
||||
@@ -8939,6 +8939,9 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
|
||||
&& TYPE_CODE_ARRAY != code && TYPE_CODE_COMPLEX != code)
|
||||
return 0;
|
||||
|
||||
if (TYPE_HAS_DYNAMIC_LENGTH (type))
|
||||
return 1;
|
||||
|
||||
if (TYPE_CODE_ARRAY == code && type->is_vector ())
|
||||
{
|
||||
/* Vector values should be returned using ARM registers if they
|
||||
@@ -9140,13 +9143,6 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
struct type *valtype, struct regcache *regcache,
|
||||
struct value **read_value, const gdb_byte *writebuf)
|
||||
{
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (valtype);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
|
||||
struct type *func_type = function ? value_type (function) : NULL;
|
||||
enum arm_vfp_cprc_base_type vfp_base_type;
|
||||
@@ -9158,6 +9154,14 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
int reg_char = arm_vfp_cprc_reg_char (vfp_base_type);
|
||||
int unit_length = arm_vfp_cprc_unit_length (vfp_base_type);
|
||||
int i;
|
||||
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (valtype);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
for (i = 0; i < vfp_base_count; i++)
|
||||
{
|
||||
if (reg_char == 'q')
|
||||
@@ -9209,12 +9213,12 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
if (tdep->struct_return == pcc_struct_return
|
||||
|| arm_return_in_memory (gdbarch, valtype))
|
||||
{
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
|
||||
regcache->cooked_read (ARM_A1_REGNUM, &addr);
|
||||
read_memory (addr, readbuf, valtype->length ());
|
||||
*read_value = value_at_non_lval (valtype, addr);
|
||||
}
|
||||
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
|
||||
}
|
||||
@@ -9228,8 +9232,12 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
if (writebuf)
|
||||
arm_store_return_value (valtype, regcache, writebuf);
|
||||
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (valtype);
|
||||
gdb_byte *readbuf = value_contents_raw (*read_value).data ();
|
||||
arm_extract_return_value (valtype, regcache, readbuf);
|
||||
}
|
||||
|
||||
return RETURN_VALUE_REGISTER_CONVENTION;
|
||||
}
|
||||
|
||||
@@ -3006,7 +3006,8 @@ i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
|
||||
|
||||
if (struct_convention == pcc_struct_convention
|
||||
|| (struct_convention == default_struct_convention
|
||||
&& tdep->struct_return == pcc_struct_return))
|
||||
&& tdep->struct_return == pcc_struct_return)
|
||||
|| TYPE_HAS_DYNAMIC_LENGTH (type))
|
||||
return 0;
|
||||
|
||||
/* Structures consisting of a single `float', `double' or 'long
|
||||
@@ -3034,13 +3035,6 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
{
|
||||
enum type_code code = type->code ();
|
||||
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
if (((code == TYPE_CODE_STRUCT
|
||||
|| code == TYPE_CODE_UNION
|
||||
|| code == TYPE_CODE_ARRAY)
|
||||
@@ -3068,12 +3062,12 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
a record, so the convention applied to records also applies
|
||||
to arrays. */
|
||||
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
ULONGEST addr;
|
||||
|
||||
regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr);
|
||||
read_memory (addr, readbuf, type->length ());
|
||||
*read_value = value_at_non_lval (type, addr);
|
||||
}
|
||||
|
||||
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
|
||||
@@ -3097,8 +3091,12 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
return result;
|
||||
}
|
||||
|
||||
if (readbuf)
|
||||
i386_extract_return_value (gdbarch, type, regcache, readbuf);
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
i386_extract_return_value (gdbarch, type, regcache,
|
||||
value_contents_raw (*read_value).data ());
|
||||
}
|
||||
if (writebuf)
|
||||
i386_store_return_value (gdbarch, type, regcache, writebuf);
|
||||
|
||||
|
||||
@@ -2492,7 +2492,8 @@ static void
|
||||
riscv_call_arg_scalar_int (struct riscv_arg_info *ainfo,
|
||||
struct riscv_call_info *cinfo)
|
||||
{
|
||||
if (ainfo->length > (2 * cinfo->xlen))
|
||||
if (TYPE_HAS_DYNAMIC_LENGTH (ainfo->type)
|
||||
|| ainfo->length > (2 * cinfo->xlen))
|
||||
{
|
||||
/* Argument is going to be passed by reference. */
|
||||
ainfo->argloc[0].loc_type
|
||||
@@ -2910,8 +2911,12 @@ riscv_arg_location (struct gdbarch *gdbarch,
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (!TYPE_HAS_DYNAMIC_LENGTH (ainfo->type))
|
||||
{
|
||||
riscv_call_arg_struct (ainfo, cinfo);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
riscv_call_arg_scalar_int (ainfo, cinfo);
|
||||
@@ -3228,13 +3233,6 @@ riscv_return_value (struct gdbarch *gdbarch,
|
||||
struct riscv_arg_info info;
|
||||
struct type *arg_type;
|
||||
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
arg_type = check_typedef (type);
|
||||
riscv_arg_location (gdbarch, &info, &call_info, arg_type, false);
|
||||
|
||||
@@ -3246,15 +3244,15 @@ riscv_return_value (struct gdbarch *gdbarch,
|
||||
gdb_printf (gdb_stdlog, "\n");
|
||||
}
|
||||
|
||||
if (readbuf != nullptr || writebuf != nullptr)
|
||||
if (read_value != nullptr || writebuf != nullptr)
|
||||
{
|
||||
unsigned int arg_len;
|
||||
struct value *abi_val;
|
||||
gdb_byte *old_readbuf = nullptr;
|
||||
gdb_byte *readbuf = nullptr;
|
||||
int regnum;
|
||||
|
||||
/* We only do one thing at a time. */
|
||||
gdb_assert (readbuf == nullptr || writebuf == nullptr);
|
||||
gdb_assert (read_value == nullptr || writebuf == nullptr);
|
||||
|
||||
/* In some cases the argument is not returned as the declared type,
|
||||
and we need to cast to or from the ABI type in order to
|
||||
@@ -3295,7 +3293,6 @@ riscv_return_value (struct gdbarch *gdbarch,
|
||||
else
|
||||
{
|
||||
abi_val = allocate_value (info.type);
|
||||
old_readbuf = readbuf;
|
||||
readbuf = value_contents_raw (abi_val).data ();
|
||||
}
|
||||
arg_len = info.type->length ();
|
||||
@@ -3375,8 +3372,17 @@ riscv_return_value (struct gdbarch *gdbarch,
|
||||
|
||||
regcache_cooked_read_unsigned (regcache, RISCV_A0_REGNUM,
|
||||
&addr);
|
||||
if (readbuf != nullptr)
|
||||
read_memory (addr, readbuf, info.length);
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
abi_val = value_at_non_lval (type, addr);
|
||||
/* Also reset the expected type, so that the cast
|
||||
later on is a no-op. If the cast is not a no-op,
|
||||
and if the return type is variably-sized, then the
|
||||
type of ABI_VAL will differ from ARG_TYPE due to
|
||||
dynamic type resolution, and so will most likely
|
||||
fail. */
|
||||
arg_type = value_type (abi_val);
|
||||
}
|
||||
if (writebuf != nullptr)
|
||||
write_memory (addr, writebuf, info.length);
|
||||
}
|
||||
@@ -3391,10 +3397,8 @@ riscv_return_value (struct gdbarch *gdbarch,
|
||||
/* This completes the cast from abi type back to the declared type
|
||||
in the case that we are reading from the machine. See the
|
||||
comment at the head of this block for more details. */
|
||||
if (readbuf != nullptr)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
struct value *arg_val;
|
||||
|
||||
if (is_fixed_point_type (arg_type))
|
||||
{
|
||||
/* Convert abi_val to the actual return type, but
|
||||
@@ -3405,15 +3409,13 @@ riscv_return_value (struct gdbarch *gdbarch,
|
||||
unscaled.read (value_contents (abi_val),
|
||||
type_byte_order (info.type),
|
||||
info.type->is_unsigned ());
|
||||
arg_val = allocate_value (arg_type);
|
||||
unscaled.write (value_contents_raw (arg_val),
|
||||
*read_value = allocate_value (arg_type);
|
||||
unscaled.write (value_contents_raw (*read_value),
|
||||
type_byte_order (arg_type),
|
||||
arg_type->is_unsigned ());
|
||||
}
|
||||
else
|
||||
arg_val = value_cast (arg_type, abi_val);
|
||||
memcpy (old_readbuf, value_contents_raw (arg_val).data (),
|
||||
arg_type->length ());
|
||||
*read_value = value_cast (arg_type, abi_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1500,13 +1500,6 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
|
||||
gdb_byte *readbuf = nullptr;
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
readbuf = value_contents_raw (*read_value).data ();
|
||||
}
|
||||
|
||||
/* The psABI says that "...every stack frame reserves the word at
|
||||
%fp+64. If a function returns a structure, union, or
|
||||
quad-precision value, this word should hold the address of the
|
||||
@@ -1519,11 +1512,11 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
ULONGEST sp;
|
||||
CORE_ADDR addr;
|
||||
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
|
||||
addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
|
||||
read_memory (addr, readbuf, type->length ());
|
||||
*read_value = value_at_non_lval (type, addr);
|
||||
}
|
||||
if (writebuf)
|
||||
{
|
||||
@@ -1535,8 +1528,12 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||
return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
|
||||
}
|
||||
|
||||
if (readbuf)
|
||||
if (read_value != nullptr)
|
||||
{
|
||||
*read_value = allocate_value (type);
|
||||
gdb_byte *readbuf = value_contents_raw (*read_value).data ();
|
||||
sparc32_extract_return_value (type, regcache, readbuf);
|
||||
}
|
||||
if (writebuf)
|
||||
sparc32_store_return_value (type, regcache, writebuf);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user