[PATCH] [gdb/tdep] Fix gdb.base/finish-pretty.exp on s390x
Andreas Arnez
arnez@linux.ibm.com
Tue Dec 17 18:49:24 GMT 2024
Hello Tom,
On Fri, Dec 06 2024, Tom de Vries wrote:
> On s390x-linux, with test-case gdb.base/finish-pretty.exp I ran into:
> ...
> (gdb) finish
> Run till exit from #0 foo () at finish-pretty.c:28
> main () at finish-pretty.c:40
> 40 return v.a + v.b;
> Value returned has type: struct s. Cannot determine contents
> (gdb) FAIL: $exp: finish foo prettyprinted function result
> ...
>
> The function being finished is foo, which returns a value of type struct s.
>
> The ABI [1] specifies:
> - that the value is returned in a storage buffer allocated by the caller, and
> - that the address of this buffer is passed as a hidden argument in r2.
>
> GDB fails to print the value when finishing foo, because it doesn't know the
> address of the buffer.
>
> Implement the gdbarch_get_return_buf_addr hook for s390x to fix this.
That's fantastic! Thanks for doing this!
> This is based on ppc_sysv_get_return_buf_addr, the only other implementation
> of gdbarch_get_return_buf_addr. For readability I've factored out
> dwarf_reg_on_entry.
>
> There is one difference with ppc_sysv_get_return_buf_addr: only
> NO_ENTRY_VALUE_ERROR is caught. If this patch is approved, I intend to submit
> a follow-up patch to fix this in ppc_sysv_get_return_buf_addr as well.
>
> The hook is not guaranteed to work, because it attempts to get the value r2
> had at function entry.
>
> The hook can be called after function entry, and the ABI doesn't guarantee
> that r2 is the same throughout the function.
>
> Using -fvar-tracking adds debug information, which allows the hook to succeed
> more often, and indeed after adding this to the test-case, it passes.
OK. I think that's acceptable.
> Do likewise in one more test-case.
>
> Tested on s390x-linux.
>
> Fixes:
> - gdb.ada/finish-large.exp
> - gdb.base/finish-pretty.exp
> - gdb.base/retval-large-struct.exp
> - gdb.cp/non-trivial-retval.exp
> - gdb.ada/array_return.exp
>
> AFAICT, I've also enabled the hook for s390 and from the ABI [1] I get the
> impression that it should work, but I haven't been able to test it.
That's perfectly fine. Establishing a test environment for s390 has
become increasingly difficult.
> [1] https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html
Please use the updated version of the s390x ABI:
https://github.com/IBM/s390x-abi
It contains various fixes, as well as some new stuff like vector
registers.
> [2] https://uclibc.org/docs/psABI-s390.pdf
For that one no updated PDF is published. It can be built from the new
sources, if needed.
> ---
> gdb/s390-tdep.c | 58 ++++++++++++++++++++++++
> gdb/testsuite/gdb.ada/array_return.exp | 8 +++-
> gdb/testsuite/gdb.base/finish-pretty.exp | 8 +++-
> 3 files changed, 72 insertions(+), 2 deletions(-)
>
> diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
> index be176f07c6f..3c4ae5abdb3 100644
> --- a/gdb/s390-tdep.c
> +++ b/gdb/s390-tdep.c
> @@ -40,6 +40,7 @@
> #include "trad-frame.h"
> #include "value.h"
> #include "inferior.h"
> +#include "dwarf2/loc.h"
>
> #include "features/s390-linux32.c"
> #include "features/s390x-linux64.c"
> @@ -2119,6 +2120,62 @@ s390_return_value (struct gdbarch *gdbarch, struct value *function,
> return rvc;
> }
>
> +/* Try to get the value of DWARF_REG in FRAME at function entry. If successful,
> + return it as value of type VAL_TYPE. */
> +
> +static struct value *
> +dwarf_reg_on_entry (int dwarf_reg, struct type *val_type,
> + const frame_info_ptr &frame)
> +{
> + enum call_site_parameter_kind kind = CALL_SITE_PARAMETER_DWARF_REG;
> + union call_site_parameter_u kind_u = { .dwarf_reg = dwarf_reg };
> +
> + try
> + {
> + return value_of_dwarf_reg_entry (val_type, frame, kind, kind_u);
> + }
> + catch (const gdb_exception_error &e)
> + {
> + if (e.error == NO_ENTRY_VALUE_ERROR)
> + return nullptr;
> +
> + throw;
> + }
> +}
I like factoring this out. It seems that this wrapper is only needed
because value_of_dwarf_reg_entry() has an unusable interface. Maybe we
want to fix that in the long run?
> +
> +/* Both the 32-bit and 64-bit ABIs specify that values of some types are
> + returned in a storage buffer provided by the caller. Return the address of
> + that storage buffer, if possible. Implements the
> + gdbarch_get_return_buf_addr hook. */
> +
> +static CORE_ADDR
> +s390_get_return_buf_addr (struct type *val_type,
> + const frame_info_ptr &cur_frame)
> +{
> + /* The address of the storage buffer is provided as a hidden argument in
> + register r2. */
> + int dwarf_reg = 2;
> +
> + /* The ABI does not guarantee that the register will not be changed while
> + executing the function. Hence, it cannot be assumed that it will still
> + contain the address of the storage buffer when execution reaches the end
> + of the function.
> +
> + Attempt to determine the value on entry using the DW_OP_entry_value DWARF
> + entries. This requires compiling the user program with -fvar-tracking. */
> + struct value *val_on_entry
> + = dwarf_reg_on_entry (dwarf_reg, lookup_pointer_type (val_type), cur_frame);
> +
> + if (val_on_entry == nullptr)
> + {
> + warning ("Cannot determine the function return value.\n"
> + "Try compiling with -fvar-tracking.");
> + return 0;
> + }
> +
> + return value_as_address (val_on_entry);
> +}
> +
> /* Frame unwinding. */
>
> /* Implement the stack_frame_destroyed_p gdbarch method. */
> @@ -7183,6 +7240,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> set_gdbarch_dummy_id (gdbarch, s390_dummy_id);
> set_gdbarch_frame_align (gdbarch, s390_frame_align);
> set_gdbarch_return_value (gdbarch, s390_return_value);
> + set_gdbarch_get_return_buf_addr (gdbarch, s390_get_return_buf_addr);
>
> /* Frame handling. */
> /* Stack grows downward. */
> diff --git a/gdb/testsuite/gdb.ada/array_return.exp b/gdb/testsuite/gdb.ada/array_return.exp
> index c6edee11f17..d1fc2ac2c98 100644
> --- a/gdb/testsuite/gdb.ada/array_return.exp
> +++ b/gdb/testsuite/gdb.ada/array_return.exp
> @@ -19,7 +19,13 @@ require allow_ada_tests
>
> standard_ada_testfile p
>
> -if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
> +set opts {}
> +lappend opts debug
> +if { [have_fvar_tracking] } {
> + lappend opts "additional_flags=-fvar-tracking"
> +}
> +
> +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $opts] != ""} {
> return -1
> }
>
> diff --git a/gdb/testsuite/gdb.base/finish-pretty.exp b/gdb/testsuite/gdb.base/finish-pretty.exp
> index 44f3340f41c..0b6bea6681d 100644
> --- a/gdb/testsuite/gdb.base/finish-pretty.exp
> +++ b/gdb/testsuite/gdb.base/finish-pretty.exp
> @@ -18,7 +18,13 @@
>
> standard_testfile
>
> -if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } {
> +set opts {}
> +lappend opts debug
> +if { [have_fvar_tracking] } {
> + lappend opts "additional_flags=-fvar-tracking"
> +}
> +
> +if { [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] } {
> return -1
> }
>
>
> base-commit: a3011beced048e66d200921b2a11c836fae31abf
LGTM. We might still need someone to approve the changes to the test
cases, though.
--
Andreas
More information about the Gdb-patches
mailing list