1 /* 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Copyright (C) 2013 Richard Weinberger <[email protected]> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10 #include <linux/kallsyms.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/sched.h> 14 #include <asm/sysrq.h> 15 16 struct stack_frame { 17 struct stack_frame *next_frame; 18 unsigned long return_address; 19 }; 20 21 static void print_stack_trace(unsigned long *sp, unsigned long bp) 22 { 23 int reliable; 24 unsigned long addr; 25 struct stack_frame *frame = (struct stack_frame *)bp; 26 27 printk(KERN_INFO "Call Trace:\n"); 28 while (((long) sp & (THREAD_SIZE-1)) != 0) { 29 addr = *sp; 30 if (__kernel_text_address(addr)) { 31 reliable = 0; 32 if ((unsigned long) sp == bp + sizeof(long)) { 33 frame = frame ? frame->next_frame : NULL; 34 bp = (unsigned long)frame; 35 reliable = 1; 36 } 37 38 printk(KERN_INFO " [<%08lx>]", addr); 39 printk(KERN_CONT " %s", reliable ? "" : "? "); 40 print_symbol(KERN_CONT "%s", addr); 41 printk(KERN_CONT "\n"); 42 } 43 sp++; 44 } 45 printk(KERN_INFO "\n"); 46 } 47 48 /*Stolen from arch/i386/kernel/traps.c */ 49 static const int kstack_depth_to_print = 24; 50 51 static unsigned long get_frame_pointer(struct task_struct *task) 52 { 53 if (!task || task == current) 54 return current_bp(); 55 else 56 return KSTK_EBP(task); 57 } 58 59 void show_stack(struct task_struct *task, unsigned long *stack) 60 { 61 unsigned long *sp = stack, bp = 0; 62 int i; 63 64 #ifdef CONFIG_FRAME_POINTER 65 bp = get_frame_pointer(task); 66 #endif 67 68 if (!stack) { 69 if (!task || task == current) 70 sp = current_sp(); 71 else 72 sp = (unsigned long *)KSTK_ESP(task); 73 } 74 75 printk(KERN_INFO "Stack:\n"); 76 stack = sp; 77 for (i = 0; i < kstack_depth_to_print; i++) { 78 if (kstack_end(stack)) 79 break; 80 if (i && ((i % STACKSLOTS_PER_LINE) == 0)) 81 printk(KERN_CONT "\n"); 82 printk(KERN_CONT " %08lx", *stack++); 83 } 84 printk(KERN_CONT "\n"); 85 86 print_stack_trace(sp, bp); 87 } 88