1/** 2 * @file backtrace.c 3 * 4 * @remark Copyright 2002 OProfile authors 5 * @remark Read the file COPYING 6 * 7 * @author John Levon 8 * @author David Smith 9 */ 10 11#include <linux/oprofile.h> 12#include <linux/sched.h> 13#include <linux/mm.h> 14#include <linux/compat.h> 15#include <linux/uaccess.h> 16 17#include <asm/ptrace.h> 18#include <asm/stacktrace.h> 19 20static int backtrace_stack(void *data, char *name) 21{ 22 /* Yes, we want all stacks */ 23 return 0; 24} 25 26static void backtrace_address(void *data, unsigned long addr, int reliable) 27{ 28 unsigned int *depth = data; 29 30 if ((*depth)--) 31 oprofile_add_trace(addr); 32} 33 34static struct stacktrace_ops backtrace_ops = { 35 .stack = backtrace_stack, 36 .address = backtrace_address, 37 .walk_stack = print_context_stack, 38}; 39 40#ifdef CONFIG_COMPAT 41static struct stack_frame_ia32 * 42dump_user_backtrace_32(struct stack_frame_ia32 *head) 43{ 44 /* Also check accessibility of one struct frame_head beyond: */ 45 struct stack_frame_ia32 bufhead[2]; 46 struct stack_frame_ia32 *fp; 47 unsigned long bytes; 48 49 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); 50 if (bytes != 0) 51 return NULL; 52 53 fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); 54 55 oprofile_add_trace(bufhead[0].return_address); 56 57 /* frame pointers should strictly progress back up the stack 58 * (towards higher addresses) */ 59 if (head >= fp) 60 return NULL; 61 62 return fp; 63} 64 65static inline int 66x86_backtrace_32(struct pt_regs * const regs, unsigned int depth) 67{ 68 struct stack_frame_ia32 *head; 69 70 /* User process is IA32 */ 71 if (!current || !test_thread_flag(TIF_IA32)) 72 return 0; 73 74 head = (struct stack_frame_ia32 *) regs->bp; 75 while (depth-- && head) 76 head = dump_user_backtrace_32(head); 77 78 return 1; 79} 80 81#else 82static inline int 83x86_backtrace_32(struct pt_regs * const regs, unsigned int depth) 84{ 85 return 0; 86} 87#endif /* CONFIG_COMPAT */ 88 89static struct stack_frame *dump_user_backtrace(struct stack_frame *head) 90{ 91 /* Also check accessibility of one struct frame_head beyond: */ 92 struct stack_frame bufhead[2]; 93 unsigned long bytes; 94 95 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); 96 if (bytes != 0) 97 return NULL; 98 99 oprofile_add_trace(bufhead[0].return_address); 100 101 /* frame pointers should strictly progress back up the stack 102 * (towards higher addresses) */ 103 if (head >= bufhead[0].next_frame) 104 return NULL; 105 106 return bufhead[0].next_frame; 107} 108 109void 110x86_backtrace(struct pt_regs * const regs, unsigned int depth) 111{ 112 struct stack_frame *head = (struct stack_frame *)frame_pointer(regs); 113 114 if (!user_mode(regs)) { 115 unsigned long stack = kernel_stack_pointer(regs); 116 if (depth) 117 dump_trace(NULL, regs, (unsigned long *)stack, 0, 118 &backtrace_ops, &depth); 119 return; 120 } 121 122 if (x86_backtrace_32(regs, depth)) 123 return; 124 125 while (depth-- && head) 126 head = dump_user_backtrace(head); 127} 128