1/* 2 * Copyright (C) 1991, 1992 Linus Torvalds 3 * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs 4 */ 5#include <linux/kallsyms.h> 6#include <linux/kprobes.h> 7#include <linux/uaccess.h> 8#include <linux/hardirq.h> 9#include <linux/kdebug.h> 10#include <linux/module.h> 11#include <linux/ptrace.h> 12#include <linux/kexec.h> 13#include <linux/sysfs.h> 14#include <linux/bug.h> 15#include <linux/nmi.h> 16 17#include <asm/stacktrace.h> 18 19 20void dump_trace(struct task_struct *task, struct pt_regs *regs, 21 unsigned long *stack, unsigned long bp, 22 const struct stacktrace_ops *ops, void *data) 23{ 24 int graph = 0; 25 26 if (!task) 27 task = current; 28 29 if (!stack) { 30 unsigned long dummy; 31 32 stack = &dummy; 33 if (task && task != current) 34 stack = (unsigned long *)task->thread.sp; 35 } 36 37#ifdef CONFIG_FRAME_POINTER 38 if (!bp) { 39 if (task == current) { 40 /* Grab bp right from our regs */ 41 get_bp(bp); 42 } else { 43 /* bp is the last reg pushed by switch_to */ 44 bp = *(unsigned long *) task->thread.sp; 45 } 46 } 47#endif 48 49 for (;;) { 50 struct thread_info *context; 51 52 context = (struct thread_info *) 53 ((unsigned long)stack & (~(THREAD_SIZE - 1))); 54 bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph); 55 56 stack = (unsigned long *)context->previous_esp; 57 if (!stack) 58 break; 59 if (ops->stack(data, "IRQ") < 0) 60 break; 61 touch_nmi_watchdog(); 62 } 63} 64EXPORT_SYMBOL(dump_trace); 65 66void 67show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, 68 unsigned long *sp, unsigned long bp, char *log_lvl) 69{ 70 unsigned long *stack; 71 int i; 72 73 if (sp == NULL) { 74 if (task) 75 sp = (unsigned long *)task->thread.sp; 76 else 77 sp = (unsigned long *)&sp; 78 } 79 80 stack = sp; 81 for (i = 0; i < kstack_depth_to_print; i++) { 82 if (kstack_end(stack)) 83 break; 84 if (i && ((i % STACKSLOTS_PER_LINE) == 0)) 85 printk("\n%s", log_lvl); 86 printk(" %08lx", *stack++); 87 touch_nmi_watchdog(); 88 } 89 printk("\n"); 90 show_trace_log_lvl(task, regs, sp, bp, log_lvl); 91} 92 93 94void show_registers(struct pt_regs *regs) 95{ 96 int i; 97 98 print_modules(); 99 __show_regs(regs, 0); 100 101 printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n", 102 TASK_COMM_LEN, current->comm, task_pid_nr(current), 103 current_thread_info(), current, task_thread_info(current)); 104 /* 105 * When in-kernel, we also print out the stack and code at the 106 * time of the fault.. 107 */ 108 if (!user_mode_vm(regs)) { 109 unsigned int code_prologue = code_bytes * 43 / 64; 110 unsigned int code_len = code_bytes; 111 unsigned char c; 112 u8 *ip; 113 114 printk(KERN_EMERG "Stack:\n"); 115 show_stack_log_lvl(NULL, regs, ®s->sp, 116 0, KERN_EMERG); 117 118 printk(KERN_EMERG "Code: "); 119 120 ip = (u8 *)regs->ip - code_prologue; 121 if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { 122 /* try starting at IP */ 123 ip = (u8 *)regs->ip; 124 code_len = code_len - code_prologue + 1; 125 } 126 for (i = 0; i < code_len; i++, ip++) { 127 if (ip < (u8 *)PAGE_OFFSET || 128 probe_kernel_address(ip, c)) { 129 printk(" Bad EIP value."); 130 break; 131 } 132 if (ip == (u8 *)regs->ip) 133 printk("<%02x> ", c); 134 else 135 printk("%02x ", c); 136 } 137 } 138 printk("\n"); 139} 140 141int is_valid_bugaddr(unsigned long ip) 142{ 143 unsigned short ud2; 144 145 if (ip < PAGE_OFFSET) 146 return 0; 147 if (probe_kernel_address((unsigned short *)ip, ud2)) 148 return 0; 149 150 return ud2 == 0x0b0f; 151} 152