aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbarch.c
diff options
context:
space:
mode:
authorCarl Love <cel@us.ibm.com>2022-11-14 16:22:37 -0500
committerCarl Love <cel@us.ibm.com>2022-11-14 16:22:37 -0500
commita0eda3df5b750ae32576a9be092b361281a41787 (patch)
tree09f3ad36fb57d2277261ca2dda523ff18d85f51c /gdb/gdbarch.c
parent24b27e5e9b6bf5a37fb39dfca151722bb801cbaa (diff)
downloadgdb-a0eda3df5b750ae32576a9be092b361281a41787.zip
gdb-a0eda3df5b750ae32576a9be092b361281a41787.tar.gz
gdb-a0eda3df5b750ae32576a9be092b361281a41787.tar.bz2
PowerPC, fix support for printing the function return value for non-trivial values.
Currently, a non-trivial return value from a function cannot currently be reliably determined on PowerPC. This is due to the fact that the PowerPC ABI uses register r3 to store the address of the buffer containing the non-trivial return value when the function is called. The PowerPC ABI does not guarantee the value in register r3 is not modified in the function. Thus the value in r3 cannot be reliably used to obtain the return addreses on exit from the function. This patch adds a new gdbarch method to allow PowerPC to access the value of r3 on entry to a function. On PowerPC, the new gdbarch method attempts to use the DW_OP_entry_value for the DWARF entries, when exiting the function, to determine the value of r3 on entry to the function. This requires the use of the -fvar-tracking compiler option to compile the user application thus generating the DW_OP_entry_value in the binary. The DW_OP_entry_value entries in the binary file allows GDB to resolve the DW_TAG_call_site entries. This new gdbarch method is used to get the return buffer address, in the case of a function returning a nontrivial data type, on exit from the function. The GDB function should_stop checks to see if RETURN_BUF is non-zero. By default, RETURN_BUF will be set to zero by the new gdbarch method call for all architectures except PowerPC. The get_return_value function will be used to obtain the return value on all other architectures as is currently being done if RETURN_BUF is zero. On PowerPC, the new gdbarch method will return a nonzero address in RETURN_BUF if the value can be determined. The value_at function uses the return buffer address to get the return value. This patch fixes five testcase failures in gdb.cp/non-trivial-retval.exp. The correct function return values are now reported. Note this patch is dependent on patch: "PowerPC, function ppc64_sysv_abi_return_value add missing return value convention". This patch has been tested on Power 10 and x86-64 with no regressions.
Diffstat (limited to 'gdb/gdbarch.c')
-rw-r--r--gdb/gdbarch.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 9d929da..3227e94 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -116,6 +116,7 @@ struct gdbarch
gdbarch_address_to_pointer_ftype *address_to_pointer = unsigned_address_to_pointer;
gdbarch_integer_to_address_ftype *integer_to_address = nullptr;
gdbarch_return_value_ftype *return_value = nullptr;
+ gdbarch_get_return_buf_addr_ftype *get_return_buf_addr = default_get_return_buf_addr;
gdbarch_return_in_first_hidden_param_p_ftype *return_in_first_hidden_param_p = default_return_in_first_hidden_param_p;
gdbarch_skip_prologue_ftype *skip_prologue = 0;
gdbarch_skip_main_prologue_ftype *skip_main_prologue = nullptr;
@@ -369,6 +370,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of address_to_pointer, invalid_p == 0 */
/* Skip verify of integer_to_address, has predicate. */
/* Skip verify of return_value, has predicate. */
+ /* Skip verify of get_return_buf_addr, invalid_p == 0 */
/* Skip verify of return_in_first_hidden_param_p, invalid_p == 0 */
if (gdbarch->skip_prologue == 0)
log.puts ("\n\tskip_prologue");
@@ -781,6 +783,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: return_value = <%s>\n",
host_address_to_string (gdbarch->return_value));
gdb_printf (file,
+ "gdbarch_dump: get_return_buf_addr = <%s>\n",
+ host_address_to_string (gdbarch->get_return_buf_addr));
+ gdb_printf (file,
"gdbarch_dump: return_in_first_hidden_param_p = <%s>\n",
host_address_to_string (gdbarch->return_in_first_hidden_param_p));
gdb_printf (file,
@@ -2587,6 +2592,23 @@ set_gdbarch_return_value (struct gdbarch *gdbarch,
gdbarch->return_value = return_value;
}
+CORE_ADDR
+gdbarch_get_return_buf_addr (struct gdbarch *gdbarch, struct type *val_type, frame_info_ptr cur_frame)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->get_return_buf_addr != NULL);
+ if (gdbarch_debug >= 2)
+ gdb_printf (gdb_stdlog, "gdbarch_get_return_buf_addr called\n");
+ return gdbarch->get_return_buf_addr (val_type, cur_frame);
+}
+
+void
+set_gdbarch_get_return_buf_addr (struct gdbarch *gdbarch,
+ gdbarch_get_return_buf_addr_ftype get_return_buf_addr)
+{
+ gdbarch->get_return_buf_addr = get_return_buf_addr;
+}
+
int
gdbarch_return_in_first_hidden_param_p (struct gdbarch *gdbarch, struct type *type)
{