diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2023-03-17 16:18:07 -0700 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2023-06-13 21:56:27 -0700 |
commit | cc34f2909d2fbc8f52d24b20f6cbedcdf477e049 (patch) | |
tree | ed0f77d767a569450de50ce644bb0c1d5f86ee1c /arch/xtensa | |
parent | f29cf77609cc401d28e2e7ec5c57d9d178ef347d (diff) | |
download | linux-stable-cc34f2909d2fbc8f52d24b20f6cbedcdf477e049.tar.gz linux-stable-cc34f2909d2fbc8f52d24b20f6cbedcdf477e049.tar.bz2 linux-stable-cc34f2909d2fbc8f52d24b20f6cbedcdf477e049.zip |
xtensa: rearrange show_stack output
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>
Diffstat (limited to 'arch/xtensa')
-rw-r--r-- | arch/xtensa/kernel/traps.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 71588bf55632..a2a9a460ec9e 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -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); } |