From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2126) id AEA043858C83; Tue, 3 Jan 2023 16:44:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AEA043858C83 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1672764292; bh=xuqGjU2nWNNdmBnlGLAKa1WSBryQru5JX/esbyX9g/U=; h=From:To:Subject:Date:From; b=JGAwdBDoNhUKQ114ICiqz6Tvi6+AsijVic5iw6jWjAXkzWYQRqXZ1q6Les9LUi12k 6AD9tDUVtJ9z+kjVhz2X3FcZlPphuZH1og50xeg2MWzaUDuMSjEsCSLYpaQZGkXgf7 wJUqhAf0b6U371b5jBbfUzcYA53IzUzhZG/dRxKU= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom Tromey To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Fix inferior calls with variably-sized return type X-Act-Checkin: binutils-gdb X-Git-Author: Tom Tromey X-Git-Refname: refs/heads/master X-Git-Oldrev: 5cb0f2d5b67ce2b4f60d5ad0b0a26ef918e8244f X-Git-Newrev: 911627e7b1bc682a18ac5a976eb33cd87d73578f Message-Id: <20230103164452.AEA043858C83@sourceware.org> Date: Tue, 3 Jan 2023 16:44:52 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D911627e7b1bc= 682a18ac5a976eb33cd87d73578f commit 911627e7b1bc682a18ac5a976eb33cd87d73578f Author: Tom Tromey Date: Wed Sep 7 09:52:44 2022 -0600 Fix inferior calls with variably-sized return type =20 This patch updates the gdbarch_return_value_as_value implementations to work correctly with variably-sized return types. Diff: --- gdb/aarch64-tdep.c | 22 ++++++++++----------- gdb/amd64-tdep.c | 18 ++++++++--------- gdb/amd64-windows-tdep.c | 19 ++++++++---------- gdb/arm-tdep.c | 30 ++++++++++++++++++----------- gdb/i386-tdep.c | 22 ++++++++++----------- gdb/riscv-tdep.c | 50 +++++++++++++++++++++++++-------------------= ---- gdb/sparc-tdep.c | 19 ++++++++---------- 7 files changed, 91 insertions(+), 89 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 0371387ac78..6345cc1aac2 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -2334,6 +2334,9 @@ aarch64_return_in_memory (struct gdbarch *gdbarch, st= ruct type *type) int elements; struct type *fundamental_type; =20 + 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, struc= t value *func_value, struct type *valtype, struct regcache *regcache, struct value **read_value, const gdb_byte *writebuf) { - gdb_byte *readbuf =3D nullptr; - if (read_value !=3D nullptr) - { - *read_value =3D allocate_value (valtype); - readbuf =3D value_contents_raw (*read_value).data (); - } - if (valtype->code () =3D=3D TYPE_CODE_STRUCT || valtype->code () =3D=3D TYPE_CODE_UNION || valtype->code () =3D=3D TYPE_CODE_ARRAY) @@ -2470,12 +2466,12 @@ aarch64_return_value (struct gdbarch *gdbarch, stru= ct value *func_value, =20 aarch64_debug_printf ("return value in memory"); =20 - if (readbuf) + if (read_value !=3D nullptr) { CORE_ADDR addr; =20 regcache->cooked_read (AARCH64_STRUCT_RETURN_REGNUM, &addr); - read_memory (addr, readbuf, valtype->length ()); + *read_value =3D value_at_non_lval (valtype, addr); } =20 return RETURN_VALUE_ABI_RETURNS_ADDRESS; @@ -2485,8 +2481,12 @@ aarch64_return_value (struct gdbarch *gdbarch, struc= t value *func_value, if (writebuf) aarch64_store_return_value (valtype, regcache, writebuf); =20 - if (readbuf) - aarch64_extract_return_value (valtype, regcache, readbuf); + if (read_value) + { + *read_value =3D allocate_value (valtype); + aarch64_extract_return_value (valtype, regcache, + value_contents_raw (*read_value).data ()); + } =20 aarch64_debug_printf ("return value in registers"); =20 diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 69d1f86b47a..76e843ecc35 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -801,13 +801,6 @@ amd64_return_value (struct gdbarch *gdbarch, struct va= lue *function, =20 gdb_assert (!(read_value && writebuf)); =20 - gdb_byte *readbuf =3D nullptr; - if (read_value !=3D nullptr) - { - *read_value =3D allocate_value (type); - readbuf =3D value_contents_raw (*read_value).data (); - } - /* 1. Classify the return type with the classification algorithm. */ amd64_classify (type, theclass); =20 @@ -824,17 +817,24 @@ amd64_return_value (struct gdbarch *gdbarch, struct v= alue *function, can always find the return value just after the function has returned. */ =20 - if (readbuf) + if (read_value !=3D nullptr) { ULONGEST addr; =20 regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr); - read_memory (addr, readbuf, type->length ()); + *read_value =3D value_at_non_lval (type, addr); } =20 return RETURN_VALUE_ABI_RETURNS_ADDRESS; } =20 + gdb_byte *readbuf =3D nullptr; + if (read_value !=3D nullptr) + { + *read_value =3D allocate_value (type); + readbuf =3D 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] =3D=3D AMD64_COMPLEX_X87) diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c index 6f7dbaa7002..411a6204a90 100644 --- a/gdb/amd64-windows-tdep.c +++ b/gdb/amd64-windows-tdep.c @@ -360,13 +360,6 @@ amd64_windows_return_value (struct gdbarch *gdbarch, s= truct value *function, int len =3D type->length (); int regnum =3D -1; =20 - gdb_byte *readbuf =3D nullptr; - if (read_value !=3D nullptr) - { - *read_value =3D allocate_value (type); - readbuf =3D 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 !=3D nullptr) { ULONGEST addr; =20 regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr); - read_memory (addr, readbuf, type->length ()); + *read_value =3D 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 !=3D nullptr) + { + *read_value =3D 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; diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index fa104392aec..6eb68cc1f0d 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -8939,6 +8939,9 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct= type *type) && TYPE_CODE_ARRAY !=3D code && TYPE_CODE_COMPLEX !=3D code) return 0; =20 + if (TYPE_HAS_DYNAMIC_LENGTH (type)) + return 1; + if (TYPE_CODE_ARRAY =3D=3D 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 va= lue *function, struct type *valtype, struct regcache *regcache, struct value **read_value, const gdb_byte *writebuf) { - gdb_byte *readbuf =3D nullptr; - if (read_value !=3D nullptr) - { - *read_value =3D allocate_value (valtype); - readbuf =3D value_contents_raw (*read_value).data (); - } - arm_gdbarch_tdep *tdep =3D gdbarch_tdep (gdbarch); struct type *func_type =3D 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 va= lue *function, int reg_char =3D arm_vfp_cprc_reg_char (vfp_base_type); int unit_length =3D arm_vfp_cprc_unit_length (vfp_base_type); int i; + + gdb_byte *readbuf =3D nullptr; + if (read_value !=3D nullptr) + { + *read_value =3D allocate_value (valtype); + readbuf =3D value_contents_raw (*read_value).data (); + } + for (i =3D 0; i < vfp_base_count; i++) { if (reg_char =3D=3D 'q') @@ -9209,12 +9213,12 @@ arm_return_value (struct gdbarch *gdbarch, struct v= alue *function, if (tdep->struct_return =3D=3D pcc_struct_return || arm_return_in_memory (gdbarch, valtype)) { - if (readbuf) + if (read_value !=3D nullptr) { CORE_ADDR addr; =20 regcache->cooked_read (ARM_A1_REGNUM, &addr); - read_memory (addr, readbuf, valtype->length ()); + *read_value =3D value_at_non_lval (valtype, addr); } return RETURN_VALUE_ABI_RETURNS_ADDRESS; } @@ -9228,8 +9232,12 @@ arm_return_value (struct gdbarch *gdbarch, struct va= lue *function, if (writebuf) arm_store_return_value (valtype, regcache, writebuf); =20 - if (readbuf) - arm_extract_return_value (valtype, regcache, readbuf); + if (read_value !=3D nullptr) + { + *read_value =3D allocate_value (valtype); + gdb_byte *readbuf =3D value_contents_raw (*read_value).data (); + arm_extract_return_value (valtype, regcache, readbuf); + } =20 return RETURN_VALUE_REGISTER_CONVENTION; } diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index cc41dd80864..dc3cbeda49d 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3006,7 +3006,8 @@ i386_reg_struct_return_p (struct gdbarch *gdbarch, st= ruct type *type) =20 if (struct_convention =3D=3D pcc_struct_convention || (struct_convention =3D=3D default_struct_convention - && tdep->struct_return =3D=3D pcc_struct_return)) + && tdep->struct_return =3D=3D pcc_struct_return) + || TYPE_HAS_DYNAMIC_LENGTH (type)) return 0; =20 /* Structures consisting of a single `float', `double' or 'long @@ -3034,13 +3035,6 @@ i386_return_value (struct gdbarch *gdbarch, struct v= alue *function, { enum type_code code =3D type->code (); =20 - gdb_byte *readbuf =3D nullptr; - if (read_value !=3D nullptr) - { - *read_value =3D allocate_value (type); - readbuf =3D value_contents_raw (*read_value).data (); - } - if (((code =3D=3D TYPE_CODE_STRUCT || code =3D=3D TYPE_CODE_UNION || code =3D=3D 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. */ =20 - if (readbuf) + if (read_value !=3D nullptr) { ULONGEST addr; =20 regcache_raw_read_unsigned (regcache, I386_EAX_REGNUM, &addr); - read_memory (addr, readbuf, type->length ()); + *read_value =3D value_at_non_lval (type, addr); } =20 return RETURN_VALUE_ABI_RETURNS_ADDRESS; @@ -3097,8 +3091,12 @@ i386_return_value (struct gdbarch *gdbarch, struct v= alue *function, return result; } =20 - if (readbuf) - i386_extract_return_value (gdbarch, type, regcache, readbuf); + if (read_value !=3D nullptr) + { + *read_value =3D 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); =20 diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index bfda24ab3be..83c6113de50 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -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; =20 case TYPE_CODE_STRUCT: - riscv_call_arg_struct (ainfo, cinfo); - break; + if (!TYPE_HAS_DYNAMIC_LENGTH (ainfo->type)) + { + riscv_call_arg_struct (ainfo, cinfo); + break; + } + /* FALLTHROUGH */ =20 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; =20 - gdb_byte *readbuf =3D nullptr; - if (read_value !=3D nullptr) - { - *read_value =3D allocate_value (type); - readbuf =3D value_contents_raw (*read_value).data (); - } - arg_type =3D check_typedef (type); riscv_arg_location (gdbarch, &info, &call_info, arg_type, false); =20 @@ -3246,15 +3244,15 @@ riscv_return_value (struct gdbarch *gdbarch, gdb_printf (gdb_stdlog, "\n"); } =20 - if (readbuf !=3D nullptr || writebuf !=3D nullptr) + if (read_value !=3D nullptr || writebuf !=3D nullptr) { unsigned int arg_len; struct value *abi_val; - gdb_byte *old_readbuf =3D nullptr; + gdb_byte *readbuf =3D nullptr; int regnum; =20 /* We only do one thing at a time. */ - gdb_assert (readbuf =3D=3D nullptr || writebuf =3D=3D nullptr); + gdb_assert (read_value =3D=3D nullptr || writebuf =3D=3D nullptr); =20 /* 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 =3D allocate_value (info.type); - old_readbuf =3D readbuf; readbuf =3D value_contents_raw (abi_val).data (); } arg_len =3D info.type->length (); @@ -3375,8 +3372,17 @@ riscv_return_value (struct gdbarch *gdbarch, =20 regcache_cooked_read_unsigned (regcache, RISCV_A0_REGNUM, &addr); - if (readbuf !=3D nullptr) - read_memory (addr, readbuf, info.length); + if (read_value !=3D nullptr) + { + abi_val =3D 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 =3D value_type (abi_val); + } if (writebuf !=3D 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 !=3D nullptr) + if (read_value !=3D 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 =3D allocate_value (arg_type); - unscaled.write (value_contents_raw (arg_val), + *read_value =3D allocate_value (arg_type); + unscaled.write (value_contents_raw (*read_value), type_byte_order (arg_type), arg_type->is_unsigned ()); } else - arg_val =3D value_cast (arg_type, abi_val); - memcpy (old_readbuf, value_contents_raw (arg_val).data (), - arg_type->length ()); + *read_value =3D value_cast (arg_type, abi_val); } } =20 diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 91cf391ec8a..55c84346f64 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1500,13 +1500,6 @@ sparc32_return_value (struct gdbarch *gdbarch, struc= t value *function, { enum bfd_endian byte_order =3D gdbarch_byte_order (gdbarch); =20 - gdb_byte *readbuf =3D nullptr; - if (read_value !=3D nullptr) - { - *read_value =3D allocate_value (type); - readbuf =3D 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, stru= ct value *function, ULONGEST sp; CORE_ADDR addr; =20 - if (readbuf) + if (read_value !=3D nullptr) { regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); addr =3D read_memory_unsigned_integer (sp + 64, 4, byte_order); - read_memory (addr, readbuf, type->length ()); + *read_value =3D value_at_non_lval (type, addr); } if (writebuf) { @@ -1535,8 +1528,12 @@ sparc32_return_value (struct gdbarch *gdbarch, struc= t value *function, return RETURN_VALUE_ABI_PRESERVES_ADDRESS; } =20 - if (readbuf) - sparc32_extract_return_value (type, regcache, readbuf); + if (read_value !=3D nullptr) + { + *read_value =3D allocate_value (type); + gdb_byte *readbuf =3D value_contents_raw (*read_value).data (); + sparc32_extract_return_value (type, regcache, readbuf); + } if (writebuf) sparc32_store_return_value (type, regcache, writebuf);