xtensa: rearrange show_stack output
authorMax Filippov <jcmvbkbc@gmail.com>
Fri, 17 Mar 2023 23:18:07 +0000 (16:18 -0700)
committerMax Filippov <jcmvbkbc@gmail.com>
Wed, 14 Jun 2023 04:56:27 +0000 (21:56 -0700)
Minimal stack alignment on xtensa is 16 bytes, having stack dump in
32-byte lines may be visually misleading as the stack frame border may
be in the middle of the line.
Arrange stack dump in 16-byte lines. Mark lines at stack frame borders
with arrows.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
arch/xtensa/kernel/traps.c

index 71588bf55632d53056536dba225ab7febe971ee1..a2a9a460ec9e6c3c9240f8182edee0755189efb8 100644 (file)
@@ -549,31 +549,58 @@ static void show_trace(struct task_struct *task, unsigned long *sp,
 }
 
 #define STACK_DUMP_ENTRY_SIZE 4
-#define STACK_DUMP_LINE_SIZE 32
+#define STACK_DUMP_LINE_SIZE 16
 static size_t kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH;
 
-void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
+struct stack_fragment
 {
-       size_t len, off = 0;
-
-       if (!sp)
-               sp = stack_pointer(task);
+       size_t len;
+       size_t off;
+       u8 *sp;
+       const char *loglvl;
+};
 
-       len = min((-(size_t)sp) & (THREAD_SIZE - STACK_DUMP_ENTRY_SIZE),
-                 kstack_depth_to_print * STACK_DUMP_ENTRY_SIZE);
+static int show_stack_fragment_cb(struct stackframe *frame, void *data)
+{
+       struct stack_fragment *sf = data;
 
-       printk("%sStack:\n", loglvl);
-       while (off < len) {
+       while (sf->off < sf->len) {
                u8 line[STACK_DUMP_LINE_SIZE];
-               size_t line_len = len - off > STACK_DUMP_LINE_SIZE ?
-                       STACK_DUMP_LINE_SIZE : len - off;
+               size_t line_len = sf->len - sf->off > STACK_DUMP_LINE_SIZE ?
+                       STACK_DUMP_LINE_SIZE : sf->len - sf->off;
+               bool arrow = sf->off == 0;
 
-               __memcpy(line, (u8 *)sp + off, line_len);
-               print_hex_dump(loglvl, " ", DUMP_PREFIX_NONE,
+               if (frame && frame->sp == (unsigned long)(sf->sp + sf->off))
+                       arrow = true;
+
+               __memcpy(line, sf->sp + sf->off, line_len);
+               print_hex_dump(sf->loglvl, arrow ? "> " : "  ", DUMP_PREFIX_NONE,
                               STACK_DUMP_LINE_SIZE, STACK_DUMP_ENTRY_SIZE,
                               line, line_len, false);
-               off += STACK_DUMP_LINE_SIZE;
+               sf->off += STACK_DUMP_LINE_SIZE;
+               if (arrow)
+                       return 0;
        }
+       return 1;
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
+{
+       struct stack_fragment sf;
+
+       if (!sp)
+               sp = stack_pointer(task);
+
+       sf.len = min((-(size_t)sp) & (THREAD_SIZE - STACK_DUMP_ENTRY_SIZE),
+                    kstack_depth_to_print * STACK_DUMP_ENTRY_SIZE);
+       sf.off = 0;
+       sf.sp = (u8 *)sp;
+       sf.loglvl = loglvl;
+
+       printk("%sStack:\n", loglvl);
+       walk_stackframe(sp, show_stack_fragment_cb, &sf);
+       while (sf.off < sf.len)
+               show_stack_fragment_cb(NULL, &sf);
        show_trace(task, sp, loglvl);
 }