diff options
author | Tom Tromey <tromey@adacore.com> | 2023-03-08 10:58:35 -0700 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2023-04-21 07:14:22 -0600 |
commit | 9df25c346f5517c0228d067c68ee2f6bfe1728ad (patch) | |
tree | a4996b2b7c579cdd89e00e27d82e399c480bf5c8 /gdb/gdbarch.c | |
parent | 532d55c0ab4bda1d5da90c6301c7d28ddd98ad18 (diff) | |
download | gdb-9df25c346f5517c0228d067c68ee2f6bfe1728ad.zip gdb-9df25c346f5517c0228d067c68ee2f6bfe1728ad.tar.gz gdb-9df25c346f5517c0228d067c68ee2f6bfe1728ad.tar.bz2 |
Handle erroneous DW_AT_call_return_pc
On PPC64, with the test case included in an earlier patch, we found
that "finish" would still not correctly find the return value via
entry values.
The issue is simple. The compiler emits:
0x00000000100032b8 <+28>: bl 0x1000320c <pck__create_large>
0x00000000100032bc <+32>: nop
0x00000000100032c0 <+36>: li r9,42
... but the DWARF says:
<162a> DW_AT_call_return_pc: 0x100032c0
That is, the declared return PC is one instruction past the actual
return PC.
This patch adds a new arch hook to handle this scenario, and
implements it for PPC64. Some care is taken so that GDB will continue
to work if this compiler bug is fixed. A GCC patch is here:
https://gcc.gnu.org/pipermail/gcc-patches/2023-March/613336.html
No check for 'nop' is done, as subsequent discussion revealed that the
linker might replace this with another instruction.
Diffstat (limited to 'gdb/gdbarch.c')
-rw-r--r-- | gdb/gdbarch.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 9406458..30199a0 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -115,6 +115,7 @@ struct gdbarch gdbarch_return_value_as_value_ftype *return_value_as_value = default_gdbarch_return_value; gdbarch_get_return_buf_addr_ftype *get_return_buf_addr = default_get_return_buf_addr; gdbarch_dwarf2_omit_typedef_p_ftype *dwarf2_omit_typedef_p = default_dwarf2_omit_typedef_p; + gdbarch_update_call_site_pc_ftype *update_call_site_pc = default_update_call_site_pc; 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 = nullptr; gdbarch_skip_main_prologue_ftype *skip_main_prologue = nullptr; @@ -372,6 +373,7 @@ verify_gdbarch (struct gdbarch *gdbarch) log.puts ("\n\treturn_value_as_value"); /* Skip verify of get_return_buf_addr, invalid_p == 0 */ /* Skip verify of dwarf2_omit_typedef_p, invalid_p == 0 */ + /* Skip verify of update_call_site_pc, 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"); @@ -794,6 +796,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: dwarf2_omit_typedef_p = <%s>\n", host_address_to_string (gdbarch->dwarf2_omit_typedef_p)); gdb_printf (file, + "gdbarch_dump: update_call_site_pc = <%s>\n", + host_address_to_string (gdbarch->update_call_site_pc)); + 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, @@ -2639,6 +2644,23 @@ set_gdbarch_dwarf2_omit_typedef_p (struct gdbarch *gdbarch, gdbarch->dwarf2_omit_typedef_p = dwarf2_omit_typedef_p; } +CORE_ADDR +gdbarch_update_call_site_pc (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->update_call_site_pc != NULL); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_update_call_site_pc called\n"); + return gdbarch->update_call_site_pc (gdbarch, pc); +} + +void +set_gdbarch_update_call_site_pc (struct gdbarch *gdbarch, + gdbarch_update_call_site_pc_ftype update_call_site_pc) +{ + gdbarch->update_call_site_pc = update_call_site_pc; +} + int gdbarch_return_in_first_hidden_param_p (struct gdbarch *gdbarch, struct type *type) { |