1 /* 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Copyright (C) 2013 Richard Weinberger <richrd@nod.at> 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 #include <os.h> 16 17 struct stack_frame { 18 struct stack_frame *next_frame; 19 unsigned long return_address; 20 }; 21 22 static void print_stack_trace(unsigned long *sp, unsigned long bp) 23 { 24 int reliable; 25 unsigned long addr; 26 struct stack_frame *frame = (struct stack_frame *)bp; 27 28 printk(KERN_INFO "Call Trace:\n"); 29 while (((long) sp & (THREAD_SIZE-1)) != 0) { 30 addr = *sp; 31 if (__kernel_text_address(addr)) { 32 reliable = 0; 33 if ((unsigned long) sp == bp + sizeof(long)) { 34 frame = frame ? frame->next_frame : NULL; 35 bp = (unsigned long)frame; 36 reliable = 1; 37 } 38 39 printk(KERN_INFO " [<%08lx>]", addr); 40 printk(KERN_CONT " %s", reliable ? "" : "? "); 41 print_symbol(KERN_CONT "%s", addr); 42 printk(KERN_CONT "\n"); 43 } 44 sp++; 45 } 46 printk(KERN_INFO "\n"); 47 } 48 49 /*Stolen from arch/i386/kernel/traps.c */ 50 static const int kstack_depth_to_print = 24; 51 52 static unsigned long get_frame_pointer(struct task_struct *task, 53 struct pt_regs *segv_regs) 54 { 55 if (!task || task == current) 56 return segv_regs ? PT_REGS_BP(segv_regs) : current_bp(); 57 else 58 return KSTK_EBP(task); 59 } 60 61 static unsigned long *get_stack_pointer(struct task_struct *task, 62 struct pt_regs *segv_regs) 63 { 64 if (!task || task == current) 65 return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp(); 66 else 67 return (unsigned long *)KSTK_ESP(task); 68 } 69 70 void show_stack(struct task_struct *task, unsigned long *stack) 71 { 72 unsigned long *sp = stack, bp = 0; 73 struct pt_regs *segv_regs = current->thread.segv_regs; 74 int i; 75 76 if (!segv_regs && os_is_signal_stack()) { 77 printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler," 78 " aborting stack trace!\n"); 79 return; 80 } 81 82 #ifdef CONFIG_FRAME_POINTER 83 bp = get_frame_pointer(task, segv_regs); 84 #endif 85 86 if (!stack) 87 sp = get_stack_pointer(task, segv_regs); 88 89 printk(KERN_INFO "Stack:\n"); 90 stack = sp; 91 for (i = 0; i < kstack_depth_to_print; i++) { 92 if (kstack_end(stack)) 93 break; 94 if (i && ((i % STACKSLOTS_PER_LINE) == 0)) 95 printk(KERN_CONT "\n"); 96 printk(KERN_CONT " %08lx", *stack++); 97 } 98 printk(KERN_CONT "\n"); 99 100 print_stack_trace(sp, bp); 101 } 102