aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/s390-tdep.c58
-rw-r--r--gdb/testsuite/gdb.ada/array_return.exp8
-rw-r--r--gdb/testsuite/gdb.base/finish-pretty.exp8
3 files changed, 72 insertions, 2 deletions
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index d4b9a24..3a672b3 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;
+ }
+}
+
+/* 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. */
@@ -7197,6 +7254,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 c6edee1..d1fc2ac 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 44f3340..0b6bea6 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
}