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 do_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 static unsigned long get_frame_pointer(struct task_struct *task, 50 struct pt_regs *segv_regs) 51 { 52 if (!task || task == current) 53 return segv_regs ? PT_REGS_BP(segv_regs) : current_bp(); 54 else 55 return KSTK_EBP(task); 56 } 57 58 static unsigned long *get_stack_pointer(struct task_struct *task, 59 struct pt_regs *segv_regs) 60 { 61 if (!task || task == current) 62 return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp(); 63 else 64 return (unsigned long *)KSTK_ESP(task); 65 } 66 67 void show_stack(struct task_struct *task, unsigned long *stack) 68 { 69 unsigned long *sp = stack, bp = 0; 70 struct pt_regs *segv_regs = current->thread.segv_regs; 71 int i; 72 73 if (!segv_regs && os_is_signal_stack()) { 74 printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler," 75 " aborting stack trace!\n"); 76 return; 77 } 78 79 #ifdef CONFIG_FRAME_POINTER 80 bp = get_frame_pointer(task, segv_regs); 81 #endif 82 83 if (!stack) 84 sp = get_stack_pointer(task, segv_regs); 85 86 printk(KERN_INFO "Stack:\n"); 87 stack = sp; 88 for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) { 89 if (kstack_end(stack)) 90 break; 91 if (i && ((i % STACKSLOTS_PER_LINE) == 0)) 92 printk(KERN_CONT "\n"); 93 printk(KERN_CONT " %08lx", *stack++); 94 } 95 printk(KERN_CONT "\n"); 96 97 do_stack_trace(sp, bp); 98 } 99