Loading arch/x86/oprofile/backtrace.c +59 −11 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <asm/ptrace.h> #include <asm/uaccess.h> #include <asm/stacktrace.h> #include <linux/compat.h> static void backtrace_warning_symbol(void *data, char *msg, unsigned long symbol) Loading Loading @@ -48,14 +49,12 @@ static struct stacktrace_ops backtrace_ops = { .walk_stack = print_context_stack, }; struct frame_head { struct frame_head *bp; unsigned long ret; } __attribute__((packed)); static struct frame_head *dump_user_backtrace(struct frame_head *head) #ifdef CONFIG_COMPAT static struct stack_frame_ia32 * dump_user_backtrace_32(struct stack_frame_ia32 *head) { struct frame_head bufhead[2]; struct stack_frame_ia32 bufhead[2]; struct stack_frame_ia32 *fp; /* Also check accessibility of one struct frame_head beyond */ if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) Loading @@ -63,20 +62,66 @@ static struct frame_head *dump_user_backtrace(struct frame_head *head) if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) return NULL; oprofile_add_trace(bufhead[0].ret); fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); oprofile_add_trace(bufhead[0].return_address); /* frame pointers should strictly progress back up the stack * (towards higher addresses) */ if (head >= fp) return NULL; return fp; } static inline int x86_backtrace_32(struct pt_regs * const regs, unsigned int depth) { struct stack_frame_ia32 *head; /* User process is 32-bit */ if (!current || !test_thread_flag(TIF_IA32)) return 0; head = (struct stack_frame_ia32 *) regs->bp; while (depth-- && head) head = dump_user_backtrace_32(head); return 1; } #else static inline int x86_backtrace_32(struct pt_regs * const regs, unsigned int depth) { return 0; } #endif /* CONFIG_COMPAT */ static struct stack_frame *dump_user_backtrace(struct stack_frame *head) { struct stack_frame bufhead[2]; /* Also check accessibility of one struct stack_frame beyond */ if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) return NULL; if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) return NULL; oprofile_add_trace(bufhead[0].return_address); /* frame pointers should strictly progress back up the stack * (towards higher addresses) */ if (head >= bufhead[0].bp) if (head >= bufhead[0].next_frame) return NULL; return bufhead[0].bp; return bufhead[0].next_frame; } void x86_backtrace(struct pt_regs * const regs, unsigned int depth) { struct frame_head *head = (struct frame_head *)frame_pointer(regs); struct stack_frame *head = (struct stack_frame *)frame_pointer(regs); if (!user_mode_vm(regs)) { unsigned long stack = kernel_stack_pointer(regs); Loading @@ -86,6 +131,9 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) return; } if (x86_backtrace_32(regs, depth)) return; while (depth-- && head) head = dump_user_backtrace(head); } arch/x86/oprofile/nmi_int.c +1 −8 Original line number Diff line number Diff line Loading @@ -695,9 +695,6 @@ static int __init ppro_init(char **cpu_type) return 1; } /* in order to get sysfs right */ static int using_nmi; int __init op_nmi_init(struct oprofile_operations *ops) { __u8 vendor = boot_cpu_data.x86_vendor; Loading @@ -705,8 +702,6 @@ int __init op_nmi_init(struct oprofile_operations *ops) char *cpu_type = NULL; int ret = 0; using_nmi = 0; if (!cpu_has_apic) return -ENODEV; Loading Loading @@ -790,13 +785,11 @@ int __init op_nmi_init(struct oprofile_operations *ops) if (ret) return ret; using_nmi = 1; printk(KERN_INFO "oprofile: using NMI interrupt.\n"); return 0; } void op_nmi_exit(void) { if (using_nmi) exit_sysfs(); } Loading
arch/x86/oprofile/backtrace.c +59 −11 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <asm/ptrace.h> #include <asm/uaccess.h> #include <asm/stacktrace.h> #include <linux/compat.h> static void backtrace_warning_symbol(void *data, char *msg, unsigned long symbol) Loading Loading @@ -48,14 +49,12 @@ static struct stacktrace_ops backtrace_ops = { .walk_stack = print_context_stack, }; struct frame_head { struct frame_head *bp; unsigned long ret; } __attribute__((packed)); static struct frame_head *dump_user_backtrace(struct frame_head *head) #ifdef CONFIG_COMPAT static struct stack_frame_ia32 * dump_user_backtrace_32(struct stack_frame_ia32 *head) { struct frame_head bufhead[2]; struct stack_frame_ia32 bufhead[2]; struct stack_frame_ia32 *fp; /* Also check accessibility of one struct frame_head beyond */ if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) Loading @@ -63,20 +62,66 @@ static struct frame_head *dump_user_backtrace(struct frame_head *head) if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) return NULL; oprofile_add_trace(bufhead[0].ret); fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); oprofile_add_trace(bufhead[0].return_address); /* frame pointers should strictly progress back up the stack * (towards higher addresses) */ if (head >= fp) return NULL; return fp; } static inline int x86_backtrace_32(struct pt_regs * const regs, unsigned int depth) { struct stack_frame_ia32 *head; /* User process is 32-bit */ if (!current || !test_thread_flag(TIF_IA32)) return 0; head = (struct stack_frame_ia32 *) regs->bp; while (depth-- && head) head = dump_user_backtrace_32(head); return 1; } #else static inline int x86_backtrace_32(struct pt_regs * const regs, unsigned int depth) { return 0; } #endif /* CONFIG_COMPAT */ static struct stack_frame *dump_user_backtrace(struct stack_frame *head) { struct stack_frame bufhead[2]; /* Also check accessibility of one struct stack_frame beyond */ if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) return NULL; if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) return NULL; oprofile_add_trace(bufhead[0].return_address); /* frame pointers should strictly progress back up the stack * (towards higher addresses) */ if (head >= bufhead[0].bp) if (head >= bufhead[0].next_frame) return NULL; return bufhead[0].bp; return bufhead[0].next_frame; } void x86_backtrace(struct pt_regs * const regs, unsigned int depth) { struct frame_head *head = (struct frame_head *)frame_pointer(regs); struct stack_frame *head = (struct stack_frame *)frame_pointer(regs); if (!user_mode_vm(regs)) { unsigned long stack = kernel_stack_pointer(regs); Loading @@ -86,6 +131,9 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) return; } if (x86_backtrace_32(regs, depth)) return; while (depth-- && head) head = dump_user_backtrace(head); }
arch/x86/oprofile/nmi_int.c +1 −8 Original line number Diff line number Diff line Loading @@ -695,9 +695,6 @@ static int __init ppro_init(char **cpu_type) return 1; } /* in order to get sysfs right */ static int using_nmi; int __init op_nmi_init(struct oprofile_operations *ops) { __u8 vendor = boot_cpu_data.x86_vendor; Loading @@ -705,8 +702,6 @@ int __init op_nmi_init(struct oprofile_operations *ops) char *cpu_type = NULL; int ret = 0; using_nmi = 0; if (!cpu_has_apic) return -ENODEV; Loading Loading @@ -790,13 +785,11 @@ int __init op_nmi_init(struct oprofile_operations *ops) if (ret) return ret; using_nmi = 1; printk(KERN_INFO "oprofile: using NMI interrupt.\n"); return 0; } void op_nmi_exit(void) { if (using_nmi) exit_sysfs(); }