98 lines
3.5 KiB
Diff
98 lines
3.5 KiB
Diff
From 6d21f33bb8f63d1d9aeda88ca815e442da0dc160 Mon Sep 17 00:00:00 2001
|
|
From: Carl Love <cel@linux.ibm.com>
|
|
Date: Tue, 23 Jan 2024 17:12:34 -0500
|
|
Subject: [PATCH 1/2] rs6000, unwind-on-each-instruction fix.
|
|
|
|
The function rs6000_epilogue_frame_cache assumes the LR and gprs have been
|
|
restored. In fact register r31 and the link register, lr, may not have
|
|
been restored yet. This patch adds support to store the lr and gpr
|
|
register unrolling rules in the cache. The LR and GPR values can now be
|
|
unrolled correctly.
|
|
|
|
Patch fixes all 10 regresion test failures for the unwind-on-each-insn.exp.
|
|
---
|
|
gdb/rs6000-tdep.c | 53 +++++++++++++++++++++++++++++++++++++++++------
|
|
1 file changed, 47 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
|
|
index 23397d037ae..ecc8766d319 100644
|
|
--- a/gdb/rs6000-tdep.c
|
|
+++ b/gdb/rs6000-tdep.c
|
|
@@ -3805,6 +3805,8 @@ rs6000_epilogue_frame_cache (frame_info_ptr this_frame, void **this_cache)
|
|
struct rs6000_frame_cache *cache;
|
|
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
|
ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
|
|
+ struct rs6000_framedata fdata;
|
|
+ int wordsize = tdep->wordsize;
|
|
|
|
if (*this_cache)
|
|
return (struct rs6000_frame_cache *) *this_cache;
|
|
@@ -3815,17 +3817,56 @@ rs6000_epilogue_frame_cache (frame_info_ptr this_frame, void **this_cache)
|
|
|
|
try
|
|
{
|
|
- /* At this point the stack looks as if we just entered the
|
|
- function, and the return address is stored in LR. */
|
|
- CORE_ADDR sp, lr;
|
|
+ /* At this point the stack looks as if we just entered the function.
|
|
+ The SP (r1) has been restored but the LR and r31 may not have been
|
|
+ restored yet. Need to update the register unrolling information in
|
|
+ the cache for the LR and the saved gprs. */
|
|
+ CORE_ADDR sp;
|
|
+ CORE_ADDR func = 0, pc = 0;
|
|
|
|
- sp = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
|
|
- lr = get_frame_register_unsigned (this_frame, tdep->ppc_lr_regnum);
|
|
+ func = get_frame_func (this_frame);
|
|
+ cache->pc = func;
|
|
+ pc = get_frame_pc (this_frame);
|
|
+ skip_prologue (gdbarch, func, pc, &fdata);
|
|
+
|
|
+ /* SP is in r1 and it has been restored. Get the current value. */
|
|
+ sp = get_frame_register_unsigned (this_frame,
|
|
+ gdbarch_sp_regnum (gdbarch));
|
|
|
|
cache->base = sp;
|
|
cache->initial_sp = sp;
|
|
|
|
- cache->saved_regs[gdbarch_pc_regnum (gdbarch)].set_value (lr);
|
|
+ /* Store the unwinding rules for the gpr registers that have not been
|
|
+ restored yet, specifically r31.
|
|
+
|
|
+ if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
|
|
+ All gpr's from saved_gpr to gpr31 are saved (except during the
|
|
+ prologue). */
|
|
+
|
|
+ if (fdata.saved_gpr >= 0)
|
|
+ {
|
|
+ int i;
|
|
+ CORE_ADDR gpr_addr = cache->base + fdata.gpr_offset;
|
|
+
|
|
+ for(i = fdata.saved_gpr; i < ppc_num_gprs; i++)
|
|
+ {
|
|
+ if (fdata.gpr_mask & (1U << i))
|
|
+ cache->saved_regs[tdep->ppc_gp0_regnum + i].set_addr (gpr_addr);
|
|
+ gpr_addr += wordsize;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Store the lr unwinding rules. */
|
|
+ if (fdata.lr_offset != 0)
|
|
+ cache->saved_regs[tdep->ppc_lr_regnum].set_addr (cache->base
|
|
+ + fdata.lr_offset);
|
|
+
|
|
+ else if (fdata.lr_register != -1)
|
|
+ cache->saved_regs[tdep->ppc_lr_regnum].set_realreg (fdata.lr_register);
|
|
+
|
|
+ /* The PC is found in the link register. */
|
|
+ cache->saved_regs[gdbarch_pc_regnum (gdbarch)]
|
|
+ = cache->saved_regs[tdep->ppc_lr_regnum];
|
|
}
|
|
catch (const gdb_exception_error &ex)
|
|
{
|
|
|
|
base-commit: 800e56a120419b457ebda18c5478ebfea99f9b3a
|
|
--
|
|
2.35.3
|
|
|