Crash doesn't support displaying backtrace for ppc on KDUMP.
Before the patch :
crash> bt
PID: 482 TASK: c7af5380 CPU: 0 COMMAND: "bash"
bt: cannot resolve "crash_save_current_state"
This patch enables backtrace for PPC.
After the patch :
crash> bt
PID: 482 TASK: c7af5380 CPU: 0 COMMAND: "bash"
R0: 00000001 R1: c7acfea0 R2: c7af5380 R3: 00000063
R4: 00001c61 R5: ffffffff R6: c01e5234 R7: c05943f8
R8: c05948a8 R9: 00000000 R10: 00003fff R11: 00001c61
R12: 24242482 R13: 100ed8f4 R14: 00000000 R15: 100e0000
R16: 100e5db8 R17: 100cccf0 R18: 100e5f60 R19: 100e5ed0
R20: 100f8c08 R21: 100e5ce4 R22: 00000001 R23: 100e0000
R24: 100e0000 R25: 00000007 R26: c0560000 R27: 00029000
R28: 00000000 R29: 00000063 R30: c01e03a8 R31: c05800ac
NIP: c01e03bc MSR: 00021000 OR3: 00000000 CTR: c01e03a8
LR: c01e06a8 XER: 20000000 CCR: 24242484 MQ: c05948a8
DAR: 00000000 DSISR: 00800000 Syscall Result: 48026000
NIP [00000000c01e03bc] sysrq_handle_crash
LR [00000000c01e06a8] __handle_sysrq
#0 [c7acfea0] sysrq_handle_crash at c01e03bc
#1 [c7acfed0] write_sysrq_trigger at c01e0810
#2 [c7acfee0] proc_reg_write at c0139f48
#3 [c7acfef0] vfs_write at c00e4a10
#4 [c7acff10] sys_write at c00e4c3c
#5 [c7acff40] ret_from_syscall at c000d8c8
crash> bt 1
PID: 1 TASK: c782c000 CPU: 0 COMMAND: "init"
#0 [c782b9f0] __schedule at c0311774
#1 [c782ba30] schedule_hrtimeout_range_clock at c0312a18
#2 [c782bab0] poll_schedule_timeout at c00f7e38
#3 [c782bac0] do_select at c00f8f80
#4 [c782bdc0] core_sys_select at c00f931c
#5 [c782bf10] sys_select at c00f9758
#6 [c782bf40] ret_from_syscall at c000d8c8
Signed-off-by: Suzuki K. Poulose <suzuki(a)in.ibm.com>
---
ppc.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 91 insertions(+), 13 deletions(-)
diff --git a/ppc.c b/ppc.c
index 869b066..d74e52d 100755
--- a/ppc.c
+++ b/ppc.c
@@ -980,16 +980,95 @@ ppc_exception_frame(ulong addr, struct bt_info *bt, struct
gnu_request *req)
}
+static void
+ppc_kdump_stack_frame(struct bt_info *bt, ulong *nip, ulong *ksp)
+{
+ struct ppc_pt_regs *pt_regs;
+ unsigned long ip, sp;
+
+ ip = sp = 0;
+
+ pt_regs = (struct ppc_pt_regs*)bt->machdep;
+
+ if (!pt_regs || !(pt_regs->gpr[1])) {
+ fprintf(fp, "0lx: GPR1 register value(SP) was not saved\n",
+ bt->task);
+ return;
+ }
+
+ sp = pt_regs->gpr[1];
+
+ if (IS_KVADDR(sp))
+ readmem(sp, KVADDR, &ip, sizeof(ulong), "Regs NIP Value",
+ FAULT_ON_ERROR);
+ else {
+ if (IN_TASK_VMA(bt->task, sp))
+ fprintf(fp, "%0lx: Task is running in userspace\n",
+ bt->task);
+ else
+ fprintf(fp, "%0lx: Invalid Stack Pointer : 0%lx\n",
+ bt->task, sp);
+ ip = pt_regs->nip;
+ }
+
+ if(nip)
+ *nip = ip;
+ if (ksp)
+ *ksp = sp;
+
+ if (bt->flags &&
+ ((BT_TEXT_SYMBOLS | BT_TEXT_SYMBOLS_PRINT |
+ BT_TEXT_SYMBOLS_NOPRINT)))
+ return TRUE;
+ /*
+ * Print the collected regs for the active task
+ */
+ ppc_print_regs(pt_regs);
+
+ if (!IS_KVADDR(sp))
+ return;
+
+ fprintf(fp, " NIP [%016lx] %s\n", pt_regs->nip,
+ closest_symbol(pt_regs->nip));
+ fprintf(fp, " LR [%016lx] %s\n", pt_regs->link,
+ closest_symbol(pt_regs->link));
+
+ fprintf(fp, "\n");
+
+ return;
+
+}
+
+static void
+ppc_dumpfile_stack_frame(struct bt_info *bt, ulong *getpc, ulong *getsp)
+{
+ struct syment *sp;
+
+ /* For KDUMP get the SP, PC from pt_regs stored in the core */
+ if (pc->flags & KDUMP) {
+ ppc_kdump_stack_frame(bt, getpc, getsp);
+ return;
+ }
+
+ if (getpc) {
+ if (!(sp = next_symbol("crash_save_current_state", NULL)))
+ *getpc = (symbol_value("crash_save_current_state")+16);
+ else
+ *getpc = (sp->value - 4);
+ }
+}
+
/*
* Get a stack frame combination of pc and ra from the most relevent spot.
*/
static void
ppc_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
{
- if (pcp)
- *pcp = ppc_get_pc(bt);
- if (spp)
- *spp = ppc_get_sp(bt);
+ if (DUMPFILE() && is_task_active(bt->task))
+ ppc_dumpfile_stack_frame(bt, pcp, spp);
+ else
+ get_ppc_frame(bt, pcp, spp);
+
}
@@ -1001,7 +1080,10 @@ ppc_get_sp(struct bt_info *bt)
{
ulong sp;
- get_ppc_frame(bt, NULL, &sp);
+ if (DUMPFILE() && is_task_active(bt->task))
+ ppc_dumpfile_stack_frame(bt, NULL, &sp);
+ else
+ get_ppc_frame(bt, NULL, &sp);
return sp;
}
@@ -1012,16 +1094,12 @@ ppc_get_sp(struct bt_info *bt)
static ulong
ppc_get_pc(struct bt_info *bt)
{
- struct syment *sp;
ulong ip;
- if (DUMPFILE() && is_task_active(bt->task)) {
- if (!(sp = next_symbol("crash_save_current_state", NULL)))
- return (symbol_value("crash_save_current_state")+16);
- else
- return (sp->value - 4);
- }
- get_ppc_frame(bt, &ip, NULL);
+ if (DUMPFILE() && is_task_active(bt->task))
+ ppc_dumpfile_stack_frame(bt, &ip, NULL);
+ else
+ get_ppc_frame(bt, &ip, NULL);
return ip;
}