diff mbox series

arm:dump the stack usage after stack overflows

Message ID 20240220113341.24523-1-haibo.li@mediatek.com (mailing list archive)
State New
Headers show
Series arm:dump the stack usage after stack overflows | expand

Commit Message

Haibo Li Feb. 20, 2024, 11:33 a.m. UTC
With the help of vmap stack,it is able to detect stack overflow.

To make it easy to debug stack overflow,dump the stack usage of
each frame by walking the stack.

After this patch,the log after stack overflows like below:

Insufficient stack space to handle exception!
Task stack:     [0xf4a70000..0xf4a72000]
IRQ stack:      [0xf0800000..0xf0802000]
Overflow stack: [0x818c1000..0x818c2000]
Depth   usage   size   Location
  0      8232     96   _prb_read_valid
  1      8136     24   prb_read_valid
  2      8112    200   printk_get_next_message
  3      7912    104   console_flush_all
  4      7808     64   console_unlock
  5      7744     40   vprintk_emit
  6      7704     16   vprintk_default
  7      7688     32   _printk
  8      7656   1048   do_circle_loop
  9      6608   1048   do_circle_loop
 10      5560   1048   do_circle_loop
 11      4512   1048   do_circle_loop
 12      3464   1048   do_circle_loop
 13      2416   1048   do_circle_loop
 14      1368   1048   do_circle_loop
 15       320      8   stack_ovf_selftest
 16       312     24   param_attr_store
 17       288     40   kernfs_fop_write_iter
 18       248    112   vfs_write
 19       136     48   ksys_write
-----    -----  -----   ------
Internal error: kernel stack overflow: 0 [#1] SMP ARM
...

Signed-off-by: Haibo Li <haibo.li@mediatek.com>
---
 arch/arm/kernel/traps.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
diff mbox series

Patch

diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 3bad79db5d6e..641ca68b44ba 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -921,6 +921,33 @@  static int __init allocate_overflow_stacks(void)
 }
 early_initcall(allocate_overflow_stacks);
 
+static void dump_stack_usage(struct pt_regs *regs)
+{
+	struct stackframe frame;
+	unsigned int depth = 0;
+	unsigned long prev_pc;
+	unsigned long prev_sp;
+	unsigned long stack_high = (unsigned long)current->stack + THREAD_SIZE;
+
+	arm_get_current_stackframe(regs, &frame);
+	pr_emerg("Depth   usage   size   Location\n");
+	while (1) {
+		prev_pc = frame.pc;
+		prev_sp = frame.sp;
+#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
+		//meet the requirement of frame_pointer_check
+		if (frame.sp < (unsigned long)current->stack)
+			frame.sp = (unsigned long)current->stack + 4;
+#endif
+		if (unwind_frame(&frame) < 0)
+			break;
+		pr_emerg("%3d     %5ld  %5ld   %ps\n",
+			 depth++, stack_high - prev_sp,
+			 frame.sp - prev_sp, (void *)prev_pc);
+	}
+	pr_emerg("-----    -----  -----   ------\n");
+}
+
 asmlinkage void handle_bad_stack(struct pt_regs *regs)
 {
 	unsigned long tsk_stk = (unsigned long)current->stack;
@@ -940,6 +967,7 @@  asmlinkage void handle_bad_stack(struct pt_regs *regs)
 #endif
 	pr_emerg("Overflow stack: [0x%08lx..0x%08lx]\n",
 		 ovf_stk - OVERFLOW_STACK_SIZE, ovf_stk);
+	dump_stack_usage(regs);
 
 	die("kernel stack overflow", regs, 0);
 }