Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only 2 : /* 3 : * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 : * Copyright (C) 2013 Richard Weinberger <richrd@nod.at> 5 : */ 6 : 7 : #include <linux/kallsyms.h> 8 : #include <linux/kernel.h> 9 : #include <linux/module.h> 10 : #include <linux/sched.h> 11 : #include <linux/sched/debug.h> 12 : #include <linux/sched/task_stack.h> 13 : 14 : #include <asm/sysrq.h> 15 : #include <asm/stacktrace.h> 16 : #include <os.h> 17 : 18 113 : static void _print_addr(void *data, unsigned long address, int reliable) 19 : { 20 113 : const char *loglvl = data; 21 : 22 113 : printk("%s [<%08lx>] %s%pS\n", loglvl, address, reliable ? "" : "? ", 23 : (void *)address); 24 113 : } 25 : 26 : static const struct stacktrace_ops stackops = { 27 : .address = _print_addr 28 : }; 29 : 30 5 : void show_stack(struct task_struct *task, unsigned long *stack, 31 : const char *loglvl) 32 : { 33 5 : struct pt_regs *segv_regs = current->thread.segv_regs; 34 : int i; 35 : 36 5 : if (!segv_regs && os_is_signal_stack()) { 37 0 : pr_err("Received SIGSEGV in SIGSEGV handler," 38 : " aborting stack trace!\n"); 39 0 : return; 40 : } 41 : 42 5 : if (!stack) 43 5 : stack = get_stack_pointer(task, segv_regs); 44 : 45 5 : printk("%sStack:\n", loglvl); 46 65 : for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) { 47 60 : if (kstack_end(stack)) 48 : break; 49 60 : if (i && ((i % STACKSLOTS_PER_LINE) == 0)) 50 10 : pr_cont("\n"); 51 60 : pr_cont(" %08lx", READ_ONCE_NOCHECK(*stack)); 52 60 : stack++; 53 : } 54 : 55 5 : printk("%sCall Trace:\n", loglvl); 56 5 : dump_trace(current, &stackops, (void *)loglvl); 57 : }