From 6d21f33bb8f63d1d9aeda88ca815e442da0dc160 Mon Sep 17 00:00:00 2001 From: Carl Love 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 (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