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:
Tom Tromey
2022-09-07 09:52:44 -06:00
parent 5cb0f2d5b6
commit 911627e7b1
7 changed files with 91 additions and 89 deletions

View File

@@ -2334,6 +2334,9 @@ aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type)
int elements; int elements;
struct type *fundamental_type; struct type *fundamental_type;
if (TYPE_HAS_DYNAMIC_LENGTH (type))
return 1;
if (aapcs_is_vfp_call_or_return_candidate (type, &elements, if (aapcs_is_vfp_call_or_return_candidate (type, &elements,
&fundamental_type)) &fundamental_type))
{ {
@@ -2448,13 +2451,6 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
struct type *valtype, struct regcache *regcache, struct type *valtype, struct regcache *regcache,
struct value **read_value, const gdb_byte *writebuf) 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 if (valtype->code () == TYPE_CODE_STRUCT
|| valtype->code () == TYPE_CODE_UNION || valtype->code () == TYPE_CODE_UNION
|| valtype->code () == TYPE_CODE_ARRAY) || 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"); aarch64_debug_printf ("return value in memory");
if (readbuf) if (read_value != nullptr)
{ {
CORE_ADDR addr; CORE_ADDR addr;
regcache->cooked_read (AARCH64_STRUCT_RETURN_REGNUM, &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; return RETURN_VALUE_ABI_RETURNS_ADDRESS;
@@ -2485,8 +2481,12 @@ aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value,
if (writebuf) if (writebuf)
aarch64_store_return_value (valtype, regcache, writebuf); aarch64_store_return_value (valtype, regcache, writebuf);
if (readbuf) if (read_value)
aarch64_extract_return_value (valtype, regcache, readbuf); {
*read_value = allocate_value (valtype);
aarch64_extract_return_value (valtype, regcache,
value_contents_raw (*read_value).data ());
}
aarch64_debug_printf ("return value in registers"); aarch64_debug_printf ("return value in registers");

View File

@@ -801,13 +801,6 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
gdb_assert (!(read_value && writebuf)); 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. */ /* 1. Classify the return type with the classification algorithm. */
amd64_classify (type, theclass); 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 can always find the return value just after the function has
returned. */ returned. */
if (readbuf) if (read_value != nullptr)
{ {
ULONGEST addr; ULONGEST addr;
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &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; 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 /* 8. If the class is COMPLEX_X87, the real part of the value is
returned in %st0 and the imaginary part in %st1. */ returned in %st0 and the imaginary part in %st1. */
if (theclass[0] == AMD64_COMPLEX_X87) if (theclass[0] == AMD64_COMPLEX_X87)

View File

@@ -360,13 +360,6 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
int len = type->length (); int len = type->length ();
int regnum = -1; 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 /* See if our value is returned through a register. If it is, then
store the associated register number in REGNUM. */ store the associated register number in REGNUM. */
switch (type->code ()) switch (type->code ())
@@ -401,20 +394,24 @@ amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
if (regnum < 0) if (regnum < 0)
{ {
/* RAX contains the address where the return value has been stored. */ /* RAX contains the address where the return value has been stored. */
if (readbuf) if (read_value != nullptr)
{ {
ULONGEST addr; ULONGEST addr;
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &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; return RETURN_VALUE_ABI_RETURNS_ADDRESS;
} }
else else
{ {
/* Extract the return value from the register where it was stored. */ /* Extract the return value from the register where it was stored. */
if (readbuf) if (read_value != nullptr)
regcache->raw_read_part (regnum, 0, len, readbuf); {
*read_value = allocate_value (type);
regcache->raw_read_part (regnum, 0, len,
value_contents_raw (*read_value).data ());
}
if (writebuf) if (writebuf)
regcache->raw_write_part (regnum, 0, len, writebuf); regcache->raw_write_part (regnum, 0, len, writebuf);
return RETURN_VALUE_REGISTER_CONVENTION; return RETURN_VALUE_REGISTER_CONVENTION;

View File

@@ -8939,6 +8939,9 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
&& TYPE_CODE_ARRAY != code && TYPE_CODE_COMPLEX != code) && TYPE_CODE_ARRAY != code && TYPE_CODE_COMPLEX != code)
return 0; return 0;
if (TYPE_HAS_DYNAMIC_LENGTH (type))
return 1;
if (TYPE_CODE_ARRAY == code && type->is_vector ()) if (TYPE_CODE_ARRAY == code && type->is_vector ())
{ {
/* Vector values should be returned using ARM registers if they /* 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 type *valtype, struct regcache *regcache,
struct value **read_value, const gdb_byte *writebuf) 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); arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
struct type *func_type = function ? value_type (function) : NULL; struct type *func_type = function ? value_type (function) : NULL;
enum arm_vfp_cprc_base_type vfp_base_type; 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 reg_char = arm_vfp_cprc_reg_char (vfp_base_type);
int unit_length = arm_vfp_cprc_unit_length (vfp_base_type); int unit_length = arm_vfp_cprc_unit_length (vfp_base_type);
int i; 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++) for (i = 0; i < vfp_base_count; i++)
{ {
if (reg_char == 'q') if (reg_char == 'q')
@@ -9209,12 +9213,12 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
if (tdep->struct_return == pcc_struct_return if (tdep->struct_return == pcc_struct_return
|| arm_return_in_memory (gdbarch, valtype)) || arm_return_in_memory (gdbarch, valtype))
{ {
if (readbuf) if (read_value != nullptr)
{ {
CORE_ADDR addr; CORE_ADDR addr;
regcache->cooked_read (ARM_A1_REGNUM, &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; return RETURN_VALUE_ABI_RETURNS_ADDRESS;
} }
@@ -9228,8 +9232,12 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
if (writebuf) if (writebuf)
arm_store_return_value (valtype, regcache, writebuf); arm_store_return_value (valtype, regcache, writebuf);
if (readbuf) if (read_value != nullptr)
arm_extract_return_value (valtype, regcache, readbuf); {
*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; return RETURN_VALUE_REGISTER_CONVENTION;
} }

View File

@@ -3006,7 +3006,8 @@ i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
if (struct_convention == pcc_struct_convention if (struct_convention == pcc_struct_convention
|| (struct_convention == default_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; return 0;
/* Structures consisting of a single `float', `double' or 'long /* 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 (); 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 if (((code == TYPE_CODE_STRUCT
|| code == TYPE_CODE_UNION || code == TYPE_CODE_UNION
|| code == TYPE_CODE_ARRAY) || 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 a record, so the convention applied to records also applies
to arrays. */ to arrays. */
if (readbuf) if (read_value != nullptr)
{ {
ULONGEST addr; ULONGEST addr;
regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &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; return RETURN_VALUE_ABI_RETURNS_ADDRESS;
@@ -3097,8 +3091,12 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function,
return result; return result;
} }
if (readbuf) if (read_value != nullptr)
i386_extract_return_value (gdbarch, type, regcache, readbuf); {
*read_value = allocate_value (type);
i386_extract_return_value (gdbarch, type, regcache,
value_contents_raw (*read_value).data ());
}
if (writebuf) if (writebuf)
i386_store_return_value (gdbarch, type, regcache, writebuf); i386_store_return_value (gdbarch, type, regcache, writebuf);

View File

@@ -2492,7 +2492,8 @@ static void
riscv_call_arg_scalar_int (struct riscv_arg_info *ainfo, riscv_call_arg_scalar_int (struct riscv_arg_info *ainfo,
struct riscv_call_info *cinfo) 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. */ /* Argument is going to be passed by reference. */
ainfo->argloc[0].loc_type ainfo->argloc[0].loc_type
@@ -2910,8 +2911,12 @@ riscv_arg_location (struct gdbarch *gdbarch,
break; break;
case TYPE_CODE_STRUCT: case TYPE_CODE_STRUCT:
riscv_call_arg_struct (ainfo, cinfo); if (!TYPE_HAS_DYNAMIC_LENGTH (ainfo->type))
break; {
riscv_call_arg_struct (ainfo, cinfo);
break;
}
/* FALLTHROUGH */
default: default:
riscv_call_arg_scalar_int (ainfo, cinfo); riscv_call_arg_scalar_int (ainfo, cinfo);
@@ -3228,13 +3233,6 @@ riscv_return_value (struct gdbarch *gdbarch,
struct riscv_arg_info info; struct riscv_arg_info info;
struct type *arg_type; 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); arg_type = check_typedef (type);
riscv_arg_location (gdbarch, &info, &call_info, arg_type, false); 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"); gdb_printf (gdb_stdlog, "\n");
} }
if (readbuf != nullptr || writebuf != nullptr) if (read_value != nullptr || writebuf != nullptr)
{ {
unsigned int arg_len; unsigned int arg_len;
struct value *abi_val; struct value *abi_val;
gdb_byte *old_readbuf = nullptr; gdb_byte *readbuf = nullptr;
int regnum; int regnum;
/* We only do one thing at a time. */ /* 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, /* 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 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 else
{ {
abi_val = allocate_value (info.type); abi_val = allocate_value (info.type);
old_readbuf = readbuf;
readbuf = value_contents_raw (abi_val).data (); readbuf = value_contents_raw (abi_val).data ();
} }
arg_len = info.type->length (); arg_len = info.type->length ();
@@ -3375,8 +3372,17 @@ riscv_return_value (struct gdbarch *gdbarch,
regcache_cooked_read_unsigned (regcache, RISCV_A0_REGNUM, regcache_cooked_read_unsigned (regcache, RISCV_A0_REGNUM,
&addr); &addr);
if (readbuf != nullptr) if (read_value != nullptr)
read_memory (addr, readbuf, info.length); {
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) if (writebuf != nullptr)
write_memory (addr, writebuf, info.length); 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 /* This completes the cast from abi type back to the declared type
in the case that we are reading from the machine. See the in the case that we are reading from the machine. See the
comment at the head of this block for more details. */ 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)) if (is_fixed_point_type (arg_type))
{ {
/* Convert abi_val to the actual return type, but /* 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), unscaled.read (value_contents (abi_val),
type_byte_order (info.type), type_byte_order (info.type),
info.type->is_unsigned ()); info.type->is_unsigned ());
arg_val = allocate_value (arg_type); *read_value = allocate_value (arg_type);
unscaled.write (value_contents_raw (arg_val), unscaled.write (value_contents_raw (*read_value),
type_byte_order (arg_type), type_byte_order (arg_type),
arg_type->is_unsigned ()); arg_type->is_unsigned ());
} }
else else
arg_val = value_cast (arg_type, abi_val); *read_value = value_cast (arg_type, abi_val);
memcpy (old_readbuf, value_contents_raw (arg_val).data (),
arg_type->length ());
} }
} }

View File

@@ -1500,13 +1500,6 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
{ {
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 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 /* The psABI says that "...every stack frame reserves the word at
%fp+64. If a function returns a structure, union, or %fp+64. If a function returns a structure, union, or
quad-precision value, this word should hold the address of the 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; ULONGEST sp;
CORE_ADDR addr; CORE_ADDR addr;
if (readbuf) if (read_value != nullptr)
{ {
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 ()); *read_value = value_at_non_lval (type, addr);
} }
if (writebuf) if (writebuf)
{ {
@@ -1535,8 +1528,12 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
return RETURN_VALUE_ABI_PRESERVES_ADDRESS; return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
} }
if (readbuf) if (read_value != nullptr)
sparc32_extract_return_value (type, regcache, readbuf); {
*read_value = allocate_value (type);
gdb_byte *readbuf = value_contents_raw (*read_value).data ();
sparc32_extract_return_value (type, regcache, readbuf);
}
if (writebuf) if (writebuf)
sparc32_store_return_value (type, regcache, writebuf); sparc32_store_return_value (type, regcache, writebuf);